js-on-sx: 10 new String.prototype methods (at, codePointAt, lastIndexOf, localeCompare, replaceAll, normalize, ...)
New methods added: - at(i) — negative-index aware - codePointAt(i) — returns char code at index - lastIndexOf — walks right-to-left via js-string-last-index-of helper - localeCompare — simple lexicographic (ignores locale) - replaceAll — works with strings and regex-source - normalize — no-op stub - toLocaleLowerCase / toLocaleUpperCase — delegate to non-locale variants - isWellFormed / toWellFormed — assume always well-formed 10 new unit tests, 489/491 total. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1624,6 +1624,61 @@
|
||||
(= idx -1)
|
||||
nil
|
||||
(let ((res (list))) (append! res needle) res))))))))
|
||||
((= name "at")
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((idx (js-num-to-int i)))
|
||||
(let
|
||||
((actual (if (< idx 0) (+ (len s) idx) idx)))
|
||||
(if
|
||||
(or (< actual 0) (>= actual (len s)))
|
||||
:js-undefined (char-at s actual))))))
|
||||
((= name "codePointAt")
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((idx (js-num-to-int i)))
|
||||
(if
|
||||
(or (< idx 0) (>= idx (len s)))
|
||||
:js-undefined (char-code (char-at s idx))))))
|
||||
((= name "lastIndexOf")
|
||||
(fn
|
||||
(&rest args)
|
||||
(if
|
||||
(empty? args)
|
||||
-1
|
||||
(let
|
||||
((needle (js-to-string (nth args 0))))
|
||||
(js-string-last-index-of s needle (- (len s) (len needle)))))))
|
||||
((= name "localeCompare")
|
||||
(fn
|
||||
(&rest args)
|
||||
(if
|
||||
(empty? args)
|
||||
0
|
||||
(let
|
||||
((other (js-to-string (nth args 0))))
|
||||
(cond ((< s other) -1) ((> s other) 1) (else 0))))))
|
||||
((= name "replaceAll")
|
||||
(fn
|
||||
(&rest args)
|
||||
(if
|
||||
(< (len args) 2)
|
||||
s
|
||||
(let
|
||||
((needle-arg (nth args 0)) (repl (nth args 1)))
|
||||
(let
|
||||
((needle (if (js-regex? needle-arg) (get needle-arg "source") (js-to-string needle-arg))))
|
||||
(js-string-replace-all
|
||||
s
|
||||
needle
|
||||
(if (js-function? repl) repl (js-to-string repl))))))))
|
||||
((= name "normalize") (fn (&rest args) s))
|
||||
((= name "toLocaleLowerCase") (fn (&rest args) (js-lower-case s)))
|
||||
((= name "toLocaleUpperCase") (fn (&rest args) (js-upper-case s)))
|
||||
((= name "isWellFormed") (fn () true))
|
||||
((= name "toWellFormed") (fn () s))
|
||||
(else js-undefined))))
|
||||
|
||||
(define
|
||||
@@ -1654,6 +1709,36 @@
|
||||
((js-string-matches? s needle i 0) i)
|
||||
(else (js-string-index-of s needle (+ i 1))))))
|
||||
|
||||
(define
|
||||
js-string-last-index-of
|
||||
(fn
|
||||
(s needle start)
|
||||
(cond
|
||||
((< start 0) -1)
|
||||
((= needle "") start)
|
||||
((js-string-matches? s needle start 0) start)
|
||||
(else (js-string-last-index-of s needle (- start 1))))))
|
||||
|
||||
(define
|
||||
js-string-replace-all
|
||||
(fn
|
||||
(s needle repl)
|
||||
(if
|
||||
(= needle "")
|
||||
s
|
||||
(let
|
||||
((idx (js-string-index-of s needle 0)))
|
||||
(if
|
||||
(= idx -1)
|
||||
s
|
||||
(str
|
||||
(js-string-slice s 0 idx)
|
||||
(if (js-function? repl) (repl needle) repl)
|
||||
(js-string-replace-all
|
||||
(js-string-slice s (+ idx (len needle)) (len s))
|
||||
needle
|
||||
repl)))))))
|
||||
|
||||
(define
|
||||
js-string-matches?
|
||||
(fn
|
||||
@@ -1791,6 +1876,18 @@
|
||||
((= key "replace") (js-string-method obj "replace"))
|
||||
((= key "search") (js-string-method obj "search"))
|
||||
((= key "match") (js-string-method obj "match"))
|
||||
((= key "at") (js-string-method obj "at"))
|
||||
((= key "codePointAt") (js-string-method obj "codePointAt"))
|
||||
((= key "lastIndexOf") (js-string-method obj "lastIndexOf"))
|
||||
((= key "localeCompare") (js-string-method obj "localeCompare"))
|
||||
((= key "replaceAll") (js-string-method obj "replaceAll"))
|
||||
((= key "normalize") (js-string-method obj "normalize"))
|
||||
((= key "toLocaleLowerCase")
|
||||
(js-string-method obj "toLocaleLowerCase"))
|
||||
((= key "toLocaleUpperCase")
|
||||
(js-string-method obj "toLocaleUpperCase"))
|
||||
((= key "isWellFormed") (js-string-method obj "isWellFormed"))
|
||||
((= key "toWellFormed") (js-string-method obj "toWellFormed"))
|
||||
(else js-undefined)))
|
||||
((= (type-of obj) "dict")
|
||||
(js-dict-get-walk obj (js-to-string key)))
|
||||
|
||||
@@ -1213,6 +1213,28 @@ cat > "$TMPFILE" << 'EPOCHS'
|
||||
(epoch 3709)
|
||||
(eval "(js-eval \"var a=[1,2,3]; a.keys().join(',')\")")
|
||||
|
||||
;; ── Phase 11.strmore: more String.prototype methods ─────────
|
||||
(epoch 3800)
|
||||
(eval "(js-eval \"'hello'.at(0)\")")
|
||||
(epoch 3801)
|
||||
(eval "(js-eval \"'hello'.at(-1)\")")
|
||||
(epoch 3802)
|
||||
(eval "(js-eval \"'hello'.codePointAt(0)\")")
|
||||
(epoch 3803)
|
||||
(eval "(js-eval \"'hello world hello'.lastIndexOf('hello')\")")
|
||||
(epoch 3804)
|
||||
(eval "(js-eval \"'abc'.localeCompare('abd')\")")
|
||||
(epoch 3805)
|
||||
(eval "(js-eval \"'abc'.localeCompare('abc')\")")
|
||||
(epoch 3806)
|
||||
(eval "(js-eval \"'hello hello'.replaceAll('hello', 'bye')\")")
|
||||
(epoch 3807)
|
||||
(eval "(js-eval \"'a,b,c'.replaceAll(',', '-')\")")
|
||||
(epoch 3808)
|
||||
(eval "(js-eval \"'hi'.toLocaleUpperCase()\")")
|
||||
(epoch 3809)
|
||||
(eval "(js-eval \"'HI'.toLocaleLowerCase()\")")
|
||||
|
||||
;; ── Phase 11.arrlike: Array.prototype.* on {length, 0:..., 1:...} ──
|
||||
(epoch 3500)
|
||||
(eval "(js-eval \"var a = {length: 3, 0: 41, 1: 42, 2: 43}; Array.prototype.slice.call(a).length\")")
|
||||
@@ -1887,6 +1909,18 @@ check 3707 "arr.toReversed" '"2,1,3"'
|
||||
check 3708 "arr.toSorted" '"1,1,3,4,5"'
|
||||
check 3709 "arr.keys" '"0,1,2"'
|
||||
|
||||
# ── Phase 11.strmore: more String.prototype methods ───────────
|
||||
check 3800 "'hello'.at(0)" '"h"'
|
||||
check 3801 "'hello'.at(-1)" '"o"'
|
||||
check 3802 "'hello'.codePointAt(0)" '104'
|
||||
check 3803 "lastIndexOf found" '12'
|
||||
check 3804 "localeCompare less" '-1'
|
||||
check 3805 "localeCompare equal" '0'
|
||||
check 3806 "replaceAll multiple" '"bye bye"'
|
||||
check 3807 "replaceAll commas" '"a-b-c"'
|
||||
check 3808 "toLocaleUpperCase" '"HI"'
|
||||
check 3809 "toLocaleLowerCase" '"hi"'
|
||||
|
||||
# ── Phase 11.arrlike: array-like receivers on Array.prototype ─
|
||||
check 3500 "slice.call arrLike length" '3'
|
||||
check 3501 "slice.call arrLike join" '"41,42,43"'
|
||||
|
||||
Reference in New Issue
Block a user