summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/Iterator.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/Iterator.js')
-rw-r--r--js/src/builtin/Iterator.js127
1 files changed, 127 insertions, 0 deletions
diff --git a/js/src/builtin/Iterator.js b/js/src/builtin/Iterator.js
new file mode 100644
index 000000000..735eec7a0
--- /dev/null
+++ b/js/src/builtin/Iterator.js
@@ -0,0 +1,127 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function IteratorIdentity() {
+ return this;
+}
+
+var LegacyIteratorWrapperMap = new std_WeakMap();
+
+function LegacyIteratorNext(arg) {
+ var iter = callFunction(std_WeakMap_get, LegacyIteratorWrapperMap, this);
+ try {
+ return { value: callContentFunction(iter.next, iter, arg), done: false };
+ } catch (e) {
+ if (e instanceof std_StopIteration)
+ return { value: undefined, done: true };
+ throw e;
+ }
+}
+
+function LegacyIteratorThrow(exn) {
+ var iter = callFunction(std_WeakMap_get, LegacyIteratorWrapperMap, this);
+ try {
+ return { value: callContentFunction(iter.throw, iter, exn), done: false };
+ } catch (e) {
+ if (e instanceof std_StopIteration)
+ return { value: undefined, done: true };
+ throw e;
+ }
+}
+
+function LegacyIterator(iter) {
+ callFunction(std_WeakMap_set, LegacyIteratorWrapperMap, this, iter);
+}
+
+function LegacyGeneratorIterator(iter) {
+ callFunction(std_WeakMap_set, LegacyIteratorWrapperMap, this, iter);
+}
+
+var LegacyIteratorsInitialized = std_Object_create(null);
+
+function InitLegacyIterators() {
+ var props = std_Object_create(null);
+
+ props.next = std_Object_create(null);
+ props.next.value = LegacyIteratorNext;
+ props.next.enumerable = false;
+ props.next.configurable = true;
+ props.next.writable = true;
+
+ props[std_iterator] = std_Object_create(null);
+ props[std_iterator].value = IteratorIdentity;
+ props[std_iterator].enumerable = false;
+ props[std_iterator].configurable = true;
+ props[std_iterator].writable = true;
+
+ var LegacyIteratorProto = std_Object_create(GetIteratorPrototype(), props);
+ MakeConstructible(LegacyIterator, LegacyIteratorProto);
+
+ props.throw = std_Object_create(null);
+ props.throw.value = LegacyIteratorThrow;
+ props.throw.enumerable = false;
+ props.throw.configurable = true;
+ props.throw.writable = true;
+
+ var LegacyGeneratorIteratorProto = std_Object_create(GetIteratorPrototype(), props);
+ MakeConstructible(LegacyGeneratorIterator, LegacyGeneratorIteratorProto);
+
+ LegacyIteratorsInitialized.initialized = true;
+}
+
+function NewLegacyIterator(iter, wrapper) {
+ if (!LegacyIteratorsInitialized.initialized)
+ InitLegacyIterators();
+
+ return new wrapper(iter);
+}
+
+function LegacyIteratorShim() {
+ return NewLegacyIterator(ToObject(this), LegacyIterator);
+}
+
+function LegacyGeneratorIteratorShim() {
+ return NewLegacyIterator(ToObject(this), LegacyGeneratorIterator);
+}
+
+// 7.4.8 CreateListIterator()
+function CreateListIterator(array) {
+ let iterator = NewListIterator();
+ UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_TARGET, array);
+ UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, 0);
+
+ // 7.4.8.1 ListIterator next()
+ // The spec requires that we use a new next function per iterator object.
+ let next = function() {
+ if (!IsObject(this) || !IsListIterator(this))
+ return callFunction(CallListIteratorMethodIfWrapped, this, "ListIteratorNext");
+
+ if (ActiveFunction() !== UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_METHOD))
+ ThrowTypeError(JSMSG_INCOMPATIBLE_METHOD, "next", "method", ToString(this));
+
+ let array = UnsafeGetObjectFromReservedSlot(this, ITERATOR_SLOT_TARGET);
+ let index = UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX);
+
+ if (index >= ToLength(array.length)) {
+ UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, 1/0);
+ return { value: undefined, done: true };
+ }
+
+ UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + 1);
+ return { value: array[index], done: false };
+ };
+
+ UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_METHOD, next);
+ iterator.next = next;
+
+ iterator[std_iterator] = ListIteratorIdentity;
+ return iterator;
+}
+
+function ListIteratorIdentity() {
+ if (!IsObject(this) || !IsListIterator(this))
+ return callFunction(CallListIteratorMethodIfWrapped, this, "ListIteratorIdentity");
+
+ return this;
+}