diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/NativeObject.java b/mozilla/js/rhino/src/org/mozilla/javascript/NativeObject.java index a46af60df57..325395f1079 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/NativeObject.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/NativeObject.java @@ -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, diff --git a/mozilla/js/rhino/src/org/mozilla/javascript/ScriptableObject.java b/mozilla/js/rhino/src/org/mozilla/javascript/ScriptableObject.java index 15fe3982d38..31ab96cac67 100644 --- a/mozilla/js/rhino/src/org/mozilla/javascript/ScriptableObject.java +++ b/mozilla/js/rhino/src/org/mozilla/javascript/ScriptableObject.java @@ -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); } diff --git a/mozilla/js/rhino/testsrc/doctests/object.freeze.doctest b/mozilla/js/rhino/testsrc/doctests/object.freeze.doctest new file mode 100644 index 00000000000..db3f023c79c --- /dev/null +++ b/mozilla/js/rhino/testsrc/doctests/object.freeze.doctest @@ -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 diff --git a/mozilla/js/rhino/testsrc/doctests/object.isfrozen.doctest b/mozilla/js/rhino/testsrc/doctests/object.isfrozen.doctest new file mode 100644 index 00000000000..b2206f92df9 --- /dev/null +++ b/mozilla/js/rhino/testsrc/doctests/object.isfrozen.doctest @@ -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 + diff --git a/mozilla/js/rhino/testsrc/doctests/object.issealed.doctest b/mozilla/js/rhino/testsrc/doctests/object.issealed.doctest new file mode 100644 index 00000000000..275b4acaf56 --- /dev/null +++ b/mozilla/js/rhino/testsrc/doctests/object.issealed.doctest @@ -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 diff --git a/mozilla/js/rhino/testsrc/doctests/object.seal.doctest b/mozilla/js/rhino/testsrc/doctests/object.seal.doctest new file mode 100644 index 00000000000..2f50804dda4 --- /dev/null +++ b/mozilla/js/rhino/testsrc/doctests/object.seal.doctest @@ -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