Index: src/js/promise.js |
diff --git a/src/js/promise.js b/src/js/promise.js |
index 4db36359db1eb54de012183914ff4d7e707eef1d..b9100513ae1c6155abc0158acde2d602f7583a3e 100644 |
--- a/src/js/promise.js |
+++ b/src/js/promise.js |
@@ -66,13 +66,13 @@ var GlobalPromise = function Promise(resolver) { |
throw MakeTypeError(kResolverNotAFunction, resolver); |
var promise = PromiseInit(%NewObject(GlobalPromise, new.target)); |
+ var callbacks = CreateResolvingFunctions(promise); |
try { |
%DebugPushPromise(promise, Promise); |
- var callbacks = CreateResolvingFunctions(promise); |
resolver(callbacks.resolve, callbacks.reject); |
} catch (e) { |
- PromiseReject(promise, e); |
+ %_Call(callbacks.reject, UNDEFINED, e); |
} finally { |
%DebugPopPromise(); |
} |
@@ -181,11 +181,11 @@ function PromiseResolve(promise, x) { |
if (instrumenting) { |
%DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
} |
+ var callbacks = CreateResolvingFunctions(promise); |
try { |
- var callbacks = CreateResolvingFunctions(promise); |
%_Call(then, x, callbacks.resolve, callbacks.reject); |
} catch (e) { |
- PromiseReject(promise, e); |
+ %_Call(callbacks.reject, UNDEFINED, e); |
} |
if (instrumenting) { |
%DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); |
@@ -338,33 +338,50 @@ function PromiseCast(x) { |
} |
function PromiseAll(iterable) { |
+ if (!IS_RECEIVER(this)) { |
+ throw MakeTypeError(kCalledOnNonObject, "Promise.all"); |
+ } |
+ |
var deferred = NewPromiseCapability(this); |
- var resolutions = []; |
+ var resolutions = new InternalArray(); |
+ var count; |
+ |
+ function CreateResolveElementFunction(index, values, promiseCapability) { |
+ var alreadyCalled = false; |
+ return function(x) { |
+ if (alreadyCalled === true) return; |
+ alreadyCalled = true; |
+ values[index] = x; |
+ if (--count === 0) { |
+ var valuesArray = []; |
+ %MoveArrayContents(values, valuesArray); |
+ %_Call(promiseCapability.resolve, UNDEFINED, valuesArray); |
+ } |
+ }; |
+ } |
+ |
try { |
- var count = 0; |
var i = 0; |
+ count = 1; |
for (var value of iterable) { |
- var reject = function(r) { deferred.reject(r) }; |
- this.resolve(value).then( |
- // Nested scope to get closure over current i. |
- // TODO(arv): Use an inner let binding once available. |
- (function(i) { |
- return function(x) { |
- resolutions[i] = x; |
- if (--count === 0) deferred.resolve(resolutions); |
- } |
- })(i), reject); |
- SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); |
- ++i; |
+ var nextPromise = this.resolve(value); |
++count; |
+ nextPromise.then( |
+ CreateResolveElementFunction(i, resolutions, deferred), |
+ deferred.reject); |
+ SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred); |
+ ++i; |
} |
- if (count === 0) { |
- deferred.resolve(resolutions); |
+ // 6.d |
+ if (--count === 0) { |
+ var valuesArray = []; |
+ %MoveArrayContents(resolutions, valuesArray); |
+ %_Call(deferred.resolve, UNDEFINED, valuesArray); |
} |
} catch (e) { |
- deferred.reject(e) |
+ %_Call(deferred.reject, UNDEFINED, e); |
} |
return deferred.promise; |
} |