Skip to content

Commit 2e51979

Browse files
committed
Move from ScriptableObjects to DescriptorInfo for descriptors.
1 parent d90c055 commit 2e51979

18 files changed

+310
-312
lines changed

rhino/src/main/java/org/mozilla/javascript/AbstractEcmaObjectOperations.java

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.Map;
88
import java.util.Objects;
99
import java.util.function.Predicate;
10+
import org.mozilla.javascript.ScriptableObject.DescriptorInfo;
1011

1112
/**
1213
* Abstract Object Operations as defined by EcmaScript
@@ -83,12 +84,12 @@ static boolean testIntegrityLevel(Context cx, Object o, INTEGRITY_LEVEL level) {
8384
ids = obj.getIds(map, true, true);
8485
}
8586
for (Object name : ids) {
86-
ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, name);
87-
if (Boolean.TRUE.equals(desc.get("configurable"))) return false;
87+
DescriptorInfo desc = obj.getOwnPropertyDescriptor(cx, name);
88+
if (Boolean.TRUE.equals(desc.configurable)) return false;
8889

8990
if (level == INTEGRITY_LEVEL.FROZEN
9091
&& ScriptableObject.isDataDescriptor(desc)
91-
&& Boolean.TRUE.equals(desc.get("writable"))) return false;
92+
&& Boolean.TRUE.equals(desc.writable)) return false;
9293
}
9394

9495
return true;
@@ -150,21 +151,20 @@ static boolean setIntegrityLevel(Context cx, Object o, INTEGRITY_LEVEL level) {
150151
ids = obj.getIds(map, true, true);
151152
}
152153
for (Object key : ids) {
153-
ScriptableObject desc = obj.getOwnPropertyDescriptor(cx, key);
154+
DescriptorInfo desc = obj.getOwnPropertyDescriptor(cx, key);
154155

155156
if (level == INTEGRITY_LEVEL.SEALED) {
156-
if (Boolean.TRUE.equals(desc.get("configurable"))) {
157-
desc.put("configurable", desc, Boolean.FALSE);
157+
if (Boolean.TRUE.equals(desc.configurable)) {
158+
desc.configurable = false;
158159

159160
obj.defineOwnProperty(cx, key, desc, false);
160161
}
161162
} else {
162-
if (ScriptableObject.isDataDescriptor(desc)
163-
&& Boolean.TRUE.equals(desc.get("writable"))) {
164-
desc.put("writable", desc, Boolean.FALSE);
163+
if (ScriptableObject.isDataDescriptor(desc) && Boolean.TRUE.equals(desc.writable)) {
164+
desc.writable = false;
165165
}
166-
if (Boolean.TRUE.equals(desc.get("configurable"))) {
167-
desc.put("configurable", desc, Boolean.FALSE);
166+
if (Boolean.TRUE.equals(desc.configurable)) {
167+
desc.configurable = false;
168168
}
169169
obj.defineOwnProperty(cx, key, desc, false);
170170
}
@@ -402,7 +402,7 @@ public static long lengthOfArrayLike(Context cx, Scriptable o) {
402402
* IsCompatiblePropertyDescriptor (Extensible, Desc, Current)</a>
403403
*/
404404
static boolean isCompatiblePropertyDescriptor(
405-
Context cx, boolean extensible, ScriptableObject desc, ScriptableObject current) {
405+
Context cx, boolean extensible, DescriptorInfo desc, DescriptorInfo current) {
406406
return validateAndApplyPropertyDescriptor(
407407
cx,
408408
Undefined.SCRIPTABLE_UNDEFINED,
@@ -424,8 +424,8 @@ static boolean validateAndApplyPropertyDescriptor(
424424
Scriptable o,
425425
Scriptable p,
426426
boolean extensible,
427-
ScriptableObject desc,
428-
ScriptableObject current) {
427+
DescriptorInfo desc,
428+
DescriptorInfo current) {
429429
if (Undefined.isUndefined(current)) {
430430
if (!extensible) {
431431
return false;
@@ -445,18 +445,22 @@ static boolean validateAndApplyPropertyDescriptor(
445445
return true;
446446
}
447447

448-
if (desc.getIds().length == 0) {
448+
if (desc.enumerable == ScriptableObject.NOT_FOUND
449+
&& desc.configurable == ScriptableObject.NOT_FOUND
450+
&& desc.writable == ScriptableObject.NOT_FOUND
451+
&& desc.getter == ScriptableObject.NOT_FOUND
452+
&& desc.setter == ScriptableObject.NOT_FOUND
453+
&& desc.value == ScriptableObject.NOT_FOUND) {
449454
return true;
450455
}
451456

452-
if (Boolean.FALSE.equals(current.get("configurable"))) {
453-
if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "configurable"))
454-
&& Boolean.TRUE.equals(desc.get("configurable"))) {
457+
if (Boolean.FALSE.equals(current.configurable)) {
458+
if (Boolean.TRUE.equals(desc.configurable)) {
455459
return false;
456460
}
457461

458-
if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "enumerable"))
459-
&& !Objects.equals(desc.get("enumerable"), current.get("enumerable"))) {
462+
if (desc.enumerable != ScriptableObject.NOT_FOUND
463+
&& !Objects.equals(desc.enumerable, current.enumerable)) {
460464
return false;
461465
}
462466
}
@@ -466,11 +470,11 @@ static boolean validateAndApplyPropertyDescriptor(
466470
}
467471

468472
if (ScriptableObject.isDataDescriptor(current) != ScriptableObject.isDataDescriptor(desc)) {
469-
if (Boolean.FALSE.equals(current.get("configurable"))) {
473+
if (Boolean.FALSE.equals(current.configurable)) {
470474
return false;
471475
}
472476
if (ScriptableObject.isDataDescriptor(current)) {
473-
if (Boolean.FALSE.equals(current.get("configurable"))) {
477+
if (Boolean.FALSE.equals(current.configurable)) {
474478
// i. i. If O is not undefined, convert the property named P of object O from a
475479
// data property to an accessor property. Preserve the existing values of the
476480
// converted property's [[Configurable]] and [[Enumerable]] attributes and set
@@ -484,26 +488,25 @@ static boolean validateAndApplyPropertyDescriptor(
484488
}
485489
} else if (ScriptableObject.isDataDescriptor(current)
486490
&& ScriptableObject.isDataDescriptor(desc)) {
487-
if (Boolean.FALSE.equals(current.get("configurable"))
488-
&& Boolean.FALSE.equals(current.get("writable"))) {
489-
if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "writable"))
490-
&& Boolean.TRUE.equals(desc.get("writable"))) {
491+
if (Boolean.FALSE.equals(current.configurable)
492+
&& Boolean.FALSE.equals(current.writable)) {
493+
if (Boolean.TRUE.equals(desc.writable)) {
491494
return false;
492495
}
493-
if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "value"))
494-
&& !Objects.equals(desc.get("value"), current.get("value"))) {
496+
if (desc.value != ScriptableObject.NOT_FOUND
497+
&& !Objects.equals(desc.value, current.value)) {
495498
return false;
496499
}
497500
return true;
498501
}
499502
} else {
500-
if (Boolean.FALSE.equals(current.get("configurable"))) {
501-
if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "set"))
502-
&& !Objects.equals(desc.get("set"), current.get("set"))) {
503+
if (Boolean.FALSE.equals(current.configurable)) {
504+
if (desc.setter != ScriptableObject.NOT_FOUND
505+
&& !Objects.equals(desc.setter, current.setter)) {
503506
return false;
504507
}
505-
if (Boolean.TRUE.equals(ScriptableObject.hasProperty(desc, "get"))
506-
&& !Objects.equals(desc.get("get"), current.get("get"))) {
508+
if (desc.getter != ScriptableObject.NOT_FOUND
509+
&& !Objects.equals(desc.getter, current.getter)) {
507510
return false;
508511
}
509512
return true;

rhino/src/main/java/org/mozilla/javascript/AccessorSlot.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.mozilla.javascript;
22

3+
import org.mozilla.javascript.ScriptableObject.DescriptorInfo;
4+
35
/**
46
* This is a specialization of Slot to store various types of values that are retrieved dynamically
57
* using Java and JavaScript functions. Unlike LambdaSlot, the fact that these values are accessed
@@ -43,45 +45,40 @@ boolean isSetterSlot() {
4345
}
4446

4547
@Override
46-
ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) {
48+
DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) {
4749
// It sounds logical that this would be the same as the logic for a normal Slot,
4850
// but the spec is super pedantic about things like the order of properties here,
4951
// so we need special support here.
5052

51-
ScriptableObject desc = (ScriptableObject) cx.newObject(scope);
5253
int attr = getAttributes();
53-
54+
DescriptorInfo desc;
5455
boolean es6 = cx.getLanguageVersion() >= Context.VERSION_ES6;
5556
if (es6) {
57+
desc = new DescriptorInfo(ScriptableObject.NOT_FOUND, attr, false);
5658
if (getter == null && setter == null) {
57-
desc.defineProperty(
58-
"writable",
59-
(attr & ScriptableObject.READONLY) == 0,
60-
ScriptableObject.EMPTY);
59+
desc.writable = (attr & ScriptableObject.READONLY) == 0;
6160
}
6261
} else {
63-
desc.setCommonDescriptorProperties(attr, getter == null && setter == null);
62+
desc =
63+
new DescriptorInfo(
64+
ScriptableObject.NOT_FOUND, attr, getter == null && setter == null);
6465
}
6566

6667
String fName = name == null ? "f" : name.toString();
6768
if (getter != null) {
6869
Function f = getter.asGetterFunction(fName, scope);
69-
desc.defineProperty("get", f == null ? Undefined.instance : f, ScriptableObject.EMPTY);
70+
desc.getter = f == null ? Undefined.instance : f;
7071
}
7172
if (setter != null) {
7273
Function f = setter.asSetterFunction(fName, scope);
73-
desc.defineProperty("set", f == null ? Undefined.instance : f, ScriptableObject.EMPTY);
74+
desc.setter = f == null ? Undefined.instance : f;
7475
} else if (es6) {
75-
desc.defineProperty("set", Undefined.instance, ScriptableObject.EMPTY);
76+
desc.setter = Undefined.instance;
7677
}
7778

7879
if (es6) {
79-
desc.defineProperty(
80-
"enumerable", (attr & ScriptableObject.DONTENUM) == 0, ScriptableObject.EMPTY);
81-
desc.defineProperty(
82-
"configurable",
83-
(attr & ScriptableObject.PERMANENT) == 0,
84-
ScriptableObject.EMPTY);
80+
desc.enumerable = (attr & ScriptableObject.DONTENUM) == 0;
81+
desc.configurable = (attr & ScriptableObject.PERMANENT) == 0;
8582
}
8683

8784
return desc;

rhino/src/main/java/org/mozilla/javascript/Arguments.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ Object[] getIds(CompoundOperationMap map, boolean getNonEnumerable, boolean getS
370370
}
371371

372372
@Override
373-
protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) {
373+
protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) {
374374
if (ScriptRuntime.isSymbol(id) || id instanceof Scriptable) {
375375
return super.getOwnPropertyDescriptor(cx, id);
376376
}
@@ -388,18 +388,16 @@ protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) {
388388
value = getFromActivation(index);
389389
}
390390
if (super.has(index, this)) { // the descriptor has been redefined
391-
ScriptableObject desc = super.getOwnPropertyDescriptor(cx, id);
392-
desc.put("value", desc, value);
391+
DescriptorInfo desc = super.getOwnPropertyDescriptor(cx, id);
392+
desc.value = value;
393393
return desc;
394394
}
395-
Scriptable scope = getParentScope();
396-
if (scope == null) scope = this;
397-
return buildDataDescriptor(scope, value, EMPTY);
395+
return buildDataDescriptor(value, EMPTY);
398396
}
399397

400398
@Override
401399
protected boolean defineOwnProperty(
402-
Context cx, Object id, ScriptableObject desc, boolean checkValid) {
400+
Context cx, Object id, DescriptorInfo desc, boolean checkValid) {
403401
super.defineOwnProperty(cx, id, desc, checkValid);
404402
if (ScriptRuntime.isSymbol(id)) {
405403
return true;
@@ -417,12 +415,12 @@ protected boolean defineOwnProperty(
417415
return true;
418416
}
419417

420-
Object newValue = getProperty(desc, "value");
418+
Object newValue = desc.value;
421419
if (newValue == NOT_FOUND) return true;
422420

423421
replaceArg(index, newValue);
424422

425-
if (isFalse(getProperty(desc, "writable"))) {
423+
if (isFalse(desc.writable)) {
426424
removeArg(index);
427425
}
428426
return true;

rhino/src/main/java/org/mozilla/javascript/BoundFunction.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,7 @@ public BoundFunction(
3838
ScriptRuntime.setFunctionProtoAndParent(this, cx, scope, false);
3939

4040
Function thrower = ScriptRuntime.typeErrorThrower(cx);
41-
NativeObject throwing = new NativeObject();
42-
ScriptRuntime.setBuiltinProtoAndParent(throwing, scope, TopLevel.Builtins.Object);
43-
throwing.put("get", throwing, thrower);
44-
throwing.put("set", throwing, thrower);
45-
throwing.put("enumerable", throwing, Boolean.FALSE);
46-
throwing.put("configurable", throwing, Boolean.FALSE);
47-
throwing.preventExtensions();
41+
var throwing = new DescriptorInfo(false, NOT_FOUND, false, thrower, thrower, NOT_FOUND);
4842

4943
this.defineOwnProperty(cx, "caller", throwing, false);
5044
this.defineOwnProperty(cx, "arguments", throwing, false);

rhino/src/main/java/org/mozilla/javascript/BuiltInSlot.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,8 @@ void setAttributes(int value) {
166166

167167
@Override
168168
@SuppressWarnings("unchecked")
169-
ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) {
170-
return ScriptableObject.buildDataDescriptor(
171-
scope, getValue((T) this.value), getAttributes());
169+
DescriptorInfo getPropertyDescriptor(Context cx, Scriptable scope) {
170+
return ScriptableObject.buildDataDescriptor(getValue((T) this.value), getAttributes());
172171
}
173172

174173
@SuppressWarnings("unchecked")

rhino/src/main/java/org/mozilla/javascript/IdScriptableObject.java

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ private IdFunctionObject newIdFunction(
852852

853853
@Override
854854
protected boolean defineOwnProperty(
855-
Context cx, Object key, ScriptableObject desc, boolean checkValid) {
855+
Context cx, Object key, DescriptorInfo desc, boolean checkValid) {
856856
if (key instanceof CharSequence) {
857857
String name = key.toString();
858858
int info = findInstanceIdInfo(name);
@@ -865,7 +865,7 @@ protected boolean defineOwnProperty(
865865
var slot = queryOrFakeSlot(cx, key);
866866
checkPropertyChangeForSlot(name, slot, desc);
867867
int attr = (info >>> 16);
868-
Object value = getProperty(desc, "value");
868+
Object value = desc.value;
869869
if (value != NOT_FOUND && ((attr & READONLY) == 0 || (attr & PERMANENT) == 0)) {
870870
Object currentValue = getInstanceIdValue(id);
871871
if (!sameValue(value, currentValue)) {
@@ -874,10 +874,7 @@ protected boolean defineOwnProperty(
874874
}
875875
attr =
876876
applyDescriptorToAttributeBitset(
877-
attr,
878-
getProperty(desc, "enumerable"),
879-
getProperty(desc, "writable"),
880-
getProperty(desc, "configurable"));
877+
attr, desc.enumerable, desc.writable, desc.configurable);
881878
setAttributes(name, attr);
882879
return true;
883880
}
@@ -892,7 +889,7 @@ protected boolean defineOwnProperty(
892889
var slot = queryOrFakeSlot(cx, key);
893890
checkPropertyChangeForSlot(name, slot, desc);
894891
int attr = prototypeValues.getAttributes(id);
895-
Object value = getProperty(desc, "value");
892+
Object value = desc.value;
896893
if (value != NOT_FOUND && (attr & READONLY) == 0) {
897894
Object currentValue = prototypeValues.get(id);
898895
if (!sameValue(value, currentValue)) {
@@ -902,10 +899,7 @@ protected boolean defineOwnProperty(
902899
prototypeValues.setAttributes(
903900
id,
904901
applyDescriptorToAttributeBitset(
905-
attr,
906-
getProperty(desc, "enumerable"),
907-
getProperty(desc, "writable"),
908-
getProperty(desc, "configurable")));
902+
attr, desc.enumerable, desc.writable, desc.configurable));
909903

910904
// Handle the regular slot that was created if this property was previously
911905
// replaced
@@ -923,8 +917,8 @@ protected boolean defineOwnProperty(
923917
}
924918

925919
@Override
926-
protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) {
927-
ScriptableObject desc = super.getOwnPropertyDescriptor(cx, id);
920+
protected DescriptorInfo getOwnPropertyDescriptor(Context cx, Object id) {
921+
var desc = super.getOwnPropertyDescriptor(cx, id);
928922
if (desc == null) {
929923
if (id instanceof String) {
930924
return getBuiltInDataDescriptor((String) id);
@@ -959,14 +953,9 @@ private Slot queryOrFakeSlot(Context cx, Object id) {
959953
return slot;
960954
}
961955

962-
private ScriptableObject getBuiltInDataDescriptor(String name) {
963-
Scriptable scope = getParentScope();
964-
if (scope == null) {
965-
scope = this;
966-
}
967-
956+
private DescriptorInfo getBuiltInDataDescriptor(String name) {
968957
var slot = getBuiltInSlot(name);
969-
return slot == null ? null : buildDataDescriptor(scope, slot.value, slot.getAttributes());
958+
return slot == null ? null : new DescriptorInfo(slot.value, slot.getAttributes(), true);
970959
}
971960

972961
private Slot getBuiltInSlot(String name) {
@@ -992,14 +981,9 @@ private Slot getBuiltInSlot(String name) {
992981
return null;
993982
}
994983

995-
private ScriptableObject getBuiltInDataDescriptor(Symbol key) {
996-
Scriptable scope = getParentScope();
997-
if (scope == null) {
998-
scope = this;
999-
}
1000-
984+
private DescriptorInfo getBuiltInDataDescriptor(Symbol key) {
1001985
var slot = getBuiltInSlot(key);
1002-
return slot == null ? null : buildDataDescriptor(scope, slot.value, slot.getAttributes());
986+
return slot == null ? null : new DescriptorInfo(slot.value, slot.getAttributes(), true);
1003987
}
1004988

1005989
private Slot getBuiltInSlot(Symbol key) {

0 commit comments

Comments
 (0)