| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c23e8b5 commit ec0ff70
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -28,7 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | 29 | # Reset this number to 0 on major V8 upgrades. | |
| 30 | 30 | # Increment by one for each non-official patch applied to deps/v8. | |
| 31 | - 'v8_embedder_string': '-node.16', | ||
| 31 | + 'v8_embedder_string': '-node.17', | ||
| 32 | 32 | ||
| 33 | 33 | # Enable disassembler for `--print-code` v8 options | |
| 34 | 34 | 'v8_enable_disassembler': 1, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6394,7 +6394,9 @@ typedef void (*PromiseHook)(PromiseHookType type, Local<Promise> promise, | |||
| 6394 | 6394 | // --- Promise Reject Callback --- | |
| 6395 | 6395 | enum PromiseRejectEvent { | |
| 6396 | 6396 | kPromiseRejectWithNoHandler = 0, | |
| 6397 | - kPromiseHandlerAddedAfterReject = 1 | ||
| 6397 | + kPromiseHandlerAddedAfterReject = 1, | ||
| 6398 | + kPromiseRejectAfterResolved = 2, | ||
| 6399 | + kPromiseResolveAfterResolved = 3, | ||
| 6398 | 6400 | }; | |
| 6399 | 6401 | ||
| 6400 | 6402 | class PromiseRejectMessage { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -247,6 +247,8 @@ Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( | |||
| 247 | 247 | Node* const context = | |
| 248 | 248 | CreatePromiseContext(native_context, kPromiseContextLength); | |
| 249 | 249 | StoreContextElementNoWriteBarrier(context, kPromiseSlot, promise); | |
| 250 | + StoreContextElementNoWriteBarrier(context, kAlreadyResolvedSlot, | ||
| 251 | + FalseConstant()); | ||
| 250 | 252 | StoreContextElementNoWriteBarrier(context, kDebugEventSlot, debug_event); | |
| 251 | 253 | return context; | |
| 252 | 254 | } | |
@@ -733,17 +735,27 @@ TF_BUILTIN(PromiseCapabilityDefaultReject, PromiseBuiltinsAssembler) { | |||
| 733 | 735 | Node* const promise = LoadContextElement(context, kPromiseSlot); | |
| 734 | 736 | ||
| 735 | 737 | // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | |
| 738 | + Label if_already_resolved(this, Label::kDeferred); | ||
| 739 | + Node* const already_resolved = | ||
| 740 | + LoadContextElement(context, kAlreadyResolvedSlot); | ||
| 741 | + | ||
| 736 | 742 | // 4. If alreadyResolved.[[Value]] is true, return undefined. | |
| 737 | - // We use undefined as a marker for the [[AlreadyResolved]] state. | ||
| 738 | - ReturnIf(IsUndefined(promise), UndefinedConstant()); | ||
| 743 | + GotoIf(IsTrue(already_resolved), &if_already_resolved); | ||
| 739 | 744 | ||
| 740 | 745 | // 5. Set alreadyResolved.[[Value]] to true. | |
| 741 | - StoreContextElementNoWriteBarrier(context, kPromiseSlot, UndefinedConstant()); | ||
| 746 | + StoreContextElementNoWriteBarrier(context, kAlreadyResolvedSlot, | ||
| 747 | + TrueConstant()); | ||
| 742 | 748 | ||
| 743 | 749 | // 6. Return RejectPromise(promise, reason). | |
| 744 | 750 | Node* const debug_event = LoadContextElement(context, kDebugEventSlot); | |
| 745 | 751 | Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason, | |
| 746 | 752 | debug_event)); | |
| 753 | + | ||
| 754 | + BIND(&if_already_resolved); | ||
| 755 | + { | ||
| 756 | + Return(CallRuntime(Runtime::kPromiseRejectAfterResolved, context, promise, | ||
| 757 | + reason)); | ||
| 758 | + } | ||
| 747 | 759 | } | |
| 748 | 760 | ||
| 749 | 761 | // ES #sec-promise-resolve-functions | |
@@ -755,16 +767,26 @@ TF_BUILTIN(PromiseCapabilityDefaultResolve, PromiseBuiltinsAssembler) { | |||
| 755 | 767 | Node* const promise = LoadContextElement(context, kPromiseSlot); | |
| 756 | 768 | ||
| 757 | 769 | // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | |
| 770 | + Label if_already_resolved(this, Label::kDeferred); | ||
| 771 | + Node* const already_resolved = | ||
| 772 | + LoadContextElement(context, kAlreadyResolvedSlot); | ||
| 773 | + | ||
| 758 | 774 | // 4. If alreadyResolved.[[Value]] is true, return undefined. | |
| 759 | - // We use undefined as a marker for the [[AlreadyResolved]] state. | ||
| 760 | - ReturnIf(IsUndefined(promise), UndefinedConstant()); | ||
| 775 | + GotoIf(IsTrue(already_resolved), &if_already_resolved); | ||
| 761 | 776 | ||
| 762 | 777 | // 5. Set alreadyResolved.[[Value]] to true. | |
| 763 | - StoreContextElementNoWriteBarrier(context, kPromiseSlot, UndefinedConstant()); | ||
| 778 | + StoreContextElementNoWriteBarrier(context, kAlreadyResolvedSlot, | ||
| 779 | + TrueConstant()); | ||
| 764 | 780 | ||
| 765 | 781 | // The rest of the logic (and the catch prediction) is | |
| 766 | 782 | // encapsulated in the dedicated ResolvePromise builtin. | |
| 767 | 783 | Return(CallBuiltin(Builtins::kResolvePromise, context, promise, resolution)); | |
| 784 | + | ||
| 785 | + BIND(&if_already_resolved); | ||
| 786 | + { | ||
| 787 | + Return(CallRuntime(Runtime::kPromiseResolveAfterResolved, context, promise, | ||
| 788 | + resolution)); | ||
| 789 | + } | ||
| 768 | 790 | } | |
| 769 | 791 | ||
| 770 | 792 | TF_BUILTIN(PromiseConstructorLazyDeoptContinuation, PromiseBuiltinsAssembler) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,11 +17,12 @@ typedef compiler::CodeAssemblerState CodeAssemblerState; | |||
| 17 | 17 | class PromiseBuiltinsAssembler : public CodeStubAssembler { | |
| 18 | 18 | public: | |
| 19 | 19 | enum PromiseResolvingFunctionContextSlot { | |
| 20 | - // The promise which resolve/reject callbacks fulfill. If this is | ||
| 21 | - // undefined, then we've already visited this callback and it | ||
| 22 | - // should be a no-op. | ||
| 20 | + // The promise which resolve/reject callbacks fulfill. | ||
| 23 | 21 | kPromiseSlot = Context::MIN_CONTEXT_SLOTS, | |
| 24 | 22 | ||
| 23 | + // Whether the callback was already invoked. | ||
| 24 | + kAlreadyResolvedSlot, | ||
| 25 | + | ||
| 25 | 26 | // Whether to trigger a debug event or not. Used in catch | |
| 26 | 27 | // prediction. | |
| 27 | 28 | kDebugEventSlot, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5345,6 +5345,10 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { | |||
| 5345 | 5345 | graph()->NewNode(simplified()->StoreField(AccessBuilder::ForContextSlot( | |
| 5346 | 5346 | PromiseBuiltinsAssembler::kPromiseSlot)), | |
| 5347 | 5347 | promise_context, promise, effect, control); | |
| 5348 | + effect = graph()->NewNode( | ||
| 5349 | + simplified()->StoreField(AccessBuilder::ForContextSlot( | ||
| 5350 | + PromiseBuiltinsAssembler::kAlreadyResolvedSlot)), | ||
| 5351 | + promise_context, jsgraph()->FalseConstant(), effect, control); | ||
| 5348 | 5352 | effect = graph()->NewNode( | |
| 5349 | 5353 | simplified()->StoreField(AccessBuilder::ForContextSlot( | |
| 5350 | 5354 | PromiseBuiltinsAssembler::kDebugEventSlot)), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3875,10 +3875,9 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { | |||
| 3875 | 3875 | void Isolate::ReportPromiseReject(Handle<JSPromise> promise, | |
| 3876 | 3876 | Handle<Object> value, | |
| 3877 | 3877 | v8::PromiseRejectEvent event) { | |
| 3878 | - DCHECK_EQ(v8::Promise::kRejected, promise->status()); | ||
| 3879 | 3878 | if (promise_reject_callback_ == nullptr) return; | |
| 3880 | 3879 | Handle<FixedArray> stack_trace; | |
| 3881 | - if (event == v8::kPromiseRejectWithNoHandler && value->IsJSObject()) { | ||
| 3880 | + if (event != v8::kPromiseHandlerAddedAfterReject && value->IsJSObject()) { | ||
| 3882 | 3881 | stack_trace = GetDetailedStackTrace(Handle<JSObject>::cast(value)); | |
| 3883 | 3882 | } | |
| 3884 | 3883 | promise_reject_callback_(v8::PromiseRejectMessage( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -38,6 +38,26 @@ RUNTIME_FUNCTION(Runtime_PromiseRejectEventFromStack) { | |||
| 38 | 38 | return isolate->heap()->undefined_value(); | |
| 39 | 39 | } | |
| 40 | 40 | ||
| 41 | + RUNTIME_FUNCTION(Runtime_PromiseRejectAfterResolved) { | ||
| 42 | + DCHECK_EQ(2, args.length()); | ||
| 43 | + HandleScope scope(isolate); | ||
| 44 | + CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); | ||
| 45 | + CONVERT_ARG_HANDLE_CHECKED(Object, reason, 1); | ||
| 46 | + isolate->ReportPromiseReject(promise, reason, | ||
| 47 | + v8::kPromiseRejectAfterResolved); | ||
| 48 | + return isolate->heap()->undefined_value(); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + RUNTIME_FUNCTION(Runtime_PromiseResolveAfterResolved) { | ||
| 52 | + DCHECK_EQ(2, args.length()); | ||
| 53 | + HandleScope scope(isolate); | ||
| 54 | + CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); | ||
| 55 | + CONVERT_ARG_HANDLE_CHECKED(Object, resolution, 1); | ||
| 56 | + isolate->ReportPromiseReject(promise, resolution, | ||
| 57 | + v8::kPromiseResolveAfterResolved); | ||
| 58 | + return isolate->heap()->undefined_value(); | ||
| 59 | + } | ||
| 60 | + | ||
| 41 | 61 | RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) { | |
| 42 | 62 | DCHECK_EQ(1, args.length()); | |
| 43 | 63 | HandleScope scope(isolate); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -433,7 +433,9 @@ namespace internal { | |||
| 433 | 433 | F(PromiseRevokeReject, 1, 1) \ | |
| 434 | 434 | F(PromiseStatus, 1, 1) \ | |
| 435 | 435 | F(RejectPromise, 3, 1) \ | |
| 436 | - F(ResolvePromise, 2, 1) | ||
| 436 | + F(ResolvePromise, 2, 1) \ | ||
| 437 | + F(PromiseRejectAfterResolved, 2, 1) \ | ||
| 438 | + F(PromiseResolveAfterResolved, 2, 1) | ||
| 437 | 439 | ||
| 438 | 440 | #define FOR_EACH_INTRINSIC_PROXY(F) \ | |
| 439 | 441 | F(CheckProxyGetSetTrapResult, 2, 1) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17625,6 +17625,8 @@ TEST(RethrowBogusErrorStackTrace) { | |||
| 17625 | 17625 | v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler; | |
| 17626 | 17626 | int promise_reject_counter = 0; | |
| 17627 | 17627 | int promise_revoke_counter = 0; | |
| 17628 | + int promise_reject_after_resolved_counter = 0; | ||
| 17629 | + int promise_resolve_after_resolved_counter = 0; | ||
| 17628 | 17630 | int promise_reject_msg_line_number = -1; | |
| 17629 | 17631 | int promise_reject_msg_column_number = -1; | |
| 17630 | 17632 | int promise_reject_line_number = -1; | |
@@ -17634,40 +17636,56 @@ int promise_reject_frame_count = -1; | |||
| 17634 | 17636 | void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) { | |
| 17635 | 17637 | v8::Local<v8::Object> global = CcTest::global(); | |
| 17636 | 17638 | v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); | |
| 17637 | - CHECK_EQ(v8::Promise::PromiseState::kRejected, | ||
| 17639 | + CHECK_NE(v8::Promise::PromiseState::kPending, | ||
| 17638 | 17640 | reject_message.GetPromise()->State()); | |
| 17639 | - if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) { | ||
| 17640 | - promise_reject_counter++; | ||
| 17641 | - global->Set(context, v8_str("rejected"), reject_message.GetPromise()) | ||
| 17642 | - .FromJust(); | ||
| 17643 | - global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust(); | ||
| 17644 | - v8::Local<v8::Message> message = v8::Exception::CreateMessage( | ||
| 17645 | - CcTest::isolate(), reject_message.GetValue()); | ||
| 17646 | - v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace(); | ||
| 17647 | - | ||
| 17648 | - promise_reject_msg_line_number = message->GetLineNumber(context).FromJust(); | ||
| 17649 | - promise_reject_msg_column_number = | ||
| 17650 | - message->GetStartColumn(context).FromJust() + 1; | ||
| 17651 | - | ||
| 17652 | - if (!stack_trace.IsEmpty()) { | ||
| 17653 | - promise_reject_frame_count = stack_trace->GetFrameCount(); | ||
| 17654 | - if (promise_reject_frame_count > 0) { | ||
| 17655 | - CHECK(stack_trace->GetFrame(0) | ||
| 17656 | - ->GetScriptName() | ||
| 17657 | - ->Equals(context, v8_str("pro")) | ||
| 17658 | - .FromJust()); | ||
| 17659 | - promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber(); | ||
| 17660 | - promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn(); | ||
| 17661 | - } else { | ||
| 17662 | - promise_reject_line_number = -1; | ||
| 17663 | - promise_reject_column_number = -1; | ||
| 17641 | + switch (reject_message.GetEvent()) { | ||
| 17642 | + case v8::kPromiseRejectWithNoHandler: { | ||
| 17643 | + promise_reject_counter++; | ||
| 17644 | + global->Set(context, v8_str("rejected"), reject_message.GetPromise()) | ||
| 17645 | + .FromJust(); | ||
| 17646 | + global->Set(context, v8_str("value"), reject_message.GetValue()) | ||
| 17647 | + .FromJust(); | ||
| 17648 | + v8::Local<v8::Message> message = v8::Exception::CreateMessage( | ||
| 17649 | + CcTest::isolate(), reject_message.GetValue()); | ||
| 17650 | + v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace(); | ||
| 17651 | + | ||
| 17652 | + promise_reject_msg_line_number = | ||
| 17653 | + message->GetLineNumber(context).FromJust(); | ||
| 17654 | + promise_reject_msg_column_number = | ||
| 17655 | + message->GetStartColumn(context).FromJust() + 1; | ||
| 17656 | + | ||
| 17657 | + if (!stack_trace.IsEmpty()) { | ||
| 17658 | + promise_reject_frame_count = stack_trace->GetFrameCount(); | ||
| 17659 | + if (promise_reject_frame_count > 0) { | ||
| 17660 | + CHECK(stack_trace->GetFrame(0) | ||
| 17661 | + ->GetScriptName() | ||
| 17662 | + ->Equals(context, v8_str("pro")) | ||
| 17663 | + .FromJust()); | ||
| 17664 | + promise_reject_line_number = | ||
| 17665 | + stack_trace->GetFrame(0)->GetLineNumber(); | ||
| 17666 | + promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn(); | ||
| 17667 | + } else { | ||
| 17668 | + promise_reject_line_number = -1; | ||
| 17669 | + promise_reject_column_number = -1; | ||
| 17670 | + } | ||
| 17664 | 17671 | } | |
| 17672 | + break; | ||
| 17673 | + } | ||
| 17674 | + case v8::kPromiseHandlerAddedAfterReject: { | ||
| 17675 | + promise_revoke_counter++; | ||
| 17676 | + global->Set(context, v8_str("revoked"), reject_message.GetPromise()) | ||
| 17677 | + .FromJust(); | ||
| 17678 | + CHECK(reject_message.GetValue().IsEmpty()); | ||
| 17679 | + break; | ||
| 17680 | + } | ||
| 17681 | + case v8::kPromiseRejectAfterResolved: { | ||
| 17682 | + promise_reject_after_resolved_counter++; | ||
| 17683 | + break; | ||
| 17684 | + } | ||
| 17685 | + case v8::kPromiseResolveAfterResolved: { | ||
| 17686 | + promise_resolve_after_resolved_counter++; | ||
| 17687 | + break; | ||
| 17665 | 17688 | } | |
| 17666 | - } else { | ||
| 17667 | - promise_revoke_counter++; | ||
| 17668 | - global->Set(context, v8_str("revoked"), reject_message.GetPromise()) | ||
| 17669 | - .FromJust(); | ||
| 17670 | - CHECK(reject_message.GetValue().IsEmpty()); | ||
| 17671 | 17689 | } | |
| 17672 | 17690 | } | |
| 17673 | 17691 | ||
@@ -17690,6 +17708,8 @@ v8::Local<v8::Value> RejectValue() { | |||
| 17690 | 17708 | void ResetPromiseStates() { | |
| 17691 | 17709 | promise_reject_counter = 0; | |
| 17692 | 17710 | promise_revoke_counter = 0; | |
| 17711 | + promise_reject_after_resolved_counter = 0; | ||
| 17712 | + promise_resolve_after_resolved_counter = 0; | ||
| 17693 | 17713 | promise_reject_msg_line_number = -1; | |
| 17694 | 17714 | promise_reject_msg_column_number = -1; | |
| 17695 | 17715 | promise_reject_line_number = -1; | |
@@ -17915,6 +17935,40 @@ TEST(PromiseRejectCallback) { | |||
| 17915 | 17935 | CHECK_EQ(0, promise_revoke_counter); | |
| 17916 | 17936 | CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust()); | |
| 17917 | 17937 | ||
| 17938 | + ResetPromiseStates(); | ||
| 17939 | + | ||
| 17940 | + // Swallowed exceptions in the Promise constructor. | ||
| 17941 | + CompileRun( | ||
| 17942 | + "var v0 = new Promise(\n" | ||
| 17943 | + " function(res, rej) {\n" | ||
| 17944 | + " res(1);\n" | ||
| 17945 | + " throw new Error();\n" | ||
| 17946 | + " }\n" | ||
| 17947 | + ");\n"); | ||
| 17948 | + CHECK(!GetPromise("v0")->HasHandler()); | ||
| 17949 | + CHECK_EQ(0, promise_reject_counter); | ||
| 17950 | + CHECK_EQ(0, promise_revoke_counter); | ||
| 17951 | + CHECK_EQ(1, promise_reject_after_resolved_counter); | ||
| 17952 | + CHECK_EQ(0, promise_resolve_after_resolved_counter); | ||
| 17953 | + | ||
| 17954 | + ResetPromiseStates(); | ||
| 17955 | + | ||
| 17956 | + // Duplication resolve. | ||
| 17957 | + CompileRun( | ||
| 17958 | + "var r;\n" | ||
| 17959 | + "var y0 = new Promise(\n" | ||
| 17960 | + " function(res, rej) {\n" | ||
| 17961 | + " r = res;\n" | ||
| 17962 | + " throw new Error();\n" | ||
| 17963 | + " }\n" | ||
| 17964 | + ");\n" | ||
| 17965 | + "r(1);\n"); | ||
| 17966 | + CHECK(!GetPromise("y0")->HasHandler()); | ||
| 17967 | + CHECK_EQ(1, promise_reject_counter); | ||
| 17968 | + CHECK_EQ(0, promise_revoke_counter); | ||
| 17969 | + CHECK_EQ(0, promise_reject_after_resolved_counter); | ||
| 17970 | + CHECK_EQ(1, promise_resolve_after_resolved_counter); | ||
| 17971 | + | ||
| 17918 | 17972 | // Test stack frames. | |
| 17919 | 17973 | env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true); | |
| 17920 | 17974 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments