diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index 0d754a0b..2a79d6aa 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -1169,7 +1169,7 @@ ((= v false) "false") ((= (type-of v) "string") v) ((= (type-of v) "number") (js-number-to-string v)) - (else (str v))))) + (else (if (= (type-of v) "dict") "[object Object]" (str v)))))) (define js-template-concat @@ -1903,7 +1903,15 @@ (char-code (char-at s idx)) 0)))) ((= name "indexOf") - (fn (needle) (js-string-index-of s (js-to-string needle) 0))) + (fn + (&rest args) + (if + (empty? args) + -1 + (js-string-index-of + s + (js-to-string (nth args 0)) + (if (< (len args) 2) 0 (max 0 (js-num-to-int (nth args 1)))))))) ((= name "slice") (fn (&rest args) @@ -1927,7 +1935,16 @@ (js-string-slice s lo (min hi (len s))))))) ((= name "toUpperCase") (fn () (js-upper-case s))) ((= name "toLowerCase") (fn () (js-lower-case s))) - ((= name "split") (fn (sep) (js-string-split s (js-to-string sep)))) + ((= name "split") + (fn + (&rest args) + (let + ((sep (if (= (len args) 0) :js-undefined (nth args 0))) + (limit + (if (< (len args) 2) -1 (js-num-to-int (nth args 1))))) + (let + ((result (js-string-split s (js-to-string sep)))) + (if (< limit 0) result (js-list-take result limit)))))) ((= name "concat") (fn (&rest args) (js-string-concat-loop s args 0))) ((= name "includes") @@ -2042,6 +2059,17 @@ (= idx -1) nil (let ((res (list))) (append! res needle) res)))))))) + ((= name "matchAll") + (fn + (&rest args) + (if + (empty? args) + (list) + (let + ((needle (js-to-string (nth args 0)))) + (let + ((loop (fn (start acc) (let ((idx (js-string-index-of s needle start))) (if (= idx -1) acc (let ((m (list))) (begin (append! m needle) (dict-set! m "index" idx) (loop (+ idx (max 1 (len needle))) (begin (append! acc m) acc))))))))) + (loop 0 (list))))))) ((= name "at") (fn (i) @@ -2068,7 +2096,14 @@ -1 (let ((needle (js-to-string (nth args 0)))) - (js-string-last-index-of s needle (- (len s) (len needle))))))) + (let + ((default-start (- (len s) (len needle))) + (from + (if (< (len args) 2) -1 (js-num-to-int (nth args 1))))) + (js-string-last-index-of + s + needle + (if (< from 0) default-start (min from default-start)))))))) ((= name "localeCompare") (fn (&rest args) @@ -2166,6 +2201,15 @@ ((not (= (char-at s (+ si ni)) (char-at needle ni))) false) (else (js-string-matches? s needle si (+ ni 1)))))) +(define + js-list-take + (fn + (lst n) + (if + (or (<= n 0) (empty? lst)) + (list) + (cons (first lst) (js-list-take (rest lst) (- n 1)))))) + (define js-string-split (fn @@ -2306,7 +2350,13 @@ (js-string-method obj "toLocaleUpperCase")) ((= key "isWellFormed") (js-string-method obj "isWellFormed")) ((= key "toWellFormed") (js-string-method obj "toWellFormed")) - (else js-undefined))) + (else + (let + ((proto (get String "prototype"))) + (if + (and (dict? proto) (contains? (keys proto) key)) + (get proto key) + js-undefined))))) ((= (type-of obj) "dict") (js-dict-get-walk obj (js-to-string key))) ((and (= obj Promise) (dict-has? __js_promise_statics__ (js-to-string key))) @@ -3028,6 +3078,35 @@ js-string-from-char-code (fn (&rest args) (js-string-from-char-code-loop args 0 ""))) +(define + js-string-from-code-point-loop + (fn + (args i acc) + (if + (>= i (len args)) + acc + (let + ((cp (floor (js-to-number (nth args i))))) + (if + (< cp 65536) + (js-string-from-code-point-loop + args + (+ i 1) + (str acc (js-code-to-char (js-num-to-int cp)))) + (let + ((hi (+ 55296 (floor (/ (- cp 65536) 1024)))) + (lo (+ 56320 (modulo (- cp 65536) 1024)))) + (js-string-from-code-point-loop + args + (+ i 1) + (str + (str acc (js-code-to-char (js-num-to-int hi))) + (js-code-to-char (js-num-to-int lo)))))))))) + +(define + js-string-from-code-point + (fn (&rest args) (js-string-from-code-point-loop args 0 ""))) + (define js-string-from-char-code-loop (fn @@ -3058,8 +3137,15 @@ (dict-set! String "name" "String") +(dict-set! String "fromCodePoint" js-string-from-code-point) + (define Boolean {:__callable__ (fn (&rest args) (if (= (len args) 0) false (js-to-boolean (nth args 0))))}) +(dict-set! + (get String "prototype") + "matchAll" + (js-string-proto-fn "matchAll")) + (dict-set! Boolean "length" 1) (dict-set! Boolean "name" "Boolean") diff --git a/lib/js/test262-scoreboard.json b/lib/js/test262-scoreboard.json index 8bb8486a..2be221a8 100644 --- a/lib/js/test262-scoreboard.json +++ b/lib/js/test262-scoreboard.json @@ -1,30 +1,26 @@ { "totals": { - "pass": 162, - "fail": 128, + "pass": 202, + "fail": 85, "skip": 1597, - "timeout": 10, + "timeout": 13, "total": 1897, "runnable": 300, - "pass_rate": 54.0 + "pass_rate": 67.3 }, "categories": [ { "category": "built-ins/Math", "total": 327, - "pass": 43, - "fail": 56, + "pass": 82, + "fail": 17, "skip": 227, "timeout": 1, - "pass_rate": 43.0, + "pass_rate": 82.0, "top_failures": [ - [ - "TypeError: not a function", - 36 - ], [ "Test262Error (assertion failed)", - 20 + 17 ], [ "Timeout", @@ -54,31 +50,31 @@ { "category": "built-ins/String", "total": 1223, - "pass": 42, - "fail": 53, + "pass": 43, + "fail": 49, "skip": 1123, - "timeout": 5, - "pass_rate": 42.0, + "timeout": 8, + "pass_rate": 43.0, "top_failures": [ [ "Test262Error (assertion failed)", - 44 + 42 ], [ "Timeout", - 5 + 8 + ], + [ + "TypeError: not a function", + 3 ], [ "ReferenceError (undefined symbol)", - 2 + 1 ], [ - "Unhandled: Not callable: {:__proto__ {:toLowerCase :propertyIsEn", + "Unhandled: Not callable: \\\\\\", 1 ], [ @@ -132,6 +120,6 @@ ] ], "pinned_commit": "d5e73fc8d2c663554fb72e2380a8c2bc1a318a33", - "elapsed_seconds": 274.5, - "workers": 1 + "elapsed_seconds": 102.4, + "workers": 2 } \ No newline at end of file diff --git a/lib/js/test262-scoreboard.md b/lib/js/test262-scoreboard.md index 315a9c7d..4a913abe 100644 --- a/lib/js/test262-scoreboard.md +++ b/lib/js/test262-scoreboard.md @@ -1,47 +1,44 @@ # test262 scoreboard Pinned commit: `d5e73fc8d2c663554fb72e2380a8c2bc1a318a33` -Wall time: 274.5s +Wall time: 102.4s -**Total:** 162/300 runnable passed (54.0%). Raw: pass=162 fail=128 skip=1597 timeout=10 total=1897. +**Total:** 202/300 runnable passed (67.3%). Raw: pass=202 fail=85 skip=1597 timeout=13 total=1897. ## Top failure modes -- **83x** Test262Error (assertion failed) -- **36x** TypeError: not a function -- **10x** Timeout -- **2x** ReferenceError (undefined symbol) -- **2x** Unhandled: Not callable: {:__proto__ {:toLowerCase :propertyIsEn +- **1x** Unhandled: Not callable: \\\ - **1x** Unhandled: js-transpile-binop: unsupported op: >>>\ ## Categories (worst pass-rate first, min 10 runnable) | Category | Pass | Fail | Skip | Timeout | Total | Pass % | |---|---:|---:|---:|---:|---:|---:| -| built-ins/String | 42 | 53 | 1123 | 5 | 1223 | 42.0% | -| built-ins/Math | 43 | 56 | 227 | 1 | 327 | 43.0% | +| built-ins/String | 43 | 49 | 1123 | 8 | 1223 | 43.0% | | built-ins/Number | 77 | 19 | 240 | 4 | 340 | 77.0% | +| built-ins/Math | 82 | 17 | 227 | 1 | 327 | 82.0% | ## Per-category top failures (min 10 runnable, worst first) -### built-ins/String (42/100 — 42.0%) +### built-ins/String (43/100 — 43.0%) -- **44x** Test262Error (assertion failed) -- **5x** Timeout -- **2x** ReferenceError (undefined symbol) -- **2x** Unhandled: Not callable: {:__proto__ {:toLowerCase