js-on-sx: rational handling in typeof/to-string/strict-eq/loose-eq
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s

This commit is contained in:
2026-05-09 04:53:11 +00:00
parent 9bf4bd6180
commit 41dbac55b8
2 changed files with 21 additions and 4 deletions

View File

@@ -1304,6 +1304,7 @@
((= v nil) "object")
((= (type-of v) "boolean") "boolean")
((= (type-of v) "number") "number")
((= (type-of v) "rational") "number")
((= (type-of v) "string") "string")
((= (type-of v) "lambda") "function")
((= (type-of v) "function") "function")
@@ -1322,6 +1323,7 @@
((= (type-of v) "list") "[object Array]")
((= (type-of v) "string") "[object String]")
((= (type-of v) "number") "[object Number]")
((= (type-of v) "rational") "[object Number]")
((= (type-of v) "boolean") "[object Boolean]")
((or (= (type-of v) "lambda") (= (type-of v) "function") (= (type-of v) "component"))
"[object Function]")
@@ -1731,6 +1733,7 @@
((= v false) "false")
((= (type-of v) "string") v)
((= (type-of v) "number") (js-number-to-string v))
((= (type-of v) "rational") (js-number-to-string (exact->inexact v)))
(else
(if
(= (type-of v) "dict")
@@ -2055,6 +2058,14 @@
js-bitnot
(fn (a) (- 0 (+ (js-num-to-int (js-to-number a)) 1))))
(define
js-numeric-type?
(fn (v) (or (= (type-of v) "number") (= (type-of v) "rational"))))
(define
js-numeric-norm
(fn (v) (if (= (type-of v) "rational") (exact->inexact v) v)))
(define
js-strict-eq
(fn
@@ -2062,6 +2073,10 @@
(cond
((and (js-undefined? a) (js-undefined? b)) true)
((or (js-undefined? a) (js-undefined? b)) false)
((and (js-numeric-type? a) (js-numeric-type? b))
(let
((an (js-numeric-norm a)) (bn (js-numeric-norm b)))
(if (or (js-number-is-nan an) (js-number-is-nan bn)) false (= an bn))))
((not (= (type-of a) (type-of b))) false)
(else
(if (or (js-number-is-nan a) (js-number-is-nan b)) false (= a b))))))
@@ -2076,10 +2091,10 @@
((js-strict-eq a b) true)
((and (= a nil) (js-undefined? b)) true)
((and (js-undefined? a) (= b nil)) true)
((and (= (type-of a) "number") (= (type-of b) "string"))
(= a (js-to-number b)))
((and (= (type-of a) "string") (= (type-of b) "number"))
(= (js-to-number a) b))
((and (js-numeric-type? a) (= (type-of b) "string"))
(= (js-numeric-norm a) (js-to-number b)))
((and (= (type-of a) "string") (js-numeric-type? b))
(= (js-to-number a) (js-numeric-norm b)))
((= (type-of a) "boolean") (js-loose-eq (js-to-number a) b))
((= (type-of b) "boolean") (js-loose-eq a (js-to-number b)))
((and (dict? a) (contains? (keys a) "__js_string_value__"))

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 — **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.
- 2026-05-09 — **`parseFloat("+")` / `parseFloat("-")` / `parseFloat(".")` return NaN (were returning 0).** `js-float-prefix-end` happily consumed leading `+`/`-` and dot characters even with no digits — and `js-parse-num-safe` of those characters returned 0. Per spec, the prefix must contain at least one digit. Added a `js-str-has-digit?` walker called between `js-float-prefix-end` and `js-parse-num-safe`; if no digit is present in the consumed slice, return NaN. Result: built-ins/parseFloat 20/30 → 23/30, built-ins/parseInt 22/30 → 24/30. Number unchanged. conformance.sh: 148/148.