js-on-sx: globalThis self-ref, toFixed range + 1e21 fallback
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s

This commit is contained in:
2026-05-10 12:01:14 +00:00
parent 0142d69212
commit 1e29bba1be
2 changed files with 36 additions and 27 deletions

View File

@@ -536,36 +536,41 @@
js-number-to-fixed
(fn
(n digits)
(cond
((js-number-is-nan n) "NaN")
((= n (js-infinity-value)) "Infinity")
((= n (- 0 (js-infinity-value))) "-Infinity")
(else
(let
((d (js-math-trunc digits)))
(if
(< d 1)
(js-to-string (js-math-round n))
(let
((scale (js-pow-int 10 d)))
(let
((d (js-math-trunc (js-to-number digits))))
(cond
((or (js-number-is-nan d) (< d 0) (> d 100))
(raise
(js-new-call RangeError
(js-args "toFixed() digits argument must be between 0 and 100"))))
((js-number-is-nan n) "NaN")
((= n (js-infinity-value)) "Infinity")
((= n (- 0 (js-infinity-value))) "-Infinity")
((or (>= n 1e21) (<= n -1e21)) (js-number-to-string n))
(else
(cond
((< d 1) (js-to-string (js-math-round n)))
(else
(let
((scaled (js-math-round (* n scale))))
((scale (js-pow-int 10 d)))
(let
((abs-scaled (if (< scaled 0) (- 0 scaled) scaled))
(sign (if (< scaled 0) "-" "")))
((scaled (js-math-round (* n scale))))
(let
((int-part (js-math-trunc (/ abs-scaled scale)))
(frac-part
(-
abs-scaled
(* (js-math-trunc (/ abs-scaled scale)) scale))))
(str
sign
(js-to-string int-part)
"."
(js-pad-int-str
(js-to-string (js-math-trunc frac-part))
d))))))))))))
((abs-scaled (if (< scaled 0) (- 0 scaled) scaled))
(sign (if (< scaled 0) "-" "")))
(let
((int-part (js-math-trunc (/ abs-scaled scale)))
(frac-part
(-
abs-scaled
(* (js-math-trunc (/ abs-scaled scale)) scale))))
(str
sign
(js-to-string int-part)
"."
(js-pad-int-str
(js-to-string (js-math-trunc frac-part))
d)))))))))))))
(define
js-pow-int
@@ -6803,3 +6808,5 @@
(define js-global {:undefined js-undefined :JSON JSON :parseInt parseInt :Object Object :isNaN js-global-is-nan :Infinity inf :NaN 0 :String String :Boolean Boolean :Array Array :Math Math :parseFloat parseFloat :Number Number :console console :isFinite js-global-is-finite :Map Map :Set Set :Date Date :RegExp RegExp :Function js-function-global :Error Error :TypeError TypeError :RangeError RangeError :SyntaxError SyntaxError :ReferenceError ReferenceError :URIError URIError :EvalError EvalError :encodeURI encodeURI :decodeURI decodeURI :encodeURIComponent encodeURIComponent :decodeURIComponent decodeURIComponent :eval js-global-eval :Promise Promise :Symbol :js-undefined :AggregateError :js-undefined :SuppressedError :js-undefined :globalThis nil})
(set! js-global-this js-global)
(dict-set! js-global "globalThis" js-global)

View File

@@ -158,6 +158,8 @@ Each item: implement → tests → update progress. Mark `[x]` when tests green.
Append-only record of completed iterations. Loop writes one line per iteration: date, what was done, test count delta.
- 2026-05-10 — **`globalThis.globalThis === globalThis`; `Number.prototype.toFixed` honours digit-range and ≥1e21 fallback.** (1) `globalThis` was bound to `nil` in the global object literal (originally to dodge an inspect-cycle hang) — added `(dict-set! js-global "globalThis" js-global)` after the literal so `globalThis.globalThis === globalThis` per spec. (2) `Number.prototype.toFixed` rewrites: RangeError when fractionDigits is NaN or outside `[0,100]` (was silently producing garbage), and for `|x| >= 1e21` returns `js-number-to-string` (the value's own ToString) per spec step 9. conformance.sh: 148/148.
- 2026-05-10 — **`delete <ident>` returns `false` instead of `true` per non-strict spec.** ES non-strict semantics: `delete x` where `x` is a declared binding (variable / function / parameter) returns `false` and does not unbind. Our transpiler was emitting `true` for any `delete <expr>` whose argument wasn't a member or index access. Now `delete <js-ident>``false`, and `delete <js-paren expr>` recurses on the inner expression so `delete (1+2)` still works. Result: language/expressions/delete 14/30 → 18/30 (+4). conformance.sh: 148/148.
- 2026-05-10 — **Parser rejects unary-op directly before `**` (e.g. `-1 ** 2`, `delete o.p ** 2`, `!x ** 2`, `~x ** 2`) per ES spec.** ES disallows `UnaryExpression ** ExponentiationExpression`; only `UpdateExpression ** ExponentiationExpression` and `(<UnaryExpr>) ** ...` are legal. Added a guard in `jp-binary-loop`: when op is `**` and the LHS is a `(js-unop ...)` node, raise SyntaxError. Parens are made transparent for everything except this check via a new `jp-paren-wrap` helper that emits `(js-paren <unop>)` only when wrapping an explicit unary op (so `(-1) ** 2` parses fine), and a new `js-paren` AST tag in `js-transpile` that just unwraps. Result: language/expressions/exponentiation 25/30 → 28/30 (+3). conformance.sh: 148/148.