Skip to content

Commit 09b53ee

Browse files
addaleaxCommit Bot
authored andcommitted
[api] Make running scripts in AddMessageListener callback work in debug mode
The existance of an `AllowJavascriptExecutionDebugOnly` scope in `Isolate::ReportPendingMessages()` indicates that the API supports running arbitrary JS code in a `AddMessageListener` callback. Currently, this can fail in debug mode: The `!isolate->external_caught_exception()` condition is checked when entering API methods inside such a handler. However, if there is a verbose `TryCatch` active when the exception occurs, this check fails, and when calling `ToString()` on the exception object leaves a pending exception itself, the flag is re-set to `true`. Fix this problem by clearing the flag and the pending exception if there was one during `ToString()`. This matches the code a few lines up in `messages.cc`, so the exception state is now consistent during the callback. This currently makes a Node.js test fail in debug mode (`parallel/test-error-reporting`). Bug: node:7144 Bug: node:17016 Change-Id: I060d00fea3e9a497f4df34c6ff8d6e29ebe96321 Reviewed-on: https://chromium-review.googlesource.com/718096 Commit-Queue: Yang Guo <yangguo@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#49466}
1 parent 87d7722 commit 09b53ee

3 files changed

Lines changed: 38 additions & 3 deletions

File tree

AUTHORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Alexis Campailla <alexis@janeasystems.com>
4444
Andreas Anyuru <andreas.anyuru@gmail.com>
4545
Andrew Paprocki <andrew@ishiboo.com>
4646
Andrei Kashcha <anvaka@gmail.com>
47-
Anna Henningsen <addaleax@gmail.com>
47+
Anna Henningsen <anna@addaleax.net>
4848
Bangfu Tao <bangfu.tao@samsung.com>
4949
Ben Noordhuis <info@bnoordhuis.nl>
5050
Benjamin Tan <demoneaux@gmail.com>

src/messages.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ void MessageHandler::ReportMessage(Isolate* isolate, const MessageLocation* loc,
113113
}
114114

115115
if (!maybe_stringified.ToHandle(&stringified)) {
116+
DCHECK(isolate->has_pending_exception());
117+
isolate->clear_pending_exception();
118+
isolate->set_external_caught_exception(false);
116119
stringified =
117120
isolate->factory()->NewStringFromAsciiChecked("exception");
118121
}

test/cctest/test-api.cc

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5696,23 +5696,55 @@ TEST(CustomErrorMessage) {
56965696

56975697
static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
56985698
v8::Local<v8::Value> data) {
5699+
CHECK(data->IsExternal());
5700+
int* callcount = static_cast<int*>(data.As<v8::External>()->Value());
5701+
++*callcount;
5702+
56995703
const char* uncaught_error = "Uncaught exception";
57005704
CHECK(message->Get()
57015705
->Equals(CcTest::isolate()->GetCurrentContext(),
57025706
v8_str(uncaught_error))
57035707
.FromJust());
5708+
// Test that compiling code inside a message handler works.
5709+
CHECK(CompileRunChecked(CcTest::isolate(), "(function(a) { return a; })(42)")
5710+
->Equals(CcTest::isolate()->GetCurrentContext(),
5711+
v8::Integer::NewFromUnsigned(CcTest::isolate(), 42))
5712+
.FromJust());
57045713
}
57055714

57065715

57075716
TEST(CustomErrorRethrowsOnToString) {
5717+
int callcount = 0;
57085718
LocalContext context;
5709-
v8::HandleScope scope(context->GetIsolate());
5710-
context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
5719+
v8::Isolate* isolate = context->GetIsolate();
5720+
v8::HandleScope scope(isolate);
5721+
context->GetIsolate()->AddMessageListener(
5722+
check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
5723+
5724+
CompileRun(
5725+
"var e = { toString: function() { throw e; } };"
5726+
"try { throw e; } finally {}");
5727+
5728+
CHECK_EQ(callcount, 1);
5729+
context->GetIsolate()->RemoveMessageListeners(
5730+
check_custom_rethrowing_message);
5731+
}
5732+
5733+
TEST(CustomErrorRethrowsOnToStringInsideVerboseTryCatch) {
5734+
int callcount = 0;
5735+
LocalContext context;
5736+
v8::Isolate* isolate = context->GetIsolate();
5737+
v8::HandleScope scope(isolate);
5738+
v8::TryCatch try_catch(isolate);
5739+
try_catch.SetVerbose(true);
5740+
context->GetIsolate()->AddMessageListener(
5741+
check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
57115742

57125743
CompileRun(
57135744
"var e = { toString: function() { throw e; } };"
57145745
"try { throw e; } finally {}");
57155746

5747+
CHECK_EQ(callcount, 1);
57165748
context->GetIsolate()->RemoveMessageListeners(
57175749
check_custom_rethrowing_message);
57185750
}

0 commit comments

Comments
 (0)