js-on-sx: js-add ToPrimitive's Date and plain Objects via valueOf/toString
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s

This commit is contained in:
2026-05-09 05:56:01 +00:00
parent 76d6528c51
commit 013ce15357
2 changed files with 26 additions and 1 deletions

View File

@@ -1969,7 +1969,30 @@
(get v "__js_number_value__"))
((contains? (keys v) "__js_boolean_value__")
(get v "__js_boolean_value__"))
(else v))))
((contains? (keys v) "__js_is_date__")
(js-add-call-method v "toString"))
(else (js-add-toprim-default v)))))
(define
js-add-toprim-default
(fn
(v)
(let
((via-valueof (js-add-call-method v "valueOf")))
(cond
((not (= (type-of via-valueof) "dict")) via-valueof)
(else (js-add-call-method v "toString"))))))
(define
js-add-call-method
(fn
(v name)
(let
((m (js-dict-get-walk v name)))
(cond
((js-undefined? m) v)
((not (js-function? m)) v)
(else (js-call-with-this v m (list)))))))
(define
js-add

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-09 — **`+` operator now ToPrimitive's plain Objects + Dates via `valueOf`/`toString`.** Followup to the wrapper-unwrap fix. `js-add-unwrap` only handled `__js_string_value__` / `__js_number_value__` / `__js_boolean_value__` markers — for plain `{}` or `new Date()`, it returned the dict as-is, which then fell into `js-to-number` and produced `NaN`. Added two helpers: `js-add-toprim-default` calls `valueOf()` first (the "default" hint, used by `+`), and falls back to `toString()` if valueOf returns an object; for Date instances (`__js_is_date__` marker) we go straight to `toString` per spec. `js-add-call-method` walks the proto chain via `js-dict-get-walk`, calls the method with the receiver bound, and gives up if the slot is missing or not callable. Now `date + date === date.toString() + date.toString()`. Result: language/expressions/addition 23/30 → 24/30. Object/Array unchanged. conformance.sh: 148/148.
- 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.