js-on-sx: 10 new Object.* globals (getPrototypeOf, create, is, hasOwn, defineProperty, ...)
Extends the Object global dict with: - getPrototypeOf / setPrototypeOf — read/write __proto__ chain - create(proto, props?) — builds new obj with proto and optional descriptors - defineProperty / defineProperties — descriptor.value only (no getters/setters) - getOwnPropertyNames / getOwnPropertyDescriptor(s) — simple shapes - isExtensible / isFrozen / isSealed (permissive stubs) - seal / preventExtensions (no-ops) - is — SameValue (NaN is NaN, -0 vs +0 distinguished via inspect string) - fromEntries — inverse of entries - hasOwn — explicit owner check for string keys 9 new unit tests, 506/508 total. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2307,7 +2307,148 @@
|
|||||||
|
|
||||||
(define js-object-freeze (fn (o) o))
|
(define js-object-freeze (fn (o) o))
|
||||||
|
|
||||||
(define Object {:entries js-object-entries :values js-object-values :freeze js-object-freeze :assign js-object-assign :keys js-object-keys})
|
(define
|
||||||
|
js-object-get-prototype-of
|
||||||
|
(fn
|
||||||
|
(o)
|
||||||
|
(cond
|
||||||
|
((= o nil) (error "TypeError: Cannot convert null to object"))
|
||||||
|
((js-undefined? o)
|
||||||
|
(error "TypeError: Cannot convert undefined to object"))
|
||||||
|
((dict? o)
|
||||||
|
(if (contains? (keys o) "__proto__") (get o "__proto__") nil))
|
||||||
|
(else nil))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-set-prototype-of
|
||||||
|
(fn
|
||||||
|
(o proto)
|
||||||
|
(begin (when (dict? o) (dict-set! o "__proto__" proto)) o)))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-create
|
||||||
|
(fn
|
||||||
|
(&rest args)
|
||||||
|
(let
|
||||||
|
((proto (if (empty? args) nil (nth args 0))))
|
||||||
|
(let
|
||||||
|
((obj (dict)))
|
||||||
|
(begin
|
||||||
|
(when (not (= proto nil)) (dict-set! obj "__proto__" proto))
|
||||||
|
(when
|
||||||
|
(and (>= (len args) 2) (dict? (nth args 1)))
|
||||||
|
(for-each
|
||||||
|
(fn
|
||||||
|
(k)
|
||||||
|
(dict-set! obj k (get (get (nth args 1) k) "value")))
|
||||||
|
(keys (nth args 1))))
|
||||||
|
obj)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-define-property
|
||||||
|
(fn
|
||||||
|
(o key desc)
|
||||||
|
(begin
|
||||||
|
(when
|
||||||
|
(and (dict? o) (dict? desc) (contains? (keys desc) "value"))
|
||||||
|
(dict-set! o (js-to-string key) (get desc "value")))
|
||||||
|
o)))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-define-properties
|
||||||
|
(fn
|
||||||
|
(o descs)
|
||||||
|
(begin
|
||||||
|
(when
|
||||||
|
(and (dict? o) (dict? descs))
|
||||||
|
(for-each
|
||||||
|
(fn (k) (js-object-define-property o k (get descs k)))
|
||||||
|
(keys descs)))
|
||||||
|
o)))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-get-own-property-names
|
||||||
|
(fn
|
||||||
|
(o)
|
||||||
|
(cond
|
||||||
|
((list? o) (let ((r (list))) (begin (js-list-keys-loop o 0 r) r)))
|
||||||
|
((dict? o) (js-object-keys o))
|
||||||
|
(else (list)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-get-own-property-descriptor
|
||||||
|
(fn
|
||||||
|
(o key)
|
||||||
|
(if
|
||||||
|
(and (dict? o) (contains? (keys o) (js-to-string key)))
|
||||||
|
{:writable true :value (get o (js-to-string key)) :enumerable true :configurable true}
|
||||||
|
:js-undefined)))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-get-own-property-descriptors
|
||||||
|
(fn
|
||||||
|
(o)
|
||||||
|
(let
|
||||||
|
((out (dict)))
|
||||||
|
(begin
|
||||||
|
(when
|
||||||
|
(dict? o)
|
||||||
|
(for-each
|
||||||
|
(fn
|
||||||
|
(k)
|
||||||
|
(dict-set! out k (js-object-get-own-property-descriptor o k)))
|
||||||
|
(keys o)))
|
||||||
|
out))))
|
||||||
|
|
||||||
|
(define js-object-is-extensible (fn (o) (not (js-undefined? o))))
|
||||||
|
|
||||||
|
(define js-object-is-frozen (fn (o) false))
|
||||||
|
|
||||||
|
(define js-object-is-sealed (fn (o) false))
|
||||||
|
|
||||||
|
(define js-object-prevent-extensions (fn (o) o))
|
||||||
|
|
||||||
|
(define js-object-seal (fn (o) o))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-is
|
||||||
|
(fn
|
||||||
|
(a b)
|
||||||
|
(cond
|
||||||
|
((and (js-number-is-nan a) (js-number-is-nan b)) true)
|
||||||
|
((and (= a 0) (= b 0))
|
||||||
|
(let ((ia (inspect a)) (ib (inspect b))) (= ia ib)))
|
||||||
|
(else (js-strict-eq a b)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-from-entries
|
||||||
|
(fn
|
||||||
|
(iter)
|
||||||
|
(let
|
||||||
|
((out (dict)) (lst (js-iterable-to-list iter)))
|
||||||
|
(begin
|
||||||
|
(for-each
|
||||||
|
(fn
|
||||||
|
(pair)
|
||||||
|
(when
|
||||||
|
(and (list? pair) (>= (len pair) 2))
|
||||||
|
(dict-set! out (js-to-string (nth pair 0)) (nth pair 1))))
|
||||||
|
lst)
|
||||||
|
out))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
js-object-has-own
|
||||||
|
(fn
|
||||||
|
(o key)
|
||||||
|
(cond
|
||||||
|
((dict? o) (contains? (keys o) (js-to-string key)))
|
||||||
|
((list? o)
|
||||||
|
(let
|
||||||
|
((idx (js-to-number key)))
|
||||||
|
(and (>= idx 0) (< idx (len o)) (integer? idx))))
|
||||||
|
(else false))))
|
||||||
|
|
||||||
|
(define Object {:entries js-object-entries :defineProperties js-object-define-properties :preventExtensions js-object-prevent-extensions :prototype {} :values js-object-values :hasOwn js-object-has-own :freeze js-object-freeze :assign js-object-assign :isFrozen js-object-is-frozen :getOwnPropertyDescriptor js-object-get-own-property-descriptor :fromEntries js-object-from-entries :defineProperty js-object-define-property :setPrototypeOf js-object-set-prototype-of :getOwnPropertyNames js-object-get-own-property-names :getOwnPropertyDescriptors js-object-get-own-property-descriptors :create js-object-create :isExtensible js-object-is-extensible :is js-object-is :keys js-object-keys :getPrototypeOf js-object-get-prototype-of :isSealed js-object-is-sealed :seal js-object-seal})
|
||||||
|
|
||||||
(define
|
(define
|
||||||
js-delete-prop
|
js-delete-prop
|
||||||
|
|||||||
@@ -1213,6 +1213,26 @@ cat > "$TMPFILE" << 'EPOCHS'
|
|||||||
(epoch 3709)
|
(epoch 3709)
|
||||||
(eval "(js-eval \"var a=[1,2,3]; a.keys().join(',')\")")
|
(eval "(js-eval \"var a=[1,2,3]; a.keys().join(',')\")")
|
||||||
|
|
||||||
|
;; ── Phase 11.objglobal: Object.getPrototypeOf, .create, .is, .hasOwn etc. ──
|
||||||
|
(epoch 3900)
|
||||||
|
(eval "(js-eval \"var o = Object.create(null); o.x=5; o.x\")")
|
||||||
|
(epoch 3901)
|
||||||
|
(eval "(js-eval \"Object.is(NaN, NaN)\")")
|
||||||
|
(epoch 3902)
|
||||||
|
(eval "(js-eval \"Object.is(0, 0)\")")
|
||||||
|
(epoch 3903)
|
||||||
|
(eval "(js-eval \"Object.hasOwn({a:1}, 'a')\")")
|
||||||
|
(epoch 3904)
|
||||||
|
(eval "(js-eval \"Object.hasOwn({a:1}, 'b')\")")
|
||||||
|
(epoch 3905)
|
||||||
|
(eval "(js-eval \"Object.fromEntries([['a',1],['b',2]]).a\")")
|
||||||
|
(epoch 3906)
|
||||||
|
(eval "(js-eval \"var o = {a:1}; Object.defineProperty(o,'b',{value:42}); o.b\")")
|
||||||
|
(epoch 3907)
|
||||||
|
(eval "(js-eval \"var o = {a:1}; Object.getOwnPropertyNames(o).length\")")
|
||||||
|
(epoch 3908)
|
||||||
|
(eval "(js-eval \"Object.isExtensible({})\")")
|
||||||
|
|
||||||
;; ── Phase 11.globals: NaN / Infinity / strict-eq ─────────────
|
;; ── Phase 11.globals: NaN / Infinity / strict-eq ─────────────
|
||||||
(epoch 3750)
|
(epoch 3750)
|
||||||
(eval "(js-eval \"typeof NaN\")")
|
(eval "(js-eval \"typeof NaN\")")
|
||||||
@@ -1927,6 +1947,17 @@ check 3707 "arr.toReversed" '"2,1,3"'
|
|||||||
check 3708 "arr.toSorted" '"1,1,3,4,5"'
|
check 3708 "arr.toSorted" '"1,1,3,4,5"'
|
||||||
check 3709 "arr.keys" '"0,1,2"'
|
check 3709 "arr.keys" '"0,1,2"'
|
||||||
|
|
||||||
|
# ── Phase 11.objglobal: Object.getPrototypeOf, .create, .is, .hasOwn ──
|
||||||
|
check 3900 "Object.create(null)" '5'
|
||||||
|
check 3901 "Object.is(NaN,NaN)" 'true'
|
||||||
|
check 3902 "Object.is(0,0)" 'true'
|
||||||
|
check 3903 "Object.hasOwn a" 'true'
|
||||||
|
check 3904 "Object.hasOwn missing" 'false'
|
||||||
|
check 3905 "Object.fromEntries" '1'
|
||||||
|
check 3906 "Object.defineProperty" '42'
|
||||||
|
check 3907 "Object.getOwnPropertyNames" '1'
|
||||||
|
check 3908 "Object.isExtensible" 'true'
|
||||||
|
|
||||||
# ── Phase 11.globals: NaN / Infinity / strict-eq ─────────────
|
# ── Phase 11.globals: NaN / Infinity / strict-eq ─────────────
|
||||||
check 3750 "typeof NaN" '"number"'
|
check 3750 "typeof NaN" '"number"'
|
||||||
check 3751 "isNaN(NaN)" 'true'
|
check 3751 "isNaN(NaN)" 'true'
|
||||||
|
|||||||
Reference in New Issue
Block a user