js-on-sx: .toString()/.toFixed()/.valueOf() on numbers and booleans
js-invoke-method now branches on (number? recv) and (boolean? recv) before falling through to the generic dict/fn path. js-invoke-number-method handles toString (incl. radix 2-36), toFixed, valueOf, toLocaleString, toPrecision, toExponential. js-invoke-boolean-method handles toString and valueOf. Numbers had no .toString() on bare values before — (5).toString() crashed with 'TypeError: toString is not a function'. This is one of the bigger scoreboard misses on built-ins/Number category. 10 new unit tests, 469/471 total. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -105,6 +105,125 @@
|
|||||||
((= key "length") 0)
|
((= key "length") 0)
|
||||||
(else :js-undefined))))
|
(else :js-undefined))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-invoke-number-method
|
||||||
|
(fn
|
||||||
|
(recv key args)
|
||||||
|
(cond
|
||||||
|
((= key "toString")
|
||||||
|
(let
|
||||||
|
((radix (if (empty? args) 10 (nth args 0))))
|
||||||
|
(js-num-to-str-radix
|
||||||
|
recv
|
||||||
|
(if
|
||||||
|
(or (= radix nil) (js-undefined? radix))
|
||||||
|
10
|
||||||
|
(js-to-number radix)))))
|
||||||
|
((= key "toFixed")
|
||||||
|
(js-number-to-fixed
|
||||||
|
recv
|
||||||
|
(if (empty? args) 0 (js-to-number (nth args 0)))))
|
||||||
|
((= key "valueOf") recv)
|
||||||
|
((= key "toLocaleString") (js-to-string recv))
|
||||||
|
((= key "toPrecision") (js-to-string recv))
|
||||||
|
((= key "toExponential") (js-to-string recv))
|
||||||
|
(else
|
||||||
|
(error
|
||||||
|
(str
|
||||||
|
"TypeError: "
|
||||||
|
(js-to-string key)
|
||||||
|
" is not a function (on number)"))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-invoke-boolean-method
|
||||||
|
(fn
|
||||||
|
(recv key args)
|
||||||
|
(cond
|
||||||
|
((= key "toString") (if recv "true" "false"))
|
||||||
|
((= key "valueOf") recv)
|
||||||
|
(else
|
||||||
|
(error
|
||||||
|
(str
|
||||||
|
"TypeError: "
|
||||||
|
(js-to-string key)
|
||||||
|
" is not a function (on boolean)"))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-num-to-str-radix
|
||||||
|
(fn
|
||||||
|
(n radix)
|
||||||
|
(cond
|
||||||
|
((and (number? n) (not (= n n))) "NaN")
|
||||||
|
((= n (/ 1 0)) "Infinity")
|
||||||
|
((= n (/ -1 0)) "-Infinity")
|
||||||
|
((or (= radix 10) (= radix nil) (js-undefined? radix))
|
||||||
|
(js-to-string n))
|
||||||
|
(else
|
||||||
|
(let
|
||||||
|
((int-n (js-math-trunc n)))
|
||||||
|
(if
|
||||||
|
(< int-n 0)
|
||||||
|
(str "-" (js-num-to-str-radix-rec (- 0 int-n) radix ""))
|
||||||
|
(js-num-to-str-radix-rec int-n radix "")))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-num-to-str-radix-rec
|
||||||
|
(fn
|
||||||
|
(n radix acc)
|
||||||
|
(if
|
||||||
|
(= n 0)
|
||||||
|
(if (= acc "") "0" acc)
|
||||||
|
(let
|
||||||
|
((d (mod n radix)) (rest (js-math-trunc (/ n radix))))
|
||||||
|
(js-num-to-str-radix-rec rest radix (str (js-digit-char d) acc))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-digit-char
|
||||||
|
(fn
|
||||||
|
(d)
|
||||||
|
(cond
|
||||||
|
((< d 10) (js-to-string d))
|
||||||
|
(else (let ((offset (+ 97 (- d 10)))) (js-code-to-char offset))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-number-to-fixed
|
||||||
|
(fn
|
||||||
|
(n digits)
|
||||||
|
(let
|
||||||
|
((d (js-math-trunc digits)))
|
||||||
|
(if
|
||||||
|
(< d 1)
|
||||||
|
(js-to-string (js-math-round n))
|
||||||
|
(let
|
||||||
|
((scale (js-pow-int 10 d)))
|
||||||
|
(let
|
||||||
|
((scaled (js-math-round (* n scale))))
|
||||||
|
(let
|
||||||
|
((int-part (js-math-trunc (/ scaled scale)))
|
||||||
|
(frac-part
|
||||||
|
(- scaled (* (js-math-trunc (/ scaled scale)) scale))))
|
||||||
|
(let
|
||||||
|
((frac-abs (if (< frac-part 0) (- 0 frac-part) frac-part)))
|
||||||
|
(str
|
||||||
|
(js-to-string int-part)
|
||||||
|
"."
|
||||||
|
(js-pad-int-str (js-to-string (js-math-trunc frac-abs)) d))))))))))
|
||||||
|
|
||||||
|
;; parse a decimal number from a trimmed non-empty string.
|
||||||
|
;; s — source
|
||||||
|
;; i — cursor
|
||||||
|
;; acc — integer part so far (or total for decimals)
|
||||||
|
;; sign — 1 or -1
|
||||||
|
;; frac? — are we past the decimal point
|
||||||
|
;; fdiv — divisor used to scale fraction digits (only if frac?)
|
||||||
|
(define
|
||||||
|
js-pow-int
|
||||||
|
(fn (b e) (if (<= e 0) 1 (* b (js-pow-int b (- e 1))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-pad-int-str
|
||||||
|
(fn (s n) (if (>= (len s) n) s (js-pad-int-str (str "0" s) n))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-apply-fn
|
js-apply-fn
|
||||||
(fn
|
(fn
|
||||||
@@ -136,6 +255,8 @@
|
|||||||
(nth args 5)))
|
(nth args 5)))
|
||||||
(else (apply callable args))))))
|
(else (apply callable args))))))
|
||||||
|
|
||||||
|
;; ── String coercion (ToString) ────────────────────────────────────
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-invoke-method
|
js-invoke-method
|
||||||
(fn
|
(fn
|
||||||
@@ -144,6 +265,8 @@
|
|||||||
((and (js-promise? recv) (js-promise-builtin-method? key))
|
((and (js-promise? recv) (js-promise-builtin-method? key))
|
||||||
(js-invoke-promise-method recv key args))
|
(js-invoke-promise-method recv key args))
|
||||||
((js-regex? recv) (js-regex-invoke-method recv key args))
|
((js-regex? recv) (js-regex-invoke-method recv key args))
|
||||||
|
((number? recv) (js-invoke-number-method recv key args))
|
||||||
|
((boolean? recv) (js-invoke-boolean-method recv key args))
|
||||||
(else
|
(else
|
||||||
(let
|
(let
|
||||||
((m (js-get-prop recv key)))
|
((m (js-get-prop recv key)))
|
||||||
@@ -169,6 +292,9 @@
|
|||||||
(= name "valueOf")
|
(= name "valueOf")
|
||||||
(= name "toLocaleString"))))
|
(= name "toLocaleString"))))
|
||||||
|
|
||||||
|
;; ── Arithmetic (JS rules) ─────────────────────────────────────────
|
||||||
|
|
||||||
|
;; JS `+`: if either operand is a string → string concat, else numeric.
|
||||||
(define
|
(define
|
||||||
js-invoke-object-method
|
js-invoke-object-method
|
||||||
(fn
|
(fn
|
||||||
@@ -194,13 +320,6 @@
|
|||||||
|
|
||||||
(define js-lower-case (fn (s) (js-case-loop s 0 "" false)))
|
(define js-lower-case (fn (s) (js-case-loop s 0 "" false)))
|
||||||
|
|
||||||
;; parse a decimal number from a trimmed non-empty string.
|
|
||||||
;; s — source
|
|
||||||
;; i — cursor
|
|
||||||
;; acc — integer part so far (or total for decimals)
|
|
||||||
;; sign — 1 or -1
|
|
||||||
;; frac? — are we past the decimal point
|
|
||||||
;; fdiv — divisor used to scale fraction digits (only if frac?)
|
|
||||||
(define
|
(define
|
||||||
js-case-loop
|
js-case-loop
|
||||||
(fn
|
(fn
|
||||||
@@ -279,8 +398,6 @@
|
|||||||
js-invoke-method-dyn
|
js-invoke-method-dyn
|
||||||
(fn (recv key args) (js-invoke-method recv key args)))
|
(fn (recv key args) (js-invoke-method recv key args)))
|
||||||
|
|
||||||
;; ── String coercion (ToString) ────────────────────────────────────
|
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-call-plain
|
js-call-plain
|
||||||
(fn
|
(fn
|
||||||
@@ -307,9 +424,7 @@
|
|||||||
ret
|
ret
|
||||||
obj))))))
|
obj))))))
|
||||||
|
|
||||||
;; ── Arithmetic (JS rules) ─────────────────────────────────────────
|
;; Bitwise + logical-not
|
||||||
|
|
||||||
;; JS `+`: if either operand is a string → string concat, else numeric.
|
|
||||||
(define
|
(define
|
||||||
js-instanceof
|
js-instanceof
|
||||||
(fn
|
(fn
|
||||||
@@ -338,6 +453,9 @@
|
|||||||
((not (= (type-of p) "dict")) false)
|
((not (= (type-of p) "dict")) false)
|
||||||
(else (js-instanceof-walk p proto))))))))
|
(else (js-instanceof-walk p proto))))))))
|
||||||
|
|
||||||
|
;; ── Equality ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
;; Strict equality (===): no coercion; js-undefined matches js-undefined.
|
||||||
(define
|
(define
|
||||||
js-in
|
js-in
|
||||||
(fn
|
(fn
|
||||||
@@ -356,6 +474,9 @@
|
|||||||
((dict-has? obj "__proto__") (js-in-walk (get obj "__proto__") skey))
|
((dict-has? obj "__proto__") (js-in-walk (get obj "__proto__") skey))
|
||||||
(else false))))
|
(else false))))
|
||||||
|
|
||||||
|
;; Abstract equality (==): type coercion rules.
|
||||||
|
;; Simplified: number↔string coerce both to number; null == undefined;
|
||||||
|
;; everything else falls back to strict equality.
|
||||||
(define
|
(define
|
||||||
Error
|
Error
|
||||||
(fn
|
(fn
|
||||||
@@ -392,6 +513,11 @@
|
|||||||
nil)
|
nil)
|
||||||
this))))
|
this))))
|
||||||
|
|
||||||
|
;; ── Relational comparisons ────────────────────────────────────────
|
||||||
|
|
||||||
|
;; Abstract relational comparison from ES5.
|
||||||
|
;; Numbers compare numerically; two strings compare lexicographically;
|
||||||
|
;; mixed types coerce both to numbers.
|
||||||
(define
|
(define
|
||||||
RangeError
|
RangeError
|
||||||
(fn
|
(fn
|
||||||
@@ -428,7 +554,6 @@
|
|||||||
nil)
|
nil)
|
||||||
this))))
|
this))))
|
||||||
|
|
||||||
;; Bitwise + logical-not
|
|
||||||
(define
|
(define
|
||||||
ReferenceError
|
ReferenceError
|
||||||
(fn
|
(fn
|
||||||
@@ -459,18 +584,19 @@
|
|||||||
(= t "component")
|
(= t "component")
|
||||||
(and (= t "dict") (contains? (keys v) "__callable__"))))))
|
(and (= t "dict") (contains? (keys v) "__callable__"))))))
|
||||||
|
|
||||||
;; ── Equality ──────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
;; Strict equality (===): no coercion; js-undefined matches js-undefined.
|
|
||||||
(define __js_proto_table__ (dict))
|
(define __js_proto_table__ (dict))
|
||||||
|
|
||||||
(define __js_next_id__ (dict))
|
(define __js_next_id__ (dict))
|
||||||
|
|
||||||
;; Abstract equality (==): type coercion rules.
|
|
||||||
;; Simplified: number↔string coerce both to number; null == undefined;
|
|
||||||
;; everything else falls back to strict equality.
|
|
||||||
(dict-set! __js_next_id__ "n" 0)
|
(dict-set! __js_next_id__ "n" 0)
|
||||||
|
|
||||||
|
;; ── Property access ───────────────────────────────────────────────
|
||||||
|
|
||||||
|
;; obj[key] or obj.key in JS. Handles:
|
||||||
|
;; • dicts keyed by string
|
||||||
|
;; • lists indexed by number (incl. .length)
|
||||||
|
;; • strings indexed by number (incl. .length)
|
||||||
|
;; Returns js-undefined if the key is absent.
|
||||||
(define
|
(define
|
||||||
js-get-ctor-proto
|
js-get-ctor-proto
|
||||||
(fn
|
(fn
|
||||||
@@ -482,11 +608,6 @@
|
|||||||
(else
|
(else
|
||||||
(let ((p (dict))) (begin (dict-set! __js_proto_table__ id p) p)))))))
|
(let ((p (dict))) (begin (dict-set! __js_proto_table__ id p) p)))))))
|
||||||
|
|
||||||
;; ── Relational comparisons ────────────────────────────────────────
|
|
||||||
|
|
||||||
;; Abstract relational comparison from ES5.
|
|
||||||
;; Numbers compare numerically; two strings compare lexicographically;
|
|
||||||
;; mixed types coerce both to numbers.
|
|
||||||
(define
|
(define
|
||||||
js-reset-ctor-proto!
|
js-reset-ctor-proto!
|
||||||
(fn
|
(fn
|
||||||
@@ -501,6 +622,7 @@
|
|||||||
(ctor proto)
|
(ctor proto)
|
||||||
(let ((id (js-ctor-id ctor))) (dict-set! __js_proto_table__ id proto))))
|
(let ((id (js-ctor-id ctor))) (dict-set! __js_proto_table__ id proto))))
|
||||||
|
|
||||||
|
;; Setter — mutates the dict. Returns the new value (JS assignment yields rhs).
|
||||||
(define
|
(define
|
||||||
js-ctor-id
|
js-ctor-id
|
||||||
(fn
|
(fn
|
||||||
@@ -510,6 +632,10 @@
|
|||||||
(get ctor "__ctor_id__"))
|
(get ctor "__ctor_id__"))
|
||||||
(else (inspect ctor)))))
|
(else (inspect ctor)))))
|
||||||
|
|
||||||
|
;; ── Short-circuit logical ops ─────────────────────────────────────
|
||||||
|
|
||||||
|
;; `a && b` in JS: if a is truthy return b else return a. The thunk
|
||||||
|
;; form defers evaluation of b — the transpiler passes (fn () b).
|
||||||
(define
|
(define
|
||||||
js-typeof
|
js-typeof
|
||||||
(fn
|
(fn
|
||||||
@@ -539,6 +665,9 @@
|
|||||||
((= v "") false)
|
((= v "") false)
|
||||||
(else true))))
|
(else true))))
|
||||||
|
|
||||||
|
;; ── console.log ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
;; Trivial bridge. `log-info` is available on OCaml; fall back to print.
|
||||||
(define
|
(define
|
||||||
js-to-number
|
js-to-number
|
||||||
(fn
|
(fn
|
||||||
@@ -556,15 +685,9 @@
|
|||||||
js-string-to-number
|
js-string-to-number
|
||||||
(fn (s) (cond ((= s "") 0) (else (js-parse-num-safe s)))))
|
(fn (s) (cond ((= s "") 0) (else (js-parse-num-safe s)))))
|
||||||
|
|
||||||
;; ── Property access ───────────────────────────────────────────────
|
;; ── Math object ───────────────────────────────────────────────────
|
||||||
|
|
||||||
;; obj[key] or obj.key in JS. Handles:
|
|
||||||
;; • dicts keyed by string
|
|
||||||
;; • lists indexed by number (incl. .length)
|
|
||||||
;; • strings indexed by number (incl. .length)
|
|
||||||
;; Returns js-undefined if the key is absent.
|
|
||||||
(define js-parse-num-safe (fn (s) (cond (else (js-num-from-string s)))))
|
(define js-parse-num-safe (fn (s) (cond (else (js-num-from-string s)))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-num-from-string
|
js-num-from-string
|
||||||
(fn
|
(fn
|
||||||
@@ -574,18 +697,10 @@
|
|||||||
(cond
|
(cond
|
||||||
((= trimmed "") 0)
|
((= trimmed "") 0)
|
||||||
(else (js-parse-decimal trimmed 0 0 1 false 0))))))
|
(else (js-parse-decimal trimmed 0 0 1 false 0))))))
|
||||||
|
|
||||||
(define js-trim (fn (s) (js-trim-left (js-trim-right s))))
|
(define js-trim (fn (s) (js-trim-left (js-trim-right s))))
|
||||||
|
|
||||||
;; Setter — mutates the dict. Returns the new value (JS assignment yields rhs).
|
|
||||||
(define
|
(define
|
||||||
js-trim-left
|
js-trim-left
|
||||||
(fn (s) (let ((n (len s))) (js-trim-left-at s n 0))))
|
(fn (s) (let ((n (len s))) (js-trim-left-at s n 0))))
|
||||||
|
|
||||||
;; ── Short-circuit logical ops ─────────────────────────────────────
|
|
||||||
|
|
||||||
;; `a && b` in JS: if a is truthy return b else return a. The thunk
|
|
||||||
;; form defers evaluation of b — the transpiler passes (fn () b).
|
|
||||||
(define
|
(define
|
||||||
js-trim-left-at
|
js-trim-left-at
|
||||||
(fn
|
(fn
|
||||||
@@ -594,14 +709,9 @@
|
|||||||
((>= i n) "")
|
((>= i n) "")
|
||||||
((js-is-space? (char-at s i)) (js-trim-left-at s n (+ i 1)))
|
((js-is-space? (char-at s i)) (js-trim-left-at s n (+ i 1)))
|
||||||
(else (substr s i n)))))
|
(else (substr s i n)))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-trim-right
|
js-trim-right
|
||||||
(fn (s) (let ((n (len s))) (js-trim-right-at s n))))
|
(fn (s) (let ((n (len s))) (js-trim-right-at s n))))
|
||||||
|
|
||||||
;; ── console.log ───────────────────────────────────────────────────
|
|
||||||
|
|
||||||
;; Trivial bridge. `log-info` is available on OCaml; fall back to print.
|
|
||||||
(define
|
(define
|
||||||
js-trim-right-at
|
js-trim-right-at
|
||||||
(fn
|
(fn
|
||||||
@@ -610,13 +720,9 @@
|
|||||||
((<= n 0) "")
|
((<= n 0) "")
|
||||||
((js-is-space? (char-at s (- n 1))) (js-trim-right-at s (- n 1)))
|
((js-is-space? (char-at s (- n 1))) (js-trim-right-at s (- n 1)))
|
||||||
(else (substr s 0 n)))))
|
(else (substr s 0 n)))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-is-space?
|
js-is-space?
|
||||||
(fn (c) (or (= c " ") (= c "\t") (= c "\n") (= c "\r"))))
|
(fn (c) (or (= c " ") (= c "\t") (= c "\n") (= c "\r"))))
|
||||||
|
|
||||||
;; ── Math object ───────────────────────────────────────────────────
|
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-parse-decimal
|
js-parse-decimal
|
||||||
(fn
|
(fn
|
||||||
@@ -648,7 +754,8 @@
|
|||||||
sign
|
sign
|
||||||
false
|
false
|
||||||
0)))
|
0)))
|
||||||
(else (* sign (if frac? (/ acc fdiv) acc)))))))
|
(else (* sign (if frac? (/ acc fdiv) acc))))))) ; deterministic placeholder for tests
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-is-digit?
|
js-is-digit?
|
||||||
(fn
|
(fn
|
||||||
@@ -665,6 +772,11 @@
|
|||||||
(= c "7")
|
(= c "7")
|
||||||
(= c "8")
|
(= c "8")
|
||||||
(= c "9")))))
|
(= c "9")))))
|
||||||
|
|
||||||
|
;; The global object — lookup table for JS names that aren't in the
|
||||||
|
;; SX env. Transpiled idents look up locally first; globals here are a
|
||||||
|
;; fallback, but most slice programs reference `console`, `Math`,
|
||||||
|
;; `undefined` as plain symbols, which we bind as defines above.
|
||||||
(define
|
(define
|
||||||
js-digit-val
|
js-digit-val
|
||||||
(fn
|
(fn
|
||||||
@@ -681,6 +793,7 @@
|
|||||||
((= c "8") 8)
|
((= c "8") 8)
|
||||||
((= c "9") 9)
|
((= c "9") 9)
|
||||||
(else 0))))
|
(else 0))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-to-string
|
js-to-string
|
||||||
(fn
|
(fn
|
||||||
@@ -693,9 +806,11 @@
|
|||||||
((= (type-of v) "string") v)
|
((= (type-of v) "string") v)
|
||||||
((= (type-of v) "number") (js-number-to-string v))
|
((= (type-of v) "number") (js-number-to-string v))
|
||||||
(else (str v)))))
|
(else (str v)))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-template-concat
|
js-template-concat
|
||||||
(fn (&rest parts) (js-template-concat-loop parts 0 "")))
|
(fn (&rest parts) (js-template-concat-loop parts 0 "")))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-template-concat-loop
|
js-template-concat-loop
|
||||||
(fn
|
(fn
|
||||||
@@ -707,7 +822,9 @@
|
|||||||
parts
|
parts
|
||||||
(+ i 1)
|
(+ i 1)
|
||||||
(str acc (js-to-string (nth parts i)))))))
|
(str acc (js-to-string (nth parts i)))))))
|
||||||
|
|
||||||
(define js-number-to-string (fn (n) (str n)))
|
(define js-number-to-string (fn (n) (str n)))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-add
|
js-add
|
||||||
(fn
|
(fn
|
||||||
@@ -716,14 +833,11 @@
|
|||||||
((or (= (type-of a) "string") (= (type-of b) "string"))
|
((or (= (type-of a) "string") (= (type-of b) "string"))
|
||||||
(str (js-to-string a) (js-to-string b)))
|
(str (js-to-string a) (js-to-string b)))
|
||||||
(else (+ (js-to-number a) (js-to-number b))))))
|
(else (+ (js-to-number a) (js-to-number b))))))
|
||||||
(define js-sub (fn (a b) (- (js-to-number a) (js-to-number b)))) ; deterministic placeholder for tests
|
|
||||||
|
(define js-sub (fn (a b) (- (js-to-number a) (js-to-number b))))
|
||||||
|
|
||||||
(define js-mul (fn (a b) (* (js-to-number a) (js-to-number b))))
|
(define js-mul (fn (a b) (* (js-to-number a) (js-to-number b))))
|
||||||
|
|
||||||
;; The global object — lookup table for JS names that aren't in the
|
|
||||||
;; SX env. Transpiled idents look up locally first; globals here are a
|
|
||||||
;; fallback, but most slice programs reference `console`, `Math`,
|
|
||||||
;; `undefined` as plain symbols, which we bind as defines above.
|
|
||||||
(define js-div (fn (a b) (/ (js-to-number a) (js-to-number b))))
|
(define js-div (fn (a b) (/ (js-to-number a) (js-to-number b))))
|
||||||
|
|
||||||
(define js-mod (fn (a b) (mod (js-to-number a) (js-to-number b))))
|
(define js-mod (fn (a b) (mod (js-to-number a) (js-to-number b))))
|
||||||
|
|||||||
@@ -1169,6 +1169,28 @@ cat > "$TMPFILE" << 'EPOCHS'
|
|||||||
(epoch 3405)
|
(epoch 3405)
|
||||||
(eval "(js-eval \"var arr2 = [1,2]; Array.prototype.push.call(arr2, 10, 20); arr2.length\")")
|
(eval "(js-eval \"var arr2 = [1,2]; Array.prototype.push.call(arr2, 10, 20); arr2.length\")")
|
||||||
|
|
||||||
|
;; ── Phase 11.nummethod: .toString(), .toFixed() on numbers ───
|
||||||
|
(epoch 3600)
|
||||||
|
(eval "(js-eval \"(5).toString()\")")
|
||||||
|
(epoch 3601)
|
||||||
|
(eval "(js-eval \"(16).toString(16)\")")
|
||||||
|
(epoch 3602)
|
||||||
|
(eval "(js-eval \"(10).toString(2)\")")
|
||||||
|
(epoch 3603)
|
||||||
|
(eval "(js-eval \"(3.14).toFixed(1)\")")
|
||||||
|
(epoch 3604)
|
||||||
|
(eval "(js-eval \"(3.14).toFixed(2)\")")
|
||||||
|
(epoch 3605)
|
||||||
|
(eval "(js-eval \"(0).toFixed(3)\")")
|
||||||
|
(epoch 3606)
|
||||||
|
(eval "(js-eval \"(7).valueOf()\")")
|
||||||
|
(epoch 3607)
|
||||||
|
(eval "(js-eval \"true.toString()\")")
|
||||||
|
(epoch 3608)
|
||||||
|
(eval "(js-eval \"false.toString()\")")
|
||||||
|
(epoch 3609)
|
||||||
|
(eval "(js-eval \"(true).valueOf()\")")
|
||||||
|
|
||||||
;; ── Phase 11.arrlike: Array.prototype.* on {length, 0:..., 1:...} ──
|
;; ── Phase 11.arrlike: Array.prototype.* on {length, 0:..., 1:...} ──
|
||||||
(epoch 3500)
|
(epoch 3500)
|
||||||
(eval "(js-eval \"var a = {length: 3, 0: 41, 1: 42, 2: 43}; Array.prototype.slice.call(a).length\")")
|
(eval "(js-eval \"var a = {length: 3, 0: 41, 1: 42, 2: 43}; Array.prototype.slice.call(a).length\")")
|
||||||
@@ -1819,6 +1841,18 @@ check 3403 "fn.call this-binding" '42'
|
|||||||
check 3404 "fn.apply arg-unpack" '7'
|
check 3404 "fn.apply arg-unpack" '7'
|
||||||
check 3405 "Array.prototype.push.call arr" '4'
|
check 3405 "Array.prototype.push.call arr" '4'
|
||||||
|
|
||||||
|
# ── Phase 11.nummethod: number/boolean methods ────────────────
|
||||||
|
check 3600 "(5).toString()" '"5"'
|
||||||
|
check 3601 "(16).toString(16)" '"10"'
|
||||||
|
check 3602 "(10).toString(2)" '"1010"'
|
||||||
|
check 3603 "(3.14).toFixed(1)" '"3.1"'
|
||||||
|
check 3604 "(3.14).toFixed(2)" '"3.14"'
|
||||||
|
check 3605 "(0).toFixed(3)" '"0.000"'
|
||||||
|
check 3606 "(7).valueOf()" '7'
|
||||||
|
check 3607 "true.toString()" '"true"'
|
||||||
|
check 3608 "false.toString()" '"false"'
|
||||||
|
check 3609 "(true).valueOf()" 'true'
|
||||||
|
|
||||||
# ── Phase 11.arrlike: array-like receivers on Array.prototype ─
|
# ── Phase 11.arrlike: array-like receivers on Array.prototype ─
|
||||||
check 3500 "slice.call arrLike length" '3'
|
check 3500 "slice.call arrLike length" '3'
|
||||||
check 3501 "slice.call arrLike join" '"41,42,43"'
|
check 3501 "slice.call arrLike join" '"41,42,43"'
|
||||||
|
|||||||
Reference in New Issue
Block a user