Fix "StopIteration is not defined" on V8
ReferenceError: StopIteration is not defined
SyntaxError: Unexpected number (legacy `yield` in a plain function)
Why it happens
Rhino supported JavaScript 1.7 iterators: an __iterator__ method, the global Iterator() helper, and ending iteration with throw StopIteration. Old-style generators used yield inside a normal function. None of these exist in standard JavaScript.
The fix
// Rhino
myList.__iterator__ = function () {
var i = 0, a = this.items;
return { next: function () { if (i >= a.length) throw StopIteration; return a[i++]; } };
};
for (var x in myList) Logger.log(x);
// V8
myList[Symbol.iterator] = function* () {
for (var i = 0; i < this.items.length; i++) yield this.items[i];
};
for (var x of myList) Logger.log(x);
Hand-written iterators return { value, done } instead of throwing:
function rangeIterator(n) {
var i = 0;
return { next: function () { return i < n ? { value: i++, done: false } : { value: undefined, done: true }; } };
}
Also Rhino-only
obj.__count__ → Object.keys(obj).length. __parent__ has no equivalent. __noSuchMethod__ → a Proxy with a get trap.
How V8Shift handles it
All iterator-protocol uses, legacy generators and __count__/__parent__/__noSuchMethod__ are flagged as errors with file and line.