| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7299421 commit ada715f
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,7 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | 30 | # Reset this number to 0 on major V8 upgrades. | |
| 31 | 31 | # Increment by one for each non-official patch applied to deps/v8. | |
| 32 | - 'v8_embedder_string': '-node.9', | ||
| 32 | + 'v8_embedder_string': '-node.10', | ||
| 33 | 33 | ||
| 34 | 34 | # Enable disassembler for `--print-code` v8 options | |
| 35 | 35 | 'v8_enable_disassembler': 1, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6520,7 +6520,9 @@ typedef void (*PromiseHook)(PromiseHookType type, Local<Promise> promise, | |||
| 6520 | 6520 | // --- Promise Reject Callback --- | |
| 6521 | 6521 | enum PromiseRejectEvent { | |
| 6522 | 6522 | kPromiseRejectWithNoHandler = 0, | |
| 6523 | - kPromiseHandlerAddedAfterReject = 1 | ||
| 6523 | + kPromiseHandlerAddedAfterReject = 1, | ||
| 6524 | + kPromiseRejectAfterResolved = 2, | ||
| 6525 | + kPromiseResolveAfterResolved = 3, | ||
| 6524 | 6526 | }; | |
| 6525 | 6527 | ||
| 6526 | 6528 | class PromiseRejectMessage { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -246,6 +246,8 @@ Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext( | |||
| 246 | 246 | Node* const context = | |
| 247 | 247 | CreatePromiseContext(native_context, kPromiseContextLength); | |
| 248 | 248 | StoreContextElementNoWriteBarrier(context, kPromiseSlot, promise); | |
| 249 | + StoreContextElementNoWriteBarrier(context, kAlreadyResolvedSlot, | ||
| 250 | + FalseConstant()); | ||
| 249 | 251 | StoreContextElementNoWriteBarrier(context, kDebugEventSlot, debug_event); | |
| 250 | 252 | return context; | |
| 251 | 253 | } | |
@@ -736,17 +738,27 @@ TF_BUILTIN(PromiseCapabilityDefaultReject, PromiseBuiltinsAssembler) { | |||
| 736 | 738 | Node* const promise = LoadContextElement(context, kPromiseSlot); | |
| 737 | 739 | ||
| 738 | 740 | // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | |
| 741 | + Label if_already_resolved(this, Label::kDeferred); | ||
| 742 | + Node* const already_resolved = | ||
| 743 | + LoadContextElement(context, kAlreadyResolvedSlot); | ||
| 744 | + | ||
| 739 | 745 | // 4. If alreadyResolved.[[Value]] is true, return undefined. | |
| 740 | - // We use undefined as a marker for the [[AlreadyResolved]] state. | ||
| 741 | - ReturnIf(IsUndefined(promise), UndefinedConstant()); | ||
| 746 | + GotoIf(IsTrue(already_resolved), &if_already_resolved); | ||
| 742 | 747 | ||
| 743 | 748 | // 5. Set alreadyResolved.[[Value]] to true. | |
| 744 | - StoreContextElementNoWriteBarrier(context, kPromiseSlot, UndefinedConstant()); | ||
| 749 | + StoreContextElementNoWriteBarrier(context, kAlreadyResolvedSlot, | ||
| 750 | + TrueConstant()); | ||
| 745 | 751 | ||
| 746 | 752 | // 6. Return RejectPromise(promise, reason). | |
| 747 | 753 | Node* const debug_event = LoadContextElement(context, kDebugEventSlot); | |
| 748 | 754 | Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason, | |
| 749 | 755 | debug_event)); | |
| 756 | + | ||
| 757 | + BIND(&if_already_resolved); | ||
| 758 | + { | ||
| 759 | + Return(CallRuntime(Runtime::kPromiseRejectAfterResolved, context, promise, | ||
| 760 | + reason)); | ||
| 761 | + } | ||
| 750 | 762 | } | |
| 751 | 763 | ||
| 752 | 764 | // ES #sec-promise-resolve-functions | |
@@ -758,16 +770,26 @@ TF_BUILTIN(PromiseCapabilityDefaultResolve, PromiseBuiltinsAssembler) { | |||
| 758 | 770 | Node* const promise = LoadContextElement(context, kPromiseSlot); | |
| 759 | 771 | ||
| 760 | 772 | // 3. Let alreadyResolved be F.[[AlreadyResolved]]. | |
| 773 | + Label if_already_resolved(this, Label::kDeferred); | ||
| 774 | + Node* const already_resolved = | ||
| 775 | + LoadContextElement(context, kAlreadyResolvedSlot); | ||
| 776 | + | ||
| 761 | 777 | // 4. If alreadyResolved.[[Value]] is true, return undefined. | |
| 762 | - // We use undefined as a marker for the [[AlreadyResolved]] state. | ||
| 763 | - ReturnIf(IsUndefined(promise), UndefinedConstant()); | ||
| 778 | + GotoIf(IsTrue(already_resolved), &if_already_resolved); | ||
| 764 | 779 | ||
| 765 | 780 | // 5. Set alreadyResolved.[[Value]] to true. | |
| 766 | - StoreContextElementNoWriteBarrier(context, kPromiseSlot, UndefinedConstant()); | ||
| 781 | + StoreContextElementNoWriteBarrier(context, kAlreadyResolvedSlot, | ||
| 782 | + TrueConstant()); | ||
| 767 | 783 | ||
| 768 | 784 | // The rest of the logic (and the catch prediction) is | |
| 769 | 785 | // encapsulated in the dedicated ResolvePromise builtin. | |
| 770 | 786 | Return(CallBuiltin(Builtins::kResolvePromise, context, promise, resolution)); | |
| 787 | + | ||
| 788 | + BIND(&if_already_resolved); | ||
| 789 | + { | ||
| 790 | + Return(CallRuntime(Runtime::kPromiseResolveAfterResolved, context, promise, | ||
| 791 | + resolution)); | ||
| 792 | + } | ||
| 771 | 793 | } | |
| 772 | 794 | ||
| 773 | 795 | 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 | |
|---|---|---|---|
@@ -5406,6 +5406,10 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) { | |||
| 5406 | 5406 | graph()->NewNode(simplified()->StoreField(AccessBuilder::ForContextSlot( | |
| 5407 | 5407 | PromiseBuiltinsAssembler::kPromiseSlot)), | |
| 5408 | 5408 | promise_context, promise, effect, control); | |
| 5409 | + effect = graph()->NewNode( | ||
| 5410 | + simplified()->StoreField(AccessBuilder::ForContextSlot( | ||
| 5411 | + PromiseBuiltinsAssembler::kAlreadyResolvedSlot)), | ||
| 5412 | + promise_context, jsgraph()->FalseConstant(), effect, control); | ||
| 5409 | 5413 | effect = graph()->NewNode( | |
| 5410 | 5414 | simplified()->StoreField(AccessBuilder::ForContextSlot( | |
| 5411 | 5415 | PromiseBuiltinsAssembler::kDebugEventSlot)), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3872,10 +3872,9 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { | |||
| 3872 | 3872 | void Isolate::ReportPromiseReject(Handle<JSPromise> promise, | |
| 3873 | 3873 | Handle<Object> value, | |
| 3874 | 3874 | v8::PromiseRejectEvent event) { | |
| 3875 | - DCHECK_EQ(v8::Promise::kRejected, promise->status()); | ||
| 3876 | 3875 | if (promise_reject_callback_ == nullptr) return; | |
| 3877 | 3876 | Handle<FixedArray> stack_trace; | |
| 3878 | - if (event == v8::kPromiseRejectWithNoHandler && value->IsJSObject()) { | ||
| 3877 | + if (event != v8::kPromiseHandlerAddedAfterReject && value->IsJSObject()) { | ||
| 3879 | 3878 | stack_trace = GetDetailedStackTrace(Handle<JSObject>::cast(value)); | |
| 3880 | 3879 | } | |
| 3881 | 3880 | 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 | |
|---|---|---|---|
@@ -432,7 +432,9 @@ namespace internal { | |||
| 432 | 432 | F(PromiseRevokeReject, 1, 1) \ | |
| 433 | 433 | F(PromiseStatus, 1, 1) \ | |
| 434 | 434 | F(RejectPromise, 3, 1) \ | |
| 435 | - F(ResolvePromise, 2, 1) | ||
| 435 | + F(ResolvePromise, 2, 1) \ | ||
| 436 | + F(PromiseRejectAfterResolved, 2, 1) \ | ||
| 437 | + F(PromiseResolveAfterResolved, 2, 1) | ||
| 436 | 438 | ||
| 437 | 439 | #define FOR_EACH_INTRINSIC_PROXY(F) \ | |
| 438 | 440 | F(CheckProxyGetSetTrapResult, 2, 1) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17700,6 +17700,8 @@ TEST(RethrowBogusErrorStackTrace) { | |||
| 17700 | 17700 | v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler; | |
| 17701 | 17701 | int promise_reject_counter = 0; | |
| 17702 | 17702 | int promise_revoke_counter = 0; | |
| 17703 | + int promise_reject_after_resolved_counter = 0; | ||
| 17704 | + int promise_resolve_after_resolved_counter = 0; | ||
| 17703 | 17705 | int promise_reject_msg_line_number = -1; | |
| 17704 | 17706 | int promise_reject_msg_column_number = -1; | |
| 17705 | 17707 | int promise_reject_line_number = -1; | |
@@ -17709,40 +17711,56 @@ int promise_reject_frame_count = -1; | |||
| 17709 | 17711 | void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) { | |
| 17710 | 17712 | v8::Local<v8::Object> global = CcTest::global(); | |
| 17711 | 17713 | v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); | |
| 17712 | - CHECK_EQ(v8::Promise::PromiseState::kRejected, | ||
| 17714 | + CHECK_NE(v8::Promise::PromiseState::kPending, | ||
| 17713 | 17715 | reject_message.GetPromise()->State()); | |
| 17714 | - if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) { | ||
| 17715 | - promise_reject_counter++; | ||
| 17716 | - global->Set(context, v8_str("rejected"), reject_message.GetPromise()) | ||
| 17717 | - .FromJust(); | ||
| 17718 | - global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust(); | ||
| 17719 | - v8::Local<v8::Message> message = v8::Exception::CreateMessage( | ||
| 17720 | - CcTest::isolate(), reject_message.GetValue()); | ||
| 17721 | - v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace(); | ||
| 17722 | - | ||
| 17723 | - promise_reject_msg_line_number = message->GetLineNumber(context).FromJust(); | ||
| 17724 | - promise_reject_msg_column_number = | ||
| 17725 | - message->GetStartColumn(context).FromJust() + 1; | ||
| 17726 | - | ||
| 17727 | - if (!stack_trace.IsEmpty()) { | ||
| 17728 | - promise_reject_frame_count = stack_trace->GetFrameCount(); | ||
| 17729 | - if (promise_reject_frame_count > 0) { | ||
| 17730 | - CHECK(stack_trace->GetFrame(0) | ||
| 17731 | - ->GetScriptName() | ||
| 17732 | - ->Equals(context, v8_str("pro")) | ||
| 17733 | - .FromJust()); | ||
| 17734 | - promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber(); | ||
| 17735 | - promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn(); | ||
| 17736 | - } else { | ||
| 17737 | - promise_reject_line_number = -1; | ||
| 17738 | - promise_reject_column_number = -1; | ||
| 17716 | + switch (reject_message.GetEvent()) { | ||
| 17717 | + case v8::kPromiseRejectWithNoHandler: { | ||
| 17718 | + promise_reject_counter++; | ||
| 17719 | + global->Set(context, v8_str("rejected"), reject_message.GetPromise()) | ||
| 17720 | + .FromJust(); | ||
| 17721 | + global->Set(context, v8_str("value"), reject_message.GetValue()) | ||
| 17722 | + .FromJust(); | ||
| 17723 | + v8::Local<v8::Message> message = v8::Exception::CreateMessage( | ||
| 17724 | + CcTest::isolate(), reject_message.GetValue()); | ||
| 17725 | + v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace(); | ||
| 17726 | + | ||
| 17727 | + promise_reject_msg_line_number = | ||
| 17728 | + message->GetLineNumber(context).FromJust(); | ||
| 17729 | + promise_reject_msg_column_number = | ||
| 17730 | + message->GetStartColumn(context).FromJust() + 1; | ||
| 17731 | + | ||
| 17732 | + if (!stack_trace.IsEmpty()) { | ||
| 17733 | + promise_reject_frame_count = stack_trace->GetFrameCount(); | ||
| 17734 | + if (promise_reject_frame_count > 0) { | ||
| 17735 | + CHECK(stack_trace->GetFrame(0) | ||
| 17736 | + ->GetScriptName() | ||
| 17737 | + ->Equals(context, v8_str("pro")) | ||
| 17738 | + .FromJust()); | ||
| 17739 | + promise_reject_line_number = | ||
| 17740 | + stack_trace->GetFrame(0)->GetLineNumber(); | ||
| 17741 | + promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn(); | ||
| 17742 | + } else { | ||
| 17743 | + promise_reject_line_number = -1; | ||
| 17744 | + promise_reject_column_number = -1; | ||
| 17745 | + } | ||
| 17739 | 17746 | } | |
| 17747 | + break; | ||
| 17748 | + } | ||
| 17749 | + case v8::kPromiseHandlerAddedAfterReject: { | ||
| 17750 | + promise_revoke_counter++; | ||
| 17751 | + global->Set(context, v8_str("revoked"), reject_message.GetPromise()) | ||
| 17752 | + .FromJust(); | ||
| 17753 | + CHECK(reject_message.GetValue().IsEmpty()); | ||
| 17754 | + break; | ||
| 17755 | + } | ||
| 17756 | + case v8::kPromiseRejectAfterResolved: { | ||
| 17757 | + promise_reject_after_resolved_counter++; | ||
| 17758 | + break; | ||
| 17759 | + } | ||
| 17760 | + case v8::kPromiseResolveAfterResolved: { | ||
| 17761 | + promise_resolve_after_resolved_counter++; | ||
| 17762 | + break; | ||
| 17740 | 17763 | } | |
| 17741 | - } else { | ||
| 17742 | - promise_revoke_counter++; | ||
| 17743 | - global->Set(context, v8_str("revoked"), reject_message.GetPromise()) | ||
| 17744 | - .FromJust(); | ||
| 17745 | - CHECK(reject_message.GetValue().IsEmpty()); | ||
| 17746 | 17764 | } | |
| 17747 | 17765 | } | |
| 17748 | 17766 | ||
@@ -17765,6 +17783,8 @@ v8::Local<v8::Value> RejectValue() { | |||
| 17765 | 17783 | void ResetPromiseStates() { | |
| 17766 | 17784 | promise_reject_counter = 0; | |
| 17767 | 17785 | promise_revoke_counter = 0; | |
| 17786 | + promise_reject_after_resolved_counter = 0; | ||
| 17787 | + promise_resolve_after_resolved_counter = 0; | ||
| 17768 | 17788 | promise_reject_msg_line_number = -1; | |
| 17769 | 17789 | promise_reject_msg_column_number = -1; | |
| 17770 | 17790 | promise_reject_line_number = -1; | |
@@ -17990,6 +18010,40 @@ TEST(PromiseRejectCallback) { | |||
| 17990 | 18010 | CHECK_EQ(0, promise_revoke_counter); | |
| 17991 | 18011 | CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust()); | |
| 17992 | 18012 | ||
| 18013 | + ResetPromiseStates(); | ||
| 18014 | + | ||
| 18015 | + // Swallowed exceptions in the Promise constructor. | ||
| 18016 | + CompileRun( | ||
| 18017 | + "var v0 = new Promise(\n" | ||
| 18018 | + " function(res, rej) {\n" | ||
| 18019 | + " res(1);\n" | ||
| 18020 | + " throw new Error();\n" | ||
| 18021 | + " }\n" | ||
| 18022 | + ");\n"); | ||
| 18023 | + CHECK(!GetPromise("v0")->HasHandler()); | ||
| 18024 | + CHECK_EQ(0, promise_reject_counter); | ||
| 18025 | + CHECK_EQ(0, promise_revoke_counter); | ||
| 18026 | + CHECK_EQ(1, promise_reject_after_resolved_counter); | ||
| 18027 | + CHECK_EQ(0, promise_resolve_after_resolved_counter); | ||
| 18028 | + | ||
| 18029 | + ResetPromiseStates(); | ||
| 18030 | + | ||
| 18031 | + // Duplication resolve. | ||
| 18032 | + CompileRun( | ||
| 18033 | + "var r;\n" | ||
| 18034 | + "var y0 = new Promise(\n" | ||
| 18035 | + " function(res, rej) {\n" | ||
| 18036 | + " r = res;\n" | ||
| 18037 | + " throw new Error();\n" | ||
| 18038 | + " }\n" | ||
| 18039 | + ");\n" | ||
| 18040 | + "r(1);\n"); | ||
| 18041 | + CHECK(!GetPromise("y0")->HasHandler()); | ||
| 18042 | + CHECK_EQ(1, promise_reject_counter); | ||
| 18043 | + CHECK_EQ(0, promise_revoke_counter); | ||
| 18044 | + CHECK_EQ(0, promise_reject_after_resolved_counter); | ||
| 18045 | + CHECK_EQ(1, promise_resolve_after_resolved_counter); | ||
| 18046 | + | ||
| 17993 | 18047 | // Test stack frames. | |
| 17994 | 18048 | env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true); | |
| 17995 | 18049 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments