Chromium Code Reviews| 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 |