summaryrefslogtreecommitdiffstats
path: root/js/src/debugger/NoExecute.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/debugger/NoExecute.cpp')
-rw-r--r--js/src/debugger/NoExecute.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/js/src/debugger/NoExecute.cpp b/js/src/debugger/NoExecute.cpp
new file mode 100644
index 0000000000..028dc65484
--- /dev/null
+++ b/js/src/debugger/NoExecute.cpp
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "debugger/NoExecute.h"
+
+#include "mozilla/Sprintf.h" // for SprintfLiteral
+
+#include <stdio.h> // for fprintf, stdout
+
+#include "debugger/Debugger.h" // for Debugger
+#include "js/friend/DumpFunctions.h" // for DumpBacktrace
+#include "js/friend/ErrorMessages.h" // for GetErrorMessage, JSMSG_DEBUGGEE_WOULD_RUN
+#include "js/Promise.h" // for AutoDebuggerJobQueueInterruption
+#include "js/RootingAPI.h" // for Handle
+#include "vm/JSContext.h" // for ProtectedDataContextArg, JSContext
+#include "vm/JSScript.h" // for JSScript
+#include "vm/Realm.h" // for AutoRealm, Realm
+#include "vm/Warnings.h" // for WarnNumberUTF8
+
+#include "gc/StableCellHasher-inl.h"
+#include "vm/Realm-inl.h" // for AutoRealm::AutoRealm
+
+using namespace js;
+
+EnterDebuggeeNoExecute::EnterDebuggeeNoExecute(
+ JSContext* cx, Debugger& dbg,
+ const JS::AutoDebuggerJobQueueInterruption& adjqiProof)
+ : dbg_(dbg), unlocked_(nullptr), reported_(false) {
+ MOZ_ASSERT(adjqiProof.initialized());
+ stack_ = &cx->noExecuteDebuggerTop.ref();
+ prev_ = *stack_;
+ *stack_ = this;
+}
+
+#ifdef DEBUG
+/* static */
+bool EnterDebuggeeNoExecute::isLockedInStack(JSContext* cx, Debugger& dbg) {
+ for (EnterDebuggeeNoExecute* it = cx->noExecuteDebuggerTop; it;
+ it = it->prev_) {
+ if (&it->debugger() == &dbg) {
+ return !it->unlocked_;
+ }
+ }
+ return false;
+}
+#endif
+
+/* static */
+EnterDebuggeeNoExecute* EnterDebuggeeNoExecute::findInStack(JSContext* cx) {
+ Realm* debuggee = cx->realm();
+ for (EnterDebuggeeNoExecute* it = cx->noExecuteDebuggerTop; it;
+ it = it->prev_) {
+ Debugger& dbg = it->debugger();
+ if (!it->unlocked_ && dbg.observesGlobal(debuggee->maybeGlobal())) {
+ return it;
+ }
+ }
+ return nullptr;
+}
+
+/* static */
+bool EnterDebuggeeNoExecute::reportIfFoundInStack(JSContext* cx,
+ HandleScript script) {
+ if (EnterDebuggeeNoExecute* nx = findInStack(cx)) {
+ bool warning = !cx->options().throwOnDebuggeeWouldRun();
+ if (!warning || !nx->reported_) {
+ AutoRealm ar(cx, nx->debugger().toJSObject());
+ nx->reported_ = true;
+ if (cx->options().dumpStackOnDebuggeeWouldRun()) {
+ fprintf(stdout, "Dumping stack for DebuggeeWouldRun:\n");
+ DumpBacktrace(cx);
+ }
+ const char* filename = script->filename() ? script->filename() : "(none)";
+ char linenoStr[15];
+ SprintfLiteral(linenoStr, "%u", script->lineno());
+ if (warning) {
+ return WarnNumberUTF8(cx, JSMSG_DEBUGGEE_WOULD_RUN, filename,
+ linenoStr);
+ }
+
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
+ JSMSG_DEBUGGEE_WOULD_RUN, filename, linenoStr);
+ return false;
+ }
+ }
+ return true;
+}