Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: src/js/promise.js

Issue 1534813005: [promise] Make Promise.all match spec, and always respect [[AlreadyResolved]] (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase again Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/test262/test262.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 (function(global, utils, extrasUtils) { 5 (function(global, utils, extrasUtils) {
6 6
7 "use strict"; 7 "use strict";
8 8
9 %CheckIsBootstrapping(); 9 %CheckIsBootstrapping();
10 10
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 59
60 var GlobalPromise = function Promise(resolver) { 60 var GlobalPromise = function Promise(resolver) {
61 if (resolver === promiseRawSymbol) { 61 if (resolver === promiseRawSymbol) {
62 return %NewObject(GlobalPromise, new.target); 62 return %NewObject(GlobalPromise, new.target);
63 } 63 }
64 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); 64 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this);
65 if (!IS_CALLABLE(resolver)) 65 if (!IS_CALLABLE(resolver))
66 throw MakeTypeError(kResolverNotAFunction, resolver); 66 throw MakeTypeError(kResolverNotAFunction, resolver);
67 67
68 var promise = PromiseInit(%NewObject(GlobalPromise, new.target)); 68 var promise = PromiseInit(%NewObject(GlobalPromise, new.target));
69 var callbacks = CreateResolvingFunctions(promise);
69 70
70 try { 71 try {
71 %DebugPushPromise(promise, Promise); 72 %DebugPushPromise(promise, Promise);
72 var callbacks = CreateResolvingFunctions(promise);
73 resolver(callbacks.resolve, callbacks.reject); 73 resolver(callbacks.resolve, callbacks.reject);
74 } catch (e) { 74 } catch (e) {
75 PromiseReject(promise, e); 75 %_Call(callbacks.reject, UNDEFINED, e);
76 } finally { 76 } finally {
77 %DebugPopPromise(); 77 %DebugPopPromise();
78 } 78 }
79 79
80 return promise; 80 return promise;
81 } 81 }
82 82
83 // Core functionality. 83 // Core functionality.
84 84
85 function PromiseSet(promise, status, value, onResolve, onReject) { 85 function PromiseSet(promise, status, value, onResolve, onReject) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } catch (e) { 174 } catch (e) {
175 return PromiseReject(promise, e); 175 return PromiseReject(promise, e);
176 } 176 }
177 if (IS_CALLABLE(then)) { 177 if (IS_CALLABLE(then)) {
178 // PromiseResolveThenableJob 178 // PromiseResolveThenableJob
179 var id, name, instrumenting = DEBUG_IS_ACTIVE; 179 var id, name, instrumenting = DEBUG_IS_ACTIVE;
180 %EnqueueMicrotask(function() { 180 %EnqueueMicrotask(function() {
181 if (instrumenting) { 181 if (instrumenting) {
182 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); 182 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
183 } 183 }
184 var callbacks = CreateResolvingFunctions(promise);
184 try { 185 try {
185 var callbacks = CreateResolvingFunctions(promise);
186 %_Call(then, x, callbacks.resolve, callbacks.reject); 186 %_Call(then, x, callbacks.resolve, callbacks.reject);
187 } catch (e) { 187 } catch (e) {
188 PromiseReject(promise, e); 188 %_Call(callbacks.reject, UNDEFINED, e);
189 } 189 }
190 if (instrumenting) { 190 if (instrumenting) {
191 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); 191 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name });
192 } 192 }
193 }); 193 });
194 if (instrumenting) { 194 if (instrumenting) {
195 id = ++lastMicrotaskId; 195 id = ++lastMicrotaskId;
196 name = "PromseResolveThenableJob"; 196 name = "PromseResolveThenableJob";
197 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); 197 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name });
198 } 198 }
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 throw MakeTypeError(kCalledOnNonObject, PromiseCast); 331 throw MakeTypeError(kCalledOnNonObject, PromiseCast);
332 } 332 }
333 if (IsPromise(x) && x.constructor === this) return x; 333 if (IsPromise(x) && x.constructor === this) return x;
334 334
335 var promiseCapability = NewPromiseCapability(this); 335 var promiseCapability = NewPromiseCapability(this);
336 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x); 336 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x);
337 return promiseCapability.promise; 337 return promiseCapability.promise;
338 } 338 }
339 339
340 function PromiseAll(iterable) { 340 function PromiseAll(iterable) {
341 if (!IS_RECEIVER(this)) {
342 throw MakeTypeError(kCalledOnNonObject, "Promise.all");
343 }
344
341 var deferred = NewPromiseCapability(this); 345 var deferred = NewPromiseCapability(this);
342 var resolutions = []; 346 var resolutions = new InternalArray();
343 try { 347 try {
344 var count = 0; 348 var count = 1;
345 var i = 0; 349 var i = 0;
346 for (var value of iterable) { 350 for (var value of iterable) {
347 var reject = function(r) { deferred.reject(r) }; 351 resolutions[i] = UNDEFINED;
adamk 2016/01/07 19:12:10 Why is this needed?
caitp (gmail) 2016/01/07 19:20:35 I _think_ the reason is to make sure `hasOwnProper
adamk 2016/01/07 19:29:30 Ah, ok. Can you just use .push()?
caitp (gmail) 2016/01/07 19:37:59 it seems to pass everything without it, presumably
348 this.resolve(value).then( 352 var nextPromise = this.resolve(value);
349 // Nested scope to get closure over current i. 353 ++count;
350 // TODO(arv): Use an inner let binding once available. 354 nextPromise.then(
351 (function(i) { 355 CreateResolveElementFunction(i, resolutions, deferred),
352 return function(x) { 356 deferred.reject);
353 resolutions[i] = x; 357 SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred);
354 if (--count === 0) deferred.resolve(resolutions);
355 }
356 })(i), reject);
357 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred);
358 ++i; 358 ++i;
359 ++count;
360 } 359 }
361 360
362 if (count === 0) { 361 // 6.d
363 deferred.resolve(resolutions); 362 if (--count === 0) {
363 var valuesArray = [];
364 %MoveArrayContents(resolutions, valuesArray);
365 %_Call(deferred.resolve, UNDEFINED, valuesArray);
364 } 366 }
365 367
366 } catch (e) { 368 } catch (e) {
367 deferred.reject(e) 369 %_Call(deferred.reject, UNDEFINED, e);
368 } 370 }
369 return deferred.promise; 371 return deferred.promise;
372
373 function CreateResolveElementFunction(index, values, promiseCapability) {
adamk 2016/01/07 19:12:10 I think I agree with Dan that this would read bett
caitp (gmail) 2016/01/07 19:20:36 ok
caitp (gmail) 2016/01/07 19:37:59 Done.
374 var alreadyCalled = false;
375 return function(x) {
376 if (alreadyCalled === true) return;
377 alreadyCalled = true;
378 values[index] = x;
379 if (--count === 0) {
380 var valuesArray = [];
381 %MoveArrayContents(values, valuesArray);
382 %_Call(promiseCapability.resolve, UNDEFINED, valuesArray);
383 }
384 };
385 }
370 } 386 }
371 387
372 function PromiseRace(iterable) { 388 function PromiseRace(iterable) {
373 if (!IS_RECEIVER(this)) { 389 if (!IS_RECEIVER(this)) {
374 throw MakeTypeError(kCalledOnNonObject, PromiseRace); 390 throw MakeTypeError(kCalledOnNonObject, PromiseRace);
375 } 391 }
376 392
377 var deferred = NewPromiseCapability(this); 393 var deferred = NewPromiseCapability(this);
378 try { 394 try {
379 for (var value of iterable) { 395 for (var value of iterable) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( 474 [PromiseChain, PromiseDeferred, PromiseResolved].forEach(
459 fn => %FunctionRemovePrototype(fn)); 475 fn => %FunctionRemovePrototype(fn));
460 476
461 utils.Export(function(to) { 477 utils.Export(function(to) {
462 to.PromiseChain = PromiseChain; 478 to.PromiseChain = PromiseChain;
463 to.PromiseDeferred = PromiseDeferred; 479 to.PromiseDeferred = PromiseDeferred;
464 to.PromiseResolved = PromiseResolved; 480 to.PromiseResolved = PromiseResolved;
465 }); 481 });
466 482
467 }) 483 })
OLDNEW
« no previous file with comments | « no previous file | test/test262/test262.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698