Implement ES5 seal, isSealed, freeze and isFrozen
git-svn-id: svn://10.0.0.236/trunk@257548 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
1bc3ca8133
commit
812bc9fd45
@ -93,6 +93,14 @@ public class NativeObject extends IdScriptableObject
|
||||
"defineProperties", 2);
|
||||
addIdFunctionProperty(ctor, OBJECT_TAG, ConstructorId_create,
|
||||
"create", 2);
|
||||
addIdFunctionProperty(ctor, OBJECT_TAG, ConstructorId_isSealed,
|
||||
"isSealed", 1);
|
||||
addIdFunctionProperty(ctor, OBJECT_TAG, ConstructorId_isFrozen,
|
||||
"isFrozen", 1);
|
||||
addIdFunctionProperty(ctor, OBJECT_TAG, ConstructorId_seal,
|
||||
"seal", 1);
|
||||
addIdFunctionProperty(ctor, OBJECT_TAG, ConstructorId_freeze,
|
||||
"freeze", 1);
|
||||
super.fillConstructorProperties(ctor);
|
||||
}
|
||||
|
||||
@ -364,10 +372,73 @@ public class NativeObject extends IdScriptableObject
|
||||
if (args.length > 1 && args[1] != Undefined.instance) {
|
||||
Scriptable props = Context.toObject(args[1], getParentScope());
|
||||
newObject.defineOwnProperties(cx, ensureScriptableObject(props));
|
||||
}
|
||||
}
|
||||
|
||||
return newObject;
|
||||
}
|
||||
}
|
||||
|
||||
case ConstructorId_isSealed:
|
||||
{
|
||||
Object arg = args.length < 1 ? Undefined.instance : args[0];
|
||||
ScriptableObject obj = ensureScriptableObject(arg);
|
||||
|
||||
for (Object name: obj.getAllIds()) {
|
||||
Object configurable = obj.getOwnPropertyDescriptor(cx, name).get("configurable");
|
||||
if (Boolean.TRUE.equals(configurable))
|
||||
return false;
|
||||
}
|
||||
|
||||
return !obj.isExtensible();
|
||||
}
|
||||
case ConstructorId_isFrozen:
|
||||
{
|
||||
Object arg = args.length < 1 ? Undefined.instance : args[0];
|
||||
ScriptableObject obj = ensureScriptableObject(arg);
|
||||
|
||||
for (Object name: obj.getAllIds()) {
|
||||
ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
|
||||
if (Boolean.TRUE.equals(desc.get("configurable")))
|
||||
return false;
|
||||
if (isDataDescriptor(desc) && Boolean.TRUE.equals(desc.get("writable")))
|
||||
return false;
|
||||
}
|
||||
|
||||
return !obj.isExtensible();
|
||||
}
|
||||
case ConstructorId_seal:
|
||||
{
|
||||
Object arg = args.length < 1 ? Undefined.instance : args[0];
|
||||
ScriptableObject obj = ensureScriptableObject(arg);
|
||||
|
||||
for (Object name: obj.getAllIds()) {
|
||||
ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
|
||||
if (Boolean.TRUE.equals(desc.get("configurable"))) {
|
||||
desc.put("configurable", desc, false);
|
||||
obj.defineOwnProperty(cx, name, desc);
|
||||
}
|
||||
}
|
||||
obj.preventExtensions();
|
||||
|
||||
return obj;
|
||||
}
|
||||
case ConstructorId_freeze:
|
||||
{
|
||||
Object arg = args.length < 1 ? Undefined.instance : args[0];
|
||||
ScriptableObject obj = ensureScriptableObject(arg);
|
||||
|
||||
for (Object name: obj.getAllIds()) {
|
||||
ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
|
||||
if (isDataDescriptor(desc) && Boolean.TRUE.equals(desc.get("writable")))
|
||||
desc.put("writable", desc, false);
|
||||
if (Boolean.TRUE.equals(desc.get("configurable")))
|
||||
desc.put("configurable", desc, false);
|
||||
obj.defineOwnProperty(cx, name, desc);
|
||||
}
|
||||
obj.preventExtensions();
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException(String.valueOf(id));
|
||||
@ -425,6 +496,10 @@ public class NativeObject extends IdScriptableObject
|
||||
ConstructorId_preventExtensions = -7,
|
||||
ConstructorId_defineProperties= -8,
|
||||
ConstructorId_create = -9,
|
||||
ConstructorId_isSealed = -10,
|
||||
ConstructorId_isFrozen = -11,
|
||||
ConstructorId_seal = -12,
|
||||
ConstructorId_freeze = -13,
|
||||
|
||||
Id_constructor = 1,
|
||||
Id_toString = 2,
|
||||
|
||||
@ -1653,15 +1653,15 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private boolean isDataDescriptor(ScriptableObject desc) {
|
||||
protected boolean isDataDescriptor(ScriptableObject desc) {
|
||||
return hasProperty(desc, "value") || hasProperty(desc, "writable");
|
||||
}
|
||||
|
||||
private boolean isAccessorDescriptor(ScriptableObject desc) {
|
||||
|
||||
protected boolean isAccessorDescriptor(ScriptableObject desc) {
|
||||
return hasProperty(desc, "get") || hasProperty(desc, "set");
|
||||
}
|
||||
|
||||
private boolean isGenericDescriptor(ScriptableObject desc) {
|
||||
|
||||
protected boolean isGenericDescriptor(ScriptableObject desc) {
|
||||
return !isDataDescriptor(desc) && !isAccessorDescriptor(desc);
|
||||
}
|
||||
|
||||
|
||||
27
mozilla/js/rhino/testsrc/doctests/object.freeze.doctest
Normal file
27
mozilla/js/rhino/testsrc/doctests/object.freeze.doctest
Normal file
@ -0,0 +1,27 @@
|
||||
js> load('testsrc/doctests/util.js');
|
||||
|
||||
js> Object.freeze;
|
||||
function freeze() { [native code for Object.freeze, arity=1] }
|
||||
|
||||
js> [undefined, null, true, 1, 'hello'].forEach(function(value) {
|
||||
> expectTypeError(function() { Object.freeze(value) })
|
||||
> })
|
||||
js> expectTypeError(function() { Object.freeze() })
|
||||
|
||||
js> var x = {}
|
||||
js> var y = Object.freeze(x)
|
||||
js> x === y
|
||||
true
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:true, writable:true})
|
||||
js> var _ = Object.freeze(obj)
|
||||
js> var a = Object.getOwnPropertyDescriptor(obj, 'a');
|
||||
js> a.configurable
|
||||
false
|
||||
js> a.writable
|
||||
false
|
||||
js> Object.isExtensible(obj)
|
||||
false
|
||||
|
||||
js> Object.isFrozen(obj)
|
||||
true
|
||||
37
mozilla/js/rhino/testsrc/doctests/object.isfrozen.doctest
Normal file
37
mozilla/js/rhino/testsrc/doctests/object.isfrozen.doctest
Normal file
@ -0,0 +1,37 @@
|
||||
js> load('testsrc/doctests/util.js');
|
||||
|
||||
js> Object.isFrozen
|
||||
function isFrozen() { [native code for Object.isFrozen, arity=1] }
|
||||
|
||||
js> expectTypeError(function() { Object.isFrozen() });
|
||||
js> [undefined, null, true, 1, 'hello'].forEach(function(value) {
|
||||
> expectTypeError(function() { Object.isFrozen(value) })
|
||||
> })
|
||||
|
||||
js> Object.isFrozen({})
|
||||
false
|
||||
|
||||
js> var obj = Object.preventExtensions({});
|
||||
js> Object.isFrozen(obj);
|
||||
true
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:true, writable:false})
|
||||
js> var _ = Object.preventExtensions(obj);
|
||||
js> Object.isFrozen(obj);
|
||||
false
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:false, writable:true})
|
||||
js> var _ = Object.preventExtensions(obj);
|
||||
js> Object.isFrozen(obj);
|
||||
false
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:false, writable:false})
|
||||
js> var _ = Object.preventExtensions(obj);
|
||||
js> Object.isFrozen(obj);
|
||||
true
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:false, set: function(){} })
|
||||
js> var _ = Object.preventExtensions(obj);
|
||||
js> Object.isFrozen(obj);
|
||||
true
|
||||
|
||||
26
mozilla/js/rhino/testsrc/doctests/object.issealed.doctest
Normal file
26
mozilla/js/rhino/testsrc/doctests/object.issealed.doctest
Normal file
@ -0,0 +1,26 @@
|
||||
js> load('testsrc/doctests/util.js');
|
||||
|
||||
js> Object.isSealed
|
||||
function isSealed() { [native code for Object.isSealed, arity=1] }
|
||||
|
||||
js> expectTypeError(function() { Object.isSealed() });
|
||||
js> [undefined, null, true, 1, 'hello'].forEach(function(value) {
|
||||
> expectTypeError(function() { Object.isSealed(value) })
|
||||
> })
|
||||
|
||||
js> Object.isSealed({})
|
||||
false
|
||||
|
||||
js> var obj = Object.preventExtensions({});
|
||||
js> Object.isSealed(obj);
|
||||
true
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:false});
|
||||
js> var _ = Object.preventExtensions(obj);
|
||||
js> Object.isSealed(obj);
|
||||
true
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:true});
|
||||
js> var _ = Object.preventExtensions(obj);
|
||||
js> Object.isSealed(obj);
|
||||
false
|
||||
24
mozilla/js/rhino/testsrc/doctests/object.seal.doctest
Normal file
24
mozilla/js/rhino/testsrc/doctests/object.seal.doctest
Normal file
@ -0,0 +1,24 @@
|
||||
js> load('testsrc/doctests/util.js');
|
||||
|
||||
js> Object.seal;
|
||||
function seal() { [native code for Object.seal, arity=1] }
|
||||
|
||||
js> [undefined, null, true, 1, 'hello'].forEach(function(value) {
|
||||
> expectTypeError(function() { Object.seal(value) })
|
||||
> })
|
||||
js> expectTypeError(function() { Object.seal() })
|
||||
|
||||
js> var x = {}
|
||||
js> var y = Object.seal(x)
|
||||
js> x === y
|
||||
true
|
||||
|
||||
js> var obj = Object.defineProperty({}, 'a', {configurable:true})
|
||||
js> var _ = Object.seal(obj)
|
||||
js> Object.getOwnPropertyDescriptor(obj, 'a').configurable
|
||||
false
|
||||
js> Object.isExtensible(obj)
|
||||
false
|
||||
|
||||
js> Object.isSealed(obj)
|
||||
true
|
||||
Loading…
x
Reference in New Issue
Block a user