| 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;
|
| }
|
|
|