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 { ...@@ -20,7 +20,8 @@ enum DebugEvent {
BeforeCompile = 4, BeforeCompile = 4,
AfterCompile = 5, AfterCompile = 5,
ScriptCollected = 6, ScriptCollected = 6,
BreakForCommand = 7 CompileError = 7,
BreakForCommand = 8
}; };
......
...@@ -19,7 +19,8 @@ Debug.DebugEvent = { Break: 1, ...@@ -19,7 +19,8 @@ Debug.DebugEvent = { Break: 1,
NewFunction: 3, NewFunction: 3,
BeforeCompile: 4, BeforeCompile: 4,
AfterCompile: 5, AfterCompile: 5,
ScriptCollected: 6 }; ScriptCollected: 6,
CompileError: 7 };
// Types of exceptions that can be broken upon. // Types of exceptions that can be broken upon.
Debug.ExceptionBreak = { Caught : 0, Debug.ExceptionBreak = { Caught : 0,
...@@ -1143,23 +1144,19 @@ ExceptionEvent.prototype.toJSONProtocol = function() { ...@@ -1143,23 +1144,19 @@ ExceptionEvent.prototype.toJSONProtocol = function() {
}; };
function MakeCompileEvent(script, before) { function MakeCompileEvent(script, type) {
return new CompileEvent(script, before); return new CompileEvent(script, type);
} }
function CompileEvent(script, before) { function CompileEvent(script, type) {
this.script_ = MakeMirror(script); this.script_ = MakeMirror(script);
this.before_ = before; this.type_ = type;
} }
CompileEvent.prototype.eventType = function() { CompileEvent.prototype.eventType = function() {
if (this.before_) { return this.type_;
return Debug.DebugEvent.BeforeCompile;
} else {
return Debug.DebugEvent.AfterCompile;
}
}; };
...@@ -1171,10 +1168,13 @@ CompileEvent.prototype.script = function() { ...@@ -1171,10 +1168,13 @@ CompileEvent.prototype.script = function() {
CompileEvent.prototype.toJSONProtocol = function() { CompileEvent.prototype.toJSONProtocol = function() {
var o = new ProtocolMessage(); var o = new ProtocolMessage();
o.running = true; o.running = true;
if (this.before_) { switch (this.type_) {
o.event = "beforeCompile"; case Debug.DebugEvent.BeforeCompile:
} else { o.event = "beforeCompile";
o.event = "afterCompile"; case Debug.DebugEvent.AfterCompile:
o.event = "afterCompile";
case Debug.DebugEvent.CompileError:
o.event = "compileError";
} }
o.body = {}; o.body = {};
o.body.script = this.script_; o.body.script = this.script_;
......
...@@ -2554,11 +2554,11 @@ MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception, ...@@ -2554,11 +2554,11 @@ MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
bool before) { v8::DebugEvent type) {
// Create the compile event object. // Create the compile event object.
Handle<Object> script_wrapper = Script::GetWrapper(script); Handle<Object> script_wrapper = Script::GetWrapper(script);
Handle<Object> argv[] = { script_wrapper, Handle<Object> argv[] = { script_wrapper,
isolate_->factory()->ToBoolean(before) }; isolate_->factory()->NewNumberFromInt(type) };
return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv); return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv);
} }
...@@ -2607,6 +2607,24 @@ void Debug::OnException(Handle<Object> exception, bool uncaught) { ...@@ -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, void Debug::OnDebugBreak(Handle<Object> break_points_hit,
bool auto_continue) { bool auto_continue) {
// The caller provided for DebugScope. // The caller provided for DebugScope.
...@@ -2637,7 +2655,8 @@ void Debug::OnBeforeCompile(Handle<Script> script) { ...@@ -2637,7 +2655,8 @@ void Debug::OnBeforeCompile(Handle<Script> script) {
// Create the event data object. // Create the event data object.
Handle<Object> event_data; Handle<Object> event_data;
// Bail out and don't call debugger if exception. // 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. // Process debug event.
ProcessDebugEvent(v8::BeforeCompile, ProcessDebugEvent(v8::BeforeCompile,
...@@ -2690,7 +2709,7 @@ void Debug::OnAfterCompile(Handle<Script> script) { ...@@ -2690,7 +2709,7 @@ void Debug::OnAfterCompile(Handle<Script> script) {
// Create the compile state object. // Create the compile state object.
Handle<Object> event_data; Handle<Object> event_data;
// Bail out and don't call debugger if exception. // 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. // Process debug event.
ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
......
...@@ -367,6 +367,7 @@ class Debug { ...@@ -367,6 +367,7 @@ class Debug {
// Debug event triggers. // Debug event triggers.
void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
void OnException(Handle<Object> exception, bool uncaught); void OnException(Handle<Object> exception, bool uncaught);
void OnCompileError(Handle<Script> script);
void OnBeforeCompile(Handle<Script> script); void OnBeforeCompile(Handle<Script> script);
void OnAfterCompile(Handle<Script> script); void OnAfterCompile(Handle<Script> script);
void OnScriptCollected(int id); void OnScriptCollected(int id);
...@@ -542,7 +543,7 @@ class Debug { ...@@ -542,7 +543,7 @@ class Debug {
bool uncaught, bool uncaught,
Handle<Object> promise); Handle<Object> promise);
MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( 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); MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id);
// Mirror cache handling. // Mirror cache handling.
......
...@@ -3888,6 +3888,8 @@ void Parser::ThrowPendingError() { ...@@ -3888,6 +3888,8 @@ void Parser::ThrowPendingError() {
.ToHandleChecked(); .ToHandleChecked();
elements->set(0, *arg_string); elements->set(0, *arg_string);
} }
isolate()->debug()->OnCompileError(script_);
Handle<JSArray> array = factory->NewJSArrayWithElements(elements); Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
Handle<Object> result = pending_error_is_reference_error_ Handle<Object> result = pending_error_is_reference_error_
? factory->NewReferenceError(pending_error_message_, array) ? factory->NewReferenceError(pending_error_message_, array)
......
...@@ -6376,6 +6376,60 @@ TEST(AfterCompileMessageWhenMessageHandlerIsReset) { ...@@ -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. // Tests that break event is sent when message handler is reset.
TEST(BreakMessageWhenMessageHandlerIsReset) { TEST(BreakMessageWhenMessageHandlerIsReset) {
DebugLocalContext env; DebugLocalContext env;
......
...@@ -32,6 +32,7 @@ Debug = debug.Debug ...@@ -32,6 +32,7 @@ Debug = debug.Debug
var exception = false; // Exception in debug event listener. var exception = false; // Exception in debug event listener.
var before_compile_count = 0; var before_compile_count = 0;
var after_compile_count = 0; var after_compile_count = 0;
var compile_error_count = 0;
var current_source = ''; // Current source being compiled. var current_source = ''; // Current source being compiled.
var source_count = 0; // Total number of scources compiled. var source_count = 0; // Total number of scources compiled.
var host_compilations = 0; // Number of scources compiled through the API. var host_compilations = 0; // Number of scources compiled through the API.
...@@ -48,11 +49,12 @@ function compileSource(source) { ...@@ -48,11 +49,12 @@ function compileSource(source) {
function listener(event, exec_state, event_data, data) { function listener(event, exec_state, event_data, data) {
try { try {
if (event == Debug.DebugEvent.BeforeCompile || if (event == Debug.DebugEvent.BeforeCompile ||
event == Debug.DebugEvent.AfterCompile) { event == Debug.DebugEvent.AfterCompile ||
event == Debug.DebugEvent.CompileError) {
// Count the events. // Count the events.
if (event == Debug.DebugEvent.BeforeCompile) { if (event == Debug.DebugEvent.BeforeCompile) {
before_compile_count++; before_compile_count++;
} else { } else if (event == Debug.DebugEvent.AfterCompile) {
after_compile_count++; after_compile_count++;
switch (event_data.script().compilationType()) { switch (event_data.script().compilationType()) {
case Debug.ScriptCompilationType.Host: case Debug.ScriptCompilationType.Host:
...@@ -62,6 +64,8 @@ function listener(event, exec_state, event_data, data) { ...@@ -62,6 +64,8 @@ function listener(event, exec_state, event_data, data) {
eval_compilations++; eval_compilations++;
break; break;
} }
} else {
compile_error_count++;
} }
// If the compiled source contains 'eval' there will be additional compile // If the compiled source contains 'eval' there will be additional compile
...@@ -105,11 +109,17 @@ compileSource('JSON.parse(\'{"a":1,"b":2}\')'); ...@@ -105,11 +109,17 @@ compileSource('JSON.parse(\'{"a":1,"b":2}\')');
// Using JSON.parse does not causes additional compilation events. // Using JSON.parse does not causes additional compilation events.
compileSource('x=1; //# sourceURL=myscript.js'); compileSource('x=1; //# sourceURL=myscript.js');
try {
compileSource('}');
} catch(e) {
}
// Make sure that the debug event listener was invoked. // Make sure that the debug event listener was invoked.
assertFalse(exception, "exception in listener") assertFalse(exception, "exception in listener")
// Number of before and after compile events should be the same. // Number of before and after + error events should be the same.
assertEquals(before_compile_count, after_compile_count); 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 // Check the actual number of events (no compilation through the API as all
// source compiled through eval). // 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