| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/builtins/builtins-promise.h" | 5 #include "src/builtins/builtins-promise.h" |
| 6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
| 7 #include "src/builtins/builtins.h" | 7 #include "src/builtins/builtins.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
| 10 #include "src/promise-utils.h" | 10 #include "src/promise-utils.h" |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags); | 173 Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags); |
| 174 | 174 |
| 175 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode, | 175 CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode, |
| 176 mode); | 176 mode); |
| 177 StoreFixedArrayElement(new_elements, length, value, barrier_mode, | 177 StoreFixedArrayElement(new_elements, length, value, barrier_mode, |
| 178 additional_offset, mode); | 178 additional_offset, mode); |
| 179 | 179 |
| 180 StoreObjectField(promise, offset, new_elements); | 180 StoreObjectField(promise, offset, new_elements); |
| 181 } | 181 } |
| 182 | 182 |
| 183 Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context, |
| 184 Node* promise, |
| 185 Node* on_resolve, |
| 186 Node* on_reject) { |
| 187 Isolate* isolate = this->isolate(); |
| 188 |
| 189 // 2. If IsPromise(promise) is false, throw a TypeError exception. |
| 190 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE, |
| 191 "Promise.prototype.then"); |
| 192 |
| 193 Node* const native_context = LoadNativeContext(context); |
| 194 Node* const promise_fun = |
| 195 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
| 196 |
| 197 // 3. Let C be ? SpeciesConstructor(promise, %Promise%). |
| 198 Node* constructor = SpeciesConstructor(context, promise, promise_fun); |
| 199 |
| 200 // 4. Let resultCapability be ? NewPromiseCapability(C). |
| 201 Callable call_callable = CodeFactory::Call(isolate); |
| 202 Label fast_promise_capability(this), promise_capability(this), |
| 203 perform_promise_then(this); |
| 204 Variable var_deferred(this, MachineRepresentation::kTagged); |
| 205 |
| 206 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, |
| 207 &promise_capability); |
| 208 |
| 209 // TODO(gsathya): Remove deferred object and move |
| 210 // NewPromiseCapabability functions to TF. |
| 211 Bind(&fast_promise_capability); |
| 212 { |
| 213 // TODO(gsathya): Move this to TF. |
| 214 Node* const promise_internal_capability = LoadContextElement( |
| 215 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); |
| 216 Node* const capability = |
| 217 CallJS(call_callable, context, promise_internal_capability, |
| 218 UndefinedConstant(), promise); |
| 219 var_deferred.Bind(capability); |
| 220 Goto(&perform_promise_then); |
| 221 } |
| 222 |
| 223 Bind(&promise_capability); |
| 224 { |
| 225 // TODO(gsathya): Move this to TF. |
| 226 Node* const new_promise_capability = LoadContextElement( |
| 227 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); |
| 228 Node* const capability = |
| 229 CallJS(call_callable, context, new_promise_capability, |
| 230 UndefinedConstant(), constructor); |
| 231 var_deferred.Bind(capability); |
| 232 Goto(&perform_promise_then); |
| 233 } |
| 234 |
| 235 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, |
| 236 // resultCapability). |
| 237 Bind(&perform_promise_then); |
| 238 Node* const result = InternalPerformPromiseThen( |
| 239 context, promise, on_resolve, on_reject, var_deferred.value()); |
| 240 return result; |
| 241 } |
| 242 |
| 183 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, | 243 Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(Node* context, |
| 184 Node* promise, | 244 Node* promise, |
| 185 Node* on_resolve, | 245 Node* on_resolve, |
| 186 Node* on_reject, | 246 Node* on_reject, |
| 187 Node* deferred) { | 247 Node* deferred) { |
| 188 Node* const native_context = LoadNativeContext(context); | 248 Node* const native_context = LoadNativeContext(context); |
| 189 | 249 |
| 190 Variable var_on_resolve(this, MachineRepresentation::kTagged), | 250 Variable var_on_resolve(this, MachineRepresentation::kTagged), |
| 191 var_on_reject(this, MachineRepresentation::kTagged); | 251 var_on_reject(this, MachineRepresentation::kTagged); |
| 192 | 252 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX); | 431 LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX); |
| 372 Node* const proto_map = LoadMap(LoadMapPrototype(map)); | 432 Node* const proto_map = LoadMap(LoadMapPrototype(map)); |
| 373 Node* const proto_has_initialmap = | 433 Node* const proto_has_initialmap = |
| 374 WordEqual(proto_map, initial_proto_initial_map); | 434 WordEqual(proto_map, initial_proto_initial_map); |
| 375 | 435 |
| 376 Branch(proto_has_initialmap, if_isunmodified, if_ismodified); | 436 Branch(proto_has_initialmap, if_isunmodified, if_ismodified); |
| 377 } | 437 } |
| 378 | 438 |
| 379 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context, | 439 void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context, |
| 380 Node* promise, | 440 Node* promise, |
| 381 Node* result, | 441 Node* result) { |
| 382 Label* out) { | |
| 383 Isolate* isolate = this->isolate(); | 442 Isolate* isolate = this->isolate(); |
| 384 | 443 |
| 385 Variable var_reason(this, MachineRepresentation::kTagged), | 444 Variable var_reason(this, MachineRepresentation::kTagged), |
| 386 var_then(this, MachineRepresentation::kTagged); | 445 var_then(this, MachineRepresentation::kTagged); |
| 387 | 446 |
| 388 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), | 447 Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred), |
| 389 if_rejectpromise(this, Label::kDeferred); | 448 if_rejectpromise(this, Label::kDeferred), out(this); |
| 390 | 449 |
| 391 Label cycle_check(this); | 450 Label cycle_check(this); |
| 392 GotoUnless(IsPromiseHookEnabled(), &cycle_check); | 451 GotoUnless(IsPromiseHookEnabled(), &cycle_check); |
| 393 CallRuntime(Runtime::kPromiseHookResolve, context, promise); | 452 CallRuntime(Runtime::kPromiseHookResolve, context, promise); |
| 394 Goto(&cycle_check); | 453 Goto(&cycle_check); |
| 395 | 454 |
| 396 Bind(&cycle_check); | 455 Bind(&cycle_check); |
| 397 // 6. If SameValue(resolution, promise) is true, then | 456 // 6. If SameValue(resolution, promise) is true, then |
| 398 GotoIf(SameValue(promise, result, context), &if_cycle); | 457 GotoIf(SameValue(promise, result, context), &if_cycle); |
| 399 | 458 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 { | 490 { |
| 432 Label if_fulfilled(this), if_rejected(this); | 491 Label if_fulfilled(this), if_rejected(this); |
| 433 Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status), | 492 Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status), |
| 434 &if_fulfilled, &if_rejected); | 493 &if_fulfilled, &if_rejected); |
| 435 | 494 |
| 436 Bind(&if_fulfilled); | 495 Bind(&if_fulfilled); |
| 437 { | 496 { |
| 438 CallRuntime(Runtime::kPromiseFulfill, context, promise, | 497 CallRuntime(Runtime::kPromiseFulfill, context, promise, |
| 439 SmiConstant(v8::Promise::kFulfilled), thenable_value); | 498 SmiConstant(v8::Promise::kFulfilled), thenable_value); |
| 440 PromiseSetHasHandler(promise); | 499 PromiseSetHasHandler(promise); |
| 441 Goto(out); | 500 Goto(&out); |
| 442 } | 501 } |
| 443 | 502 |
| 444 Bind(&if_rejected); | 503 Bind(&if_rejected); |
| 445 { | 504 { |
| 446 Label reject(this); | 505 Label reject(this); |
| 447 Node* const has_handler = PromiseHasHandler(result); | 506 Node* const has_handler = PromiseHasHandler(result); |
| 448 | 507 |
| 449 // Promise has already been rejected, but had no handler. | 508 // Promise has already been rejected, but had no handler. |
| 450 // Revoke previously triggered reject event. | 509 // Revoke previously triggered reject event. |
| 451 GotoIf(has_handler, &reject); | 510 GotoIf(has_handler, &reject); |
| 452 CallRuntime(Runtime::kPromiseRevokeReject, context, result); | 511 CallRuntime(Runtime::kPromiseRevokeReject, context, result); |
| 453 Goto(&reject); | 512 Goto(&reject); |
| 454 | 513 |
| 455 Bind(&reject); | 514 Bind(&reject); |
| 456 // Don't cause a debug event as this case is forwarding a rejection | 515 // Don't cause a debug event as this case is forwarding a rejection |
| 457 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value, | 516 CallRuntime(Runtime::kPromiseReject, context, promise, thenable_value, |
| 458 FalseConstant()); | 517 FalseConstant()); |
| 459 PromiseSetHasHandler(result); | 518 PromiseSetHasHandler(result); |
| 460 Goto(out); | 519 Goto(&out); |
| 461 } | 520 } |
| 462 } | 521 } |
| 463 } | 522 } |
| 464 | 523 |
| 465 Bind(&if_notnativepromise); | 524 Bind(&if_notnativepromise); |
| 466 { | 525 { |
| 467 // 8. Let then be Get(resolution, "then"). | 526 // 8. Let then be Get(resolution, "then"). |
| 468 Node* const then_str = HeapConstant(isolate->factory()->then_string()); | 527 Node* const then_str = HeapConstant(isolate->factory()->then_string()); |
| 469 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 528 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
| 470 Node* const then = | 529 Node* const then = |
| (...skipping 22 matching lines...) Expand all Loading... |
| 493 CallRuntime(Runtime::kSetProperty, context, result, key, promise, | 552 CallRuntime(Runtime::kSetProperty, context, result, key, promise, |
| 494 SmiConstant(STRICT)); | 553 SmiConstant(STRICT)); |
| 495 Goto(&enqueue); | 554 Goto(&enqueue); |
| 496 | 555 |
| 497 // 12. Perform EnqueueJob("PromiseJobs", | 556 // 12. Perform EnqueueJob("PromiseJobs", |
| 498 // PromiseResolveThenableJob, « promise, resolution, thenAction | 557 // PromiseResolveThenableJob, « promise, resolution, thenAction |
| 499 // »). | 558 // »). |
| 500 Bind(&enqueue); | 559 Bind(&enqueue); |
| 501 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, | 560 CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, promise, |
| 502 result, var_then.value()); | 561 result, var_then.value()); |
| 503 Goto(out); | 562 Goto(&out); |
| 504 } | 563 } |
| 505 | 564 |
| 506 // 7.b Return FulfillPromise(promise, resolution). | 565 // 7.b Return FulfillPromise(promise, resolution). |
| 507 Bind(&fulfill); | 566 Bind(&fulfill); |
| 508 { | 567 { |
| 509 CallRuntime(Runtime::kPromiseFulfill, context, promise, | 568 CallRuntime(Runtime::kPromiseFulfill, context, promise, |
| 510 SmiConstant(v8::Promise::kFulfilled), result); | 569 SmiConstant(v8::Promise::kFulfilled), result); |
| 511 Goto(out); | 570 Goto(&out); |
| 512 } | 571 } |
| 513 | 572 |
| 514 Bind(&if_cycle); | 573 Bind(&if_cycle); |
| 515 { | 574 { |
| 516 // 6.a Let selfResolutionError be a newly created TypeError object. | 575 // 6.a Let selfResolutionError be a newly created TypeError object. |
| 517 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic); | 576 Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic); |
| 518 Node* const error = | 577 Node* const error = |
| 519 CallRuntime(Runtime::kNewTypeError, context, message_id, result); | 578 CallRuntime(Runtime::kNewTypeError, context, message_id, result); |
| 520 var_reason.Bind(error); | 579 var_reason.Bind(error); |
| 521 | 580 |
| 522 // 6.b Return RejectPromise(promise, selfResolutionError). | 581 // 6.b Return RejectPromise(promise, selfResolutionError). |
| 523 Goto(&if_rejectpromise); | 582 Goto(&if_rejectpromise); |
| 524 } | 583 } |
| 525 | 584 |
| 526 // 9.a Return RejectPromise(promise, then.[[Value]]). | 585 // 9.a Return RejectPromise(promise, then.[[Value]]). |
| 527 Bind(&if_rejectpromise); | 586 Bind(&if_rejectpromise); |
| 528 { | 587 { |
| 529 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(), | 588 CallRuntime(Runtime::kPromiseReject, context, promise, var_reason.value(), |
| 530 TrueConstant()); | 589 TrueConstant()); |
| 531 Goto(out); | 590 Goto(&out); |
| 532 } | 591 } |
| 592 |
| 593 Bind(&out); |
| 533 } | 594 } |
| 534 | 595 |
| 535 // ES#sec-promise-reject-functions | 596 // ES#sec-promise-reject-functions |
| 536 // Promise Reject Functions | 597 // Promise Reject Functions |
| 537 BUILTIN(PromiseRejectClosure) { | 598 BUILTIN(PromiseRejectClosure) { |
| 538 HandleScope scope(isolate); | 599 HandleScope scope(isolate); |
| 539 | 600 |
| 540 Handle<Context> context(isolate->context(), isolate); | 601 Handle<Context> context(isolate->context(), isolate); |
| 541 | 602 |
| 542 if (PromiseUtils::HasAlreadyVisited(context)) { | 603 if (PromiseUtils::HasAlreadyVisited(context)) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 Node* const deferred = Parameter(4); | 816 Node* const deferred = Parameter(4); |
| 756 Node* const context = Parameter(7); | 817 Node* const context = Parameter(7); |
| 757 | 818 |
| 758 Node* const result = InternalPerformPromiseThen(context, promise, on_resolve, | 819 Node* const result = InternalPerformPromiseThen(context, promise, on_resolve, |
| 759 on_reject, deferred); | 820 on_reject, deferred); |
| 760 | 821 |
| 761 // TODO(gsathya): This is unused, but value is returned according to spec. | 822 // TODO(gsathya): This is unused, but value is returned according to spec. |
| 762 Return(result); | 823 Return(result); |
| 763 } | 824 } |
| 764 | 825 |
| 826 // ES#sec-promise.prototype.then |
| 827 // Promise.prototype.catch ( onFulfilled, onRejected ) |
| 765 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { | 828 TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) { |
| 766 // 1. Let promise be the this value. | 829 // 1. Let promise be the this value. |
| 767 Node* const promise = Parameter(0); | 830 Node* const promise = Parameter(0); |
| 768 Node* const on_resolve = Parameter(1); | 831 Node* const on_resolve = Parameter(1); |
| 769 Node* const on_reject = Parameter(2); | 832 Node* const on_reject = Parameter(2); |
| 770 Node* const context = Parameter(5); | 833 Node* const context = Parameter(5); |
| 771 Isolate* isolate = this->isolate(); | |
| 772 | 834 |
| 773 // 2. If IsPromise(promise) is false, throw a TypeError exception. | 835 Node* const result = |
| 774 ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE, | 836 InternalPromiseThen(context, promise, on_resolve, on_reject); |
| 775 "Promise.prototype.then"); | |
| 776 | |
| 777 Node* const native_context = LoadNativeContext(context); | |
| 778 Node* const promise_fun = | |
| 779 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); | |
| 780 | |
| 781 // 3. Let C be ? SpeciesConstructor(promise, %Promise%). | |
| 782 Node* constructor = SpeciesConstructor(context, promise, promise_fun); | |
| 783 | |
| 784 // 4. Let resultCapability be ? NewPromiseCapability(C). | |
| 785 Callable call_callable = CodeFactory::Call(isolate); | |
| 786 Label fast_promise_capability(this), promise_capability(this), | |
| 787 perform_promise_then(this); | |
| 788 Variable var_deferred(this, MachineRepresentation::kTagged); | |
| 789 | |
| 790 Branch(WordEqual(promise_fun, constructor), &fast_promise_capability, | |
| 791 &promise_capability); | |
| 792 | |
| 793 // TODO(gsathya): Remove deferred object and move | |
| 794 // NewPromiseCapabability functions to TF. | |
| 795 Bind(&fast_promise_capability); | |
| 796 { | |
| 797 // TODO(gsathya): Move this to TF. | |
| 798 Node* const promise_internal_capability = LoadContextElement( | |
| 799 native_context, Context::INTERNAL_PROMISE_CAPABILITY_INDEX); | |
| 800 Node* const capability = | |
| 801 CallJS(call_callable, context, promise_internal_capability, | |
| 802 UndefinedConstant(), promise); | |
| 803 var_deferred.Bind(capability); | |
| 804 Goto(&perform_promise_then); | |
| 805 } | |
| 806 | |
| 807 Bind(&promise_capability); | |
| 808 { | |
| 809 // TODO(gsathya): Move this to TF. | |
| 810 Node* const new_promise_capability = LoadContextElement( | |
| 811 native_context, Context::NEW_PROMISE_CAPABILITY_INDEX); | |
| 812 Node* const capability = | |
| 813 CallJS(call_callable, context, new_promise_capability, | |
| 814 UndefinedConstant(), constructor); | |
| 815 var_deferred.Bind(capability); | |
| 816 Goto(&perform_promise_then); | |
| 817 } | |
| 818 | |
| 819 // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, | |
| 820 // resultCapability). | |
| 821 Bind(&perform_promise_then); | |
| 822 Node* const result = InternalPerformPromiseThen( | |
| 823 context, promise, on_resolve, on_reject, var_deferred.value()); | |
| 824 Return(result); | 837 Return(result); |
| 825 } | 838 } |
| 826 | 839 |
| 827 // ES#sec-promise-resolve-functions | 840 // ES#sec-promise-resolve-functions |
| 828 // Promise Resolve Functions | 841 // Promise Resolve Functions |
| 829 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { | 842 TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) { |
| 830 Node* const value = Parameter(1); | 843 Node* const value = Parameter(1); |
| 831 Node* const context = Parameter(4); | 844 Node* const context = Parameter(4); |
| 832 | 845 |
| 833 Label out(this); | 846 Label out(this); |
| 834 | 847 |
| 835 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | 848 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. |
| 836 Node* const has_already_visited_slot = | 849 Node* const has_already_visited_slot = |
| 837 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); | 850 IntPtrConstant(PromiseUtils::kAlreadyVisitedSlot); |
| 838 | 851 |
| 839 Node* const has_already_visited = | 852 Node* const has_already_visited = |
| 840 LoadFixedArrayElement(context, has_already_visited_slot); | 853 LoadFixedArrayElement(context, has_already_visited_slot); |
| 841 | 854 |
| 842 // 4. If alreadyResolved.[[Value]] is true, return undefined. | 855 // 4. If alreadyResolved.[[Value]] is true, return undefined. |
| 843 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); | 856 GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out); |
| 844 | 857 |
| 845 // 5.Set alreadyResolved.[[Value]] to true. | 858 // 5.Set alreadyResolved.[[Value]] to true. |
| 846 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); | 859 StoreFixedArrayElement(context, has_already_visited_slot, SmiConstant(1)); |
| 847 | 860 |
| 848 // 2. Let promise be F.[[Promise]]. | 861 // 2. Let promise be F.[[Promise]]. |
| 849 Node* const promise = LoadFixedArrayElement( | 862 Node* const promise = LoadFixedArrayElement( |
| 850 context, IntPtrConstant(PromiseUtils::kPromiseSlot)); | 863 context, IntPtrConstant(PromiseUtils::kPromiseSlot)); |
| 851 | 864 |
| 852 InternalResolvePromise(context, promise, value, &out); | 865 InternalResolvePromise(context, promise, value); |
| 866 Return(UndefinedConstant()); |
| 853 | 867 |
| 854 Bind(&out); | 868 Bind(&out); |
| 855 Return(UndefinedConstant()); | 869 Return(UndefinedConstant()); |
| 856 } | 870 } |
| 857 | 871 |
| 858 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { | 872 TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { |
| 859 Node* const promise = Parameter(1); | 873 Node* const promise = Parameter(1); |
| 860 Node* const result = Parameter(2); | 874 Node* const result = Parameter(2); |
| 861 Node* const context = Parameter(5); | 875 Node* const context = Parameter(5); |
| 862 | 876 |
| 863 Label out(this); | 877 InternalResolvePromise(context, promise, result); |
| 864 InternalResolvePromise(context, promise, result, &out); | |
| 865 | |
| 866 Bind(&out); | |
| 867 Return(UndefinedConstant()); | 878 Return(UndefinedConstant()); |
| 868 } | 879 } |
| 869 | 880 |
| 870 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) { | 881 TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) { |
| 871 typedef PromiseHandleRejectDescriptor Descriptor; | 882 typedef PromiseHandleRejectDescriptor Descriptor; |
| 872 | 883 |
| 873 Node* const promise = Parameter(Descriptor::kPromise); | 884 Node* const promise = Parameter(Descriptor::kPromise); |
| 874 Node* const on_reject = Parameter(Descriptor::kOnReject); | 885 Node* const on_reject = Parameter(Descriptor::kOnReject); |
| 875 Node* const exception = Parameter(Descriptor::kException); | 886 Node* const exception = Parameter(Descriptor::kException); |
| 876 Node* const context = Parameter(Descriptor::kContext); | 887 Node* const context = Parameter(Descriptor::kContext); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 | 949 |
| 939 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. | 950 // TODO(gsathya): Remove this lookup by getting rid of the deferred object. |
| 940 Node* const key = HeapConstant(isolate->factory()->resolve_string()); | 951 Node* const key = HeapConstant(isolate->factory()->resolve_string()); |
| 941 Node* const on_resolve = | 952 Node* const on_resolve = |
| 942 CallStub(getproperty_callable, context, deferred, key); | 953 CallStub(getproperty_callable, context, deferred, key); |
| 943 | 954 |
| 944 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); | 955 Label if_internalhandler(this), if_customhandler(this, Label::kDeferred); |
| 945 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); | 956 Branch(IsUndefined(on_resolve), &if_internalhandler, &if_customhandler); |
| 946 | 957 |
| 947 Bind(&if_internalhandler); | 958 Bind(&if_internalhandler); |
| 948 InternalResolvePromise(context, deferred_promise, result, | 959 InternalResolvePromise(context, deferred_promise, result); |
| 949 &promisehook_after); | 960 Goto(&promisehook_after); |
| 950 | 961 |
| 951 Bind(&if_customhandler); | 962 Bind(&if_customhandler); |
| 952 { | 963 { |
| 953 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, | 964 Node* const maybe_exception = CallJS(call_callable, context, on_resolve, |
| 954 UndefinedConstant(), result); | 965 UndefinedConstant(), result); |
| 955 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); | 966 GotoIfException(maybe_exception, &if_rejectpromise, &var_reason); |
| 956 Goto(&promisehook_after); | 967 Goto(&promisehook_after); |
| 957 } | 968 } |
| 958 } | 969 } |
| 959 | 970 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 983 | 994 |
| 984 GotoUnless(is_debug_active, &out); | 995 GotoUnless(is_debug_active, &out); |
| 985 CallRuntime(Runtime::kDebugPopPromise, context); | 996 CallRuntime(Runtime::kDebugPopPromise, context); |
| 986 Goto(&out); | 997 Goto(&out); |
| 987 | 998 |
| 988 Bind(&out); | 999 Bind(&out); |
| 989 Return(UndefinedConstant()); | 1000 Return(UndefinedConstant()); |
| 990 } | 1001 } |
| 991 } | 1002 } |
| 992 | 1003 |
| 1004 // ES#sec-promise.prototype.catch |
| 1005 // Promise.prototype.catch ( onRejected ) |
| 1006 TF_BUILTIN(PromiseCatch, PromiseBuiltinsAssembler) { |
| 1007 // 1. Let promise be the this value. |
| 1008 Node* const promise = Parameter(0); |
| 1009 Node* const on_resolve = UndefinedConstant(); |
| 1010 Node* const on_reject = Parameter(1); |
| 1011 Node* const context = Parameter(4); |
| 1012 |
| 1013 Label if_internalthen(this), if_customthen(this, Label::kDeferred); |
| 1014 BranchIfFastPath(context, promise, &if_internalthen, &if_customthen); |
| 1015 |
| 1016 Bind(&if_internalthen); |
| 1017 { |
| 1018 Node* const result = |
| 1019 InternalPromiseThen(context, promise, on_resolve, on_reject); |
| 1020 Return(result); |
| 1021 } |
| 1022 |
| 1023 Bind(&if_customthen); |
| 1024 { |
| 1025 Isolate* isolate = this->isolate(); |
| 1026 Node* const then_str = HeapConstant(isolate->factory()->then_string()); |
| 1027 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
| 1028 Node* const then = |
| 1029 CallStub(getproperty_callable, context, promise, then_str); |
| 1030 Callable call_callable = CodeFactory::Call(isolate); |
| 1031 Node* const result = |
| 1032 CallJS(call_callable, context, then, promise, on_resolve, on_reject); |
| 1033 Return(result); |
| 1034 } |
| 1035 } |
| 1036 |
| 993 } // namespace internal | 1037 } // namespace internal |
| 994 } // namespace v8 | 1038 } // namespace v8 |
| OLD | NEW |