Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
3
* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef debugger_NoExecute_h
8
#define debugger_NoExecute_h
9
10
#include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT
11
#include "mozilla/Attributes.h" // for MOZ_RAII
12
13
#include "jsapi.h"
14
15
#include "NamespaceImports.h" // for HandleScript
16
#include "js/Promise.h" // for JS::AutoDebuggerJobQueueInterruption
17
18
namespace js {
19
20
class Debugger;
21
class LeaveDebuggeeNoExecute;
22
23
// Prevents all the debuggeee compartments of a given Debugger from executing
24
// scripts. Attempts to run script will throw an
25
// instance of Debugger.DebuggeeWouldRun from the topmost locked Debugger's
26
// compartment.
27
class MOZ_RAII EnterDebuggeeNoExecute {
28
friend class LeaveDebuggeeNoExecute;
29
30
Debugger& dbg_;
31
EnterDebuggeeNoExecute** stack_;
32
EnterDebuggeeNoExecute* prev_;
33
34
// Non-nullptr when unlocked temporarily by a LeaveDebuggeeNoExecute.
35
LeaveDebuggeeNoExecute* unlocked_;
36
37
// When DebuggeeWouldRun is a warning instead of an error, whether we've
38
// reported a warning already.
39
bool reported_;
40
41
public:
42
// Mark execution in dbg's debuggees as forbidden, for the lifetime of this
43
// object. Require an AutoDebuggerJobQueueInterruption in scope.
44
explicit EnterDebuggeeNoExecute(
45
JSContext* cx, Debugger& dbg,
46
const JS::AutoDebuggerJobQueueInterruption& adjqiProof);
47
48
~EnterDebuggeeNoExecute() {
49
MOZ_ASSERT(*stack_ == this);
50
*stack_ = prev_;
51
}
52
53
Debugger& debugger() const { return dbg_; }
54
55
#ifdef DEBUG
56
static bool isLockedInStack(JSContext* cx, Debugger& dbg);
57
#endif
58
59
// Given a JSContext entered into a debuggee realm, find the lock
60
// that locks it. Returns nullptr if not found.
61
static EnterDebuggeeNoExecute* findInStack(JSContext* cx);
62
63
// Given a JSContext entered into a debuggee compartment, report a
64
// warning or an error if there is a lock that locks it.
65
static bool reportIfFoundInStack(JSContext* cx, HandleScript script);
66
};
67
68
// Given a JSContext entered into a debuggee compartment, if it is in
69
// an NX section, unlock the topmost EnterDebuggeeNoExecute instance.
70
//
71
// Does nothing if debuggee is not in an NX section. For example, this
72
// situation arises when invocation functions are called without entering
73
// Debugger code, e.g., calling D.O.p.executeInGlobal or D.O.p.apply.
74
class MOZ_RAII LeaveDebuggeeNoExecute {
75
EnterDebuggeeNoExecute* prevLocked_;
76
77
public:
78
explicit LeaveDebuggeeNoExecute(JSContext* cx)
79
: prevLocked_(EnterDebuggeeNoExecute::findInStack(cx)) {
80
if (prevLocked_) {
81
MOZ_ASSERT(!prevLocked_->unlocked_);
82
prevLocked_->unlocked_ = this;
83
}
84
}
85
86
~LeaveDebuggeeNoExecute() {
87
if (prevLocked_) {
88
MOZ_ASSERT(prevLocked_->unlocked_ == this);
89
prevLocked_->unlocked_ = nullptr;
90
}
91
}
92
};
93
94
} /* namespace js */
95
96
#endif /* debugger_NoExecute_h */