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(
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
class ConnectTask : public TaskRunner::Task {
......@@ -76,6 +117,7 @@ InspectorClientImpl::~InspectorClientImpl() {}
void InspectorClientImpl::connect(v8::Local<v8::Context> context) {
isolate_ = context->GetIsolate();
isolate_->AddMessageListener(MessageHandler);
channel_.reset(new ChannelImpl(frontend_channel_));
inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
......@@ -154,9 +196,6 @@ void SendMessageToBackendExtension::SendMessageToBackend(
CHECK(backend_task_runner_);
CHECK(args.Length() == 1 && args[0]->IsString());
v8::Local<v8::String> message = args[0].As<v8::String>();
std::unique_ptr<uint16_t[]> buffer(new uint16_t[message->Length()]);
message.As<v8::String>()->Write(reinterpret_cast<uint16_t*>(buffer.get()), 0,
message->Length());
v8_inspector::String16 message_string(buffer.get(), message->Length());
backend_task_runner_->Append(new SendMessageToBackendTask(message_string));
backend_task_runner_->Append(
new SendMessageToBackendTask(ToString16(message)));
}
......@@ -128,15 +128,25 @@ class SetTimeoutExtension : public v8::Extension {
private:
static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
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) {
fprintf(stderr,
"Internal error: only setTimeout(function, 0) is supported.");
Exit();
}
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
TaskRunner::FromContext(context)->Append(new SetTimeoutTask(
args.GetIsolate(), v8::Local<v8::Function>::Cast(args[0])));
if (args[0]->IsFunction()) {
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[]) {
const char* backend_extensions[] = {"v8_inspector/setTimeout"};
v8::ExtensionConfiguration backend_configuration(
arraysize(backend_extensions), backend_extensions);
TaskRunner backend_runner(&backend_configuration, &ready_semaphore);
TaskRunner backend_runner(&backend_configuration, false, &ready_semaphore);
ready_semaphore.Wait();
SendMessageToBackendExtension::set_backend_task_runner(&backend_runner);
......@@ -197,7 +207,7 @@ int main(int argc, char* argv[]) {
"v8_inspector/frontend"};
v8::ExtensionConfiguration frontend_configuration(
arraysize(frontend_extensions), frontend_extensions);
TaskRunner frontend_runner(&frontend_configuration, &ready_semaphore);
TaskRunner frontend_runner(&frontend_configuration, true, &ready_semaphore);
ready_semaphore.Wait();
FrontendChannelImpl frontend_channel(&frontend_runner);
......
......@@ -36,7 +36,7 @@ InspectorTest.logMessage = function(message)
if (message.id)
message.id = "<messageId>";
const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "timestamp"]);
const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "timestamp", "executionContextId"]);
var objects = [ message ];
while (objects.length) {
var object = objects.shift();
......@@ -104,9 +104,9 @@ InspectorTest.completeTest = quit.bind(null);
InspectorTest.completeTestAfterPendingTimeouts = function()
{
InspectorTest.sendCommand("Runtime.evaluate", {
Protocol.Runtime.evaluate({
expression: "new Promise(resolve => setTimeout(resolve, 0))",
awaitPromise: true }, InspectorTest.completeTest);
awaitPromise: true }).then(InspectorTest.completeTest);
}
InspectorTest.addScript = function(string)
......
......@@ -8,7 +8,7 @@
value : 239
}
]
executionContextId : 1
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
......@@ -34,7 +34,7 @@
value : 239
}
]
executionContextId : 1
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[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,
} // namespace
TaskRunner::TaskRunner(v8::ExtensionConfiguration* extensions,
bool catch_exceptions,
v8::base::Semaphore* ready_semaphore)
: Thread(Options("Task Runner")),
extensions_(extensions),
catch_exceptions_(catch_exceptions),
ready_semaphore_(ready_semaphore),
isolate_(nullptr),
process_queue_semaphore_(0),
......@@ -64,14 +66,19 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
while (nested_loop_count_ == loop_number) {
TaskRunner::Task* task = GetNext(only_protocol);
v8::Isolate::Scope isolate_scope(isolate_);
v8::TryCatch try_catch(isolate_);
task->Run(isolate_, context_);
delete task;
if (try_catch.HasCaught()) {
ReportUncaughtException(isolate_, try_catch);
fflush(stdout);
fflush(stderr);
_exit(0);
if (catch_exceptions_) {
v8::TryCatch try_catch(isolate_);
task->Run(isolate_, context_);
delete task;
if (try_catch.HasCaught()) {
ReportUncaughtException(isolate_, try_catch);
fflush(stdout);
fflush(stderr);
_exit(0);
}
} else {
task->Run(isolate_, context_);
delete task;
}
}
}
......
......@@ -23,8 +23,8 @@ class TaskRunner : public v8::base::Thread {
const v8::Global<v8::Context>& context) = 0;
};
explicit TaskRunner(v8::ExtensionConfiguration* extensions,
v8::base::Semaphore* ready_semaphore);
TaskRunner(v8::ExtensionConfiguration* extensions, bool catch_exceptions,
v8::base::Semaphore* ready_semaphore);
virtual ~TaskRunner();
// Thread implementation.
......@@ -44,6 +44,7 @@ class TaskRunner : public v8::base::Thread {
Task* GetNext(bool only_protocol);
v8::ExtensionConfiguration* extensions_;
bool catch_exceptions_;
v8::base::Semaphore* ready_semaphore_;
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