Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions NativeScript/inspector/JsV8InspectorClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class JsV8InspectorClient : V8InspectorClient, V8Inspector::Channel {
void runMessageLoopOnPause(int contextGroupId) override;
void quitMessageLoopOnPause() override;

void scheduleBreak();
void pauseBeforeApp();
void registerModules();

void consoleLog(v8::Isolate* isolate, ConsoleAPIType method,
Expand Down Expand Up @@ -106,7 +106,7 @@ class JsV8InspectorClient : V8InspectorClient, V8Inspector::Channel {
uint64_t sessionConnectionId_ = 0;
uint64_t frontendGeneration_ = 0; // guarded by senderMutex_
bool isWaitingForDebugger_ = false;
bool hasScheduledDebugBreak_ = false;
bool debuggerAttachedWhileWaiting_ = false;

std::unique_ptr<tns::inspector::TracingAgentImpl> tracing_agent_;

Expand Down
44 changes: 24 additions & 20 deletions NativeScript/inspector/JsV8InspectorClient.mm
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ bool ShouldRewriteSourceMapURLs() {
do {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
} while (this->isWaitingForDebugger_);
if (this->debuggerAttachedWhileWaiting_) {
this->pauseBeforeApp();
}
});
CFRunLoopWakeUp(CFRunLoopGetMain());
});
Expand Down Expand Up @@ -216,14 +219,13 @@ bool ShouldRewriteSourceMapURLs() {
std::function<void(const std::string&)> sender) {
std::lock_guard<std::mutex> lifecycle(this->frontendLifecycleMutex_);

if (this->isWaitingForDebugger_) {
this->isWaitingForDebugger_ = NO;
CFRunLoopRef runloop = CFRunLoopGetMain();
CFRunLoopPerformBlock(runloop, (__bridge CFTypeRef)(NSRunLoopCommonModes), ^{
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false);
this->scheduleBreak();
if (this->isWaitingForDebugger_ && !this->debuggerAttachedWhileWaiting_) {
this->debuggerAttachedWhileWaiting_ = true;
// Frontends that don't send Runtime.runIfWaitingForDebugger still get the app
// going, once they've had time to enable the debugger.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 3), dispatch_get_main_queue(), ^{
this->isWaitingForDebugger_ = NO;
});
CFRunLoopWakeUp(runloop);
}

bool replacesFrontend;
Expand Down Expand Up @@ -748,6 +750,13 @@ bool ShouldRewriteSourceMapURLs() {
auto json_message = json::parse(message);
std::string method = json_message["method"];

// The frontend's last message before it expects the app to run, so it arrives
// after the Debugger.enable that the pause depends on. The Runtime domain still
// answers it below.
if (method == "Runtime.runIfWaitingForDebugger") {
this->isWaitingForDebugger_ = NO;
}

// Note: the Tracing domain is handled in onFrontendMessageReceived, so it
// never waits on the message queue or takes the Locker below.

Expand Down Expand Up @@ -1097,26 +1106,21 @@ json WithSessionId(json message, const std::string& sessionId) {
return result;
}

void JsV8InspectorClient::scheduleBreak() {
void JsV8InspectorClient::pauseBeforeApp() {
Isolate* isolate = isolate_;
v8::Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
auto context = isolate->GetCurrentContext();
Local<Context> context = tns::Caches::Get(isolate)->GetContext();
Context::Scope context_scope(context);

if (!this->hasScheduledDebugBreak_) {
this->hasScheduledDebugBreak_ = true;
// hack: force a debugger; statement in ModuleInternal to actually break before loading the next
// (main) script...
// FIXME: find a proper fix to not need to resort to this hack.
context->Global()
->Set(context, tns::ToV8String(isolate, "__pauseOnNextRequire"),
v8::Boolean::New(isolate, true))
.ToChecked();
// schedulePauseOnNextStatement doesn't break on the evaluation of the main
// module, and an ES module has no require call to stop at either. This stops
// before any app code has run, so its breakpoints can still be set.
Local<Script> script;
if (Script::Compile(context, tns::ToV8String(isolate, "debugger;")).ToLocal(&script)) {
script->Run(context).IsEmpty();
}

this->session_->schedulePauseOnNextStatement({}, {});
}

void JsV8InspectorClient::registerModules() {
Expand Down
Loading