Commit e90a79c6 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] introduced exceptionThrown support in test runner

BUG=chromium:635948
R=dgozman@chromium.org

Review-Url: https://codereview.chromium.org/2384373002
Cr-Commit-Position: refs/heads/master@{#39998}
parent 360ee4f9
...@@ -40,6 +40,47 @@ InspectorClientImpl* InspectorClientFromContext( ...@@ -40,6 +40,47 @@ InspectorClientImpl* InspectorClientFromContext(
return inspector_client; return inspector_client;
} }
v8_inspector::String16 ToString16(v8::Local<v8::String> str) {
std::unique_ptr<uint16_t[]> buffer(new uint16_t[str->Length()]);
str->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0, str->Length());
return v8_inspector::String16(buffer.get(), str->Length());
}
void MessageHandler(v8::Local<v8::Message> message,
v8::Local<v8::Value> exception) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Context> context = isolate->GetEnteredContext();
if (context.IsEmpty()) return;
v8_inspector::V8Inspector* inspector =
InspectorClientImpl::InspectorFromContext(context);
v8::Local<v8::StackTrace> stack = message->GetStackTrace();
int script_id = message->GetScriptOrigin().ScriptID()->Value();
if (!stack.IsEmpty() && stack->GetFrameCount() > 0) {
int top_script_id = stack->GetFrame(0)->GetScriptId();
if (top_script_id == script_id) script_id = 0;
}
int line_number = message->GetLineNumber(context).FromMaybe(0);
int column_number = 0;
if (message->GetStartColumn(context).IsJust())
column_number = message->GetStartColumn(context).FromJust() + 1;
v8_inspector::StringView detailed_message;
v8_inspector::String16 message_text_string = ToString16(message->Get());
v8_inspector::StringView message_text(message_text_string.characters16(),
message_text_string.length());
v8_inspector::String16 url_string;
if (message->GetScriptOrigin().ResourceName()->IsString()) {
url_string =
ToString16(message->GetScriptOrigin().ResourceName().As<v8::String>());
}
v8_inspector::StringView url(url_string.characters16(), url_string.length());
inspector->exceptionThrown(context, message_text, exception, detailed_message,
url, line_number, column_number,
inspector->createStackTrace(stack), script_id);
}
} // namespace } // namespace
class ConnectTask : public TaskRunner::Task { class ConnectTask : public TaskRunner::Task {
...@@ -76,6 +117,7 @@ InspectorClientImpl::~InspectorClientImpl() {} ...@@ -76,6 +117,7 @@ InspectorClientImpl::~InspectorClientImpl() {}
void InspectorClientImpl::connect(v8::Local<v8::Context> context) { void InspectorClientImpl::connect(v8::Local<v8::Context> context) {
isolate_ = context->GetIsolate(); isolate_ = context->GetIsolate();
isolate_->AddMessageListener(MessageHandler);
channel_.reset(new ChannelImpl(frontend_channel_)); channel_.reset(new ChannelImpl(frontend_channel_));
inspector_ = v8_inspector::V8Inspector::create(isolate_, this); inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
...@@ -154,9 +196,6 @@ void SendMessageToBackendExtension::SendMessageToBackend( ...@@ -154,9 +196,6 @@ void SendMessageToBackendExtension::SendMessageToBackend(
CHECK(backend_task_runner_); CHECK(backend_task_runner_);
CHECK(args.Length() == 1 && args[0]->IsString()); CHECK(args.Length() == 1 && args[0]->IsString());
v8::Local<v8::String> message = args[0].As<v8::String>(); v8::Local<v8::String> message = args[0].As<v8::String>();
std::unique_ptr<uint16_t[]> buffer(new uint16_t[message->Length()]); backend_task_runner_->Append(
message.As<v8::String>()->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0, new SendMessageToBackendTask(ToString16(message)));
message->Length());
v8_inspector::String16 message_string(buffer.get(), message->Length());
backend_task_runner_->Append(new SendMessageToBackendTask(message_string));
} }
...@@ -128,15 +128,25 @@ class SetTimeoutExtension : public v8::Extension { ...@@ -128,15 +128,25 @@ class SetTimeoutExtension : public v8::Extension {
private: private:
static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate(); v8::Isolate* isolate = args.GetIsolate();
if (args.Length() != 2 || !args[1]->IsNumber() || !args[0]->IsFunction() || if (args.Length() != 2 || !args[1]->IsNumber() ||
(!args[0]->IsFunction() && !args[0]->IsString()) ||
args[1].As<v8::Number>()->Value() != 0.0) { args[1].As<v8::Number>()->Value() != 0.0) {
fprintf(stderr, fprintf(stderr,
"Internal error: only setTimeout(function, 0) is supported."); "Internal error: only setTimeout(function, 0) is supported.");
Exit(); Exit();
} }
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
TaskRunner::FromContext(context)->Append(new SetTimeoutTask( if (args[0]->IsFunction()) {
args.GetIsolate(), v8::Local<v8::Function>::Cast(args[0]))); TaskRunner::FromContext(context)->Append(new SetTimeoutTask(
args.GetIsolate(), v8::Local<v8::Function>::Cast(args[0])));
} else {
v8::Local<v8::String> data = args[0].As<v8::String>();
std::unique_ptr<uint16_t[]> buffer(new uint16_t[data->Length()]);
data->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0, data->Length());
v8_inspector::String16 source =
v8_inspector::String16(buffer.get(), data->Length());
TaskRunner::FromContext(context)->Append(new ExecuteStringTask(source));
}
} }
}; };
...@@ -189,7 +199,7 @@ int main(int argc, char* argv[]) { ...@@ -189,7 +199,7 @@ int main(int argc, char* argv[]) {
const char* backend_extensions[] = {"v8_inspector/setTimeout"}; const char* backend_extensions[] = {"v8_inspector/setTimeout"};
v8::ExtensionConfiguration backend_configuration( v8::ExtensionConfiguration backend_configuration(
arraysize(backend_extensions), backend_extensions); arraysize(backend_extensions), backend_extensions);
TaskRunner backend_runner(&backend_configuration, &ready_semaphore); TaskRunner backend_runner(&backend_configuration, false, &ready_semaphore);
ready_semaphore.Wait(); ready_semaphore.Wait();
SendMessageToBackendExtension::set_backend_task_runner(&backend_runner); SendMessageToBackendExtension::set_backend_task_runner(&backend_runner);
...@@ -197,7 +207,7 @@ int main(int argc, char* argv[]) { ...@@ -197,7 +207,7 @@ int main(int argc, char* argv[]) {
"v8_inspector/frontend"}; "v8_inspector/frontend"};
v8::ExtensionConfiguration frontend_configuration( v8::ExtensionConfiguration frontend_configuration(
arraysize(frontend_extensions), frontend_extensions); arraysize(frontend_extensions), frontend_extensions);
TaskRunner frontend_runner(&frontend_configuration, &ready_semaphore); TaskRunner frontend_runner(&frontend_configuration, true, &ready_semaphore);
ready_semaphore.Wait(); ready_semaphore.Wait();
FrontendChannelImpl frontend_channel(&frontend_runner); FrontendChannelImpl frontend_channel(&frontend_runner);
......
...@@ -36,7 +36,7 @@ InspectorTest.logMessage = function(message) ...@@ -36,7 +36,7 @@ InspectorTest.logMessage = function(message)
if (message.id) if (message.id)
message.id = "<messageId>"; message.id = "<messageId>";
const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "timestamp"]); const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "timestamp", "executionContextId"]);
var objects = [ message ]; var objects = [ message ];
while (objects.length) { while (objects.length) {
var object = objects.shift(); var object = objects.shift();
...@@ -104,9 +104,9 @@ InspectorTest.completeTest = quit.bind(null); ...@@ -104,9 +104,9 @@ InspectorTest.completeTest = quit.bind(null);
InspectorTest.completeTestAfterPendingTimeouts = function() InspectorTest.completeTestAfterPendingTimeouts = function()
{ {
InspectorTest.sendCommand("Runtime.evaluate", { Protocol.Runtime.evaluate({
expression: "new Promise(resolve => setTimeout(resolve, 0))", expression: "new Promise(resolve => setTimeout(resolve, 0))",
awaitPromise: true }, InspectorTest.completeTest); awaitPromise: true }).then(InspectorTest.completeTest);
} }
InspectorTest.addScript = function(string) InspectorTest.addScript = function(string)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
value : 239 value : 239
} }
] ]
executionContextId : 1 executionContextId : <executionContextId>
stackTrace : { stackTrace : {
callFrames : [ callFrames : [
[0] : { [0] : {
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
value : 239 value : 239
} }
] ]
executionContextId : 1 executionContextId : <executionContextId>
stackTrace : { stackTrace : {
callFrames : [ callFrames : [
[0] : { [0] : {
......
Check that exceptionThrown is supported by test runner.
{
method : Runtime.exceptionThrown
params : {
exceptionDetails : {
columnNumber : 2
exception : {
className : Error
description : Error at setTimeout (<anonymous>:2:9)
objectId : <objectId>
preview : {
description : Error at setTimeout (<anonymous>:2:9)
overflow : false
properties : [
[0] : {
name : stack
type : string
value : Error at setTimeout (<anonymous>:2:9)
}
]
subtype : error
type : object
}
subtype : error
type : object
}
exceptionId : <exceptionId>
executionContextId : <executionContextId>
lineNumber : 1
stackTrace : {
callFrames : [
[0] : {
columnNumber : 8
functionName : setTimeout
lineNumber : 1
scriptId : <scriptId>
url :
}
]
}
text : Uncaught Error
}
timestamp : <timestamp>
}
}
{
method : Runtime.exceptionThrown
params : {
exceptionDetails : {
columnNumber : 1
exception : {
className : SyntaxError
description : SyntaxError: Unexpected token }
objectId : <objectId>
preview : {
description : SyntaxError: Unexpected token }
overflow : false
properties : [
[0] : {
name : stack
type : string
value : SyntaxError: Unexpected token }
}
[1] : {
name : message
type : string
value : Unexpected token }
}
]
subtype : error
type : object
}
subtype : error
type : object
}
exceptionId : <exceptionId>
executionContextId : <executionContextId>
lineNumber : 0
scriptId : <scriptId>
stackTrace : {
callFrames : [
]
}
text : Uncaught SyntaxError: Unexpected token }
}
timestamp : <timestamp>
}
}
{
method : Runtime.exceptionThrown
params : {
exceptionDetails : {
columnNumber : 2
exception : {
description : 239
type : number
value : 239
}
exceptionId : <exceptionId>
executionContextId : <executionContextId>
lineNumber : 1
stackTrace : {
callFrames : [
[0] : {
columnNumber : 2
functionName : setTimeout
lineNumber : 1
scriptId : <scriptId>
url :
}
]
}
text : Uncaught 239
}
timestamp : <timestamp>
}
}
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
print("Check that exceptionThrown is supported by test runner.")
Protocol.Runtime.enable();
Protocol.Runtime.onExceptionThrown(message => InspectorTest.logMessage(message));
Protocol.Runtime.evaluate({ expression: "setTimeout(() => { \n throw new Error() }, 0)" });
Protocol.Runtime.evaluate({ expression: "setTimeout(\" }\", 0)" });
Protocol.Runtime.evaluate({ expression: "setTimeout(() => { \n throw 239; }, 0)" });
InspectorTest.completeTestAfterPendingTimeouts();
...@@ -23,9 +23,11 @@ void ReportUncaughtException(v8::Isolate* isolate, ...@@ -23,9 +23,11 @@ void ReportUncaughtException(v8::Isolate* isolate,
} // namespace } // namespace
TaskRunner::TaskRunner(v8::ExtensionConfiguration* extensions, TaskRunner::TaskRunner(v8::ExtensionConfiguration* extensions,
bool catch_exceptions,
v8::base::Semaphore* ready_semaphore) v8::base::Semaphore* ready_semaphore)
: Thread(Options("Task Runner")), : Thread(Options("Task Runner")),
extensions_(extensions), extensions_(extensions),
catch_exceptions_(catch_exceptions),
ready_semaphore_(ready_semaphore), ready_semaphore_(ready_semaphore),
isolate_(nullptr), isolate_(nullptr),
process_queue_semaphore_(0), process_queue_semaphore_(0),
...@@ -64,14 +66,19 @@ void TaskRunner::RunMessageLoop(bool only_protocol) { ...@@ -64,14 +66,19 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
while (nested_loop_count_ == loop_number) { while (nested_loop_count_ == loop_number) {
TaskRunner::Task* task = GetNext(only_protocol); TaskRunner::Task* task = GetNext(only_protocol);
v8::Isolate::Scope isolate_scope(isolate_); v8::Isolate::Scope isolate_scope(isolate_);
v8::TryCatch try_catch(isolate_); if (catch_exceptions_) {
task->Run(isolate_, context_); v8::TryCatch try_catch(isolate_);
delete task; task->Run(isolate_, context_);
if (try_catch.HasCaught()) { delete task;
ReportUncaughtException(isolate_, try_catch); if (try_catch.HasCaught()) {
fflush(stdout); ReportUncaughtException(isolate_, try_catch);
fflush(stderr); fflush(stdout);
_exit(0); fflush(stderr);
_exit(0);
}
} else {
task->Run(isolate_, context_);
delete task;
} }
} }
} }
......
...@@ -23,8 +23,8 @@ class TaskRunner : public v8::base::Thread { ...@@ -23,8 +23,8 @@ class TaskRunner : public v8::base::Thread {
const v8::Global<v8::Context>& context) = 0; const v8::Global<v8::Context>& context) = 0;
}; };
explicit TaskRunner(v8::ExtensionConfiguration* extensions, TaskRunner(v8::ExtensionConfiguration* extensions, bool catch_exceptions,
v8::base::Semaphore* ready_semaphore); v8::base::Semaphore* ready_semaphore);
virtual ~TaskRunner(); virtual ~TaskRunner();
// Thread implementation. // Thread implementation.
...@@ -44,6 +44,7 @@ class TaskRunner : public v8::base::Thread { ...@@ -44,6 +44,7 @@ class TaskRunner : public v8::base::Thread {
Task* GetNext(bool only_protocol); Task* GetNext(bool only_protocol);
v8::ExtensionConfiguration* extensions_; v8::ExtensionConfiguration* extensions_;
bool catch_exceptions_;
v8::base::Semaphore* ready_semaphore_; v8::base::Semaphore* ready_semaphore_;
v8::Isolate* isolate_; v8::Isolate* isolate_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment