diff --git a/rhino/src/main/java/org/mozilla/javascript/AbstractEcmaObjectOperations.java b/rhino/src/main/java/org/mozilla/javascript/AbstractEcmaObjectOperations.java index b35b4879ce..60976f69ad 100644 --- a/rhino/src/main/java/org/mozilla/javascript/AbstractEcmaObjectOperations.java +++ b/rhino/src/main/java/org/mozilla/javascript/AbstractEcmaObjectOperations.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.Objects; import java.util.function.Predicate; +import org.mozilla.javascript.ScriptableObject.DescriptorInfo; /** * Abstract Object Operations as defined by EcmaScript @@ -83,12 +84,11 @@ static boolean testIntegrityLevel(Context cx, Object o, INTEGRITY_LEVEL level) { ids = obj.getIds(map, true, true); } for (Object name : ids) { - ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name); - if (Boolean.TRUE.equals(desc.get("configurable"))) return false; + DescriptorInfo desc = obj.getOwnPropertyDescriptor(cx, name); + if (desc.isConfigurable()) return false; - if (level == INTEGRITY_LEVEL.FROZEN - && ScriptableObject.isDataDescriptor(desc) - && Boolean.TRUE.equals(desc.get("writable"))) return false; + if (level == INTEGRITY_LEVEL.FROZEN && desc.isDataDescriptor() && desc.isWritable()) + return false; } return true; @@ -150,21 +150,20 @@ static boolean setIntegrityLevel(Context cx, Object o, INTEGRITY_LEVEL level) { ids = obj.getIds(map, true, true); } for (Object key : ids) { - ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, key); + DescriptorInfo desc = obj.getOwnPropertyDescriptor(cx, key); if (level == INTEGRITY_LEVEL.SEALED) { - if (Boolean.TRUE.equals(desc.get("configurable"))) { - desc.put("configurable", desc, Boolean.FALSE); + if (desc.isConfigurable()) { + desc.configurable = false; obj.defineOwnProperty(cx, key, desc, false); } } else { - if (ScriptableObject.isDataDescriptor(desc) - && Boolean.TRUE.equals(desc.get("writable"))) { - desc.put("writable", desc, Boolean.FALSE); + if (desc.isDataDescriptor() && desc.isWritable()) { + desc.writable = false; } - if (Boolean.TRUE.equals(desc.get("configurable"))) { - desc.put("configurable", desc, Boolean.FALSE); + if (desc.isConfigurable()) { + desc.configurable = false; } obj.defineOwnProperty(cx, key, desc, false); } @@ -402,7 +401,7 @@ public static long lengthOfArrayLike(Context cx, Scriptable o) { * IsCompatiblePropertyDescriptor (Extensible, Desc, Current) */ static boolean isCompatiblePropertyDescriptor( - Context cx, boolean extensible, ScriptableObject desc, ScriptableObject current) { + Context cx, boolean extensible, DescriptorInfo desc, DescriptorInfo current) { return validateAndApplyPropertyDescriptor( cx, Undefined.SCRIPTABLE_UNDEFINED, @@ -424,15 +423,14 @@ static boolean validateAndApplyPropertyDescriptor( Scriptable o, Scriptable p, boolean extensible, - ScriptableObject desc, - ScriptableObject current) { + DescriptorInfo desc, + DescriptorInfo current) { if (Undefined.isUndefined(current)) { if (!extensible) { return false; } - if (ScriptableObject.isGenericDescriptor(desc) - || ScriptableObject.isDataDescriptor(desc)) { + if (desc.isGenericDescriptor() || desc.isDataDescriptor()) { /* i. i. If O is not undefined, create an own data property named P of object O whose [[Value]], [[Writable]], [[Enumerable]], and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value. @@ -445,32 +443,35 @@ static boolean validateAndApplyPropertyDescriptor( return true; } - if (desc.getIds().length == 0) { + if (!desc.hasEnumerable() + && !desc.hasConfigurable() + && !desc.hasWritable() + && !desc.hasGetter() + && !desc.hasSetter() + && !desc.hasValue()) { return true; } - if (Boolean.FALSE.equals(current.get("configurable"))) { - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "configurable")) - && Boolean.TRUE.equals(desc.get("configurable"))) { + if (current.isConfigurable(false)) { + if (desc.isConfigurable()) { return false; } - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "enumerable")) - && !Objects.equals(desc.get("enumerable"), current.get("enumerable"))) { + if (desc.hasEnumerable() && !Objects.equals(desc.enumerable, current.enumerable)) { return false; } } - if (ScriptableObject.isGenericDescriptor(desc)) { + if (desc.isGenericDescriptor()) { return true; } - if (ScriptableObject.isDataDescriptor(current) != ScriptableObject.isDataDescriptor(desc)) { - if (Boolean.FALSE.equals(current.get("configurable"))) { + if (current.isDataDescriptor() != desc.isDataDescriptor()) { + if (current.isConfigurable(false)) { return false; } - if (ScriptableObject.isDataDescriptor(current)) { - if (Boolean.FALSE.equals(current.get("configurable"))) { + if (current.isDataDescriptor()) { + if (current.isConfigurable(false)) { // i. i. If O is not undefined, convert the property named P of object O from a // data property to an accessor property. Preserve the existing values of the // converted property's [[Configurable]] and [[Enumerable]] attributes and set @@ -482,28 +483,22 @@ static boolean validateAndApplyPropertyDescriptor( // the rest of the property's attributes to their default values. } } - } else if (ScriptableObject.isDataDescriptor(current) - && ScriptableObject.isDataDescriptor(desc)) { - if (Boolean.FALSE.equals(current.get("configurable")) - && Boolean.FALSE.equals(current.get("writable"))) { - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "writable")) - && Boolean.TRUE.equals(desc.get("writable"))) { + } else if (current.isDataDescriptor() && desc.isDataDescriptor()) { + if (current.isConfigurable(false) && current.isWritable(false)) { + if (desc.isWritable()) { return false; } - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "value")) - && !Objects.equals(desc.get("value"), current.get("value"))) { + if (desc.hasValue() && !Objects.equals(desc.value, current.value)) { return false; } return true; } } else { - if (Boolean.FALSE.equals(current.get("configurable"))) { - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "set")) - && !Objects.equals(desc.get("set"), current.get("set"))) { + if (current.isConfigurable(false)) { + if (desc.hasSetter() && !Objects.equals(desc.setter, current.setter)) { return false; } - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "get")) - && !Objects.equals(desc.get("get"), current.get("get"))) { + if (desc.hasGetter() && !Objects.equals(desc.getter, current.getter)) { return false; } return true; diff --git a/rhino/src/main/java/org/mozilla/javascript/AccessorSlot.java b/rhino/src/main/java/org/mozilla/javascript/AccessorSlot.java index 768544d07a..f0e941dae0 100644 --- a/rhino/src/main/java/org/mozilla/javascript/AccessorSlot.java +++ b/rhino/src/main/java/org/mozilla/javascript/AccessorSlot.java @@ -1,5 +1,7 @@ package org.mozilla.javascript; +import org.mozilla.javascript.ScriptableObject.DescriptorInfo; + /** * This is a specialization of Slot to store various types of values that are retrieved dynamically * using Java and JavaScript functions. Unlike LambdaSlot, the fact that these values are accessed @@ -43,45 +45,40 @@ boolean isSetterSlot() { } @Override - ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { + DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) { // It sounds logical that this would be the same as the logic for a normal Slot, // but the spec is super pedantic about things like the order of properties here, // so we need special support here. - ScriptableObject desc = (ScriptableObject) cx.newObject(scope); int attr = getAttributes(); - + DescriptorInfo desc; boolean es6 = cx.getLanguageVersion() >= Context.VERSION_ES6; if (es6) { + desc = new DescriptorInfo(ScriptableObject.NOT_FOUND, attr, false); if (getter == null && setter == null) { - desc.defineProperty( - "writable", - (attr & ScriptableObject.READONLY) == 0, - ScriptableObject.EMPTY); + desc.writable = (attr & ScriptableObject.READONLY) == 0; } } else { - desc.setCommonDescriptorProperties(attr, getter == null && setter == null); + desc = + new DescriptorInfo( + ScriptableObject.NOT_FOUND, attr, getter == null && setter == null); } String fName = name == null ? "f" : name.toString(); if (getter != null) { Function f = getter.asGetterFunction(fName, scope); - desc.defineProperty("get", f == null ? Undefined.instance : f, ScriptableObject.EMPTY); + desc.getter = f == null ? Undefined.instance : f; } if (setter != null) { Function f = setter.asSetterFunction(fName, scope); - desc.defineProperty("set", f == null ? Undefined.instance : f, ScriptableObject.EMPTY); + desc.setter = f == null ? Undefined.instance : f; } else if (es6) { - desc.defineProperty("set", Undefined.instance, ScriptableObject.EMPTY); + desc.setter = Undefined.instance; } if (es6) { - desc.defineProperty( - "enumerable", (attr & ScriptableObject.DONTENUM) == 0, ScriptableObject.EMPTY); - desc.defineProperty( - "configurable", - (attr & ScriptableObject.PERMANENT) == 0, - ScriptableObject.EMPTY); + desc.enumerable = (attr & ScriptableObject.DONTENUM) == 0; + desc.configurable = (attr & ScriptableObject.PERMANENT) == 0; } return desc; diff --git a/rhino/src/main/java/org/mozilla/javascript/Arguments.java b/rhino/src/main/java/org/mozilla/javascript/Arguments.java index aa8f3730d0..84a23ca5ac 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Arguments.java +++ b/rhino/src/main/java/org/mozilla/javascript/Arguments.java @@ -254,7 +254,7 @@ Object[] getIds(CompoundOperationMap map, boolean getNonEnumerable, boolean getS } @Override - protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { + protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) { if (ScriptRuntime.isSymbol(id) || id instanceof Scriptable) { return super.getOwnPropertyDescriptor(cx, id); } @@ -272,18 +272,16 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { value = getFromActivation(index); } if (super.has(index, this)) { // the descriptor has been redefined - ScriptableObject desc = super.getOwnPropertyDescriptor(cx, id); - desc.put("value", desc, value); + DescriptorInfo desc = super.getOwnPropertyDescriptor(cx, id); + desc.value = value; return desc; } - Scriptable scope = getParentScope(); - if (scope == null) scope = this; - return buildDataDescriptor(scope, value, EMPTY); + return buildDataDescriptor(value, EMPTY); } @Override protected boolean defineOwnProperty( - Context cx, Object id, ScriptableObject desc, boolean checkValid) { + Context cx, Object id, DescriptorInfo desc, boolean checkValid) { super.defineOwnProperty(cx, id, desc, checkValid); if (ScriptRuntime.isSymbol(id)) { return true; @@ -296,17 +294,17 @@ protected boolean defineOwnProperty( Object value = arg(index); if (value == NOT_FOUND) return true; - if (isAccessorDescriptor(desc)) { + if (desc.isAccessorDescriptor()) { removeArg(index); return true; } - Object newValue = getProperty(desc, "value"); + Object newValue = desc.value; if (newValue == NOT_FOUND) return true; replaceArg(index, newValue); - if (isFalse(getProperty(desc, "writable"))) { + if (isFalse(desc.writable)) { removeArg(index); } return true; diff --git a/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java b/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java index 86d5f6753f..299264fb1f 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java +++ b/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java @@ -6,6 +6,7 @@ import java.io.Serializable; import java.util.Comparator; +import org.mozilla.javascript.ScriptableObject.DescriptorInfo; /** Contains implementation of shared methods useful for arrays and typed arrays. */ public class ArrayLikeAbstractOperations { @@ -275,11 +276,7 @@ static void defineElem(Context cx, Scriptable target, long index, Object value) if (!(target instanceof NativeArray && ((NativeArray) target).getDenseOnly()) && target instanceof ScriptableObject) { var so = (ScriptableObject) target; - ScriptableObject desc = new NativeObject(); - desc.defineProperty("value", value, 0); - desc.defineProperty("writable", Boolean.TRUE, 0); - desc.defineProperty("enumerable", Boolean.TRUE, 0); - desc.defineProperty("configurable", Boolean.TRUE, 0); + var desc = new DescriptorInfo(true, true, true, value); so.defineOwnProperty(cx, index, desc); return; } diff --git a/rhino/src/main/java/org/mozilla/javascript/BoundFunction.java b/rhino/src/main/java/org/mozilla/javascript/BoundFunction.java index b756e29375..16d3f9b216 100644 --- a/rhino/src/main/java/org/mozilla/javascript/BoundFunction.java +++ b/rhino/src/main/java/org/mozilla/javascript/BoundFunction.java @@ -38,13 +38,7 @@ public BoundFunction( ScriptRuntime.setFunctionProtoAndParent(this, cx, scope, false); Function thrower = ScriptRuntime.typeErrorThrower(cx); - NativeObject throwing = new NativeObject(); - ScriptRuntime.setBuiltinProtoAndParent(throwing, scope, TopLevel.Builtins.Object); - throwing.put("get", throwing, thrower); - throwing.put("set", throwing, thrower); - throwing.put("enumerable", throwing, Boolean.FALSE); - throwing.put("configurable", throwing, Boolean.FALSE); - throwing.preventExtensions(); + var throwing = new DescriptorInfo(false, NOT_FOUND, false, thrower, thrower, NOT_FOUND); this.defineOwnProperty(cx, "caller", throwing, false); this.defineOwnProperty(cx, "arguments", throwing, false); diff --git a/rhino/src/main/java/org/mozilla/javascript/BuiltInSlot.java b/rhino/src/main/java/org/mozilla/javascript/BuiltInSlot.java index eb9777b862..32742afdbb 100644 --- a/rhino/src/main/java/org/mozilla/javascript/BuiltInSlot.java +++ b/rhino/src/main/java/org/mozilla/javascript/BuiltInSlot.java @@ -166,9 +166,8 @@ void setAttributes(int value) { @Override @SuppressWarnings("unchecked") - ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { - return ScriptableObject.buildDataDescriptor( - scope, getValue((T) this.value), getAttributes()); + DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) { + return ScriptableObject.buildDataDescriptor(getValue((T) this.value), getAttributes()); } @SuppressWarnings("unchecked") diff --git a/rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java b/rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java index 56870c8be4..51b6ee016e 100644 --- a/rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java +++ b/rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java @@ -852,20 +852,20 @@ private IdFunctionObject newIdFunction( @Override protected boolean defineOwnProperty( - Context cx, Object key, ScriptableObject desc, boolean checkValid) { + Context cx, Object key, DescriptorInfo desc, boolean checkValid) { if (key instanceof CharSequence) { String name = key.toString(); int info = findInstanceIdInfo(name); if (info != 0) { int id = (info & 0xFFFF); - if (isAccessorDescriptor(desc)) { + if (desc.isAccessorDescriptor()) { delete(id); // it will be replaced with a slot } else { checkPropertyDefinition(desc); var slot = queryOrFakeSlot(cx, key); checkPropertyChangeForSlot(name, slot, desc); int attr = (info >>> 16); - Object value = getProperty(desc, "value"); + Object value = desc.value; if (value != NOT_FOUND && ((attr & READONLY) == 0 || (attr & PERMANENT) == 0)) { Object currentValue = getInstanceIdValue(id); if (!sameValue(value, currentValue)) { @@ -874,10 +874,7 @@ protected boolean defineOwnProperty( } attr = applyDescriptorToAttributeBitset( - attr, - getProperty(desc, "enumerable"), - getProperty(desc, "writable"), - getProperty(desc, "configurable")); + attr, desc.enumerable, desc.writable, desc.configurable); setAttributes(name, attr); return true; } @@ -885,14 +882,14 @@ protected boolean defineOwnProperty( if (prototypeValues != null) { int id = prototypeValues.findId(name); if (id != 0) { - if (isAccessorDescriptor(desc)) { + if (desc.isAccessorDescriptor()) { prototypeValues.delete(id); // it will be replaced with a slot } else { checkPropertyDefinition(desc); var slot = queryOrFakeSlot(cx, key); checkPropertyChangeForSlot(name, slot, desc); int attr = prototypeValues.getAttributes(id); - Object value = getProperty(desc, "value"); + Object value = desc.value; if (value != NOT_FOUND && (attr & READONLY) == 0) { Object currentValue = prototypeValues.get(id); if (!sameValue(value, currentValue)) { @@ -902,10 +899,7 @@ protected boolean defineOwnProperty( prototypeValues.setAttributes( id, applyDescriptorToAttributeBitset( - attr, - getProperty(desc, "enumerable"), - getProperty(desc, "writable"), - getProperty(desc, "configurable"))); + attr, desc.enumerable, desc.writable, desc.configurable)); // Handle the regular slot that was created if this property was previously // replaced @@ -923,8 +917,8 @@ protected boolean defineOwnProperty( } @Override - protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { - ScriptableObject desc = super.getOwnPropertyDescriptor(cx, id); + protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) { + var desc = super.getOwnPropertyDescriptor(cx, id); if (desc == null) { if (id instanceof String) { return getBuiltInDataDescriptor((String) id); @@ -959,14 +953,9 @@ private Slot queryOrFakeSlot(Context cx, Object id) { return slot; } - private ScriptableObject getBuiltInDataDescriptor(String name) { - Scriptable scope = getParentScope(); - if (scope == null) { - scope = this; - } - + private DescriptorInfo getBuiltInDataDescriptor(String name) { var slot = getBuiltInSlot(name); - return slot == null ? null : buildDataDescriptor(scope, slot.value, slot.getAttributes()); + return slot == null ? null : new DescriptorInfo(slot.value, slot.getAttributes(), true); } private Slot getBuiltInSlot(String name) { @@ -992,14 +981,9 @@ private Slot getBuiltInSlot(String name) { return null; } - private ScriptableObject getBuiltInDataDescriptor(Symbol key) { - Scriptable scope = getParentScope(); - if (scope == null) { - scope = this; - } - + private DescriptorInfo getBuiltInDataDescriptor(Symbol key) { var slot = getBuiltInSlot(key); - return slot == null ? null : buildDataDescriptor(scope, slot.value, slot.getAttributes()); + return slot == null ? null : new DescriptorInfo(slot.value, slot.getAttributes(), true); } private Slot getBuiltInSlot(Symbol key) { diff --git a/rhino/src/main/java/org/mozilla/javascript/LambdaAccessorSlot.java b/rhino/src/main/java/org/mozilla/javascript/LambdaAccessorSlot.java index fec3a920fb..a20f171574 100644 --- a/rhino/src/main/java/org/mozilla/javascript/LambdaAccessorSlot.java +++ b/rhino/src/main/java/org/mozilla/javascript/LambdaAccessorSlot.java @@ -1,5 +1,7 @@ package org.mozilla.javascript; +import org.mozilla.javascript.ScriptableObject.DescriptorInfo; + /** * A specialized property accessor using lambda functions, similar to {@link LambdaSlot}, but allows * defining properties with getter and setter lambdas that require access to the owner object @@ -60,7 +62,7 @@ boolean isSetterSlot() { } @Override - ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { + DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) { return buildPropertyDescriptor(cx); } @@ -70,40 +72,36 @@ ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { * it can be problematic when called from inside ThreadSafeSlotMapContainer::compute lambda * which can lead to deadlocks. */ - public ScriptableObject buildPropertyDescriptor(Context cx) { - ScriptableObject desc = new NativeObject(); - + public DescriptorInfo buildPropertyDescriptor(Context cx) { int attr = getAttributes(); + DescriptorInfo desc; boolean es6 = cx.getLanguageVersion() >= Context.VERSION_ES6; if (es6) { + desc = new DescriptorInfo(ScriptableObject.NOT_FOUND, attr, false); if (getterFunction == null && setterFunction == null) { - desc.defineProperty( - "writable", - (attr & ScriptableObject.READONLY) == 0, - ScriptableObject.EMPTY); + desc.writable = (attr & ScriptableObject.READONLY) == 0; } } else { - desc.setCommonDescriptorProperties( - attr, getterFunction == null && setterFunction == null); + desc = + new DescriptorInfo( + ScriptableObject.NOT_FOUND, + attr, + getterFunction == null && setterFunction == null); } if (getterFunction != null) { - desc.defineProperty("get", this.getterFunction, ScriptableObject.EMPTY); + desc.getter = this.getterFunction; } if (setterFunction != null) { - desc.defineProperty("set", this.setterFunction, ScriptableObject.EMPTY); + desc.setter = this.setterFunction; } else if (es6) { - desc.defineProperty("set", Undefined.instance, ScriptableObject.EMPTY); + desc.setter = Undefined.instance; } if (es6) { - desc.defineProperty( - "enumerable", (attr & ScriptableObject.DONTENUM) == 0, ScriptableObject.EMPTY); - desc.defineProperty( - "configurable", - (attr & ScriptableObject.PERMANENT) == 0, - ScriptableObject.EMPTY); + desc.enumerable = (attr & ScriptableObject.DONTENUM) == 0; + desc.configurable = (attr & ScriptableObject.PERMANENT) == 0; } return desc; } diff --git a/rhino/src/main/java/org/mozilla/javascript/LambdaSlot.java b/rhino/src/main/java/org/mozilla/javascript/LambdaSlot.java index d5fe6e11f1..f879d67ae3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/LambdaSlot.java +++ b/rhino/src/main/java/org/mozilla/javascript/LambdaSlot.java @@ -2,6 +2,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; +import org.mozilla.javascript.ScriptableObject.DescriptorInfo; /** * This is a specialization of property access using some lambda functions. It behaves exactly like @@ -47,15 +48,8 @@ boolean isSetterSlot() { } @Override - ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { - ScriptableObject desc = (ScriptableObject) cx.newObject(scope); - if (getter != null) { - desc.defineProperty("value", getter.get(), ScriptableObject.EMPTY); - } else { - desc.defineProperty("value", value, ScriptableObject.EMPTY); - } - desc.setCommonDescriptorProperties(getAttributes(), true); - return desc; + DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) { + return new DescriptorInfo(getter == null ? value : getter.get(), getAttributes(), true); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeArray.java b/rhino/src/main/java/org/mozilla/javascript/NativeArray.java index bd1d2054d5..736781f99f 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeArray.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeArray.java @@ -246,7 +246,7 @@ private static Object makeUnscopables(Context cx, Scriptable scope) { obj = (NativeObject) cx.newObject(scope); - ScriptableObject desc = ScriptableObject.buildDataDescriptor(obj, true, EMPTY); + var desc = ScriptableObject.buildDataDescriptor(true, EMPTY); for (var k : UNSCOPABLES) { obj.defineOwnProperty(cx, k, desc); } @@ -464,16 +464,8 @@ public Object getDefaultValue(Class hint) { return super.getDefaultValue(hint); } - private ScriptableObject defaultIndexPropertyDescriptor(Object value) { - Scriptable scope = getParentScope(); - if (scope == null) scope = this; - ScriptableObject desc = new NativeObject(); - ScriptRuntime.setBuiltinProtoAndParent(desc, scope, TopLevel.Builtins.Object); - desc.defineProperty("value", value, EMPTY); - desc.defineProperty("writable", Boolean.TRUE, EMPTY); - desc.defineProperty("enumerable", Boolean.TRUE, EMPTY); - desc.defineProperty("configurable", Boolean.TRUE, EMPTY); - return desc; + private DescriptorInfo defaultIndexPropertyDescriptor(Object value) { + return new DescriptorInfo(true, true, true, NOT_FOUND, NOT_FOUND, value); } @Override @@ -485,7 +477,7 @@ public int getAttributes(int index) { } @Override - protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { + protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) { if (dense != null) { int index = toDenseIndex(id); if (0 <= index && index < dense.length && dense[index] != NOT_FOUND) { @@ -498,7 +490,7 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { @Override protected boolean defineOwnProperty( - Context cx, Object id, ScriptableObject desc, boolean checkValid) { + Context cx, Object id, DescriptorInfo desc, boolean checkValid) { long index = toArrayIndex(id); if (index >= length) { length = index + 1; @@ -748,9 +740,9 @@ private static Object js_of(Context cx, Scriptable scope, Scriptable thisObj, Ob callConstructorOrCreateArray(cx, scope, thisObj, args.length, true); if (cx.getLanguageVersion() >= Context.VERSION_ES6 && result instanceof ScriptableObject) { - ScriptableObject desc = ScriptableObject.buildDataDescriptor(result, null, EMPTY); + var desc = ScriptableObject.buildDataDescriptor(null, EMPTY); for (int i = 0; i < args.length; i++) { - desc.put("value", desc, args[i]); + desc.value = args[i]; ((ScriptableObject) result).defineOwnProperty(cx, i, desc); } } else { diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeObject.java b/rhino/src/main/java/org/mozilla/javascript/NativeObject.java index bba1b14198..a6bc3aece3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeObject.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeObject.java @@ -571,8 +571,8 @@ private static Object js_getOwnPropDesc( Scriptable s = getCompatibleObject(cx, scope, arg); ScriptableObject obj = ensureScriptableObject(s); Object nameArg = args.length < 2 ? Undefined.instance : args[1]; - Scriptable desc = obj.getOwnPropertyDescriptor(cx, nameArg); - return desc == null ? Undefined.instance : desc; + var desc = obj.getOwnPropertyDescriptor(cx, nameArg); + return desc == null ? Undefined.instance : desc.toObject(scope); } private static Object js_getOwnPropDescs( @@ -587,15 +587,15 @@ private static Object js_getOwnPropDescs( ids = obj.getIds(map, true, true); } for (Object key : ids) { - Scriptable desc = obj.getOwnPropertyDescriptor(cx, key); + var desc = obj.getOwnPropertyDescriptor(cx, key); if (desc == null) { continue; } else if (key instanceof Symbol) { - descs.put((Symbol) key, descs, desc); + descs.put((Symbol) key, descs, desc.toObject(scope)); } else if (key instanceof Integer) { - descs.put((Integer) key, descs, desc); + descs.put((Integer) key, descs, desc.toObject(scope)); } else { - descs.put(ScriptRuntime.toString(key), descs, desc); + descs.put(ScriptRuntime.toString(key), descs, desc.toObject(scope)); } } return descs; @@ -607,7 +607,8 @@ private static Object js_defineProperty( ScriptableObject obj = ensureScriptableObject(arg); Object name = args.length < 2 ? Undefined.instance : args[1]; Object descArg = args.length < 3 ? Undefined.instance : args[2]; - ScriptableObject desc = ensureScriptableObject(descArg); + var desc = new DescriptorInfo(ensureScriptableObject(descArg)); + ScriptableObject.checkPropertyDefinition(desc); obj.defineOwnProperty(cx, name, desc); return obj; } diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeProxy.java b/rhino/src/main/java/org/mozilla/javascript/NativeProxy.java index cbd202db23..cb27e5e6c0 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeProxy.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeProxy.java @@ -125,7 +125,7 @@ public Scriptable construct(Context cx, Scriptable scope, Object[] args) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_CONSTRUCT); + Function trap = getTrap(TRAP_CONSTRUCT); if (trap != null) { Object result = callTrap(trap, new Object[] {target, args, this}); if (!(result instanceof Scriptable) || ScriptRuntime.isSymbol(result)) { @@ -164,17 +164,16 @@ public boolean has(String name, Scriptable start) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_HAS); + Function trap = getTrap(TRAP_HAS); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, name})); if (!booleanTrapResult) { - ScriptableObject targetDesc = + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), name); if (targetDesc != null) { - if (Boolean.FALSE.equals(targetDesc.get("configurable")) - || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't report an existing own property '" + name @@ -218,17 +217,16 @@ public boolean has(int index, Scriptable start) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_HAS); + Function trap = getTrap(TRAP_HAS); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean( callTrap(trap, new Object[] {target, ScriptRuntime.toString(index)})); if (!booleanTrapResult) { - ScriptableObject targetDesc = + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), index); if (targetDesc != null) { - if (Boolean.FALSE.equals(targetDesc.get("configurable")) - || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't check an existing property ' + name + ' existance on an not configurable or not extensible object"); } @@ -253,16 +251,15 @@ public boolean has(int index, Scriptable start) { public boolean has(Symbol key, Scriptable start) { ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_HAS); + Function trap = getTrap(TRAP_HAS); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, key})); if (!booleanTrapResult) { - ScriptableObject targetDesc = + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), key); if (targetDesc != null) { - if (Boolean.FALSE.equals(targetDesc.get("configurable")) - || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't check an existing property ' + name + ' existance on an not configurable or not extensible object"); } @@ -324,7 +321,7 @@ Object[] getIds(CompoundOperationMap map, boolean getNonEnumerable, boolean getS */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_OWN_KEYS); + Function trap = getTrap(TRAP_OWN_KEYS); if (trap != null) { Object res = callTrap(trap, new Object[] {target}); if (!(res instanceof Scriptable)) { @@ -361,8 +358,8 @@ Object[] getIds(CompoundOperationMap map, boolean getNonEnumerable, boolean getS ArrayList targetConfigurableKeys = new ArrayList<>(); ArrayList targetNonconfigurableKeys = new ArrayList<>(); for (Object targetKey : targetKeys) { - ScriptableObject desc = target.getOwnPropertyDescriptor(cx, targetKey); - if (desc != null && Boolean.FALSE.equals(desc.get("configurable"))) { + DescriptorInfo desc = target.getOwnPropertyDescriptor(cx, targetKey); + if (desc != null && desc.isConfigurable(false)) { targetNonconfigurableKeys.add(targetKey); } else { targetConfigurableKeys.add(targetKey); @@ -431,24 +428,19 @@ public Object get(String name, Scriptable start) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_GET); + Function trap = getTrap(TRAP_GET); if (trap != null) { Object trapResult = callTrap(trap, new Object[] {target, name, this}); - ScriptableObject targetDesc = - target.getOwnPropertyDescriptor(Context.getContext(), name); - if (targetDesc != null - && !Undefined.isUndefined(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable"))) { - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("writable"))) { - if (!Objects.equals(trapResult, targetDesc.get("value"))) { + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), name); + if (targetDesc != null && targetDesc.isConfigurable(false)) { + if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) { + if (!Objects.equals(trapResult, targetDesc.value)) { throw ScriptRuntime.typeError( "proxy get has to return the same value as the plain call"); } } - if (ScriptableObject.isAccessorDescriptor(targetDesc) - && Undefined.isUndefined(targetDesc.get("get"))) { + if (targetDesc.isAccessorDescriptor() && Undefined.isUndefined(targetDesc.getter)) { if (!Undefined.isUndefined(trapResult)) { throw ScriptRuntime.typeError( "proxy get has to return the same value as the plain call"); @@ -491,25 +483,23 @@ public Object get(int index, Scriptable start) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_GET); + Function trap = getTrap(TRAP_GET); if (trap != null) { Object trapResult = callTrap(trap, new Object[] {target, ScriptRuntime.toString(index), this}); - ScriptableObject targetDesc = + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), index); if (targetDesc != null && !Undefined.isUndefined(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable"))) { - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("writable"))) { - if (!Objects.equals(trapResult, targetDesc.get("value"))) { + && targetDesc.isConfigurable(false)) { + if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) { + if (!Objects.equals(trapResult, targetDesc.value)) { throw ScriptRuntime.typeError( "proxy get has to return the same value as the plain call"); } } - if (ScriptableObject.isAccessorDescriptor(targetDesc) - && Undefined.isUndefined(targetDesc.get("get"))) { + if (targetDesc.isAccessorDescriptor() && Undefined.isUndefined(targetDesc.getter)) { if (!Undefined.isUndefined(trapResult)) { throw ScriptRuntime.typeError( "proxy get has to return the same value as the plain call"); @@ -552,24 +542,21 @@ public Object get(Symbol key, Scriptable start) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_GET); + Function trap = getTrap(TRAP_GET); if (trap != null) { Object trapResult = callTrap(trap, new Object[] {target, key, this}); - ScriptableObject targetDesc = - target.getOwnPropertyDescriptor(Context.getContext(), key); + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), key); if (targetDesc != null && !Undefined.isUndefined(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable"))) { - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("writable"))) { - if (!Objects.equals(trapResult, targetDesc.get("value"))) { + && targetDesc.isConfigurable(false)) { + if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) { + if (!Objects.equals(trapResult, targetDesc.value)) { throw ScriptRuntime.typeError( "proxy get has to return the same value as the plain call"); } } - if (ScriptableObject.isAccessorDescriptor(targetDesc) - && Undefined.isUndefined(targetDesc.get("get"))) { + if (targetDesc.isAccessorDescriptor() && Undefined.isUndefined(targetDesc.getter)) { if (!Undefined.isUndefined(trapResult)) { throw ScriptRuntime.typeError( "proxy get has to return the same value as the plain call"); @@ -614,7 +601,7 @@ public void put(String name, Scriptable start, Object value) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_SET); + Function trap = getTrap(TRAP_SET); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, name, value})); @@ -622,20 +609,17 @@ public void put(String name, Scriptable start, Object value) { return; // false } - ScriptableObject targetDesc = - target.getOwnPropertyDescriptor(Context.getContext(), name); + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), name); if (targetDesc != null && !Undefined.isUndefined(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable"))) { - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("writable"))) { - if (!Objects.equals(value, targetDesc.get("value"))) { + && targetDesc.isConfigurable(false)) { + if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) { + if (!Objects.equals(value, targetDesc.value)) { throw ScriptRuntime.typeError( "proxy set has to use the same value as the plain call"); } } - if (ScriptableObject.isAccessorDescriptor(targetDesc) - && Undefined.isUndefined(targetDesc.get("set"))) { + if (targetDesc.isAccessorDescriptor() && Undefined.isUndefined(targetDesc.setter)) { throw ScriptRuntime.typeError("proxy set has to be available"); } } @@ -676,7 +660,7 @@ public void put(int index, Scriptable start, Object value) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_SET); + Function trap = getTrap(TRAP_SET); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean( @@ -687,20 +671,18 @@ public void put(int index, Scriptable start, Object value) { return; // false } - ScriptableObject targetDesc = + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), index); if (targetDesc != null && !Undefined.isUndefined(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable"))) { - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("writable"))) { - if (!Objects.equals(value, targetDesc.get("value"))) { + && targetDesc.isConfigurable(false)) { + if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) { + if (!Objects.equals(value, targetDesc.value)) { throw ScriptRuntime.typeError( "proxy set has to use the same value as the plain call"); } } - if (ScriptableObject.isAccessorDescriptor(targetDesc) - && Undefined.isUndefined(targetDesc.get("set"))) { + if (targetDesc.isAccessorDescriptor() && Undefined.isUndefined(targetDesc.setter)) { throw ScriptRuntime.typeError("proxy set has to be available"); } } @@ -741,7 +723,7 @@ public void put(Symbol key, Scriptable start, Object value) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_SET); + Function trap = getTrap(TRAP_SET); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, key, value})); @@ -749,20 +731,17 @@ public void put(Symbol key, Scriptable start, Object value) { return; // false } - ScriptableObject targetDesc = - target.getOwnPropertyDescriptor(Context.getContext(), key); + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), key); if (targetDesc != null && !Undefined.isUndefined(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable"))) { - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("writable"))) { - if (!Objects.equals(value, targetDesc.get("value"))) { + && targetDesc.isConfigurable(false)) { + if (targetDesc.isDataDescriptor() && targetDesc.isWritable(false)) { + if (!Objects.equals(value, targetDesc.value)) { throw ScriptRuntime.typeError( "proxy set has to use the same value as the plain call"); } } - if (ScriptableObject.isAccessorDescriptor(targetDesc) - && Undefined.isUndefined(targetDesc.get("set"))) { + if (targetDesc.isAccessorDescriptor() && Undefined.isUndefined(targetDesc.setter)) { throw ScriptRuntime.typeError("proxy set has to be available"); } } @@ -803,7 +782,7 @@ public void delete(String name) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_DELETE_PROPERTY); + Function trap = getTrap(TRAP_DELETE_PROPERTY); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, name})); @@ -811,12 +790,11 @@ public void delete(String name) { return; // false } - ScriptableObject targetDesc = - target.getOwnPropertyDescriptor(Context.getContext(), name); + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), name); if (targetDesc == null) { return; // true } - if (Boolean.FALSE.equals(targetDesc.get("configurable")) || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't delete an existing own property ' + name + ' on an not configurable or not extensible object"); } @@ -854,7 +832,7 @@ public void delete(int index) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_DELETE_PROPERTY); + Function trap = getTrap(TRAP_DELETE_PROPERTY); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean( @@ -863,12 +841,12 @@ public void delete(int index) { return; // false } - ScriptableObject targetDesc = + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), index); if (targetDesc == null) { return; // true } - if (Boolean.FALSE.equals(targetDesc.get("configurable")) || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't delete an existing own property ' + name + ' on an not configurable or not extensible object"); } @@ -906,7 +884,7 @@ public void delete(Symbol key) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_DELETE_PROPERTY); + Function trap = getTrap(TRAP_DELETE_PROPERTY); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, key})); @@ -914,12 +892,11 @@ public void delete(Symbol key) { return; // false } - ScriptableObject targetDesc = - target.getOwnPropertyDescriptor(Context.getContext(), key); + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), key); if (targetDesc == null) { return; // true } - if (Boolean.FALSE.equals(targetDesc.get("configurable")) || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't delete an existing own property ' + name + ' on an not configurable or not extensible object"); } @@ -937,7 +914,7 @@ public void delete(Symbol key) { * [[GetOwnProperty]] (P) */ @Override - protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { + protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) { /* * 1. Assert: IsPropertyKey(P) is true. * 2. Let handler be O.[[ProxyHandler]]. @@ -970,7 +947,7 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_GET_OWN_PROPERTY_DESCRIPTOR); + Function trap = getTrap(TRAP_GET_OWN_PROPERTY_DESCRIPTOR); if (trap != null) { Object trapResultObj = callTrap(trap, new Object[] {target, id}); if (!Undefined.isUndefined(trapResultObj) @@ -980,20 +957,17 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { "getOwnPropertyDescriptor trap has to return undefined or an object"); } - ScriptableObject targetDesc; - if (ScriptRuntime.isSymbol(id)) { - targetDesc = target.getOwnPropertyDescriptor(cx, id); - } else { - targetDesc = target.getOwnPropertyDescriptor(cx, ScriptRuntime.toString(id)); - } + var targetDesc = + ScriptRuntime.isSymbol(id) + ? target.getOwnPropertyDescriptor(cx, id) + : target.getOwnPropertyDescriptor(cx, ScriptRuntime.toString(id)); if (Undefined.isUndefined(trapResultObj)) { if (Undefined.isUndefined(targetDesc)) { return null; } - if (Boolean.FALSE.equals(targetDesc.get("configurable")) - || !target.isExtensible()) { + if (targetDesc.isConfigurable(false) || !target.isExtensible()) { throw ScriptRuntime.typeError( "proxy can't report an existing own property '" + id @@ -1012,8 +986,7 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { getProperty(trapResult, "writable"), getProperty(trapResult, "configurable")); - ScriptableObject desc = - ScriptableObject.buildDataDescriptor(target, value, attributes); + var desc = ScriptableObject.buildDataDescriptor(value, attributes); return desc; } return null; @@ -1032,7 +1005,7 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { * [[DefineOwnProperty]] (P, Desc) */ @Override - public boolean defineOwnProperty(Context cx, Object id, ScriptableObject desc) { + public boolean defineOwnProperty(Context cx, Object id, DescriptorInfo desc) { /* * 1. Assert: IsPropertyKey(P) is true. * 2. Let handler be O.[[ProxyHandler]]. @@ -1062,20 +1035,23 @@ public boolean defineOwnProperty(Context cx, Object id, ScriptableObject desc) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_DEFINE_PROPERTY); + Function trap = getTrap(TRAP_DEFINE_PROPERTY); if (trap != null) { boolean booleanTrapResult = - ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, id, desc})); + ScriptRuntime.toBoolean( + callTrap( + trap, + new Object[] { + target, id, desc.toObject(trap.getDeclarationScope()) + })); if (!booleanTrapResult) { return false; } - ScriptableObject targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), id); + DescriptorInfo targetDesc = target.getOwnPropertyDescriptor(Context.getContext(), id); boolean extensibleTarget = target.isExtensible(); - boolean settingConfigFalse = - Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "configurable")) - && Boolean.FALSE.equals(desc.get("configurable")); + boolean settingConfigFalse = desc.isConfigurable(false); if (targetDesc == null) { if (!extensibleTarget || settingConfigFalse) { @@ -1089,16 +1065,15 @@ public boolean defineOwnProperty(Context cx, Object id, ScriptableObject desc) { "proxy can't define an incompatible property descriptor"); } - if (settingConfigFalse && Boolean.TRUE.equals(targetDesc.get("configurable"))) { + if (settingConfigFalse && targetDesc.isConfigurable()) { throw ScriptRuntime.typeError( "proxy can't define an incompatible property descriptor"); } - if (ScriptableObject.isDataDescriptor(targetDesc) - && Boolean.FALSE.equals(targetDesc.get("configurable")) - && Boolean.TRUE.equals(targetDesc.get("writable"))) { - if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "writable")) - && Boolean.FALSE.equals(desc.get("writable"))) { + if (targetDesc.isDataDescriptor() + && targetDesc.isConfigurable(false) + && targetDesc.isWritable()) { + if (desc.isWritable(false)) { throw ScriptRuntime.typeError( "proxy can't define an incompatible property descriptor"); } @@ -1132,7 +1107,7 @@ public boolean isExtensible() { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_IS_EXTENSIBLE); + Function trap = getTrap(TRAP_IS_EXTENSIBLE); if (trap == null) { return target.isExtensible(); } @@ -1168,7 +1143,7 @@ public boolean preventExtensions() { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_PREVENT_EXTENSIONS); + Function trap = getTrap(TRAP_PREVENT_EXTENSIONS); if (trap == null) { return target.preventExtensions(); } @@ -1210,7 +1185,7 @@ public Scriptable getPrototype() { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_GET_PROTOTYPE_OF); + Function trap = getTrap(TRAP_GET_PROTOTYPE_OF); if (trap != null) { Object handlerProto = callTrap(trap, new Object[] {target}); @@ -1267,7 +1242,7 @@ public void setPrototype(Scriptable prototype) { */ ScriptableObject target = getTargetThrowIfRevoked(); - Callable trap = getTrap(TRAP_SET_PROTOTYPE_OF); + Function trap = getTrap(TRAP_SET_PROTOTYPE_OF); if (trap != null) { boolean booleanTrapResult = ScriptRuntime.toBoolean(callTrap(trap, new Object[] {target, prototype})); @@ -1306,7 +1281,7 @@ public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] ar Scriptable argumentsList = cx.newArray(scope, args); - Callable trap = getTrap(TRAP_APPLY); + Function trap = getTrap(TRAP_APPLY); if (trap != null) { return callTrap(trap, new Object[] {target, thisObj, argumentsList}); } @@ -1357,7 +1332,7 @@ private static Object revocable( return revocable; } - private Callable getTrap(String trapName) { + private Function getTrap(String trapName) { Object handlerProp = ScriptableObject.getProperty(handlerObj, trapName); if (Scriptable.NOT_FOUND == handlerProp) { return null; @@ -1369,11 +1344,11 @@ private Callable getTrap(String trapName) { throw ScriptRuntime.notFunctionError(handlerProp, trapName); } - return (Callable) handlerProp; + return (Function) handlerProp; } - private Object callTrap(Callable trap, Object[] args) { - return trap.call(Context.getContext(), handlerObj, handlerObj, args); + private Object callTrap(Function trap, Object[] args) { + return trap.call(Context.getContext(), trap.getDeclarationScope(), handlerObj, args); } ScriptableObject getTargetThrowIfRevoked() { diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeReflect.java b/rhino/src/main/java/org/mozilla/javascript/NativeReflect.java index 177fb86015..94dde4c832 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeReflect.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeReflect.java @@ -171,7 +171,7 @@ private static Object defineProperty( } ScriptableObject target = checkTarget(args); - ScriptableObject desc = ScriptableObject.ensureScriptableObject(args[2]); + DescriptorInfo desc = new DescriptorInfo(ScriptableObject.ensureScriptableObject(args[2])); Object key = args[1]; @@ -229,13 +229,12 @@ private static Scriptable getOwnPropertyDescriptor( if (args.length > 1) { if (ScriptRuntime.isSymbol(args[1])) { - ScriptableObject desc = target.getOwnPropertyDescriptor(cx, args[1]); - return desc == null ? Undefined.SCRIPTABLE_UNDEFINED : desc; + var desc = target.getOwnPropertyDescriptor(cx, args[1]); + return desc == null ? Undefined.SCRIPTABLE_UNDEFINED : desc.toObject(scope); } - ScriptableObject desc = - target.getOwnPropertyDescriptor(cx, ScriptRuntime.toString(args[1])); - return desc == null ? Undefined.SCRIPTABLE_UNDEFINED : desc; + var desc = target.getOwnPropertyDescriptor(cx, ScriptRuntime.toString(args[1])); + return desc == null ? Undefined.SCRIPTABLE_UNDEFINED : desc.toObject(scope); } return Undefined.SCRIPTABLE_UNDEFINED; } @@ -308,15 +307,15 @@ private static Object set(Context cx, Scriptable scope, Scriptable thisObj, Obje ScriptableObject receiver = args.length > 3 ? ScriptableObject.ensureScriptableObject(args[3]) : target; if (receiver != target) { - ScriptableObject descriptor = target.getOwnPropertyDescriptor(cx, args[1]); + DescriptorInfo descriptor = target.getOwnPropertyDescriptor(cx, args[1]); if (descriptor != null) { - Object setter = descriptor.get("set"); + Object setter = descriptor.setter; if (setter != null && setter != NOT_FOUND) { ((Function) setter).call(cx, scope, receiver, new Object[] {args[2]}); return true; } - if (Boolean.FALSE.equals(descriptor.get("configurable"))) { + if (descriptor.isConfigurable(false)) { return false; } } diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeString.java b/rhino/src/main/java/org/mozilla/javascript/NativeString.java index 2e03bf0030..90a8b9a9d7 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeString.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeString.java @@ -561,7 +561,7 @@ protected Object[] getIds(CompoundOperationMap map, boolean nonEnumerable, boole } @Override - protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { + protected ScriptableObject.DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) { if (!(id instanceof Symbol) && (cx != null) && (cx.getLanguageVersion() >= Context.VERSION_ES6)) { @@ -574,16 +574,8 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { return super.getOwnPropertyDescriptor(cx, id); } - private ScriptableObject defaultIndexPropertyDescriptor(Object value) { - Scriptable scope = getParentScope(); - if (scope == null) scope = this; - ScriptableObject desc = new NativeObject(); - ScriptRuntime.setBuiltinProtoAndParent(desc, scope, TopLevel.Builtins.Object); - desc.defineProperty("value", value, EMPTY); - desc.defineProperty("writable", Boolean.FALSE, EMPTY); - desc.defineProperty("enumerable", Boolean.TRUE, EMPTY); - desc.defineProperty("configurable", Boolean.FALSE, EMPTY); - return desc; + private ScriptableObject.DescriptorInfo defaultIndexPropertyDescriptor(Object value) { + return new ScriptableObject.DescriptorInfo(true, false, false, NOT_FOUND, NOT_FOUND, value); } /* diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntimeES6.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntimeES6.java index a151b7e8d3..0d81061c52 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntimeES6.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntimeES6.java @@ -6,6 +6,8 @@ package org.mozilla.javascript; +import org.mozilla.javascript.ScriptableObject.DescriptorInfo; + public class ScriptRuntimeES6 { public static Object requireObjectCoercible( @@ -30,20 +32,23 @@ public static Object requireObjectCoercible( /** Registers the symbol {@code [Symbol.species]} on the given constructor function. */ public static void addSymbolSpecies( Context cx, Scriptable scope, ScriptableObject constructor) { - ScriptableObject speciesDescriptor = (ScriptableObject) cx.newObject(scope); - ScriptableObject.putProperty(speciesDescriptor, "enumerable", false); - ScriptableObject.putProperty(speciesDescriptor, "configurable", true); - ScriptableObject.putProperty( - speciesDescriptor, - "get", - new LambdaFunction( - scope, - "get [Symbol.species]", - 0, - (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> - thisObj, - false)); - constructor.defineOwnProperty(cx, SymbolKey.SPECIES, speciesDescriptor, false); + DescriptorInfo desc = + new DescriptorInfo( + false, + ScriptableObject.NOT_FOUND, + true, + new LambdaFunction( + scope, + "get [Symbol.species]", + 0, + (Context lcx, + Scriptable lscope, + Scriptable thisObj, + Object[] args) -> thisObj, + false), + ScriptableObject.NOT_FOUND, + ScriptableObject.NOT_FOUND); + constructor.defineOwnProperty(cx, SymbolKey.SPECIES, desc, false); } /** Registers the symbol {@code [Symbol.unscopables]} on the given constructor function. */ diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java b/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java index c0dc49be44..b0408dfbc3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptableObject.java @@ -127,13 +127,8 @@ public abstract class ScriptableObject extends SlotMapOwner } } - protected static ScriptableObject buildDataDescriptor( - Scriptable scope, Object value, int attributes) { - ScriptableObject desc = new NativeObject(); - ScriptRuntime.setBuiltinProtoAndParent(desc, scope, TopLevel.Builtins.Object); - desc.defineProperty("value", value, EMPTY); - desc.setCommonDescriptorProperties(attributes, true); - return desc; + protected static DescriptorInfo buildDataDescriptor(Object value, int attributes) { + return new DescriptorInfo(value, attributes, true); } protected void setCommonDescriptorProperties(int attributes, boolean defineWritable) { @@ -1637,10 +1632,10 @@ public void defineOwnProperties(Context cx, ScriptableObject props) { try (var map = props.startCompoundOp(false)) { ids = props.getIds(map, false, true); } - ScriptableObject[] descs = new ScriptableObject[ids.length]; + DescriptorInfo[] descs = new DescriptorInfo[ids.length]; for (int i = 0, len = ids.length; i < len; ++i) { Object descObj = ScriptRuntime.getObjectElem(props, ids[i], cx); - ScriptableObject desc = ensureScriptableObject(descObj); + var desc = new DescriptorInfo(ensureScriptableObject(descObj)); checkPropertyDefinition(desc); descs[i] = desc; } @@ -1658,6 +1653,10 @@ public void defineOwnProperties(Context cx, ScriptableObject props) { */ public boolean defineOwnProperty(Context cx, Object id, ScriptableObject desc) { checkPropertyDefinition(desc); + return defineOwnProperty(cx, id, new DescriptorInfo(desc), true); + } + + public boolean defineOwnProperty(Context cx, Object id, DescriptorInfo desc) { return defineOwnProperty(cx, id, desc, true); } @@ -1674,7 +1673,7 @@ public boolean defineOwnProperty(Context cx, Object id, ScriptableObject desc) { * @return always true at the moment */ protected boolean defineOwnProperty( - Context cx, Object id, ScriptableObject desc, boolean checkValid) { + Context cx, Object id, DescriptorInfo desc, boolean checkValid) { Object key = null; int index = 0; @@ -1691,11 +1690,6 @@ protected boolean defineOwnProperty( Slot aSlot = getMap().query(key, index); - // We convert the whole object to a descriptor at this point - // because we have no good way to reliably to do so inside a - // compound operation. - var info = new DescriptorInfo(desc); - if (aSlot instanceof BuiltInSlot) { // 10.4.2.4 ArrayLengthSet requires we check that any new // value is valid and throw a range error if not before @@ -1708,7 +1702,7 @@ protected boolean defineOwnProperty( // modify the current descriptor as part of operations // performed as part of applying the descriptor. - return ((BuiltInSlot) aSlot).applyNewDescriptor(id, info, checkValid, key, index); + return ((BuiltInSlot) aSlot).applyNewDescriptor(id, desc, checkValid, key, index); } else { try (var map = startCompoundOp(true)) { return defineOrdinaryProperty( @@ -1716,7 +1710,7 @@ protected boolean defineOwnProperty( this, map, id, - info, + desc, checkValid, key, index); @@ -1725,15 +1719,15 @@ protected boolean defineOwnProperty( } public static final class DescriptorInfo { - Object enumerable; - Object writable; - Object configurable; - Object getter; - Object setter; - Object value; + public Object enumerable = NOT_FOUND; + public Object writable = NOT_FOUND; + public Object configurable = NOT_FOUND; + public Object getter = NOT_FOUND; + public Object setter = NOT_FOUND; + public Object value = NOT_FOUND; boolean accessorDescriptor; - DescriptorInfo(ScriptableObject desc) { + public DescriptorInfo(ScriptableObject desc) { enumerable = getProperty(desc, "enumerable"); writable = getProperty(desc, "writable"); configurable = getProperty(desc, "configurable"); @@ -1742,6 +1736,114 @@ public static final class DescriptorInfo { value = getProperty(desc, "value"); accessorDescriptor = getter != NOT_FOUND || setter != NOT_FOUND; } + + public DescriptorInfo( + boolean enumerable, boolean writable, boolean configurable, Object value) { + this.enumerable = enumerable; + this.writable = writable; + this.configurable = configurable; + this.getter = NOT_FOUND; + this.setter = NOT_FOUND; + this.value = value; + accessorDescriptor = false; + } + + public DescriptorInfo( + Object enumerable, + Object writable, + Object configurable, + Object getter, + Object setter, + Object value) { + this.enumerable = enumerable; + this.writable = writable; + this.configurable = configurable; + this.getter = getter; + this.setter = setter; + this.value = value; + accessorDescriptor = getter != NOT_FOUND || setter != NOT_FOUND; + } + + DescriptorInfo(Object value, int attributes, boolean defineWritable) { + this.value = value; + if (defineWritable) { + writable = (attributes & READONLY) == 0; + } + enumerable = (attributes & DONTENUM) == 0; + configurable = (attributes & PERMANENT) == 0; + } + + Scriptable toObject(Scriptable scope) { + ScriptableObject desc = new NativeObject(); + ScriptRuntime.setBuiltinProtoAndParent(desc, scope, TopLevel.Builtins.Object); + if (hasValue()) desc.defineProperty("value", value, EMPTY); + if (hasWritable()) desc.defineProperty("writable", writable, EMPTY); + if (hasGetter()) desc.defineProperty("get", getter, EMPTY); + if (hasSetter()) desc.defineProperty("set", setter, EMPTY); + if (hasEnumerable()) desc.defineProperty("enumerable", enumerable, EMPTY); + if (hasConfigurable()) desc.defineProperty("configurable", configurable, EMPTY); + return desc; + } + + public boolean isWritable() { + return Boolean.TRUE.equals(writable); + } + + public boolean isWritable(boolean value) { + return ((Boolean) value).equals(writable); + } + + public boolean hasWritable() { + return writable != NOT_FOUND; + } + + public boolean isEnumerable() { + return Boolean.TRUE.equals(enumerable); + } + + public boolean isEnumerable(boolean value) { + return ((Boolean) value).equals(enumerable); + } + + public boolean hasEnumerable() { + return enumerable != NOT_FOUND; + } + + public boolean isConfigurable() { + return Boolean.TRUE.equals(configurable); + } + + public boolean isConfigurable(boolean value) { + return ((Boolean) value).equals(configurable); + } + + public boolean hasConfigurable() { + return configurable != NOT_FOUND; + } + + public boolean hasValue() { + return value != NOT_FOUND; + } + + public boolean hasGetter() { + return getter != NOT_FOUND; + } + + public boolean hasSetter() { + return setter != NOT_FOUND; + } + + public boolean isDataDescriptor() { + return hasValue() || hasWritable(); + } + + public boolean isAccessorDescriptor() { + return hasGetter() || hasSetter(); + } + + public boolean isGenericDescriptor() { + return !isDataDescriptor() && !isAccessorDescriptor(); + } } static boolean defineOrdinaryProperty( @@ -1838,7 +1940,7 @@ static Slot setSlotValue( ((BuiltInSlot) slot).setValueFromDescriptor(info.value, owner, owner, true); } } else { - if (!slot.isValueSlot() && isDataDescriptor(info)) { + if (!slot.isValueSlot() && info.isDataDescriptor()) { // Replace a non-base slot with a regular slot slot = new Slot(slot); } @@ -1942,7 +2044,7 @@ public void defineProperty( } private void replaceLambdaAccessorSlot(Context cx, Object key, LambdaAccessorSlot newSlot) { - ScriptableObject newDesc = newSlot.buildPropertyDescriptor(cx); + var newDesc = newSlot.buildPropertyDescriptor(cx); checkPropertyDefinition(newDesc); getMap().compute( this, @@ -1989,7 +2091,7 @@ private LambdaAccessorSlot createLambdaAccessorSlot( return slot; } - protected void checkPropertyDefinition(ScriptableObject desc) { + protected static void checkPropertyDefinition(ScriptableObject desc) { Object getter = getProperty(desc, "get"); if (getter != NOT_FOUND && getter != Undefined.instance && !(getter instanceof Callable)) { throw ScriptRuntime.notFunctionError(getter); @@ -2003,6 +2105,20 @@ protected void checkPropertyDefinition(ScriptableObject desc) { } } + protected static void checkPropertyDefinition(DescriptorInfo desc) { + Object getter = desc.getter; + if (getter != NOT_FOUND && getter != Undefined.instance && !(getter instanceof Callable)) { + throw ScriptRuntime.notFunctionError(getter); + } + Object setter = desc.setter; + if (setter != NOT_FOUND && setter != Undefined.instance && !(setter instanceof Callable)) { + throw ScriptRuntime.notFunctionError(setter); + } + if (desc.isDataDescriptor() && desc.isAccessorDescriptor()) { + throw ScriptRuntime.typeErrorById("msg.both.data.and.accessor.desc"); + } + } + protected final void checkPropertyChangeForSlot( Object id, Slot current, ScriptableObject desc) { checkPropertyChangeForSlot(id, current, new DescriptorInfo(desc)); @@ -2019,7 +2135,7 @@ protected final void checkPropertyChangeForSlot(Object id, Slot current, Descrip if (((current.getAttributes() & DONTENUM) == 0) != isTrue(info.enumerable)) throw ScriptRuntime.typeErrorById( "msg.change.enumerable.with.configurable.false", id); - boolean isData = isDataDescriptor(info); + boolean isData = info.isDataDescriptor(); boolean isBuiltIn = current instanceof BuiltInSlot; boolean isAccessor = info.accessorDescriptor; if (!isData && !isAccessor) { @@ -2128,10 +2244,6 @@ protected static boolean isDataDescriptor(ScriptableObject desc) { return hasProperty(desc, "value") || hasProperty(desc, "writable"); } - protected static boolean isDataDescriptor(DescriptorInfo info) { - return info.value != NOT_FOUND || info.writable != NOT_FOUND; - } - /** * Implements IsAccessorDescriptor as described in ES5 8.10.1 * @@ -2142,6 +2254,10 @@ protected static boolean isAccessorDescriptor(ScriptableObject desc) { return hasProperty(desc, "get") || hasProperty(desc, "set"); } + protected static boolean isAccessorDescriptor(DescriptorInfo desc) { + return desc.hasGetter() || desc.hasSetter(); + } + /** * Implements IsGenericDescriptor as described in ES5 8.10.3 * @@ -2152,6 +2268,10 @@ protected static boolean isGenericDescriptor(ScriptableObject desc) { return !isDataDescriptor(desc) && !isAccessorDescriptor(desc); } + protected static boolean isGenericDescriptor(DescriptorInfo desc) { + return desc.isDataDescriptor() && !desc.isAccessorDescriptor(); + } + protected static Scriptable ensureScriptable(Object arg) { if (!(arg instanceof Scriptable)) throw ScriptRuntime.typeErrorById("msg.arg.not.object", ScriptRuntime.typeof(arg)); @@ -3085,7 +3205,7 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE } } - protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { + protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) { Slot slot = querySlot(cx, id); if (slot == null) return null; return slot.getPropertyDescriptor(cx, this); diff --git a/rhino/src/main/java/org/mozilla/javascript/Slot.java b/rhino/src/main/java/org/mozilla/javascript/Slot.java index a065b96123..f0c89631c3 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Slot.java +++ b/rhino/src/main/java/org/mozilla/javascript/Slot.java @@ -94,8 +94,8 @@ void setAttributes(int value) { attributes = (short) value; } - ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { - return ScriptableObject.buildDataDescriptor(scope, value, attributes); + ScriptableObject.DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) { + return ScriptableObject.buildDataDescriptor(value, attributes); } protected void throwNoSetterException(Scriptable start, Object newValue) { diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java index dfeae01b66..9afc73fd8c 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java @@ -143,7 +143,7 @@ public Object[] getIds() { @Override protected boolean defineOwnProperty( - Context cx, Object id, ScriptableObject desc, boolean checkValid) { + Context cx, Object id, DescriptorInfo desc, boolean checkValid) { if (id instanceof CharSequence) { String name = id.toString(); Optional num = ScriptRuntime.canonicalNumericIndexString(name); @@ -153,21 +153,20 @@ protected boolean defineOwnProperty( return false; } - if (Boolean.FALSE.equals(getProperty(desc, "configurable"))) { + if (desc.isConfigurable(false)) { return false; } - if (Boolean.FALSE.equals(getProperty(desc, "enumerable"))) { + if (desc.isEnumerable(false)) { return false; } - if (isAccessorDescriptor(desc)) { + if (desc.isAccessorDescriptor()) { return false; } - if (Boolean.FALSE.equals(getProperty(desc, "writable"))) { + if (desc.isWritable(false)) { return false; } - Object value = getProperty(desc, "value"); - if (value != NOT_FOUND) { - js_set(idx, value); + if (desc.hasValue()) { + js_set(idx, desc.value); } return true; } diff --git a/tests/testsrc/doctests/object.defineproperty.doctest b/tests/testsrc/doctests/object.defineproperty.doctest index 99ca62d33c..133ff0990e 100644 --- a/tests/testsrc/doctests/object.defineproperty.doctest +++ b/tests/testsrc/doctests/object.defineproperty.doctest @@ -130,7 +130,7 @@ js> var obj = define(obj, 'a', {get : function() { return 4 }}); js> obj.a 4 js> describe(obj, 'a').toSource() -({enumerable:false, configurable:true, get:function() { return 4 }}) +({get:function() { return 4 }, enumerable:false, configurable:true}) js> // can change from accessor property to data property when configurable is true js> var obj = define({}, 'a', {get : function() { return 2 }, configurable:true}); js> var obj = define(obj, 'a', {value : 5}); diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index cba22a3615..e573617d77 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -2023,7 +2023,7 @@ built-ins/Promise 383/639 (59.94%) resolve-thenable-deferred.js {unsupported: [async]} resolve-thenable-immed.js {unsupported: [async]} -built-ins/Proxy 68/311 (21.86%) +built-ins/Proxy 66/311 (21.22%) construct/arguments-realm.js construct/call-parameters.js construct/call-parameters-new-target.js @@ -2053,7 +2053,6 @@ built-ins/Proxy 68/311 (21.86%) getOwnPropertyDescriptor/resultdesc-is-not-configurable-targetdesc-is-configurable.js getOwnPropertyDescriptor/resultdesc-is-not-configurable-targetdesc-is-undefined.js getOwnPropertyDescriptor/trap-is-null-target-is-proxy.js - get/accessor-get-is-undefined-throws.js get/trap-is-undefined-receiver.js has/call-in-prototype.js has/call-in-prototype-index.js @@ -2082,7 +2081,6 @@ built-ins/Proxy 68/311 (21.86%) set/call-parameters-prototype.js set/call-parameters-prototype-dunder-proto.js set/call-parameters-prototype-index.js - set/target-property-is-accessor-not-configurable-set-is-undefined.js set/trap-is-missing-receiver-multiple-calls.js set/trap-is-missing-receiver-multiple-calls-index.js set/trap-is-missing-target-is-proxy.js