Bug 1147371 - Convert self-hosted code that need to call IteratorClose to use for-of. (r=arai)
☠☠ backed out by 3db3783de0f2 ☠ ☠
authorShu-yu Guo <shu@rfrn.org>
Thu, 12 Jan 2017 23:51:35 -0800
changeset 374303 314efb239b642cbeb4ea9c8fd22806fe0f2a2ea1
parent 374302 1304f6c59821ebc6776614af64a7801445c631f0
child 374304 7872a2456195318b5fad224f4026a2de32720acc
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1147371
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1147371 - Convert self-hosted code that need to call IteratorClose to use for-of. (r=arai)
js/src/builtin/Array.js
js/src/builtin/Classes.js
js/src/builtin/Map.js
js/src/builtin/Set.js
js/src/builtin/Utilities.js
js/src/builtin/WeakMap.js
js/src/builtin/WeakSet.js
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -804,64 +804,42 @@ function ArrayFrom(items, mapfn=undefine
     // Step 4.
     var usingIterator = GetMethod(items, std_iterator);
 
     // Step 5.
     if (usingIterator !== undefined) {
         // Steps 5.a-c.
         var A = IsConstructor(C) ? new C() : [];
 
-        // Step 5.c.
-        var iterator = GetIterator(items, usingIterator);
-
         // Step 5.d.
         var k = 0;
 
-        // Step 5.e.
-        // These steps cannot be implemented using a for-of loop.
-        // See <https://bugs.ecmascript.org/show_bug.cgi?id=2883>.
-        while (true) {
+        // Step 5.c, 5.e.
+        var iteratorWrapper = { [std_iterator]() { return GetIterator(items, usingIterator); } };
+        for (var nextValue of allowContentIter(iteratorWrapper)) {
             // Step 5.e.i.
             // Disabled for performance reason.  We won't hit this case on
             // normal array, since _DefineDataProperty will throw before it.
             // We could hit this when |A| is a proxy and it ignores
             // |_DefineDataProperty|, but it happens only after too long loop.
             /*
-            if (k >= 0x1fffffffffffff) {
-                IteratorCloseThrow(iterator);
+            if (k >= 0x1fffffffffffff)
                 ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
-            }
             */
 
-            // Step 5.e.iii.
-            var next = callContentFunction(iterator.next, iterator);
-            if (!IsObject(next))
-                ThrowTypeError(JSMSG_NEXT_RETURNED_PRIMITIVE);
-
-            // Step 5.e.iv.
-            if (next.done) {
-                A.length = k;
-                return A;
-            }
+            // Steps 5.e.vi-vii.
+            var mappedValue = mapping ? callContentFunction(mapfn, thisArg, nextValue, k) : nextValue;
 
-            // Steps 5.e.v.
-            var nextValue = next.value;
-
-            // Steps 5.e.vi-vii.
-            try {
-                var mappedValue = mapping ? callContentFunction(mapfn, thisArg, nextValue, k) : nextValue;
+            // Steps 5.e.ii (reordered), 5.e.viii.
+            _DefineDataProperty(A, k++, mappedValue);
+        }
 
-                // Steps 5.e.ii (reordered), 5.e.viii.
-                _DefineDataProperty(A, k++, mappedValue);
-            } catch (e) {
-                // Steps 5.e.vi.2, 5.e.ix.
-                IteratorCloseThrow(iterator);
-                throw e;
-            }
-        }
+        // Step 5.e.iv.
+        A.length = k;
+        return A;
     }
 
     // Step 7.
     assert(usingIterator === undefined, "`items` can't be an Iterable after step 6.g.iv");
 
     // Steps 8-9.
     var arrayLike = ToObject(items);
 
--- a/js/src/builtin/Classes.js
+++ b/js/src/builtin/Classes.js
@@ -1,16 +1,16 @@
 // Give a builtin constructor that we can use as the default. When we give
 // it to our newly made class, we will be sure to set it up with the correct name
 // and .prototype, so that everything works properly.
 
 var DefaultDerivedClassConstructor =
     class extends null {
         constructor(...args) {
-            super(...allowContentSpread(args));
+            super(...allowContentIter(args));
         }
     };
 MakeDefaultConstructor(DefaultDerivedClassConstructor);
 
 var DefaultBaseClassConstructor =
     class {
         constructor() { }
     };
--- a/js/src/builtin/Map.js
+++ b/js/src/builtin/Map.js
@@ -9,54 +9,24 @@ function MapConstructorInit(iterable) {
 
     // Step 6.a.
     var adder = map.set;
 
     // Step 6.b.
     if (!IsCallable(adder))
         ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
 
-    // Step 6.c.
-    var iterFn = iterable[std_iterator];
-    if (!IsCallable(iterFn))
-        ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
-
-    var iter = callContentFunction(iterFn, iterable);
-    if (!IsObject(iter))
-        ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
-
-    // Step 7 (not applicable).
-
-    // Step 8.
-    while (true) {
-        // Step 8.a.
-        var next = callContentFunction(iter.next, iter);
-        if (!IsObject(next))
-            ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
-
-        // Step 8.b.
-        if (next.done)
-            return;
-
-        // Step 8.c.
-        var nextItem = next.value;
-
+    // Steps 6.c-8.
+    for (var nextItem of allowContentIter(iterable)) {
         // Step 8.d.
-        if (!IsObject(nextItem)) {
-            IteratorCloseThrow(iter);
+        if (!IsObject(nextItem))
             ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "Map");
-        }
 
         // Steps 8.e-j.
-        try {
-            callContentFunction(adder, map, nextItem[0], nextItem[1]);
-        } catch (e) {
-            IteratorCloseThrow(iter);
-            throw e;
-        }
+        callContentFunction(adder, map, nextItem[0], nextItem[1]);
     }
 }
 
 /* ES6 20121122 draft 15.14.4.4. */
 function MapForEach(callbackfn, thisArg = undefined) {
     /* Step 1-2. */
     var M = this;
     if (!IsObject(M))
--- a/js/src/builtin/Set.js
+++ b/js/src/builtin/Set.js
@@ -9,49 +9,19 @@ function SetConstructorInit(iterable) {
 
     // Step 6.a.
     var adder = set.add;
 
     // Step 6.b.
     if (!IsCallable(adder))
         ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
 
-    // Step 6.c.
-    var iterFn = iterable[std_iterator];
-    if (!IsCallable(iterFn))
-        ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
-
-    var iter = callContentFunction(iterFn, iterable);
-    if (!IsObject(iter))
-        ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
-
-    // Step 7 (not applicable).
-
-    // Step 8.
-    while (true) {
-        // Step 8.a.
-        var next = callContentFunction(iter.next, iter);
-        if (!IsObject(next))
-            ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
-
-        // Step 8.b.
-        if (next.done)
-            return;
-
-        // Step 8.c.
-        var nextValue = next.value;
-
-        // Steps 8.d-e.
-        try {
-            callContentFunction(adder, set, nextValue);
-        } catch (e) {
-            IteratorCloseThrow(iter);
-            throw e;
-        }
-    }
+    // Steps 6.c-8.
+    for (var nextValue of allowContentIter(iterable))
+        callContentFunction(adder, set, nextValue);
 }
 
 /* ES6 20121122 draft 15.16.4.6. */
 function SetForEach(callbackfn, thisArg = undefined) {
     /* Step 1-2. */
     var S = this;
     if (!IsObject(S))
         ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "Set", "forEach", typeof S);
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -149,39 +149,16 @@ function GetIterator(obj, method) {
     // Step 5.
     if (!IsObject(iterator))
         ThrowTypeError(JSMSG_NOT_ITERATOR, ToString(iterator));
 
     // Step 6.
     return iterator;
 }
 
-// ES2017 draft rev 7.4.6.
-// When completion.[[Type]] is throw.
-function IteratorCloseThrow(iter) {
-    // Steps 1-2 (implicit)
-
-    // Step 3.
-    var returnMethod = GetMethod(iter, "return");
-
-    // Step 4 (done in caller).
-    if (returnMethod === undefined)
-        return;
-
-    try {
-        // Step 5.
-        callContentFunction(returnMethod, iter);
-    } catch (e) {
-    }
-
-    // Step 6 (done in caller).
-
-    // Steps 7-9 (skipped).
-}
-
 var _builtinCtorsCache = {__proto__: null};
 
 function GetBuiltinConstructor(builtinName) {
     var ctor = _builtinCtorsCache[builtinName] ||
                (_builtinCtorsCache[builtinName] = GetBuiltinConstructorImpl(builtinName));
     assert(ctor, `No builtin with name "${builtinName}" found`);
     return ctor;
 }
--- a/js/src/builtin/WeakMap.js
+++ b/js/src/builtin/WeakMap.js
@@ -9,48 +9,18 @@ function WeakMapConstructorInit(iterable
 
     // Step 6.a.
     var adder = map.set;
 
     // Step 6.b.
     if (!IsCallable(adder))
         ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
 
-    // Step 6.c.
-    var iterFn = iterable[std_iterator];
-    if (!IsCallable(iterFn))
-        ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
-
-    var iter = callContentFunction(iterFn, iterable);
-    if (!IsObject(iter))
-        ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
-
-    // Step 7 (not applicable).
-
-    // Step 8.
-    while (true) {
-        // Step 8.a.
-        var next = callContentFunction(iter.next, iter);
-        if (!IsObject(next))
-            ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
-
-        // Step 8.b.
-        if (next.done)
-            return;
-
-        // Step 8.c.
-        var nextItem = next.value;
-
+    // Steps 6.c-8.
+    for (var nextItem of allowContentIter(iterable)) {
         // Step 8.d.
-        if (!IsObject(nextItem)) {
-            IteratorCloseThrow(iter);
+        if (!IsObject(nextItem))
             ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "WeakMap");
-        }
 
         // Steps 8.e-j.
-        try {
-            callContentFunction(adder, map, nextItem[0], nextItem[1]);
-        } catch (e) {
-            IteratorCloseThrow(iter);
-            throw e;
-        }
+        callContentFunction(adder, map, nextItem[0], nextItem[1]);
     }
 }
--- a/js/src/builtin/WeakSet.js
+++ b/js/src/builtin/WeakSet.js
@@ -9,49 +9,19 @@ function WeakSetConstructorInit(iterable
 
     // Step 6.a.
     var adder = set.add;
 
     // Step 6.b.
     if (!IsCallable(adder))
         ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder);
 
-    // Step 6.c.
-    var iterFn = iterable[std_iterator];
-    if (!IsCallable(iterFn))
-        ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, iterable));
-
-    var iter = callContentFunction(iterFn, iterable);
-    if (!IsObject(iter))
-        ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof iter);
-
-    // Step 7 (not applicable).
-
-    // Step 8.
-    while (true) {
-        // Step 8.a.
-        var next = callContentFunction(iter.next, iter);
-        if (!IsObject(next))
-            ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, typeof next);
-
-        // Step 8.b.
-        if (next.done)
-            return;
-
-        // Step 8.c.
-        var nextValue = next.value;
-
-        // Steps 8.d-e.
-        try {
-            callContentFunction(adder, set, nextValue);
-        } catch (e) {
-            IteratorCloseThrow(iter);
-            throw e;
-        }
-    }
+    // Steps 6.c-8.
+    for (var nextValue of allowContentIter(iterable))
+        callContentFunction(adder, set, nextValue);
 }
 
 // 23.4.3.1
 function WeakSet_add(value) {
     // Steps 1-3.
     var S = this;
     if (!IsObject(S) || !IsWeakSet(S))
         return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_add");