1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* 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/. */
use Deref;
use NonNull;
pub use crateJSContext as RawJSContext;
/// A wrapper for [raw JSContext pointers](RawJSContext) that are strongly associated with the [Runtime](crate::rust::Runtime) type.
///
/// This type is fundamental for safe SpiderMonkey usage.
/// Each (SpiderMonkey) function which takes [`&mut JSContext`](JSContext) as argument can trigger GC.
/// SpiderMonkey functions that takes [`&JSContext`](JSContext) are guaranteed to not trigger GC.
/// We must not hold any unrooted or borrowed data while calling any functions that can trigger GC.
/// That can causes panics or UB.
/// For cases where notion of no GC but no actual context is needed, we have [`&NoGC`](NoGC) token.
///
/// ```rust
/// use std::marker::PhantomData;
/// use mozjs::context::*;
///
/// struct ShouldNotBeHoldAcrossGC<'a>(PhantomData<&'a ()>);
///
/// impl<'a> Drop for ShouldNotBeHoldAcrossGC<'a> {
/// fn drop(&mut self) {}
/// }
///
/// fn something_that_should_not_hold_across_gc<'a>(_no_gc: &'a NoGC) -> ShouldNotBeHoldAcrossGC<'a> {
/// ShouldNotBeHoldAcrossGC(PhantomData)
/// }
///
/// fn SM_function_that_can_trigger_gc(_cx: *mut RawJSContext) {}
///
/// // this lives in mozjs
/// fn safe_wrapper_to_SM_function_that_can_trigger_gc(cx: &mut JSContext) {
/// unsafe { SM_function_that_can_trigger_gc(cx.raw_cx()) }
/// }
///
/// fn can_cause_gc(cx: &mut JSContext) {
/// safe_wrapper_to_SM_function_that_can_trigger_gc(cx);
/// {
/// let t = something_that_should_not_hold_across_gc(&cx.no_gc());
/// // do something with it
/// } // t get dropped
/// safe_wrapper_to_SM_function_that_can_trigger_gc(cx); // we can call GC again
/// }
/// ```
///
/// One cannot call any GC function, while any [`&JSContext`](JSContext) or [`&NoGC`](NoGC) is alive,
/// because they require such functions accept [`&mut JSContext`](JSContext):
///
/// ```compile_fail
/// use std::marker::PhantomData;
/// use mozjs::context::*;
/// use mozjs::jsapi::JSContext as RawJSContext;
///
/// struct ShouldNotBeHoldAcrossGC<'a>(PhantomData<&'a ()>);
///
/// impl<'a> Drop for ShouldNotBeHoldAcrossGC<'a> {
/// fn drop(&mut self) {} // make type not trivial, or else compiler can shorten it's lifetime
/// }
///
/// fn something_that_should_not_hold_across_gc<'a>(_no_gc: &'a NoGC) -> ShouldNotBeHoldAcrossGC<'a> {
/// ShouldNotBeHoldAcrossGC(PhantomData)
/// }
///
/// fn safe_wrapper_to_SM_function_that_can_trigger_gc(_cx: &mut JSContext) {
/// }
///
/// fn can_cause_gc(cx: &mut JSContext) {
/// safe_wrapper_to_SM_function_that_can_trigger_gc(cx);
/// let t = something_that_should_not_hold_across_gc(&cx.no_gc());
/// // this will create compile error, because we cannot hold NoGc across C triggering function.
/// // more specifically we cannot borrow `JSContext` as mutable because it is also borrowed as immutable (NoGC).
/// safe_wrapper_to_SM_function_that_can_trigger_gc(cx);
/// }
/// ```
///
/// ### WIP
///
/// This model is still being incrementally introduced, so there are currently some escape hatches.
/// Token that ensures that no GC can happen while it is alive.
///
/// This type is similar to `&JSContext`,
/// but it is used in cases where no actual context is needed.
///
/// For more info and examples see [JSContext].
); // zero-sized type that cannot be constructed from outside