Commit 0339d069 authored by yurys@chromium.org's avatar yurys@chromium.org

Add OnCompileError handler and v8::CompileError debug event.

This event is generated when the parser can not generate code.

R=vsevik@chromium.org, yangguo@chromium.org, yurys@chromium.org

Review URL: https://codereview.chromium.org/264333007

Patch from Alexey Kozyatinskiy <kozyatinskiy@google.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22043 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 013bb22c
......@@ -20,7 +20,8 @@ enum DebugEvent {
BeforeCompile = 4,
AfterCompile = 5,
ScriptCollected = 6,
BreakForCommand = 7
CompileError = 7,
BreakForCommand = 8
};
......
......@@ -19,7 +19,8 @@ Debug.DebugEvent = { Break: 1,
NewFunction: 3,
BeforeCompile: 4,
AfterCompile: 5,
ScriptCollected: 6 };
ScriptCollected: 6,
CompileError: 7 };
// Types of exceptions that can be broken upon.
Debug.ExceptionBreak = { Caught : 0,
......@@ -1143,23 +1144,19 @@ ExceptionEvent.prototype.toJSONProtocol = function() {
};
function MakeCompileEvent(script, before) {
return new CompileEvent(script, before);
function MakeCompileEvent(script, type) {
return new CompileEvent(script, type);
}
function CompileEvent(script, before) {
function CompileEvent(script, type) {
this.script_ = MakeMirror(script);
this.before_ = before;
this.type_ = type;
}
CompileEvent.prototype.eventType = function() {
if (this.before_) {
return Debug.DebugEvent.BeforeCompile;
} else {
return Debug.DebugEvent.AfterCompile;
}
return this.type_;
};
......@@ -1171,10 +1168,13 @@ CompileEvent.prototype.script = function() {
CompileEvent.prototype.toJSONProtocol = function() {
var o = new ProtocolMessage();
o.running = true;
if (this.before_) {
switch (this.type_) {
case Debug.DebugEvent.BeforeCompile:
o.event = "beforeCompile";
} else {
case Debug.DebugEvent.AfterCompile:
o.event = "afterCompile";
case Debug.DebugEvent.CompileError:
o.event = "compileError";
}
o.body = {};
o.body.script = this.script_;
......
......@@ -2554,11 +2554,11 @@ MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
bool before) {
v8::DebugEvent type) {
// Create the compile event object.
Handle<Object> script_wrapper = Script::GetWrapper(script);
Handle<Object> argv[] = { script_wrapper,
isolate_->factory()->ToBoolean(before) };
isolate_->factory()->NewNumberFromInt(type) };
return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv);
}
......@@ -2607,6 +2607,24 @@ void Debug::OnException(Handle<Object> exception, bool uncaught) {
}
void Debug::OnCompileError(Handle<Script> script) {
// No more to do if not debugging.
if (in_debug_scope() || ignore_events()) return;
HandleScope scope(isolate_);
DebugScope debug_scope(this);
if (debug_scope.failed()) return;
// Create the compile state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
}
void Debug::OnDebugBreak(Handle<Object> break_points_hit,
bool auto_continue) {
// The caller provided for DebugScope.
......@@ -2637,7 +2655,8 @@ void Debug::OnBeforeCompile(Handle<Script> script) {
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return;
if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
return;
// Process debug event.
ProcessDebugEvent(v8::BeforeCompile,
......@@ -2690,7 +2709,7 @@ void Debug::OnAfterCompile(Handle<Script> script) {
// Create the compile state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return;
if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
// Process debug event.
ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
......
......@@ -367,6 +367,7 @@ class Debug {
// Debug event triggers.
void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
void OnException(Handle<Object> exception, bool uncaught);
void OnCompileError(Handle<Script> script);
void OnBeforeCompile(Handle<Script> script);
void OnAfterCompile(Handle<Script> script);
void OnScriptCollected(int id);
......@@ -542,7 +543,7 @@ class Debug {
bool uncaught,
Handle<Object> promise);
MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent(
Handle<Script> script, bool before);
Handle<Script> script, v8::DebugEvent type);
MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id);
// Mirror cache handling.
......
......@@ -3888,6 +3888,8 @@ void Parser::ThrowPendingError() {
.ToHandleChecked();
elements->set(0, *arg_string);
}
isolate()->debug()->OnCompileError(script_);
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
Handle<Object> result = pending_error_is_reference_error_
? factory->NewReferenceError(pending_error_message_, array)
......
......@@ -6376,6 +6376,60 @@ TEST(AfterCompileMessageWhenMessageHandlerIsReset) {
}
// Syntax error event handler which counts a number of events.
int compile_error_event_count = 0;
static void CompileErrorEventCounterClear() {
compile_error_event_count = 0;
}
static void CompileErrorEventCounter(
const v8::Debug::EventDetails& event_details) {
v8::DebugEvent event = event_details.GetEvent();
if (event == v8::CompileError) {
compile_error_event_count++;
}
}
// Tests that syntax error event is sent as many times as there are scripts
// with syntax error compiled.
TEST(SyntaxErrorMessageOnSyntaxException) {
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
// For this test, we want to break on uncaught exceptions:
ChangeBreakOnException(false, true);
v8::Debug::SetDebugEventListener(CompileErrorEventCounter);
CompileErrorEventCounterClear();
// Check initial state.
CHECK_EQ(0, compile_error_event_count);
// Throws SyntaxError: Unexpected end of input
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "+++"));
CHECK_EQ(1, compile_error_event_count);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "/sel\\/: \\"));
CHECK_EQ(2, compile_error_event_count);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "JSON.parse('1234:')"));
CHECK_EQ(2, compile_error_event_count);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "new RegExp('/\\/\\\\');"));
CHECK_EQ(2, compile_error_event_count);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "throw 1;"));
CHECK_EQ(2, compile_error_event_count);
}
// Tests that break event is sent when message handler is reset.
TEST(BreakMessageWhenMessageHandlerIsReset) {
DebugLocalContext env;
......
......@@ -32,6 +32,7 @@ Debug = debug.Debug
var exception = false; // Exception in debug event listener.
var before_compile_count = 0;
var after_compile_count = 0;
var compile_error_count = 0;
var current_source = ''; // Current source being compiled.
var source_count = 0; // Total number of scources compiled.
var host_compilations = 0; // Number of scources compiled through the API.
......@@ -48,11 +49,12 @@ function compileSource(source) {
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.BeforeCompile ||
event == Debug.DebugEvent.AfterCompile) {
event == Debug.DebugEvent.AfterCompile ||
event == Debug.DebugEvent.CompileError) {
// Count the events.
if (event == Debug.DebugEvent.BeforeCompile) {
before_compile_count++;
} else {
} else if (event == Debug.DebugEvent.AfterCompile) {
after_compile_count++;
switch (event_data.script().compilationType()) {
case Debug.ScriptCompilationType.Host:
......@@ -62,6 +64,8 @@ function listener(event, exec_state, event_data, data) {
eval_compilations++;
break;
}
} else {
compile_error_count++;
}
// If the compiled source contains 'eval' there will be additional compile
......@@ -105,11 +109,17 @@ compileSource('JSON.parse(\'{"a":1,"b":2}\')');
// Using JSON.parse does not causes additional compilation events.
compileSource('x=1; //# sourceURL=myscript.js');
try {
compileSource('}');
} catch(e) {
}
// Make sure that the debug event listener was invoked.
assertFalse(exception, "exception in listener")
// Number of before and after compile events should be the same.
assertEquals(before_compile_count, after_compile_count);
// Number of before and after + error events should be the same.
assertEquals(before_compile_count, after_compile_count + compile_error_count);
assertEquals(compile_error_count, 1);
// Check the actual number of events (no compilation through the API as all
// source compiled through eval).
......
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