js-on-sx: String fixes — fromCodePoint, multi-arg indexOf/split/lastIndexOf, matchAll, constructor, js-to-string dict
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
- String.fromCodePoint added (BMP + surrogate pairs) - indexOf/lastIndexOf/split now accept optional second argument (fromIndex / limit) - matchAll stub added to js-string-method and String.prototype - String property else-branch now falls back to String.prototype (fixes 'a'.constructor === String) - js-to-string for dict returns [object Object] instead of recursing into circular String.prototype.constructor structure - js-list-take helper added for split limit Scoreboard: String 42→43, timeouts 32→13, total 162→202/300 (54%→67.3%). 529/530 unit, 148/148 slice. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user