js-on-sx: js-add unwraps wrapper objects before string-concat decision
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s
This commit is contained in:
@@ -1957,14 +1957,30 @@
|
||||
((= (char-at s i) "0") (js-strip-zeros-loop s (+ i 1) n))
|
||||
(else (js-string-slice s i n)))))
|
||||
|
||||
(define
|
||||
js-add-unwrap
|
||||
(fn
|
||||
(v)
|
||||
(cond
|
||||
((not (= (type-of v) "dict")) v)
|
||||
((contains? (keys v) "__js_string_value__")
|
||||
(get v "__js_string_value__"))
|
||||
((contains? (keys v) "__js_number_value__")
|
||||
(get v "__js_number_value__"))
|
||||
((contains? (keys v) "__js_boolean_value__")
|
||||
(get v "__js_boolean_value__"))
|
||||
(else v))))
|
||||
|
||||
(define
|
||||
js-add
|
||||
(fn
|
||||
(a b)
|
||||
(cond
|
||||
((or (= (type-of a) "string") (= (type-of b) "string"))
|
||||
(str (js-to-string a) (js-to-string b)))
|
||||
(else (+ (js-to-number a) (js-to-number b))))))
|
||||
(let
|
||||
((ap (js-add-unwrap a)) (bp (js-add-unwrap b)))
|
||||
(cond
|
||||
((or (= (type-of ap) "string") (= (type-of bp) "string"))
|
||||
(str (js-to-string ap) (js-to-string bp)))
|
||||
(else (+ (js-to-number ap) (js-to-number bp)))))))
|
||||
|
||||
(define js-sub (fn (a b) (- (js-to-number a) (js-to-number b))))
|
||||
|
||||
|
||||
@@ -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-09 — **`+` operator unwraps Number/String/Boolean wrapper objects before deciding string-vs-numeric.** `js-add` was only checking `(type-of a)` / `(type-of b)` for `"string"` to decide string concat — but a `new String("1")` instance is type `"dict"`, so `new String("1") + "1"` was falling into the numeric branch and producing `2` instead of `"11"`. Added `js-add-unwrap` (mirrors ToPrimitive for the wrapper cases): if a dict has `__js_string_value__` / `__js_number_value__` / `__js_boolean_value__`, return the inner primitive. Then `js-add` applies the string-concat-vs-numeric decision to the unwrapped values. Result: language/expressions/addition 19/30 → 23/30. String stays 30/30. Number/Object unchanged. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-09 — **Rational handling in `js-typeof` / `js-to-string` / `js-strict-eq` / `js-loose-eq` / `Object.prototype.toString`.** Followup to the `js-to-number` fix. SX rationals were leaking into other paths: `typeof 1/2` returned `"object"` (should be `"number"`), `String(1/2)` fell into the dict branch and returned `"[object Object]"`, and `1/2 === 0.5` was false because strict-eq compared types and `"rational"` ≠ `"number"`. Added rational arms to `js-typeof` and `js-object-tostring-class`, normalised rationals via `(exact->inexact)` in `js-to-string`'s number branch, and introduced a `js-numeric-type?` / `js-numeric-norm` pair that lets strict-eq and loose-eq treat both numeric kinds uniformly. Result: language/expressions/strict-equals 16/22 → 19/22; Math 30/30 confirmed (no regression — but it never had one). Object/Array/Map unchanged. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-09 — **`js-to-number` now coerces SX rationals via `exact->inexact`.** SX `(/ 59 16)` returns the rational `59/16` with `(type-of)` `"rational"` — not `"number"` — so `js-to-number` was falling through to the dict branch and ultimately returning `0`. That broke any path that did integer-divide intermediate math (e.g. `js-hex-2` for percent-encoding: `(js-math-trunc (/ 59 16))` was returning 0, so `encodeURIComponent(";")` produced `"%0B"` instead of `"%3B"`). Added a `((= (type-of v) "rational") (exact->inexact v))` clause in `js-to-number` between the existing `"number"` and `"string"` branches. Result: built-ins/encodeURIComponent 9/30 → 15/30, built-ins/encodeURI 22/60 → 28/60, built-ins/decodeURI 11/60 → 20/60. Object/Array unchanged. conformance.sh: 148/148.
|
||||
|
||||
Reference in New Issue
Block a user