|
6 | 6 |
|
7 | 7 | import java.io.Closeable; |
8 | 8 | import java.util.Iterator; |
9 | | -import java.util.List; |
10 | 9 | import java.util.NoSuchElementException; |
11 | 10 |
|
12 | 11 | /** |
@@ -84,37 +83,63 @@ public Itr iterator(Context cx, Scriptable scope) { |
84 | 83 | } |
85 | 84 |
|
86 | 85 | public final class Itr implements Iterator<Object> { |
87 | | - private final List<Object> values; |
88 | | - private int index = 0; |
| 86 | + private final Context cx; |
| 87 | + private final Scriptable scope; |
| 88 | + private final Callable nextMethod; |
| 89 | + private Object nextVal; |
| 90 | + private boolean isDone; |
89 | 91 |
|
90 | 92 | private Itr(Context cx, Scriptable scope) { |
91 | | - // Use IteratorOperations to collect all values Context-safely |
92 | | - this.values = IteratorOperations.collectToList(cx, scope, iterator); |
| 93 | + this.cx = cx; |
| 94 | + this.scope = scope; |
| 95 | + |
| 96 | + // Get next method - already validated in constructor |
| 97 | + Object nextProp = ScriptableObject.getProperty(iterator, "next"); |
| 98 | + this.nextMethod = (Callable) nextProp; |
93 | 99 | } |
94 | 100 |
|
95 | 101 | @Override |
96 | 102 | public boolean hasNext() { |
97 | | - return index < values.size(); |
| 103 | + if (isDone) { |
| 104 | + return false; |
| 105 | + } |
| 106 | + |
| 107 | + // Call next() to get the next value - this enables lazy iteration |
| 108 | + Object iterResult = nextMethod.call(cx, scope, iterator, ScriptRuntime.emptyArgs); |
| 109 | + |
| 110 | + if (!(iterResult instanceof Scriptable)) { |
| 111 | + throw ScriptRuntime.typeErrorById("msg.arg.not.object", ScriptRuntime.typeof(iterResult)); |
| 112 | + } |
| 113 | + |
| 114 | + Scriptable result = (Scriptable) iterResult; |
| 115 | + Object done = ScriptableObject.getProperty(result, "done"); |
| 116 | + |
| 117 | + if (ScriptRuntime.toBoolean(done)) { |
| 118 | + isDone = true; |
| 119 | + return false; |
| 120 | + } |
| 121 | + |
| 122 | + nextVal = ScriptableObject.getProperty(result, "value"); |
| 123 | + nextVal = (nextVal == Scriptable.NOT_FOUND) ? Undefined.instance : nextVal; |
| 124 | + return true; |
98 | 125 | } |
99 | 126 |
|
100 | 127 | @Override |
101 | 128 | public Object next() { |
102 | | - if (!hasNext()) { |
| 129 | + if (isDone) { |
103 | 130 | throw new NoSuchElementException(); |
104 | 131 | } |
105 | | - return values.get(index++); |
| 132 | + return nextVal; |
106 | 133 | } |
107 | 134 |
|
108 | 135 | /** Find out if "hasNext" returned done without invoking the function again. */ |
109 | 136 | public boolean isDone() { |
110 | | - return !hasNext(); |
| 137 | + return isDone; |
111 | 138 | } |
112 | 139 |
|
113 | 140 | /** Manually set "done." Used for exception handling in promises. */ |
114 | 141 | public void setDone(boolean done) { |
115 | | - if (done) { |
116 | | - index = values.size(); |
117 | | - } |
| 142 | + this.isDone = done; |
118 | 143 | } |
119 | 144 | } |
120 | 145 | } |
0 commit comments