| 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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 | 173 |
| 174 function PromiseIdResolveHandler(x) { return x; } | 174 function PromiseIdResolveHandler(x) { return x; } |
| 175 function PromiseIdRejectHandler(r) { %_ReThrow(r); } | 175 function PromiseIdRejectHandler(r) { %_ReThrow(r); } |
| 176 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); | 176 SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true); |
| 177 | 177 |
| 178 // ------------------------------------------------------------------- | 178 // ------------------------------------------------------------------- |
| 179 // Define exported functions. | 179 // Define exported functions. |
| 180 | 180 |
| 181 // For bootstrapper. | 181 // For bootstrapper. |
| 182 | 182 |
| 183 // Only used by utils | |
| 184 // ES#sec-ispromise IsPromise ( x ) | |
| 185 function IsPromise(x) { | |
| 186 return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol); | |
| 187 } | |
| 188 | |
| 189 function PromiseCreate() { | 183 function PromiseCreate() { |
| 190 return PromiseInit(%promise_internal_constructor()); | 184 return PromiseInit(%promise_internal_constructor()); |
| 191 } | 185 } |
| 192 | 186 |
| 193 // ES#sec-promise-resolve-functions | 187 // ES#sec-promise-resolve-functions |
| 194 // Promise Resolve Functions, steps 6-13 | 188 // Promise Resolve Functions, steps 6-13 |
| 195 function ResolvePromise(promise, resolution) { | 189 function ResolvePromise(promise, resolution) { |
| 196 if (resolution === promise) { | 190 if (resolution === promise) { |
| 197 var exception = %make_type_error(kPromiseCyclic, resolution); | 191 var exception = %make_type_error(kPromiseCyclic, resolution); |
| 198 %PromiseReject(promise, exception, true); | 192 %PromiseReject(promise, exception, true); |
| 199 PromiseSet(promise, kRejected, exception); | 193 PromiseSet(promise, kRejected, exception); |
| 200 return; | 194 return; |
| 201 } | 195 } |
| 202 if (IS_RECEIVER(resolution)) { | 196 if (IS_RECEIVER(resolution)) { |
| 203 // 25.4.1.3.2 steps 8-12 | 197 // 25.4.1.3.2 steps 8-12 |
| 204 try { | 198 try { |
| 205 var then = resolution.then; | 199 var then = resolution.then; |
| 206 } catch (e) { | 200 } catch (e) { |
| 207 %PromiseReject(promise, e, true); | 201 %PromiseReject(promise, e, true); |
| 208 PromiseSet(promise, kRejected, e); | 202 PromiseSet(promise, kRejected, e); |
| 209 return; | 203 return; |
| 210 } | 204 } |
| 211 | 205 |
| 212 // Resolution is a native promise and if it's already resolved or | 206 // Resolution is a native promise and if it's already resolved or |
| 213 // rejected, shortcircuit the resolution procedure by directly | 207 // rejected, shortcircuit the resolution procedure by directly |
| 214 // reusing the value from the promise. | 208 // reusing the value from the promise. |
| 215 if (IsPromise(resolution) && then === PromiseThen) { | 209 if (%is_promise(resolution) && then === PromiseThen) { |
| 216 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); | 210 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); |
| 217 if (thenableState === kFulfilled) { | 211 if (thenableState === kFulfilled) { |
| 218 // This goes inside the if-else to save one symbol lookup in | 212 // This goes inside the if-else to save one symbol lookup in |
| 219 // the slow path. | 213 // the slow path. |
| 220 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 214 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
| 221 %PromiseFulfill(promise, kFulfilled, thenableValue, | 215 %PromiseFulfill(promise, kFulfilled, thenableValue, |
| 222 promiseFulfillReactionsSymbol); | 216 promiseFulfillReactionsSymbol); |
| 223 PromiseSet(promise, kFulfilled, thenableValue); | 217 PromiseSet(promise, kFulfilled, thenableValue); |
| 224 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 218 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
| 225 return; | 219 return; |
| 226 } else if (thenableState === kRejected) { | 220 } else if (thenableState === kRejected) { |
| 227 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 221 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
| 228 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { | 222 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { |
| 229 // Promise has already been rejected, but had no handler. | 223 // Promise has already been rejected, but had no handler. |
| 230 // Revoke previously triggered reject event. | 224 // Revoke previously triggered reject event. |
| 231 %PromiseRevokeReject(resolution); | 225 %PromiseRevokeReject(resolution); |
| 232 } | 226 } |
| 233 // Don't cause a debug event as this case is forwarding a rejection | 227 // Don't cause a debug event as this case is forwarding a rejection |
| 234 %PromiseReject(promise, thenableValue, false); | 228 %PromiseReject(promise, thenableValue, false); |
| 235 PromiseSet(promise, kRejected, thenableValue); | 229 PromiseSet(promise, kRejected, thenableValue); |
| 236 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); | 230 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); |
| 237 return; | 231 return; |
| 238 } | 232 } |
| 239 } | 233 } |
| 240 | 234 |
| 241 if (IS_CALLABLE(then)) { | 235 if (IS_CALLABLE(then)) { |
| 242 if (DEBUG_IS_ACTIVE && IsPromise(resolution)) { | 236 if (DEBUG_IS_ACTIVE && %is_promise(resolution)) { |
| 243 // Mark the dependency of the new promise on the resolution | 237 // Mark the dependency of the new promise on the resolution |
| 244 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); | 238 SET_PRIVATE(resolution, promiseHandledBySymbol, promise); |
| 245 } | 239 } |
| 246 %EnqueuePromiseResolveThenableJob(promise, resolution, then); | 240 %EnqueuePromiseResolveThenableJob(promise, resolution, then); |
| 247 return; | 241 return; |
| 248 } | 242 } |
| 249 } | 243 } |
| 250 %PromiseFulfill(promise, kFulfilled, resolution, | 244 %PromiseFulfill(promise, kFulfilled, resolution, |
| 251 promiseFulfillReactionsSymbol); | 245 promiseFulfillReactionsSymbol); |
| 252 PromiseSet(promise, kFulfilled, resolution); | 246 PromiseSet(promise, kFulfilled, resolution); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 345 |
| 352 // Mark this promise as having handler. | 346 // Mark this promise as having handler. |
| 353 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 347 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
| 354 return resultCapability.promise; | 348 return resultCapability.promise; |
| 355 } | 349 } |
| 356 | 350 |
| 357 // ES#sec-promise.prototype.then | 351 // ES#sec-promise.prototype.then |
| 358 // Promise.prototype.then ( onFulfilled, onRejected ) | 352 // Promise.prototype.then ( onFulfilled, onRejected ) |
| 359 // Multi-unwrapped chaining with thenable coercion. | 353 // Multi-unwrapped chaining with thenable coercion. |
| 360 function PromiseThen(onResolve, onReject) { | 354 function PromiseThen(onResolve, onReject) { |
| 361 if (!IsPromise(this)) { | 355 if (!%is_promise(this)) { |
| 362 throw %make_type_error(kNotAPromise, this); | 356 throw %make_type_error(kNotAPromise, this); |
| 363 } | 357 } |
| 364 | 358 |
| 365 var constructor = SpeciesConstructor(this, GlobalPromise); | 359 var constructor = SpeciesConstructor(this, GlobalPromise); |
| 366 var resultCapability; | 360 var resultCapability; |
| 367 if (constructor === GlobalPromise) { | 361 if (constructor === GlobalPromise) { |
| 368 resultCapability = CreateInternalPromiseCapability(); | 362 resultCapability = CreateInternalPromiseCapability(); |
| 369 } else { | 363 } else { |
| 370 // Pass false for debugEvent so .then chaining does not trigger | 364 // Pass false for debugEvent so .then chaining does not trigger |
| 371 // redundant ExceptionEvents. | 365 // redundant ExceptionEvents. |
| 372 resultCapability = NewPromiseCapability(constructor, false); | 366 resultCapability = NewPromiseCapability(constructor, false); |
| 373 } | 367 } |
| 374 return PerformPromiseThen(this, onResolve, onReject, resultCapability); | 368 return PerformPromiseThen(this, onResolve, onReject, resultCapability); |
| 375 } | 369 } |
| 376 | 370 |
| 377 // ES#sec-promise.prototype.catch | 371 // ES#sec-promise.prototype.catch |
| 378 // Promise.prototype.catch ( onRejected ) | 372 // Promise.prototype.catch ( onRejected ) |
| 379 function PromiseCatch(onReject) { | 373 function PromiseCatch(onReject) { |
| 380 return this.then(UNDEFINED, onReject); | 374 return this.then(UNDEFINED, onReject); |
| 381 } | 375 } |
| 382 | 376 |
| 383 // Combinators. | 377 // Combinators. |
| 384 | 378 |
| 385 // ES#sec-promise.resolve | 379 // ES#sec-promise.resolve |
| 386 // Promise.resolve ( x ) | 380 // Promise.resolve ( x ) |
| 387 function PromiseResolve(x) { | 381 function PromiseResolve(x) { |
| 388 if (!IS_RECEIVER(this)) { | 382 if (!IS_RECEIVER(this)) { |
| 389 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 383 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
| 390 } | 384 } |
| 391 if (IsPromise(x) && x.constructor === this) return x; | 385 if (%is_promise(x) && x.constructor === this) return x; |
| 392 | 386 |
| 393 // Avoid creating resolving functions. | 387 // Avoid creating resolving functions. |
| 394 if (this === GlobalPromise) { | 388 if (this === GlobalPromise) { |
| 395 var promise = PromiseCreate(); | 389 var promise = PromiseCreate(); |
| 396 ResolvePromise(promise, x); | 390 ResolvePromise(promise, x); |
| 397 return promise; | 391 return promise; |
| 398 } | 392 } |
| 399 | 393 |
| 400 // debugEvent is not so meaningful here as it will be resolved | 394 // debugEvent is not so meaningful here as it will be resolved |
| 401 var promiseCapability = NewPromiseCapability(this, true); | 395 var promiseCapability = NewPromiseCapability(this, true); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 var i = 0; | 435 var i = 0; |
| 442 count = 1; | 436 count = 1; |
| 443 for (var value of iterable) { | 437 for (var value of iterable) { |
| 444 var nextPromise = this.resolve(value); | 438 var nextPromise = this.resolve(value); |
| 445 ++count; | 439 ++count; |
| 446 var throwawayPromise = nextPromise.then( | 440 var throwawayPromise = nextPromise.then( |
| 447 CreateResolveElementFunction(i, resolutions, deferred), | 441 CreateResolveElementFunction(i, resolutions, deferred), |
| 448 deferred.reject); | 442 deferred.reject); |
| 449 // For catch prediction, mark that rejections here are semantically | 443 // For catch prediction, mark that rejections here are semantically |
| 450 // handled by the combined Promise. | 444 // handled by the combined Promise. |
| 451 if (instrumenting && IsPromise(throwawayPromise)) { | 445 if (instrumenting && %is_promise(throwawayPromise)) { |
| 452 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); | 446 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); |
| 453 } | 447 } |
| 454 ++i; | 448 ++i; |
| 455 } | 449 } |
| 456 | 450 |
| 457 // 6.d | 451 // 6.d |
| 458 if (--count === 0) { | 452 if (--count === 0) { |
| 459 var valuesArray = []; | 453 var valuesArray = []; |
| 460 %MoveArrayContents(resolutions, valuesArray); | 454 %MoveArrayContents(resolutions, valuesArray); |
| 461 %_Call(deferred.resolve, UNDEFINED, valuesArray); | 455 %_Call(deferred.resolve, UNDEFINED, valuesArray); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 484 if (instrumenting) { | 478 if (instrumenting) { |
| 485 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); | 479 SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true); |
| 486 } | 480 } |
| 487 | 481 |
| 488 try { | 482 try { |
| 489 for (var value of iterable) { | 483 for (var value of iterable) { |
| 490 var throwawayPromise = this.resolve(value).then(deferred.resolve, | 484 var throwawayPromise = this.resolve(value).then(deferred.resolve, |
| 491 deferred.reject); | 485 deferred.reject); |
| 492 // For catch prediction, mark that rejections here are semantically | 486 // For catch prediction, mark that rejections here are semantically |
| 493 // handled by the combined Promise. | 487 // handled by the combined Promise. |
| 494 if (instrumenting && IsPromise(throwawayPromise)) { | 488 if (instrumenting && %is_promise(throwawayPromise)) { |
| 495 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); | 489 SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise); |
| 496 } | 490 } |
| 497 } | 491 } |
| 498 } catch (e) { | 492 } catch (e) { |
| 499 %_Call(deferred.reject, UNDEFINED, e); | 493 %_Call(deferred.reject, UNDEFINED, e); |
| 500 } | 494 } |
| 501 return deferred.promise; | 495 return deferred.promise; |
| 502 } | 496 } |
| 503 | 497 |
| 504 | 498 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 // resolve/reject closures, and allows them to later resolve and reject any | 598 // resolve/reject closures, and allows them to later resolve and reject any |
| 605 // promise without having to hold on to those closures forever. | 599 // promise without having to hold on to those closures forever. |
| 606 utils.InstallFunctions(extrasUtils, 0, [ | 600 utils.InstallFunctions(extrasUtils, 0, [ |
| 607 "createPromise", PromiseCreate, | 601 "createPromise", PromiseCreate, |
| 608 "resolvePromise", ResolvePromise, | 602 "resolvePromise", ResolvePromise, |
| 609 "rejectPromise", DoRejectPromise, | 603 "rejectPromise", DoRejectPromise, |
| 610 "markPromiseAsHandled", MarkPromiseAsHandled | 604 "markPromiseAsHandled", MarkPromiseAsHandled |
| 611 ]); | 605 ]); |
| 612 | 606 |
| 613 utils.Export(function(to) { | 607 utils.Export(function(to) { |
| 614 to.IsPromise = IsPromise; | |
| 615 to.PromiseCreate = PromiseCreate; | 608 to.PromiseCreate = PromiseCreate; |
| 616 to.PromiseThen = PromiseThen; | 609 to.PromiseThen = PromiseThen; |
| 617 | 610 |
| 618 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; | 611 to.CreateInternalPromiseCapability = CreateInternalPromiseCapability; |
| 619 to.PerformPromiseThen = PerformPromiseThen; | 612 to.PerformPromiseThen = PerformPromiseThen; |
| 620 to.ResolvePromise = ResolvePromise; | 613 to.ResolvePromise = ResolvePromise; |
| 621 to.RejectPromise = RejectPromise; | 614 to.RejectPromise = RejectPromise; |
| 622 }); | 615 }); |
| 623 | 616 |
| 624 }) | 617 }) |
| OLD | NEW |