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

[inspector] introduced debug::SetCompileEventListener

Listener is called instead of event listener for v8::AfterCompile and v8::CompileError events if installed.
- removed v8::debug::Script::Wrap.

BUG=v8:5510
R=yangguo@chromium.org,jgruber@chromium.org,dgozman@chromium.org,clemensh@chromium.org, alph@chromium.org,

Review-Url: https://codereview.chromium.org/2626283002
Cr-Commit-Position: refs/heads/master@{#42477}
parent 80234ee3
......@@ -9234,26 +9234,6 @@ int debug::Script::GetSourcePosition(const debug::Location& location) const {
return std::min(prev_line_offset + column + 1, line_offset);
}
MaybeLocal<debug::Script> debug::Script::Wrap(v8::Isolate* v8_isolate,
v8::Local<v8::Object> script) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8(isolate);
i::HandleScope handle_scope(isolate);
i::Handle<i::JSReceiver> script_receiver(Utils::OpenHandle(*script));
if (!script_receiver->IsJSValue()) return MaybeLocal<Script>();
i::Handle<i::Object> script_value(
i::Handle<i::JSValue>::cast(script_receiver)->value(), isolate);
if (!script_value->IsScript()) {
return MaybeLocal<Script>();
}
i::Handle<i::Script> script_obj = i::Handle<i::Script>::cast(script_value);
if (script_obj->type() != i::Script::TYPE_NORMAL &&
script_obj->type() != i::Script::TYPE_WASM) {
return MaybeLocal<Script>();
}
return ToApiHandle<debug::Script>(handle_scope.CloseAndEscape(script_obj));
}
debug::WasmScript* debug::WasmScript::Cast(debug::Script* script) {
CHECK(script->IsWasm());
return static_cast<WasmScript*>(script);
......@@ -9359,6 +9339,14 @@ void debug::SetAsyncTaskListener(Isolate* v8_isolate,
isolate->debug()->SetAsyncTaskListener(listener, data);
}
void debug::SetCompileEventListener(Isolate* v8_isolate,
debug::CompileEventListener listener,
void* data) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8(isolate);
isolate->debug()->SetCompileEventListener(listener, data);
}
Local<String> CpuProfileNode::GetFunctionName() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
i::Isolate* isolate = node->isolate();
......
......@@ -173,17 +173,6 @@ class Script {
const debug::Location& end,
std::vector<debug::Location>* locations) const;
/**
* script parameter is a wrapper v8::internal::JSObject for
* v8::internal::Script.
* This function gets v8::internal::Script from v8::internal::JSObject and
* wraps it with DebugInterface::Script.
* Returns empty local if not called with a valid wrapper of
* v8::internal::Script.
*/
static MaybeLocal<Script> Wrap(Isolate* isolate,
v8::Local<v8::Object> script);
private:
int GetSourcePosition(const debug::Location& location) const;
};
......@@ -210,6 +199,12 @@ typedef std::function<void(debug::PromiseDebugActionType type, int id,
void SetAsyncTaskListener(Isolate* isolate, AsyncTaskListener listener,
void* data);
typedef std::function<void(v8::Local<Script> script, bool has_compile_error,
void* data)>
CompileEventListener;
void SetCompileEventListener(Isolate* isolate, CompileEventListener listener,
void* data);
} // namespace debug
} // namespace v8
......
......@@ -1866,17 +1866,7 @@ void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) {
if (async_task_listener_) {
async_task_listener_(type, id, async_task_listener_data_);
// There are three types of event listeners: C++ message_handler,
// JavaScript event listener and C++ event listener.
// Currently inspector still uses C++ event listener and installs
// more specific event listeners for part of events. Calling of
// C++ event listener is redundant when more specific event listener
// is presented. Other clients can install JavaScript event listener
// (e.g. some of NodeJS module).
bool non_inspector_listener_exists =
message_handler_ != nullptr ||
(event_listener_.is_null() && !event_listener_->IsForeign());
if (!non_inspector_listener_exists) return;
if (!non_inspector_listener_exists()) return;
}
HandleScope scope(isolate_);
......@@ -1955,6 +1945,12 @@ void Debug::CallEventCallback(v8::DebugEvent event,
in_debug_event_listener_ = previous;
}
void Debug::SetCompileEventListener(debug::CompileEventListener listener,
void* data) {
compile_event_listener_ = listener;
compile_event_listener_data_ = data;
UpdateState();
}
void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
if (ignore_events()) return;
......@@ -1963,12 +1959,18 @@ void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
return;
}
SuppressDebug while_processing(this);
bool in_nested_debug_scope = in_debug_scope();
HandleScope scope(isolate_);
DebugScope debug_scope(this);
if (debug_scope.failed()) return;
if (compile_event_listener_) {
compile_event_listener_(ToApiHandle<debug::Script>(script),
event != v8::AfterCompile,
compile_event_listener_data_);
if (!non_inspector_listener_exists()) return;
}
HandleScope scope(isolate_);
// Create the compile state object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
......@@ -2162,7 +2164,8 @@ void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
void Debug::UpdateState() {
bool is_active = message_handler_ != nullptr || !event_listener_.is_null() ||
async_task_listener_ != nullptr;
async_task_listener_ != nullptr ||
compile_event_listener_ != nullptr;
if (is_active || in_debug_scope()) {
// Note that the debug context could have already been loaded to
// bootstrap test cases.
......
......@@ -467,6 +467,8 @@ class Debug {
int NextAsyncTaskId(Handle<JSObject> promise);
void SetAsyncTaskListener(debug::AsyncTaskListener listener, void* data);
void SetCompileEventListener(debug::CompileEventListener listener,
void* data);
// Returns whether the operation succeeded. Compilation can only be triggered
// if a valid closure is passed as the second argument, otherwise the shared
......@@ -595,6 +597,18 @@ class Debug {
return thread_local_.suspended_generator_ != Smi::kZero;
}
// There are three types of event listeners: C++ message_handler,
// JavaScript event listener and C++ event listener.
// Currently inspector still uses C++ event listener and installs
// more specific event listeners for part of events. Calling of
// C++ event listener is redundant when more specific event listener
// is presented. Other clients can install JavaScript event listener
// (e.g. some of NodeJS module).
bool non_inspector_listener_exists() const {
return message_handler_ != nullptr ||
(!event_listener_.is_null() && !event_listener_->IsForeign());
}
void OnException(Handle<Object> exception, Handle<Object> promise);
// Constructors for debug event objects.
......@@ -667,6 +681,8 @@ class Debug {
debug::AsyncTaskListener async_task_listener_ = nullptr;
void* async_task_listener_data_ = nullptr;
debug::CompileEventListener compile_event_listener_ = nullptr;
void* compile_event_listener_data_ = nullptr;
static const int kQueueInitialSize = 4;
base::Semaphore command_received_; // Signaled for each command received.
......
......@@ -72,6 +72,8 @@ void V8Debugger::enable() {
v8::External::New(m_isolate, this));
v8::debug::SetAsyncTaskListener(m_isolate, &V8Debugger::v8AsyncTaskListener,
this);
v8::debug::SetCompileEventListener(m_isolate,
&V8Debugger::v8CompileEventListener, this);
m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate));
v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException);
m_pauseOnExceptionsState = v8::debug::NoBreakOnException;
......@@ -88,6 +90,7 @@ void V8Debugger::disable() {
m_wasmTranslation.Clear();
v8::debug::SetDebugEventListener(m_isolate, nullptr);
v8::debug::SetAsyncTaskListener(m_isolate, nullptr, nullptr);
v8::debug::SetCompileEventListener(m_isolate, nullptr, nullptr);
}
bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); }
......@@ -536,9 +539,7 @@ void V8Debugger::handleV8DebugEvent(
v8::HandleScope scope(m_isolate);
v8::DebugEvent event = eventDetails.GetEvent();
if (event != v8::Break && event != v8::Exception &&
event != v8::AfterCompile && event != v8::CompileError)
return;
if (event != v8::Break && event != v8::Exception) return;
v8::Local<v8::Context> eventContext = eventDetails.GetEventContext();
DCHECK(!eventContext.IsEmpty());
......@@ -546,28 +547,7 @@ void V8Debugger::handleV8DebugEvent(
m_inspector->contextGroupId(eventContext));
if (!agent) return;
if (event == v8::AfterCompile || event == v8::CompileError) {
v8::Context::Scope contextScope(debuggerContext());
// Determine if the script is a wasm script.
v8::Local<v8::Value> scriptMirror =
callInternalGetterFunction(eventDetails.GetEventData(), "script");
DCHECK(scriptMirror->IsObject());
v8::Local<v8::Value> scriptWrapper =
callInternalGetterFunction(scriptMirror.As<v8::Object>(), "value");
DCHECK(scriptWrapper->IsObject());
v8::Local<v8::debug::Script> script;
if (!v8::debug::Script::Wrap(m_isolate, scriptWrapper.As<v8::Object>())
.ToLocal(&script)) {
return;
}
if (script->IsWasm()) {
m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(), agent);
} else if (m_ignoreScriptParsedEventsCounter == 0) {
agent->didParseSource(
V8DebuggerScript::Create(m_isolate, script, inLiveEditScope),
event == v8::AfterCompile);
}
} else if (event == v8::Exception) {
if (event == v8::Exception) {
v8::Local<v8::Context> context = debuggerContext();
v8::Local<v8::Object> eventData = eventDetails.GetEventData();
v8::Local<v8::Value> exception =
......@@ -593,6 +573,29 @@ void V8Debugger::handleV8DebugEvent(
}
}
void V8Debugger::v8CompileEventListener(v8::Local<v8::debug::Script> script,
bool has_compile_error, void* data) {
V8Debugger* debugger = static_cast<V8Debugger*>(data);
v8::Local<v8::Value> contextData;
if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) {
return;
}
int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value());
int contextGroupId = debugger->m_inspector->contextGroupId(contextId);
if (!contextGroupId) return;
V8DebuggerAgentImpl* agent =
debugger->m_inspector->enabledDebuggerAgentForGroup(contextGroupId);
if (!agent) return;
if (script->IsWasm()) {
debugger->m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(),
agent);
} else if (debugger->m_ignoreScriptParsedEventsCounter == 0) {
agent->didParseSource(
V8DebuggerScript::Create(debugger->m_isolate, script, inLiveEditScope),
!has_compile_error);
}
}
void V8Debugger::v8AsyncTaskListener(v8::debug::PromiseDebugActionType type,
int id, void* data) {
V8Debugger* debugger = static_cast<V8Debugger*>(data);
......
......@@ -116,6 +116,8 @@ class V8Debugger {
void handleV8DebugEvent(const v8::debug::EventDetails&);
static void v8AsyncTaskListener(v8::debug::PromiseDebugActionType type,
int id, void* data);
static void v8CompileEventListener(v8::Local<v8::debug::Script> script,
bool has_compile_error, void* data);
v8::Local<v8::Value> collectionEntries(v8::Local<v8::Context>,
v8::Local<v8::Object>);
......
......@@ -725,6 +725,8 @@ Handle<Script> CreateWasmScript(Isolate* isolate,
const ModuleWireBytes& wire_bytes) {
Handle<Script> script =
isolate->factory()->NewScript(isolate->factory()->empty_string());
FixedArray* array = isolate->native_context()->embedder_data();
script->set_context_data(array->get(v8::Context::kDebugIdIndex));
script->set_type(Script::TYPE_WASM);
int hash = StringHasher::HashSequentialString(
......
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