| 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 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 // [[PromiseState]] values: | 38 // [[PromiseState]] values: |
| 39 const kPending = 0; | 39 const kPending = 0; |
| 40 const kFulfilled = +1; | 40 const kFulfilled = +1; |
| 41 const kRejected = -1; | 41 const kRejected = -1; |
| 42 | 42 |
| 43 var lastMicrotaskId = 0; | 43 var lastMicrotaskId = 0; |
| 44 | 44 |
| 45 // ES#sec-createresolvingfunctions | 45 // ES#sec-createresolvingfunctions |
| 46 // CreateResolvingFunctions ( promise ) | 46 // CreateResolvingFunctions ( promise ) |
| 47 function CreateResolvingFunctions(promise) { | 47 function CreateResolvingFunctions(promise, debugEvent) { |
| 48 var alreadyResolved = false; | 48 var alreadyResolved = false; |
| 49 | 49 |
| 50 // ES#sec-promise-resolve-functions | 50 // ES#sec-promise-resolve-functions |
| 51 // Promise Resolve Functions | 51 // Promise Resolve Functions |
| 52 var resolve = value => { | 52 var resolve = value => { |
| 53 if (alreadyResolved === true) return; | 53 if (alreadyResolved === true) return; |
| 54 alreadyResolved = true; | 54 alreadyResolved = true; |
| 55 ResolvePromise(promise, value); | 55 ResolvePromise(promise, value); |
| 56 }; | 56 }; |
| 57 | 57 |
| 58 // ES#sec-promise-reject-functions | 58 // ES#sec-promise-reject-functions |
| 59 // Promise Reject Functions | 59 // Promise Reject Functions |
| 60 var reject = reason => { | 60 var reject = reason => { |
| 61 if (alreadyResolved === true) return; | 61 if (alreadyResolved === true) return; |
| 62 alreadyResolved = true; | 62 alreadyResolved = true; |
| 63 RejectPromise(promise, reason); | 63 RejectPromise(promise, reason, debugEvent); |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 return { | 66 return { |
| 67 __proto__: null, | 67 __proto__: null, |
| 68 resolve: resolve, | 68 resolve: resolve, |
| 69 reject: reject | 69 reject: reject |
| 70 }; | 70 }; |
| 71 } | 71 } |
| 72 | 72 |
| 73 | 73 |
| 74 // ES#sec-promise-executor | 74 // ES#sec-promise-executor |
| 75 // Promise ( executor ) | 75 // Promise ( executor ) |
| 76 var GlobalPromise = function Promise(executor) { | 76 var GlobalPromise = function Promise(executor) { |
| 77 if (executor === promiseRawSymbol) { | 77 if (executor === promiseRawSymbol) { |
| 78 return %_NewObject(GlobalPromise, new.target); | 78 return %_NewObject(GlobalPromise, new.target); |
| 79 } | 79 } |
| 80 if (IS_UNDEFINED(new.target)) throw %make_type_error(kNotAPromise, this); | 80 if (IS_UNDEFINED(new.target)) throw %make_type_error(kNotAPromise, this); |
| 81 if (!IS_CALLABLE(executor)) { | 81 if (!IS_CALLABLE(executor)) { |
| 82 throw %make_type_error(kResolverNotAFunction, executor); | 82 throw %make_type_error(kResolverNotAFunction, executor); |
| 83 } | 83 } |
| 84 | 84 |
| 85 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); | 85 var promise = PromiseInit(%_NewObject(GlobalPromise, new.target)); |
| 86 var callbacks = CreateResolvingFunctions(promise); | 86 // Calling the reject function would be a new exception, so debugEvent = true |
| 87 var callbacks = CreateResolvingFunctions(promise, true); |
| 87 var debug_is_active = DEBUG_IS_ACTIVE; | 88 var debug_is_active = DEBUG_IS_ACTIVE; |
| 88 try { | 89 try { |
| 89 if (debug_is_active) %DebugPushPromise(promise); | 90 if (debug_is_active) %DebugPushPromise(promise); |
| 90 executor(callbacks.resolve, callbacks.reject); | 91 executor(callbacks.resolve, callbacks.reject); |
| 91 } %catch (e) { // Natives syntax to mark this catch block. | 92 } %catch (e) { // Natives syntax to mark this catch block. |
| 92 %_Call(callbacks.reject, UNDEFINED, e); | 93 %_Call(callbacks.reject, UNDEFINED, e); |
| 93 } finally { | 94 } finally { |
| 94 if (debug_is_active) %DebugPopPromise(); | 95 if (debug_is_active) %DebugPopPromise(); |
| 95 } | 96 } |
| 96 | 97 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 } | 232 } |
| 232 | 233 |
| 233 function PromiseCreate() { | 234 function PromiseCreate() { |
| 234 return new GlobalPromise(PromiseNopResolver) | 235 return new GlobalPromise(PromiseNopResolver) |
| 235 } | 236 } |
| 236 | 237 |
| 237 // ES#sec-promise-resolve-functions | 238 // ES#sec-promise-resolve-functions |
| 238 // Promise Resolve Functions, steps 6-13 | 239 // Promise Resolve Functions, steps 6-13 |
| 239 function ResolvePromise(promise, resolution) { | 240 function ResolvePromise(promise, resolution) { |
| 240 if (resolution === promise) { | 241 if (resolution === promise) { |
| 241 return RejectPromise(promise, %make_type_error(kPromiseCyclic, resolution)); | 242 return RejectPromise(promise, |
| 243 %make_type_error(kPromiseCyclic, resolution), |
| 244 true); |
| 242 } | 245 } |
| 243 if (IS_RECEIVER(resolution)) { | 246 if (IS_RECEIVER(resolution)) { |
| 244 // 25.4.1.3.2 steps 8-12 | 247 // 25.4.1.3.2 steps 8-12 |
| 245 try { | 248 try { |
| 246 var then = resolution.then; | 249 var then = resolution.then; |
| 247 } catch (e) { | 250 } catch (e) { |
| 248 return RejectPromise(promise, e); | 251 return RejectPromise(promise, e, true); |
| 249 } | 252 } |
| 250 | 253 |
| 251 // Resolution is a native promise and if it's already resolved or | 254 // Resolution is a native promise and if it's already resolved or |
| 252 // rejected, shortcircuit the resolution procedure by directly | 255 // rejected, shortcircuit the resolution procedure by directly |
| 253 // reusing the value from the promise. | 256 // reusing the value from the promise. |
| 254 if (IsPromise(resolution) && then === PromiseThen) { | 257 if (IsPromise(resolution) && then === PromiseThen) { |
| 255 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); | 258 var thenableState = GET_PRIVATE(resolution, promiseStateSymbol); |
| 256 if (thenableState === kFulfilled) { | 259 if (thenableState === kFulfilled) { |
| 257 // This goes inside the if-else to save one symbol lookup in | 260 // This goes inside the if-else to save one symbol lookup in |
| 258 // the slow path. | 261 // the slow path. |
| 259 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 262 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
| 260 FulfillPromise(promise, kFulfilled, thenableValue, | 263 FulfillPromise(promise, kFulfilled, thenableValue, |
| 261 promiseFulfillReactionsSymbol); | 264 promiseFulfillReactionsSymbol); |
| 262 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); | 265 SET_PRIVATE(promise, promiseHasHandlerSymbol, true); |
| 263 return; | 266 return; |
| 264 } else if (thenableState === kRejected) { | 267 } else if (thenableState === kRejected) { |
| 265 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); | 268 var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol); |
| 266 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { | 269 if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) { |
| 267 // Promise has already been rejected, but had no handler. | 270 // Promise has already been rejected, but had no handler. |
| 268 // Revoke previously triggered reject event. | 271 // Revoke previously triggered reject event. |
| 269 %PromiseRevokeReject(resolution); | 272 %PromiseRevokeReject(resolution); |
| 270 } | 273 } |
| 271 RejectPromise(promise, thenableValue); | 274 // Don't cause a debug event as this case is forwarding a rejection |
| 275 RejectPromise(promise, thenableValue, false); |
| 272 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); | 276 SET_PRIVATE(resolution, promiseHasHandlerSymbol, true); |
| 273 return; | 277 return; |
| 274 } | 278 } |
| 275 } | 279 } |
| 276 | 280 |
| 277 if (IS_CALLABLE(then)) { | 281 if (IS_CALLABLE(then)) { |
| 278 // PromiseResolveThenableJob | 282 // PromiseResolveThenableJob |
| 279 var id; | 283 var id; |
| 280 var name = "PromiseResolveThenableJob"; | 284 var name = "PromiseResolveThenableJob"; |
| 281 var instrumenting = DEBUG_IS_ACTIVE; | 285 var instrumenting = DEBUG_IS_ACTIVE; |
| 282 %EnqueueMicrotask(function() { | 286 %EnqueueMicrotask(function() { |
| 283 if (instrumenting) { | 287 if (instrumenting) { |
| 284 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); | 288 %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
| 285 } | 289 } |
| 286 var callbacks = CreateResolvingFunctions(promise); | 290 // These resolving functions simply forward the exception, so |
| 291 // don't create a new debugEvent. |
| 292 var callbacks = CreateResolvingFunctions(promise, false); |
| 287 try { | 293 try { |
| 288 %_Call(then, resolution, callbacks.resolve, callbacks.reject); | 294 %_Call(then, resolution, callbacks.resolve, callbacks.reject); |
| 289 } catch (e) { | 295 } catch (e) { |
| 290 %_Call(callbacks.reject, UNDEFINED, e); | 296 %_Call(callbacks.reject, UNDEFINED, e); |
| 291 } | 297 } |
| 292 if (instrumenting) { | 298 if (instrumenting) { |
| 293 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); | 299 %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); |
| 294 } | 300 } |
| 295 }); | 301 }); |
| 296 if (instrumenting) { | 302 if (instrumenting) { |
| 297 id = ++lastMicrotaskId; | 303 id = ++lastMicrotaskId; |
| 298 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); | 304 %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); |
| 299 } | 305 } |
| 300 return; | 306 return; |
| 301 } | 307 } |
| 302 } | 308 } |
| 303 FulfillPromise(promise, kFulfilled, resolution, promiseFulfillReactionsSymbol)
; | 309 FulfillPromise(promise, kFulfilled, resolution, promiseFulfillReactionsSymbol)
; |
| 304 } | 310 } |
| 305 | 311 |
| 306 // ES#sec-rejectpromise | 312 // ES#sec-rejectpromise |
| 307 // RejectPromise ( promise, reason ) | 313 // RejectPromise ( promise, reason ) |
| 308 function RejectPromise(promise, reason) { | 314 function RejectPromise(promise, reason, debugEvent) { |
| 309 // Check promise status to confirm that this reject has an effect. | 315 // Check promise status to confirm that this reject has an effect. |
| 310 // Call runtime for callbacks to the debugger or for unhandled reject. | 316 // Call runtime for callbacks to the debugger or for unhandled reject. |
| 317 // The debugEvent parameter sets whether a debug ExceptionEvent should |
| 318 // be triggered. It should be set to false when forwarding a rejection |
| 319 // rather than creating a new one. |
| 311 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { | 320 if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { |
| 312 var debug_is_active = DEBUG_IS_ACTIVE; | 321 // This check is redundant with checks in the runtime, but it may help |
| 313 if (debug_is_active || | 322 // avoid unnecessary runtime calls. |
| 323 if ((debugEvent && DEBUG_IS_ACTIVE) || |
| 314 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { | 324 !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) { |
| 315 %PromiseRejectEvent(promise, reason, debug_is_active); | 325 %PromiseRejectEvent(promise, reason, debugEvent); |
| 316 } | 326 } |
| 317 } | 327 } |
| 318 FulfillPromise(promise, kRejected, reason, promiseRejectReactionsSymbol) | 328 FulfillPromise(promise, kRejected, reason, promiseRejectReactionsSymbol) |
| 319 } | 329 } |
| 320 | 330 |
| 331 // Export to bindings |
| 332 function DoRejectPromise(promise, reason) { |
| 333 return RejectPromise(promise, reason, true); |
| 334 } |
| 335 |
| 321 // ES#sec-newpromisecapability | 336 // ES#sec-newpromisecapability |
| 322 // NewPromiseCapability ( C ) | 337 // NewPromiseCapability ( C ) |
| 323 function NewPromiseCapability(C) { | 338 function NewPromiseCapability(C, debugEvent) { |
| 324 if (C === GlobalPromise) { | 339 if (C === GlobalPromise) { |
| 325 // Optimized case, avoid extra closure. | 340 // Optimized case, avoid extra closure. |
| 326 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); | 341 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); |
| 327 var callbacks = CreateResolvingFunctions(promise); | 342 var callbacks = CreateResolvingFunctions(promise, debugEvent); |
| 328 return { | 343 return { |
| 329 promise: promise, | 344 promise: promise, |
| 330 resolve: callbacks.resolve, | 345 resolve: callbacks.resolve, |
| 331 reject: callbacks.reject | 346 reject: callbacks.reject |
| 332 }; | 347 }; |
| 333 } | 348 } |
| 334 | 349 |
| 335 var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED }; | 350 var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED }; |
| 336 result.promise = new C((resolve, reject) => { | 351 result.promise = new C((resolve, reject) => { |
| 337 if (!IS_UNDEFINED(result.resolve) || !IS_UNDEFINED(result.reject)) | 352 if (!IS_UNDEFINED(result.resolve) || !IS_UNDEFINED(result.reject)) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 348 | 363 |
| 349 // ES#sec-promise.reject | 364 // ES#sec-promise.reject |
| 350 // Promise.reject ( x ) | 365 // Promise.reject ( x ) |
| 351 function PromiseReject(r) { | 366 function PromiseReject(r) { |
| 352 if (!IS_RECEIVER(this)) { | 367 if (!IS_RECEIVER(this)) { |
| 353 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 368 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
| 354 } | 369 } |
| 355 if (this === GlobalPromise) { | 370 if (this === GlobalPromise) { |
| 356 // Optimized case, avoid extra closure. | 371 // Optimized case, avoid extra closure. |
| 357 var promise = PromiseCreateAndSet(kRejected, r); | 372 var promise = PromiseCreateAndSet(kRejected, r); |
| 358 // The debug event for this would always be an uncaught promise reject, | 373 // Trigger debug events if the debugger is on, as Promise.reject is |
| 359 // which is usually simply noise. Do not trigger that debug event. | 374 // equivalent to throwing an exception directly. |
| 360 %PromiseRejectEvent(promise, r, false); | 375 %PromiseRejectEventFromStack(promise, r); |
| 361 return promise; | 376 return promise; |
| 362 } else { | 377 } else { |
| 363 var promiseCapability = NewPromiseCapability(this); | 378 var promiseCapability = NewPromiseCapability(this, true); |
| 364 %_Call(promiseCapability.reject, UNDEFINED, r); | 379 %_Call(promiseCapability.reject, UNDEFINED, r); |
| 365 return promiseCapability.promise; | 380 return promiseCapability.promise; |
| 366 } | 381 } |
| 367 } | 382 } |
| 368 | 383 |
| 369 // Shortcut Promise.reject and Promise.resolve() implementations, used by | 384 // Shortcut Promise.reject and Promise.resolve() implementations, used by |
| 370 // Async Functions implementation. | 385 // Async Functions implementation. |
| 371 function PromiseCreateRejected(r) { | 386 function PromiseCreateRejected(r) { |
| 372 return %_Call(PromiseReject, GlobalPromise, r); | 387 var promise = PromiseCreateAndSet(kRejected, r); |
| 388 // This is called from the desugaring of async/await; no reason to |
| 389 // create a redundant reject event. |
| 390 %PromiseRejectEvent(promise, r, false); |
| 391 return promise; |
| 373 } | 392 } |
| 374 | 393 |
| 375 function PromiseCreateResolved(value) { | 394 function PromiseCreateResolved(value) { |
| 376 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); | 395 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); |
| 377 var resolveResult = ResolvePromise(promise, value); | 396 var resolveResult = ResolvePromise(promise, value); |
| 378 return promise; | 397 return promise; |
| 379 } | 398 } |
| 380 | 399 |
| 381 function PromiseCastResolved(value) { | 400 function PromiseCastResolved(value) { |
| 382 if (IsPromise(value)) { | 401 if (IsPromise(value)) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 // ES#sec-promise.prototype.then | 439 // ES#sec-promise.prototype.then |
| 421 // Promise.prototype.then ( onFulfilled, onRejected ) | 440 // Promise.prototype.then ( onFulfilled, onRejected ) |
| 422 // Multi-unwrapped chaining with thenable coercion. | 441 // Multi-unwrapped chaining with thenable coercion. |
| 423 function PromiseThen(onResolve, onReject) { | 442 function PromiseThen(onResolve, onReject) { |
| 424 var status = GET_PRIVATE(this, promiseStateSymbol); | 443 var status = GET_PRIVATE(this, promiseStateSymbol); |
| 425 if (IS_UNDEFINED(status)) { | 444 if (IS_UNDEFINED(status)) { |
| 426 throw %make_type_error(kNotAPromise, this); | 445 throw %make_type_error(kNotAPromise, this); |
| 427 } | 446 } |
| 428 | 447 |
| 429 var constructor = SpeciesConstructor(this, GlobalPromise); | 448 var constructor = SpeciesConstructor(this, GlobalPromise); |
| 430 var resultCapability = NewPromiseCapability(constructor); | 449 // Pass false for debugEvent so .then chaining does not trigger |
| 450 // redundant ExceptionEvents. |
| 451 var resultCapability = NewPromiseCapability(constructor, false); |
| 431 return PerformPromiseThen(this, onResolve, onReject, resultCapability); | 452 return PerformPromiseThen(this, onResolve, onReject, resultCapability); |
| 432 } | 453 } |
| 433 | 454 |
| 434 // ES#sec-promise.prototype.catch | 455 // ES#sec-promise.prototype.catch |
| 435 // Promise.prototype.catch ( onRejected ) | 456 // Promise.prototype.catch ( onRejected ) |
| 436 function PromiseCatch(onReject) { | 457 function PromiseCatch(onReject) { |
| 437 return this.then(UNDEFINED, onReject); | 458 return this.then(UNDEFINED, onReject); |
| 438 } | 459 } |
| 439 | 460 |
| 440 // Combinators. | 461 // Combinators. |
| 441 | 462 |
| 442 // ES#sec-promise.resolve | 463 // ES#sec-promise.resolve |
| 443 // Promise.resolve ( x ) | 464 // Promise.resolve ( x ) |
| 444 function PromiseResolve(x) { | 465 function PromiseResolve(x) { |
| 445 if (!IS_RECEIVER(this)) { | 466 if (!IS_RECEIVER(this)) { |
| 446 throw %make_type_error(kCalledOnNonObject, PromiseResolve); | 467 throw %make_type_error(kCalledOnNonObject, PromiseResolve); |
| 447 } | 468 } |
| 448 if (IsPromise(x) && x.constructor === this) return x; | 469 if (IsPromise(x) && x.constructor === this) return x; |
| 449 | 470 |
| 450 // Avoid creating resolving functions. | 471 // Avoid creating resolving functions. |
| 451 if (this === GlobalPromise) { | 472 if (this === GlobalPromise) { |
| 452 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); | 473 var promise = PromiseInit(new GlobalPromise(promiseRawSymbol)); |
| 453 var resolveResult = ResolvePromise(promise, x); | 474 var resolveResult = ResolvePromise(promise, x); |
| 454 return promise; | 475 return promise; |
| 455 } | 476 } |
| 456 | 477 |
| 457 var promiseCapability = NewPromiseCapability(this); | 478 // debugEvent is not so meaningful here as it will be resolved |
| 479 var promiseCapability = NewPromiseCapability(this, true); |
| 458 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x); | 480 var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x); |
| 459 return promiseCapability.promise; | 481 return promiseCapability.promise; |
| 460 } | 482 } |
| 461 | 483 |
| 462 // ES#sec-promise.all | 484 // ES#sec-promise.all |
| 463 // Promise.all ( iterable ) | 485 // Promise.all ( iterable ) |
| 464 function PromiseAll(iterable) { | 486 function PromiseAll(iterable) { |
| 465 if (!IS_RECEIVER(this)) { | 487 if (!IS_RECEIVER(this)) { |
| 466 throw %make_type_error(kCalledOnNonObject, "Promise.all"); | 488 throw %make_type_error(kCalledOnNonObject, "Promise.all"); |
| 467 } | 489 } |
| 468 | 490 |
| 469 var deferred = NewPromiseCapability(this); | 491 // false debugEvent so that forwarding the rejection through all does not |
| 492 // trigger redundant ExceptionEvents |
| 493 var deferred = NewPromiseCapability(this, false); |
| 470 var resolutions = new InternalArray(); | 494 var resolutions = new InternalArray(); |
| 471 var count; | 495 var count; |
| 472 | 496 |
| 473 function CreateResolveElementFunction(index, values, promiseCapability) { | 497 function CreateResolveElementFunction(index, values, promiseCapability) { |
| 474 var alreadyCalled = false; | 498 var alreadyCalled = false; |
| 475 return (x) => { | 499 return (x) => { |
| 476 if (alreadyCalled === true) return; | 500 if (alreadyCalled === true) return; |
| 477 alreadyCalled = true; | 501 alreadyCalled = true; |
| 478 values[index] = x; | 502 values[index] = x; |
| 479 if (--count === 0) { | 503 if (--count === 0) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 510 return deferred.promise; | 534 return deferred.promise; |
| 511 } | 535 } |
| 512 | 536 |
| 513 // ES#sec-promise.race | 537 // ES#sec-promise.race |
| 514 // Promise.race ( iterable ) | 538 // Promise.race ( iterable ) |
| 515 function PromiseRace(iterable) { | 539 function PromiseRace(iterable) { |
| 516 if (!IS_RECEIVER(this)) { | 540 if (!IS_RECEIVER(this)) { |
| 517 throw %make_type_error(kCalledOnNonObject, PromiseRace); | 541 throw %make_type_error(kCalledOnNonObject, PromiseRace); |
| 518 } | 542 } |
| 519 | 543 |
| 520 var deferred = NewPromiseCapability(this); | 544 // false debugEvent so that forwarding the rejection through race does not |
| 545 // trigger redundant ExceptionEvents |
| 546 var deferred = NewPromiseCapability(this, false); |
| 521 try { | 547 try { |
| 522 for (var value of iterable) { | 548 for (var value of iterable) { |
| 523 this.resolve(value).then(deferred.resolve, deferred.reject); | 549 this.resolve(value).then(deferred.resolve, deferred.reject); |
| 524 SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred); | 550 SET_PRIVATE(deferred.reject, promiseCombinedDeferredSymbol, deferred); |
| 525 } | 551 } |
| 526 } catch (e) { | 552 } catch (e) { |
| 527 deferred.reject(e) | 553 deferred.reject(e) |
| 528 } | 554 } |
| 529 return deferred.promise; | 555 return deferred.promise; |
| 530 } | 556 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 | 617 |
| 592 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ | 618 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ |
| 593 "then", PromiseThen, | 619 "then", PromiseThen, |
| 594 "catch", PromiseCatch | 620 "catch", PromiseCatch |
| 595 ]); | 621 ]); |
| 596 | 622 |
| 597 %InstallToContext([ | 623 %InstallToContext([ |
| 598 "promise_catch", PromiseCatch, | 624 "promise_catch", PromiseCatch, |
| 599 "promise_create", PromiseCreate, | 625 "promise_create", PromiseCreate, |
| 600 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, | 626 "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, |
| 601 "promise_reject", RejectPromise, | 627 "promise_reject", DoRejectPromise, |
| 602 "promise_resolve", ResolvePromise, | 628 "promise_resolve", ResolvePromise, |
| 603 "promise_then", PromiseThen, | 629 "promise_then", PromiseThen, |
| 604 "promise_create_rejected", PromiseCreateRejected, | 630 "promise_create_rejected", PromiseCreateRejected, |
| 605 "promise_create_resolved", PromiseCreateResolved | 631 "promise_create_resolved", PromiseCreateResolved |
| 606 ]); | 632 ]); |
| 607 | 633 |
| 608 // This allows extras to create promises quickly without building extra | 634 // This allows extras to create promises quickly without building extra |
| 609 // resolve/reject closures, and allows them to later resolve and reject any | 635 // resolve/reject closures, and allows them to later resolve and reject any |
| 610 // promise without having to hold on to those closures forever. | 636 // promise without having to hold on to those closures forever. |
| 611 utils.InstallFunctions(extrasUtils, 0, [ | 637 utils.InstallFunctions(extrasUtils, 0, [ |
| 612 "createPromise", PromiseCreate, | 638 "createPromise", PromiseCreate, |
| 613 "resolvePromise", ResolvePromise, | 639 "resolvePromise", ResolvePromise, |
| 614 "rejectPromise", RejectPromise | 640 "rejectPromise", DoRejectPromise |
| 615 ]); | 641 ]); |
| 616 | 642 |
| 617 utils.Export(function(to) { | 643 utils.Export(function(to) { |
| 618 to.PromiseCastResolved = PromiseCastResolved; | 644 to.PromiseCastResolved = PromiseCastResolved; |
| 619 to.PromiseThen = PromiseThen; | 645 to.PromiseThen = PromiseThen; |
| 620 | 646 |
| 621 to.GlobalPromise = GlobalPromise; | 647 to.GlobalPromise = GlobalPromise; |
| 622 to.NewPromiseCapability = NewPromiseCapability; | 648 to.NewPromiseCapability = NewPromiseCapability; |
| 623 to.PerformPromiseThen = PerformPromiseThen; | 649 to.PerformPromiseThen = PerformPromiseThen; |
| 624 }); | 650 }); |
| 625 | 651 |
| 626 }) | 652 }) |
| OLD | NEW |