Skip to content

Commit ad0dd02

Browse files
authored
Migrated NativeIterator away from IdScriptableObject
* Migrated `NativeIterator` away from `IdScriptableObject` * Sorted fields * Removed unnecessary unboxing --------- Co-authored-by: andrea.bergia <andrea.bergia@servicenow.com>
1 parent b3c7a63 commit ad0dd02

1 file changed

Lines changed: 75 additions & 108 deletions

File tree

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

Lines changed: 75 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,35 @@
1414
*
1515
* @author Norris Boyd
1616
*/
17-
public final class NativeIterator extends IdScriptableObject {
17+
public final class NativeIterator extends ScriptableObject {
1818
private static final long serialVersionUID = -4136968203581667681L;
1919
private static final Object ITERATOR_TAG = "Iterator";
20+
private static final String CLASS_NAME = "Iterator";
21+
22+
private Object objectIterator;
2023

2124
static void init(Context cx, ScriptableObject scope, boolean sealed) {
22-
// Iterator
23-
NativeIterator iterator = new NativeIterator();
24-
iterator.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
25+
LambdaConstructor constructor =
26+
new LambdaConstructor(
27+
scope,
28+
CLASS_NAME,
29+
2,
30+
NativeIterator::jsConstructorCall,
31+
NativeIterator::jsConstructor);
32+
constructor.setPrototypePropertyAttributes(PERMANENT | READONLY | DONTENUM);
33+
34+
NativeIterator proto = new NativeIterator();
35+
constructor.setPrototypeScriptable(proto);
36+
37+
constructor.definePrototypeMethod(scope, "next", 0, NativeIterator::js_next);
38+
constructor.definePrototypeMethod(
39+
scope, ITERATOR_PROPERTY_NAME, 1, NativeIterator::js_iteratorMethod);
40+
41+
ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, ScriptableObject.DONTENUM);
42+
if (sealed) {
43+
constructor.sealObject();
44+
((ScriptableObject) constructor.getPrototypeProperty()).sealObject();
45+
}
2546

2647
// Generator
2748
if (cx.getLanguageVersion() >= Context.VERSION_ES6) {
@@ -98,95 +119,59 @@ public boolean hasInstance(Scriptable instance) {
98119

99120
@Override
100121
public String getClassName() {
101-
return "Iterator";
122+
return CLASS_NAME;
102123
}
103124

104-
@Override
105-
protected void initPrototypeId(int id) {
106-
String s;
107-
int arity;
108-
switch (id) {
109-
case Id_constructor:
110-
arity = 2;
111-
s = "constructor";
112-
break;
113-
case Id_next:
114-
arity = 0;
115-
s = "next";
116-
break;
117-
case Id___iterator__:
118-
arity = 1;
119-
s = ITERATOR_PROPERTY_NAME;
120-
break;
121-
default:
122-
throw new IllegalArgumentException(String.valueOf(id));
123-
}
124-
initPrototypeMethod(ITERATOR_TAG, id, s, arity);
125-
}
125+
private static Object jsConstructorCall(
126+
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
127+
Scriptable target = requireIteratorTarget(cx, scope, args);
128+
boolean keyOnly = isKeyOnly(args);
126129

127-
@Override
128-
public Object execIdCall(
129-
IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
130-
if (!f.hasTag(ITERATOR_TAG)) {
131-
return super.execIdCall(f, cx, scope, thisObj, args);
130+
Iterator<?> iterator = getJavaIterator(target);
131+
if (iterator != null) {
132+
Scriptable topScope = ScriptableObject.getTopLevelScope(scope);
133+
return cx.getWrapFactory()
134+
.wrap(
135+
cx,
136+
topScope,
137+
new WrappedJavaIterator(iterator, topScope),
138+
WrappedJavaIterator.class);
132139
}
133-
int id = f.methodId();
134140

135-
if (id == Id_constructor) {
136-
return jsConstructor(cx, scope, thisObj, args);
141+
Scriptable jsIterator = ScriptRuntime.toIterator(cx, target, keyOnly);
142+
if (jsIterator != null) {
143+
return jsIterator;
137144
}
138145

139-
NativeIterator iterator = ensureType(thisObj, NativeIterator.class, f);
140-
141-
switch (id) {
142-
case Id_next:
143-
return iterator.next(cx, scope);
144-
145-
case Id___iterator__:
146-
/// XXX: what about argument? SpiderMonkey apparently ignores it
147-
return thisObj;
146+
return createNativeIterator(cx, scope, target, keyOnly);
147+
}
148148

149-
default:
150-
throw new IllegalArgumentException(String.valueOf(id));
151-
}
149+
private static Scriptable jsConstructor(Context cx, Scriptable scope, Object[] args) {
150+
Scriptable target = requireIteratorTarget(cx, scope, args);
151+
boolean keyOnly = isKeyOnly(args);
152+
return createNativeIterator(cx, scope, target, keyOnly);
152153
}
153154

154-
/* The JavaScript constructor */
155-
private static Object jsConstructor(
156-
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
155+
private static Scriptable requireIteratorTarget(Context cx, Scriptable scope, Object[] args) {
157156
if (args.length == 0 || args[0] == null || args[0] == Undefined.instance) {
158157
Object argument = args.length == 0 ? Undefined.instance : args[0];
159158
throw ScriptRuntime.typeErrorById(
160159
"msg.no.properties", ScriptRuntime.toString(argument));
161160
}
162-
Scriptable obj = ScriptRuntime.toObject(cx, scope, args[0]);
163-
boolean keyOnly = args.length > 1 && ScriptRuntime.toBoolean(args[1]);
164-
if (thisObj != null) {
165-
// Called as a function. Convert to iterator if possible.
166-
167-
// For objects that implement java.lang.Iterable or
168-
// java.util.Iterator, have JavaScript Iterator call the underlying
169-
// iteration methods
170-
Iterator<?> iterator = getJavaIterator(obj);
171-
if (iterator != null) {
172-
scope = ScriptableObject.getTopLevelScope(scope);
173-
return cx.getWrapFactory()
174-
.wrap(
175-
cx,
176-
scope,
177-
new WrappedJavaIterator(iterator, scope),
178-
WrappedJavaIterator.class);
179-
}
161+
return ScriptRuntime.toObject(cx, scope, args[0]);
162+
}
180163

181-
// Otherwise, just call the runtime routine
182-
Scriptable jsIterator = ScriptRuntime.toIterator(cx, obj, keyOnly);
183-
if (jsIterator != null) {
184-
return jsIterator;
185-
}
186-
}
164+
private static boolean isKeyOnly(Object[] args) {
165+
return args.length > 1 && ScriptRuntime.toBoolean(args[1]);
166+
}
167+
168+
private static Object js_next(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
169+
NativeIterator iterator = realThis(thisObj);
170+
return iterator.next(cx, scope);
171+
}
187172

188-
// Otherwise, just set up to iterate over the properties of the object.
189-
// Do not call __iterator__ method.
173+
private static NativeIterator createNativeIterator(
174+
Context cx, Scriptable scope, Scriptable obj, boolean keyOnly) {
190175
Object objectIterator =
191176
ScriptRuntime.enumInit(
192177
obj,
@@ -197,14 +182,23 @@ private static Object jsConstructor(
197182
: ScriptRuntime.ENUMERATE_ARRAY_NO_ITERATOR);
198183
ScriptRuntime.setEnumNumbers(objectIterator, true);
199184
NativeIterator result = new NativeIterator(objectIterator);
200-
result.setPrototype(ScriptableObject.getClassPrototype(scope, result.getClassName()));
185+
result.setPrototype(ScriptableObject.getClassPrototype(scope, CLASS_NAME));
201186
result.setParentScope(scope);
202187
return result;
203188
}
204189

190+
private static Object js_iteratorMethod(
191+
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
192+
return realThis(thisObj);
193+
}
194+
195+
private static NativeIterator realThis(Scriptable thisObj) {
196+
return LambdaConstructor.convertThisObject(thisObj, NativeIterator.class);
197+
}
198+
205199
private Object next(Context cx, Scriptable scope) {
206200
Boolean b = ScriptRuntime.enumNext(this.objectIterator, cx);
207-
if (!b.booleanValue()) {
201+
if (!b) {
208202
// Out of values. Throw StopIteration.
209203
throw new JavaScriptException(NativeIterator.getStopIterationObject(scope), null, 0);
210204
}
@@ -227,6 +221,9 @@ private static Iterator<?> getJavaIterator(Object obj) {
227221
}
228222

229223
public static class WrappedJavaIterator {
224+
private final Iterator<?> iterator;
225+
private final Scriptable scope;
226+
230227
WrappedJavaIterator(Iterator<?> iterator, Scriptable scope) {
231228
this.iterator = iterator;
232229
this.scope = scope;
@@ -244,35 +241,5 @@ public Object next() {
244241
public Object __iterator__(boolean b) {
245242
return this;
246243
}
247-
248-
private Iterator<?> iterator;
249-
private Scriptable scope;
250244
}
251-
252-
@Override
253-
protected int findPrototypeId(String s) {
254-
int id;
255-
switch (s) {
256-
case "constructor":
257-
id = Id_constructor;
258-
break;
259-
case "next":
260-
id = Id_next;
261-
break;
262-
case "__iterator__":
263-
id = Id___iterator__;
264-
break;
265-
default:
266-
id = 0;
267-
break;
268-
}
269-
return id;
270-
}
271-
272-
private static final int Id_constructor = 1,
273-
Id_next = 2,
274-
Id___iterator__ = 3,
275-
MAX_PROTOTYPE_ID = 3;
276-
277-
private Object objectIterator;
278245
}

0 commit comments

Comments
 (0)