Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorGus Caplan <me@gus.host>2020-06-12 22:45:40 +0300
committerAnna Henningsen <anna@addaleax.net>2020-06-19 19:04:52 +0300
commit8f000ea09f6ee20b50cb83e6f7b2cb25671ef6f2 (patch)
tree8a4007fb5d3a79f4ed62a2e2b5dcef355000e988 /deps
parenta86a295fd7162a7fdf406a21b3c3c679819c60b5 (diff)
deps: V8: cherry-pick 767e65f945e7
Original commit message: [API] Fix microtask message reporting RunSingleMicrotask calls Runtime::ReportMessage, but the implementation of ReportMessage would unconditionally discard these exceptions. This CL removes all of the intermediate logic and directly calls MessageHandler::ReportMessage, restoring the ability of RunSingleMicrotask to report exceptions that occur in microtasks. Bug: v8:8326 Change-Id: I493de74383b2ab191d786611fb9eba9d27e7a243 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2162121 Commit-Queue: Gus Caplan <me@gus.host> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#67630} Refs: https://github.com/v8/v8/commit/767e65f945e7caa4becc2bd4b5e9ea8562da0ca4 PR-URL: https://github.com/nodejs/node/pull/33859 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps')
-rw-r--r--deps/v8/src/builtins/builtins-microtask-queue-gen.cc2
-rw-r--r--deps/v8/src/builtins/promise-reaction-job.tq14
-rw-r--r--deps/v8/src/execution/isolate.cc170
-rw-r--r--deps/v8/src/execution/isolate.h6
-rw-r--r--deps/v8/src/runtime/runtime-internal.cc16
-rw-r--r--deps/v8/src/runtime/runtime.h2
-rw-r--r--deps/v8/test/cctest/test-api.cc20
7 files changed, 90 insertions, 140 deletions
diff --git a/deps/v8/src/builtins/builtins-microtask-queue-gen.cc b/deps/v8/src/builtins/builtins-microtask-queue-gen.cc
index c71faa116c1..e6787b2da8c 100644
--- a/deps/v8/src/builtins/builtins-microtask-queue-gen.cc
+++ b/deps/v8/src/builtins/builtins-microtask-queue-gen.cc
@@ -327,7 +327,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
BIND(&if_exception);
{
// Report unhandled exceptions from microtasks.
- CallRuntime(Runtime::kReportMessage, current_context,
+ CallRuntime(Runtime::kReportMessageFromMicrotask, current_context,
var_exception.value());
RewindEnteredContext(saved_entered_context_count);
SetCurrentContext(current_context);
diff --git a/deps/v8/src/builtins/promise-reaction-job.tq b/deps/v8/src/builtins/promise-reaction-job.tq
index 1d20d22efbb..f17886c0d18 100644
--- a/deps/v8/src/builtins/promise-reaction-job.tq
+++ b/deps/v8/src/builtins/promise-reaction-job.tq
@@ -4,11 +4,6 @@
#include 'src/builtins/builtins-promise-gen.h'
-namespace runtime {
- extern transitioning runtime
- ReportMessage(implicit context: Context)(JSAny): JSAny;
-}
-
namespace promise {
transitioning
@@ -30,13 +25,8 @@ namespace promise {
case (capability: PromiseCapability): {
// In the general case we need to call the (user provided)
// promiseCapability.[[Reject]] function.
- try {
- const reject = UnsafeCast<Callable>(capability.reject);
- return Call(context, reject, Undefined, reason);
- } catch (e) {
- // Swallow the exception here.
- return runtime::ReportMessage(e);
- }
+ const reject = UnsafeCast<Callable>(capability.reject);
+ return Call(context, reject, Undefined, reason);
}
}
} else {
diff --git a/deps/v8/src/execution/isolate.cc b/deps/v8/src/execution/isolate.cc
index 5c21b0982e9..033d23d85b8 100644
--- a/deps/v8/src/execution/isolate.cc
+++ b/deps/v8/src/execution/isolate.cc
@@ -1412,6 +1412,8 @@ void Isolate::InvokeApiInterruptCallbacks() {
}
}
+namespace {
+
void ReportBootstrappingException(Handle<Object> exception,
MessageLocation* location) {
base::OS::PrintError("Exception thrown during bootstrapping\n");
@@ -1467,6 +1469,36 @@ void ReportBootstrappingException(Handle<Object> exception,
#endif
}
+} // anonymous namespace
+
+Handle<JSMessageObject> Isolate::CreateMessageOrAbort(
+ Handle<Object> exception, MessageLocation* location) {
+ Handle<JSMessageObject> message_obj = CreateMessage(exception, location);
+
+ // If the abort-on-uncaught-exception flag is specified, and if the
+ // embedder didn't specify a custom uncaught exception callback,
+ // or if the custom callback determined that V8 should abort, then
+ // abort.
+ if (FLAG_abort_on_uncaught_exception) {
+ CatchType prediction = PredictExceptionCatcher();
+ if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
+ (!abort_on_uncaught_exception_callback_ ||
+ abort_on_uncaught_exception_callback_(
+ reinterpret_cast<v8::Isolate*>(this)))) {
+ // Prevent endless recursion.
+ FLAG_abort_on_uncaught_exception = false;
+ // This flag is intended for use by JavaScript developers, so
+ // print a user-friendly stack trace (not an internal one).
+ PrintF(stderr, "%s\n\nFROM\n",
+ MessageHandler::GetLocalizedMessage(this, message_obj).get());
+ PrintCurrentStackTrace(stderr);
+ base::OS::Abort();
+ }
+ }
+
+ return message_obj;
+}
+
Object Isolate::Throw(Object raw_exception, MessageLocation* location) {
DCHECK(!has_pending_exception());
@@ -1538,38 +1570,14 @@ Object Isolate::Throw(Object raw_exception, MessageLocation* location) {
if (location == nullptr && ComputeLocation(&computed_location)) {
location = &computed_location;
}
-
if (bootstrapper()->IsActive()) {
// It's not safe to try to make message objects or collect stack traces
// while the bootstrapper is active since the infrastructure may not have
// been properly initialized.
ReportBootstrappingException(exception, location);
} else {
- Handle<Object> message_obj = CreateMessage(exception, location);
+ Handle<Object> message_obj = CreateMessageOrAbort(exception, location);
thread_local_top()->pending_message_obj_ = *message_obj;
-
- // For any exception not caught by JavaScript, even when an external
- // handler is present:
- // If the abort-on-uncaught-exception flag is specified, and if the
- // embedder didn't specify a custom uncaught exception callback,
- // or if the custom callback determined that V8 should abort, then
- // abort.
- if (FLAG_abort_on_uncaught_exception) {
- CatchType prediction = PredictExceptionCatcher();
- if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
- (!abort_on_uncaught_exception_callback_ ||
- abort_on_uncaught_exception_callback_(
- reinterpret_cast<v8::Isolate*>(this)))) {
- // Prevent endless recursion.
- FLAG_abort_on_uncaught_exception = false;
- // This flag is intended for use by JavaScript developers, so
- // print a user-friendly stack trace (not an internal one).
- PrintF(stderr, "%s\n\nFROM\n",
- MessageHandler::GetLocalizedMessage(this, message_obj).get());
- PrintCurrentStackTrace(stderr);
- base::OS::Abort();
- }
- }
}
}
@@ -2106,7 +2114,7 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
bool is_at_number_conversion =
elements->IsAsmJsWasmFrame(i) &&
elements->Flags(i).value() & FrameArray::kAsmJsAtNumberConversion;
- if (elements->IsWasmCompiledFrame(i)) {
+ if (elements->IsWasmCompiledFrame(i) || elements->IsAsmJsWasmFrame(i)) {
// WasmCode* held alive by the {GlobalWasmCodeRef}.
wasm::WasmCode* code =
Managed<wasm::GlobalWasmCodeRef>::cast(elements->WasmCodeObject(i))
@@ -2230,9 +2238,28 @@ bool Isolate::IsExternalHandlerOnTop(Object exception) {
return (entry_handler > external_handler);
}
-void Isolate::ReportPendingMessagesImpl(bool report_externally) {
+std::vector<MemoryRange>* Isolate::GetCodePages() const {
+ return code_pages_.load(std::memory_order_acquire);
+}
+
+void Isolate::SetCodePages(std::vector<MemoryRange>* new_code_pages) {
+ code_pages_.store(new_code_pages, std::memory_order_release);
+}
+
+void Isolate::ReportPendingMessages() {
+ DCHECK(AllowExceptions::IsAllowed(this));
+
+ // The embedder might run script in response to an exception.
+ AllowJavascriptExecutionDebugOnly allow_script(this);
+
Object exception_obj = pending_exception();
+ // Try to propagate the exception to an external v8::TryCatch handler. If
+ // propagation was unsuccessful, then we will get another chance at reporting
+ // the pending message if the exception is re-thrown.
+ bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
+ if (!has_been_propagated) return;
+
// Clear the pending message object early to avoid endless recursion.
Object message_obj = thread_local_top()->pending_message_obj_;
clear_pending_message();
@@ -2245,7 +2272,7 @@ void Isolate::ReportPendingMessagesImpl(bool report_externally) {
// depending on whether and external v8::TryCatch or an internal JavaScript
// handler is on top.
bool should_report_exception;
- if (report_externally) {
+ if (IsExternalHandlerOnTop(exception_obj)) {
// Only report the exception if the external handler is verbose.
should_report_exception = try_catch_handler()->is_verbose_;
} else {
@@ -2271,93 +2298,6 @@ void Isolate::ReportPendingMessagesImpl(bool report_externally) {
}
}
-std::vector<MemoryRange>* Isolate::GetCodePages() const {
- return code_pages_.load(std::memory_order_acquire);
-}
-
-void Isolate::SetCodePages(std::vector<MemoryRange>* new_code_pages) {
- code_pages_.store(new_code_pages, std::memory_order_release);
-}
-
-void Isolate::ReportPendingMessages() {
- DCHECK(AllowExceptions::IsAllowed(this));
-
- // The embedder might run script in response to an exception.
- AllowJavascriptExecutionDebugOnly allow_script(this);
-
- Object exception = pending_exception();
-
- // Try to propagate the exception to an external v8::TryCatch handler. If
- // propagation was unsuccessful, then we will get another chance at reporting
- // the pending message if the exception is re-thrown.
- bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
- if (!has_been_propagated) return;
-
- ReportPendingMessagesImpl(IsExternalHandlerOnTop(exception));
-}
-
-void Isolate::ReportPendingMessagesFromJavaScript() {
- DCHECK(AllowExceptions::IsAllowed(this));
-
- auto IsHandledByJavaScript = [=]() {
- // In this situation, the exception is always a non-terminating exception.
-
- // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
- Address entry_handler = Isolate::handler(thread_local_top());
- DCHECK_NE(entry_handler, kNullAddress);
- entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
-
- // Get the address of the external handler so we can compare the address to
- // determine which one is closer to the top of the stack.
- Address external_handler = thread_local_top()->try_catch_handler_address();
- if (external_handler == kNullAddress) return true;
-
- return (entry_handler < external_handler);
- };
-
- auto IsHandledExternally = [=]() {
- Address external_handler = thread_local_top()->try_catch_handler_address();
- if (external_handler == kNullAddress) return false;
-
- // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
- Address entry_handler = Isolate::handler(thread_local_top());
- DCHECK_NE(entry_handler, kNullAddress);
- entry_handler = StackHandler::FromAddress(entry_handler)->next_address();
- return (entry_handler > external_handler);
- };
-
- auto PropagateToExternalHandler = [=]() {
- if (IsHandledByJavaScript()) {
- thread_local_top()->external_caught_exception_ = false;
- return false;
- }
-
- if (!IsHandledExternally()) {
- thread_local_top()->external_caught_exception_ = false;
- return true;
- }
-
- thread_local_top()->external_caught_exception_ = true;
- v8::TryCatch* handler = try_catch_handler();
- DCHECK(thread_local_top()->pending_message_obj_.IsJSMessageObject() ||
- thread_local_top()->pending_message_obj_.IsTheHole(this));
- handler->can_continue_ = true;
- handler->has_terminated_ = false;
- handler->exception_ = reinterpret_cast<void*>(pending_exception().ptr());
- // Propagate to the external try-catch only if we got an actual message.
- if (thread_local_top()->pending_message_obj_.IsTheHole(this)) return true;
-
- handler->message_obj_ =
- reinterpret_cast<void*>(thread_local_top()->pending_message_obj_.ptr());
- return true;
- };
-
- // Try to propagate to an external v8::TryCatch handler.
- if (!PropagateToExternalHandler()) return;
-
- ReportPendingMessagesImpl(true);
-}
-
bool Isolate::OptionalRescheduleException(bool clear_exception) {
DCHECK(has_pending_exception());
PropagatePendingExceptionToExternalTryCatch();
diff --git a/deps/v8/src/execution/isolate.h b/deps/v8/src/execution/isolate.h
index 037e6ea7f59..edf9a1a95ad 100644
--- a/deps/v8/src/execution/isolate.h
+++ b/deps/v8/src/execution/isolate.h
@@ -822,10 +822,6 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
// Un-schedule an exception that was caught by a TryCatch handler.
void CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler);
void ReportPendingMessages();
- void ReportPendingMessagesFromJavaScript();
-
- // Implements code shared between the two above methods
- void ReportPendingMessagesImpl(bool report_externally);
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
Object PromoteScheduledException();
@@ -842,6 +838,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
Handle<JSMessageObject> CreateMessage(Handle<Object> exception,
MessageLocation* location);
+ Handle<JSMessageObject> CreateMessageOrAbort(Handle<Object> exception,
+ MessageLocation* location);
// Out of resource exception helpers.
Object StackOverflow();
diff --git a/deps/v8/src/runtime/runtime-internal.cc b/deps/v8/src/runtime/runtime-internal.cc
index b3d9f26ee54..4806922a970 100644
--- a/deps/v8/src/runtime/runtime-internal.cc
+++ b/deps/v8/src/runtime/runtime-internal.cc
@@ -578,19 +578,21 @@ RUNTIME_FUNCTION(Runtime_GetTemplateObject) {
isolate, native_context, description, shared_info, slot_id);
}
-RUNTIME_FUNCTION(Runtime_ReportMessage) {
+RUNTIME_FUNCTION(Runtime_ReportMessageFromMicrotask) {
// Helper to report messages and continue JS execution. This is intended to
- // behave similarly to reporting exceptions which reach the top-level in
- // Execution.cc, but allow the JS code to continue. This is useful for
- // implementing algorithms such as RunMicrotasks in JS.
+ // behave similarly to reporting exceptions which reach the top-level, but
+ // allow the JS code to continue.
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
- CONVERT_ARG_HANDLE_CHECKED(Object, message_obj, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, exception, 0);
DCHECK(!isolate->has_pending_exception());
- isolate->set_pending_exception(*message_obj);
- isolate->ReportPendingMessagesFromJavaScript();
+ isolate->set_pending_exception(*exception);
+ MessageLocation* no_location = nullptr;
+ Handle<JSMessageObject> message =
+ isolate->CreateMessageOrAbort(exception, no_location);
+ MessageHandler::ReportMessage(isolate, no_location, message);
isolate->clear_pending_exception();
return ReadOnlyRoots(isolate).undefined_value();
}
diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h
index 57500be5107..c9ee6d88ac1 100644
--- a/deps/v8/src/runtime/runtime.h
+++ b/deps/v8/src/runtime/runtime.h
@@ -225,7 +225,7 @@ namespace internal {
F(NewTypeError, 2, 1) \
F(OrdinaryHasInstance, 2, 1) \
F(PromoteScheduledException, 0, 1) \
- F(ReportMessage, 1, 1) \
+ F(ReportMessageFromMicrotask, 1, 1) \
F(ReThrow, 1, 1) \
F(RunMicrotaskCallback, 2, 1) \
F(PerformMicrotaskCheckpoint, 0, 1) \
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index a12d4788e4b..191bb63b8e5 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -19845,11 +19845,30 @@ static void MicrotaskExceptionTwo(
v8::Exception::Error(v8_str("second")));
}
+int handler_call_count = 0;
+static void MicrotaskExceptionHandler(Local<Message> message,
+ Local<Value> exception) {
+ CHECK(exception->IsNativeError());
+ Local<Context> context = message->GetIsolate()->GetCurrentContext();
+ Local<String> str = exception->ToString(context).ToLocalChecked();
+ switch (handler_call_count++) {
+ case 0:
+ CHECK(str->StrictEquals(v8_str("Error: first")));
+ break;
+ case 1:
+ CHECK(str->StrictEquals(v8_str("Error: second")));
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
TEST(RunMicrotasksIgnoresThrownExceptions) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
+ isolate->AddMessageListenerWithErrorLevel(MicrotaskExceptionHandler,
+ v8::Isolate::kMessageAll);
CompileRun(
"var exception1Calls = 0;"
"var exception2Calls = 0;");
@@ -19860,6 +19879,7 @@ TEST(RunMicrotasksIgnoresThrownExceptions) {
TryCatch try_catch(isolate);
CompileRun("1+1;");
CHECK(!try_catch.HasCaught());
+ CHECK_EQ(handler_call_count, 2);
CHECK_EQ(1,
CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(1,