mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00
Add Object.isExtensible & Object.preventExtensions...
...and fix the deep implementation of defineOwnProperty so that they can work (more or less) properly
This commit is contained in:
parent
2e0fe63a64
commit
683e3956aa
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
15
object.go
15
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 {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user