js-on-sx: ** / Math.pow spec edges (NaN exp, abs(base)=1+inf), Number.valueOf ignores args
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 42s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 42s
This commit is contained in:
@@ -2048,7 +2048,23 @@
|
||||
(sh (modulo (js-math-trunc (js-to-number b)) 32)))
|
||||
(if (= sh 0) ai (floor (/ ai (js-math-pow 2 sh)))))))
|
||||
|
||||
(define js-pow (fn (a b) (pow (js-to-number a) (js-to-number b))))
|
||||
(define
|
||||
js-pow-spec
|
||||
(fn
|
||||
(b e)
|
||||
(let
|
||||
((bn (js-to-number b)) (en (js-to-number e)))
|
||||
(let
|
||||
((inf (js-infinity-value)) (abs-b (if (< bn 0) (- 0 bn) bn)))
|
||||
(cond
|
||||
((js-number-is-nan en) (js-nan-value))
|
||||
((= en 0) 1)
|
||||
((js-number-is-nan bn) (js-nan-value))
|
||||
((and (= abs-b 1) (or (= en inf) (= en (- 0 inf))))
|
||||
(js-nan-value))
|
||||
(else (pow bn en)))))))
|
||||
|
||||
(define js-pow (fn (a b) (js-pow-spec a b)))
|
||||
|
||||
(define js-neg (fn (a) (* -1 (exact->inexact (js-to-number a)))))
|
||||
|
||||
@@ -3653,7 +3669,7 @@
|
||||
|
||||
(define js-math-sqrt (fn (x) (sqrt (js-to-number x))))
|
||||
|
||||
(define js-math-pow (fn (a b) (pow (js-to-number a) (js-to-number b))))
|
||||
(define js-math-pow (fn (a b) (js-pow-spec a b)))
|
||||
|
||||
(define
|
||||
js-math-trunc
|
||||
@@ -3788,7 +3804,7 @@
|
||||
(else
|
||||
(raise (js-new-call TypeError (js-args "Number.prototype method requires a Number"))))))))
|
||||
|
||||
(define Number {:MIN_SAFE_INTEGER -9007199254740991 :MIN_VALUE 4.94066e-324 :isNaN js-number-is-nan :isSafeInteger js-number-is-safe-integer :NEGATIVE_INFINITY (- 0 (js-infinity-value)) :NaN (js-nan-value) :prototype {:toFixed {:__callable__ (fn (d) (js-number-to-fixed (js-number-this-val) (if (= d nil) 0 (js-to-number d)))) :length 1 :name "toFixed"} :toExponential {:__callable__ (fn (&rest args) (js-number-to-string (js-number-this-val))) :length 1 :name "toExponential"} :toLocaleString {:__callable__ (fn () (js-number-to-string (js-number-this-val))) :length 0 :name "toLocaleString"} :toString {:__callable__ (fn (&rest args) (let ((this-val (js-number-this-val)) (radix (if (empty? args) 10 (js-to-number (nth args 0))))) (js-num-to-str-radix this-val (if (or (= radix nil) (js-undefined? radix)) 10 radix)))) :length 1 :name "toString"} :toPrecision {:__callable__ (fn (&rest args) (js-number-to-string (js-number-this-val))) :length 1 :name "toPrecision"} :valueOf {:__callable__ (fn () (js-number-this-val)) :length 0 :name "valueOf"}} :isInteger js-number-is-integer :__callable__ js-to-number :MAX_VALUE (js-max-value-approx) :POSITIVE_INFINITY (js-infinity-value) :isFinite js-number-is-finite :MAX_SAFE_INTEGER 9007199254740991 :EPSILON 2.22045e-16})
|
||||
(define Number {:MIN_SAFE_INTEGER -9007199254740991 :MIN_VALUE 4.94066e-324 :isNaN js-number-is-nan :isSafeInteger js-number-is-safe-integer :NEGATIVE_INFINITY (- 0 (js-infinity-value)) :NaN (js-nan-value) :prototype {:toFixed {:__callable__ (fn (d) (js-number-to-fixed (js-number-this-val) (if (= d nil) 0 (js-to-number d)))) :length 1 :name "toFixed"} :toExponential {:__callable__ (fn (&rest args) (js-number-to-string (js-number-this-val))) :length 1 :name "toExponential"} :toLocaleString {:__callable__ (fn () (js-number-to-string (js-number-this-val))) :length 0 :name "toLocaleString"} :toString {:__callable__ (fn (&rest args) (let ((this-val (js-number-this-val)) (radix (if (empty? args) 10 (js-to-number (nth args 0))))) (js-num-to-str-radix this-val (if (or (= radix nil) (js-undefined? radix)) 10 radix)))) :length 1 :name "toString"} :toPrecision {:__callable__ (fn (&rest args) (js-number-to-string (js-number-this-val))) :length 1 :name "toPrecision"} :valueOf {:__callable__ (fn (&rest args) (js-number-this-val)) :length 0 :name "valueOf"}} :isInteger js-number-is-integer :__callable__ js-to-number :MAX_VALUE (js-max-value-approx) :POSITIVE_INFINITY (js-infinity-value) :isFinite js-number-is-finite :MAX_SAFE_INTEGER 9007199254740991 :EPSILON 2.22045e-16})
|
||||
|
||||
(dict-set! Number "length" 1)
|
||||
|
||||
|
||||
@@ -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 — **`**` / `Math.pow` honour JS spec edge cases for NaN, ±0, abs(base)=1+Infinity, plus `Number.prototype.valueOf` accepts ignored args.** (1) New `js-pow-spec` shared by `js-pow` (operator) and `js-math-pow`: NaN exponent → NaN, exponent 0 → 1 (even with NaN base), NaN base + non-zero exp → NaN, abs(base)=1 with exp=±Infinity → NaN. Underlying `pow` handles the rest. (2) Number.prototype.valueOf was `(fn () ...)` and rejected the spec-allowed extra arg with "lambda expects 0 args, got 1"; now `(fn (&rest args) ...)`. Result: language/expressions/exponentiation 23/30 → 25/30 (+2). built-ins/Math/pow 27/27 holds. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-10 — **`Number.prototype.toString(radix)` no longer crashes on rational division-by-zero.** `js-num-to-str-radix` was probing for ±Infinity by comparing against `(/ 1 0)` / `(/ -1 0)` — but on the rational arithmetic path that throws "rational: division by zero" before the comparison ever happens, so every `Number(x).toString(radix)` call exploded. Replaced the probes with `(js-infinity-value)` / `(- 0 (js-infinity-value))` and the NaN check with `js-number-is-nan`. Result: built-ins/Number/prototype/toString 0/30 → 29/30 (+29). Number 26/30. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-10 — **Array literal elision (holes), `list instanceof Array`, `array.toString` identity.** Three coupled fixes for `language/expressions/array`. (1) Parser: `jp-array-loop` accepts a leading or interior `,` as elision and pushes `(js-undef)`, so `[,]`, `[,,3,,,]`, `[1,,3]` parse and produce length 1, 5, 3. (2) Runtime: `js-instanceof` adds a `(list? obj)` arm that returns true when the right-hand side is `Array` (or `Object`). (3) Runtime: `js-get-prop` for `key="toString"` on a list returns the actual `Array.prototype.toString` slot via `js-dict-get-walk` instead of a fresh `js-array-method` callable, so `[1,2,3].toString === Array.prototype.toString`. `toLocaleString` left on the legacy arm — its proto entry is a dict-with-`__callable__` whose body re-enters `js-invoke-method`, which would loop. Result: language/expressions/array 13/30 → 21/30 (+8). conformance.sh: 148/148.
|
||||
|
||||
Reference in New Issue
Block a user