From 683e3956aaafd4b620bb800789f438de51970fae Mon Sep 17 00:00:00 2001 From: Robert Krimen Date: Fri, 3 May 2013 21:36:22 +0200 Subject: [PATCH] Add Object.isExtensible & Object.preventExtensions... ...and fix the deep implementation of defineOwnProperty so that they can work (more or less) properly --- builtin_object.go | 18 ++++++++++++++++++ global.go | 6 ++++-- object.go | 15 ++++++++++----- object_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/builtin_object.go b/builtin_object.go index 439e9cd..764cc5f 100644 --- a/builtin_object.go +++ b/builtin_object.go @@ -126,3 +126,21 @@ func builtinObject_create(call FunctionCall) Value { return toValue(object) } + +func builtinObject_isExtensible(call FunctionCall) Value { + object := call.Argument(0) + if object := object._object(); object != nil { + return toValue(object.stash.extensible()) + } + panic(newTypeError()) +} + +func builtinObject_preventExtensions(call FunctionCall) Value { + object := call.Argument(0) + if object := object._object(); object != nil { + object.stash.lock() + } else { + panic(newTypeError()) + } + return object +} diff --git a/global.go b/global.go index bc63058..d27e611 100644 --- a/global.go +++ b/global.go @@ -175,6 +175,8 @@ func newContext() *_runtime { "defineProperty", 3, builtinObject_defineProperty, "defineProperties", 2, builtinObject_defineProperties, "create", 2, builtinObject_create, + "isExtensible", -1, builtinObject_isExtensible, + "preventExtensions", -1, builtinObject_preventExtensions, ) self.Global.Function = self.newGlobalFunction( @@ -669,7 +671,7 @@ func newContext() *_runtime { "RegExp", builtinRegExp, builtinNewRegExp, self.Global.RegExpPrototype, - "toString", -0xff, builtinRegExp_toString, + "toString", -255, builtinRegExp_toString, "exec", -1, builtinRegExp_exec, "test", -1, builtinRegExp_test, ) @@ -832,7 +834,7 @@ func (runtime *_runtime) newNativeFunction(_nativeFunction _nativeFunction, leng if 0 > length { length *= -1 // TODO Achk... hack - if length == 0xff { + if length == 255 { length = 0 } prototype = false diff --git a/object.go b/object.go index e4edb07..22dce36 100644 --- a/object.go +++ b/object.go @@ -196,7 +196,7 @@ func (self *_object) defineOwnProperty(name string, descriptor _property, throw { if !exists { if !self.extensible() { - return false + goto Reject } self.stash.defineProperty(name, descriptor.value, descriptor.mode) return true @@ -213,7 +213,7 @@ func (self *_object) defineOwnProperty(name string, descriptor _property, throw configurable := property.configurable() if !configurable { if descriptor.configurable() { - return false + goto Reject } // Test that, if enumerable is set on the property descriptor, then it should // be the same as the existing property @@ -237,22 +237,27 @@ func (self *_object) defineOwnProperty(name string, descriptor _property, throw } else if isDataDescriptor && descriptor.isDataDescriptor() { if !configurable { if property.writable() != descriptor.writable() { - return false + goto Reject } else if !sameValue(value, descriptor.value.(Value)) { - return false + goto Reject } } } else { if !configurable { defineGetSet, _ := descriptor.value.(_propertyGetSet) if getSet[0] != defineGetSet[0] || getSet[1] != defineGetSet[1] { - return false + goto Reject } } } self.stash.defineProperty(name, descriptor.value, descriptor.mode) return true } +Reject: + if throw { + panic(newTypeError()) + } + return false } func (self *_object) hasOwnProperty(name string) bool { diff --git a/object_test.go b/object_test.go index 1fa62a1..3d9b929 100644 --- a/object_test.go +++ b/object_test.go @@ -62,3 +62,49 @@ func TestObject_toLocaleString(t *testing.T) { object.toLocaleString(); `, "Nothing happens.") } + +func TestObject_isExtensible(t *testing.T) { + Terst(t) + + test := runTest() + test(`raise: + Object.isExtensible(); + `, "TypeError") + test(`raise: + Object.isExtensible({}); + `, "true") + + test(`Object.isExtensible.length`, "1") + test(`Object.isExtensible.prototype`, "undefined") +} + +func TestObject_preventExtensions(t *testing.T) { + Terst(t) + + test := runTest() + test(`raise: + Object.preventExtensions() + `, "TypeError") + + test(`raise: + var abc = { def: true }; + var ghi = Object.preventExtensions(abc); + [ ghi.def === true, Object.isExtensible(abc), Object.isExtensible(ghi) ]; + `, "true,false,false") + + test(` + var abc = new String(); + var def = Object.isExtensible(abc); + Object.preventExtensions(abc); + var ghi = false; + try { + Object.defineProperty(abc, "0", { value: "~" }); + } catch (err) { + ghi = err instanceof TypeError; + } + [ def, ghi, abc.hasOwnProperty("0"), typeof abc[0] ]; + `, "true,true,false,undefined") + + test(`Object.preventExtensions.length`, "1") + test(`Object.preventExtensions.prototype`, "undefined") +}