Skip to content

Commit 74bcd8b

Browse files
darshjoshimasenfFarhanAliRaza
authored
fix: parenthesize a unary base in the compiled ** expression (#7565)
* fix: parenthesize a unary base in the compiled ** expression * Add a news fragment * Move the exponent test next to the other reflex_base.vars tests * Keep test_var.py as it is on the base branch --------- Co-authored-by: Masen Furer <m_github@0x26.net> Co-authored-by: Farhan Ali Raza <62690310+FarhanAliRaza@users.noreply.github.com>
1 parent b2e009a commit 74bcd8b

3 files changed

Lines changed: 26 additions & 1 deletion

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Raising a negative number or a negated var to a power, such as `(-State.x) ** 2`, now compiles to valid JavaScript instead of failing the frontend build with "A unary expression with the '-' operator cannot be used as the left operand of an exponentiation expression".

‎packages/reflex-base/src/reflex_base/vars/number.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import decimal
77
import json
88
import math
9+
import re
910
from collections.abc import Callable
1011
from typing import TYPE_CHECKING, Any, NoReturn, TypeVar, overload
1112

@@ -647,6 +648,9 @@ def number_modulo_operation(lhs: NumberVar, rhs: NumberVar):
647648
return f"({lhs!s} % {rhs!s})"
648649

649650

651+
_STARTS_WITH_UNARY_OPERATOR = re.compile(r"[-+!~]|(?:typeof|void|delete|await)\b")
652+
653+
650654
@binary_number_operation
651655
def number_exponent_operation(lhs: NumberVar, rhs: NumberVar):
652656
"""Exponentiate two numbers.
@@ -658,7 +662,12 @@ def number_exponent_operation(lhs: NumberVar, rhs: NumberVar):
658662
Returns:
659663
The number exponent operation.
660664
"""
661-
return f"({lhs!s} ** {rhs!s})"
665+
base = str(lhs)
666+
# JavaScript rejects a unary expression as the base of `**` (`-2 ** 2` is a
667+
# SyntaxError), so a negative literal or a negated var must be parenthesized.
668+
if _STARTS_WITH_UNARY_OPERATOR.match(base):
669+
base = f"({base})"
670+
return f"({base} ** {rhs!s})"
662671

663672

664673
@var_operation
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Tests for reflex_base.vars.number."""
2+
3+
from reflex_base.vars.base import Var
4+
from reflex_base.vars.number import LiteralNumberVar
5+
6+
7+
def test_exponent_parenthesizes_a_unary_base():
8+
"""JavaScript rejects a unary expression as the base of `**` (`-2 ** 2` is a SyntaxError)."""
9+
x = Var(_js_expr="x").to(int)
10+
assert str(LiteralNumberVar.create(-2) ** 3) == "((-2) ** 3)"
11+
assert str(LiteralNumberVar.create(-2.5) ** x) == "((-2.5) ** x)"
12+
assert str((-x) ** 2) == "((-(x)) ** 2)"
13+
assert str(-(x**2)) == "-((x ** 2))"
14+
assert str(x**-1) == "(x ** -1)"
15+
assert str(2**-x) == "(2 ** -(x))"

0 commit comments

Comments
 (0)