OLD | NEW |
---|---|
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 | 62 |
63 var GlobalPromise = function Promise(resolver) { | 63 var GlobalPromise = function Promise(resolver) { |
64 if (resolver === promiseRawSymbol) { | 64 if (resolver === promiseRawSymbol) { |
65 return %NewObject(GlobalPromise, new.target); | 65 return %NewObject(GlobalPromise, new.target); |
66 } | 66 } |
67 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); | 67 if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this); |
68 if (!IS_CALLABLE(resolver)) | 68 if (!IS_CALLABLE(resolver)) |
69 throw MakeTypeError(kResolverNotAFunction, resolver); | 69 throw MakeTypeError(kResolverNotAFunction, resolver); |
70 | 70 |
71 var promise = PromiseInit(%NewObject(GlobalPromise, new.target)); | 71 var promise = PromiseInit(%NewObject(GlobalPromise, new.target)); |
72 var callbacks = CreateResolvingFunctions(promise); | |
72 | 73 |
73 try { | 74 try { |
74 %DebugPushPromise(promise, Promise); | 75 %DebugPushPromise(promise, Promise); |
75 var callbacks = CreateResolvingFunctions(promise); | |
76 resolver(callbacks.resolve, callbacks.reject); | 76 resolver(callbacks.resolve, callbacks.reject); |
77 } catch (e) { | 77 } catch (e) { |
78 PromiseReject(promise, e); | 78 callbacks.reject(e); |
Dan Ehrenberg
2016/01/04 02:49:15
I think this needs to be %_Call(callbacks.reject,
| |
79 } finally { | 79 } finally { |
80 %DebugPopPromise(); | 80 %DebugPopPromise(); |
81 } | 81 } |
82 | 82 |
83 return promise; | 83 return promise; |
84 } | 84 } |
85 | 85 |
86 // Core functionality. | 86 // Core functionality. |
87 | 87 |
88 function PromiseSet(promise, status, value, onResolve, onReject) { | 88 function PromiseSet(promise, status, value, onResolve, onReject) { |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 if (IS_RECEIVER(x)) { | 197 if (IS_RECEIVER(x)) { |
198 // 25.4.1.3.2 steps 8-12 | 198 // 25.4.1.3.2 steps 8-12 |
199 try { | 199 try { |
200 var then = x.then; | 200 var then = x.then; |
201 } catch (e) { | 201 } catch (e) { |
202 return PromiseReject(promise, e); | 202 return PromiseReject(promise, e); |
203 } | 203 } |
204 if (IS_CALLABLE(then)) { | 204 if (IS_CALLABLE(then)) { |
205 // PromiseResolveThenableJob | 205 // PromiseResolveThenableJob |
206 return %EnqueueMicrotask(function() { | 206 return %EnqueueMicrotask(function() { |
207 var callbacks = CreateResolvingFunctions(promise); | |
207 try { | 208 try { |
208 var callbacks = CreateResolvingFunctions(promise); | |
209 %_Call(then, x, callbacks.resolve, callbacks.reject); | 209 %_Call(then, x, callbacks.resolve, callbacks.reject); |
210 } catch (e) { | 210 } catch (e) { |
211 PromiseReject(promise, e); | 211 callbacks.reject(promise, e); |
Dan Ehrenberg
2016/01/04 02:49:15
Here too
| |
212 } | 212 } |
213 }); | 213 }); |
214 } | 214 } |
215 } | 215 } |
216 PromiseDone(promise, +1, x, promiseOnResolveSymbol); | 216 PromiseDone(promise, +1, x, promiseOnResolveSymbol); |
217 } | 217 } |
218 } | 218 } |
219 | 219 |
220 function PromiseReject(promise, r) { | 220 function PromiseReject(promise, r) { |
221 // Check promise status to confirm that this reject has an effect. | 221 // Check promise status to confirm that this reject has an effect. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 | 355 |
356 function PromiseCast(x) { | 356 function PromiseCast(x) { |
357 if (IsPromise(x) && x.constructor === this) { | 357 if (IsPromise(x) && x.constructor === this) { |
358 return x; | 358 return x; |
359 } else { | 359 } else { |
360 return new this(function(resolve) { resolve(x) }); | 360 return new this(function(resolve) { resolve(x) }); |
361 } | 361 } |
362 } | 362 } |
363 | 363 |
364 function PromiseAll(iterable) { | 364 function PromiseAll(iterable) { |
365 if (!IS_RECEIVER(this)) { | |
366 throw MakeTypeError(kCalledOnNonObject, "Promise.all"); | |
367 } | |
368 | |
365 var deferred = NewPromiseCapability(this); | 369 var deferred = NewPromiseCapability(this); |
366 var resolutions = []; | 370 var resolutions = []; |
367 try { | 371 try { |
368 var count = 0; | 372 var count = 1; |
369 var i = 0; | 373 var i = 0; |
370 for (var value of iterable) { | 374 for (var value of iterable) { |
371 var reject = function(r) { deferred.reject(r) }; | 375 resolutions[i] = UNDEFINED; |
372 this.resolve(value).then( | 376 var nextPromise = this.resolve(value); |
373 // Nested scope to get closure over current i. | 377 ++count; |
374 // TODO(arv): Use an inner let binding once available. | 378 nextPromise.then( |
375 (function(i) { | 379 CreateResolveElementFunction(i, resolutions, deferred), |
376 return function(x) { | 380 deferred.reject); |
377 resolutions[i] = x; | 381 SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred); |
378 if (--count === 0) deferred.resolve(resolutions); | |
379 } | |
380 })(i), reject); | |
381 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); | |
382 ++i; | 382 ++i; |
383 ++count; | |
384 } | 383 } |
385 | 384 |
386 if (count === 0) { | 385 // 6.d |
386 if (--count === 0) { | |
387 deferred.resolve(resolutions); | 387 deferred.resolve(resolutions); |
388 } | 388 } |
389 | 389 |
390 } catch (e) { | 390 } catch (e) { |
391 deferred.reject(e) | 391 deferred.reject(e) |
392 } | 392 } |
393 return deferred.promise; | 393 return deferred.promise; |
394 | |
395 function CreateResolveElementFunction(index, values, promiseCapability) { | |
396 var alreadyCalled = false; | |
397 return function(x) { | |
398 if (alreadyCalled === true) return; | |
399 alreadyCalled = true; | |
400 values[index] = x; | |
401 if (--count === 0) promiseCapability.resolve(values); | |
402 }; | |
403 } | |
394 } | 404 } |
395 | 405 |
396 function PromiseRace(iterable) { | 406 function PromiseRace(iterable) { |
397 var deferred = NewPromiseCapability(this); | 407 var deferred = NewPromiseCapability(this); |
398 try { | 408 try { |
399 for (var value of iterable) { | 409 for (var value of iterable) { |
400 var reject = function(r) { deferred.reject(r) }; | 410 var reject = function(r) { deferred.reject(r) }; |
401 this.resolve(value).then(function(x) { deferred.resolve(x) }, reject); | 411 this.resolve(value).then(function(x) { deferred.resolve(x) }, reject); |
402 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); | 412 SET_PRIVATE(reject, promiseCombinedDeferredSymbol, deferred); |
403 } | 413 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
478 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( | 488 [PromiseChain, PromiseDeferred, PromiseResolved].forEach( |
479 fn => %FunctionRemovePrototype(fn)); | 489 fn => %FunctionRemovePrototype(fn)); |
480 | 490 |
481 utils.Export(function(to) { | 491 utils.Export(function(to) { |
482 to.PromiseChain = PromiseChain; | 492 to.PromiseChain = PromiseChain; |
483 to.PromiseDeferred = PromiseDeferred; | 493 to.PromiseDeferred = PromiseDeferred; |
484 to.PromiseResolved = PromiseResolved; | 494 to.PromiseResolved = PromiseResolved; |
485 }); | 495 }); |
486 | 496 |
487 }) | 497 }) |
OLD | NEW |