v8
10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
v8-local-handle.h
Go to the documentation of this file.
1
// Copyright 2021 the V8 project authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#
ifndef
INCLUDE_V8_LOCAL_HANDLE_H_
6
#
define
INCLUDE_V8_LOCAL_HANDLE_H_
7
8
#
include
<
stddef
.
h
>
9
10
#
include
<
type_traits
>
11
12
#
include
"v8-internal.h"
// NOLINT(build/include_directory)
13
14
namespace
v8
{
15
16
class
Boolean
;
17
template
<
class
T>
18
class
BasicTracedReference
;
19
class
Context
;
20
class
EscapableHandleScope
;
21
template
<
class
F>
22
class
Eternal
;
23
template
<
class
F>
24
class
FunctionCallbackInfo
;
25
class
Isolate
;
26
template
<
class
F>
27
class
MaybeLocal
;
28
template
<
class
T>
29
class
NonCopyablePersistentTraits;
30
class
Object
;
31
template
<
class
T,
class
M = NonCopyablePersistentTraits<T>>
32
class
Persistent
;
33
template
<
class
T>
34
class
PersistentBase
;
35
template
<
class
F1,
class
F2,
class
F3>
36
class
PersistentValueMapBase
;
37
template
<
class
F1,
class
F2>
38
class
PersistentValueVector
;
39
class
Primitive
;
40
class
Private
;
41
template
<
class
F>
42
class
PropertyCallbackInfo
;
43
template
<
class
F>
44
class
ReturnValue
;
45
class
String
;
46
template
<
class
F>
47
class
Traced
;
48
template
<
class
F>
49
class
TracedGlobal
;
50
template
<
class
F>
51
class
TracedReference
;
52
class
TracedReferenceBase
;
53
class
Utils;
54
55
namespace
internal
{
56
template
<
typename
T>
57
class
CustomArguments
;
58
}
// namespace internal
59
60
namespace
api_internal
{
61
// Called when ToLocalChecked is called on an empty Local.
62
V8_EXPORT
void
ToLocalEmpty
();
63
}
// namespace api_internal
64
65
/**
66
* A stack-allocated class that governs a number of local handles.
67
* After a handle scope has been created, all local handles will be
68
* allocated within that handle scope until either the handle scope is
69
* deleted or another handle scope is created. If there is already a
70
* handle scope and a new one is created, all allocations will take
71
* place in the new handle scope until it is deleted. After that,
72
* new handles will again be allocated in the original handle scope.
73
*
74
* After the handle scope of a local handle has been deleted the
75
* garbage collector will no longer track the object stored in the
76
* handle and may deallocate it. The behavior of accessing a handle
77
* for which the handle scope has been deleted is undefined.
78
*/
79
class
V8_EXPORT
V8_NODISCARD
HandleScope
{
80
public
:
81
explicit
HandleScope
(
Isolate
* isolate);
82
83
~
HandleScope
();
84
85
/**
86
* Counts the number of allocated handles.
87
*/
88
static
int
NumberOfHandles
(
Isolate
* isolate);
89
90
V8_INLINE
Isolate
*
GetIsolate
()
const
{
91
return
reinterpret_cast
<
Isolate
*>(isolate_);
92
}
93
94
HandleScope
(
const
HandleScope
&) =
delete
;
95
void
operator
=(
const
HandleScope
&) =
delete
;
96
97
protected
:
98
V8_INLINE
HandleScope
() =
default
;
99
100
void
Initialize
(
Isolate
* isolate);
101
102
static
internal
::
Address
*
CreateHandle
(
internal
::Isolate* isolate,
103
internal
::
Address
value);
104
105
private
:
106
// Declaring operator new and delete as deleted is not spec compliant.
107
// Therefore declare them private instead to disable dynamic alloc
108
void
* operator
new
(size_t size);
109
void
* operator
new
[](size_t size);
110
void
operator
delete
(
void
*, size_t);
111
void
operator
delete
[](
void
*, size_t);
112
113
internal
::Isolate* isolate_;
114
internal
::
Address
* prev_next_;
115
internal
::
Address
* prev_limit_;
116
117
// Local::New uses CreateHandle with an Isolate* parameter.
118
template
<
class
F>
119
friend
class
Local
;
120
121
// Object::GetInternalField and Context::GetEmbedderData use CreateHandle with
122
// a HeapObject in their shortcuts.
123
friend
class
Object
;
124
friend
class
Context
;
125
};
126
127
/**
128
* An object reference managed by the v8 garbage collector.
129
*
130
* All objects returned from v8 have to be tracked by the garbage collector so
131
* that it knows that the objects are still alive. Also, because the garbage
132
* collector may move objects, it is unsafe to point directly to an object.
133
* Instead, all objects are stored in handles which are known by the garbage
134
* collector and updated whenever an object moves. Handles should always be
135
* passed by value (except in cases like out-parameters) and they should never
136
* be allocated on the heap.
137
*
138
* There are two types of handles: local and persistent handles.
139
*
140
* Local handles are light-weight and transient and typically used in local
141
* operations. They are managed by HandleScopes. That means that a HandleScope
142
* must exist on the stack when they are created and that they are only valid
143
* inside of the HandleScope active during their creation. For passing a local
144
* handle to an outer HandleScope, an EscapableHandleScope and its Escape()
145
* method must be used.
146
*
147
* Persistent handles can be used when storing objects across several
148
* independent operations and have to be explicitly deallocated when they're no
149
* longer used.
150
*
151
* It is safe to extract the object stored in the handle by dereferencing the
152
* handle (for instance, to extract the Object* from a Local<Object>); the value
153
* will still be governed by a handle behind the scenes and the same rules apply
154
* to these values as to their handles.
155
*/
156
template
<
class
T>
157
class
Local
{
158
public
:
159
V8_INLINE
Local
() : val_(
nullptr
) {}
160
template
<
class
S>
161
V8_INLINE
Local
(
Local
<S> that) : val_(
reinterpret_cast
<T*>(*that)) {
162
/**
163
* This check fails when trying to convert between incompatible
164
* handles. For example, converting from a Local<String> to a
165
* Local<Number>.
166
*/
167
static_assert
(std::is_base_of<T, S>::value,
"type check"
);
168
}
169
170
/**
171
* Returns true if the handle is empty.
172
*/
173
V8_INLINE
bool
IsEmpty
()
const
{
return
val_ ==
nullptr
; }
174
175
/**
176
* Sets the handle to be empty. IsEmpty() will then return true.
177
*/
178
V8_INLINE
void
Clear
() { val_ =
nullptr
; }
179
180
V8_INLINE
T*
operator
->()
const
{
return
val_; }
181
182
V8_INLINE
T*
operator
*()
const
{
return
val_; }
183
184
/**
185
* Checks whether two handles are the same.
186
* Returns true if both are empty, or if the objects to which they refer
187
* are identical.
188
*
189
* If both handles refer to JS objects, this is the same as strict equality.
190
* For primitives, such as numbers or strings, a `false` return value does not
191
* indicate that the values aren't equal in the JavaScript sense.
192
* Use `Value::StrictEquals()` to check primitives for equality.
193
*/
194
template
<
class
S>
195
V8_INLINE
bool
operator
==(
const
Local
<S>& that)
const
{
196
internal
::
Address
* a =
reinterpret_cast
<
internal
::
Address
*>(
this
->val_);
197
internal
::
Address
* b =
reinterpret_cast
<
internal
::
Address
*>(that.val_);
198
if
(a ==
nullptr
)
return
b ==
nullptr
;
199
if
(b ==
nullptr
)
return
false
;
200
return
*a == *b;
201
}
202
203
template
<
class
S>
204
V8_INLINE
bool
operator
==(
const
PersistentBase
<S>& that)
const
{
205
internal
::
Address
* a =
reinterpret_cast
<
internal
::
Address
*>(
this
->val_);
206
internal
::
Address
* b =
reinterpret_cast
<
internal
::
Address
*>(that.val_);
207
if
(a ==
nullptr
)
return
b ==
nullptr
;
208
if
(b ==
nullptr
)
return
false
;
209
return
*a == *b;
210
}
211
212
/**
213
* Checks whether two handles are different.
214
* Returns true if only one of the handles is empty, or if
215
* the objects to which they refer are different.
216
*
217
* If both handles refer to JS objects, this is the same as strict
218
* non-equality. For primitives, such as numbers or strings, a `true` return
219
* value does not indicate that the values aren't equal in the JavaScript
220
* sense. Use `Value::StrictEquals()` to check primitives for equality.
221
*/
222
template
<
class
S>
223
V8_INLINE
bool
operator
!=(
const
Local
<S>& that)
const
{
224
return
!operator==(that);
225
}
226
227
template
<
class
S>
228
V8_INLINE
bool
operator
!=(
const
Persistent
<S>& that)
const
{
229
return
!operator==(that);
230
}
231
232
/**
233
* Cast a handle to a subclass, e.g. Local<Value> to Local<Object>.
234
* This is only valid if the handle actually refers to a value of the
235
* target type.
236
*/
237
template
<
class
S>
238
V8_INLINE
static
Local
<T>
Cast
(
Local
<S> that) {
239
#
ifdef
V8_ENABLE_CHECKS
240
// If we're going to perform the type check then we have to check
241
// that the handle isn't empty before doing the checked cast.
242
if
(that.IsEmpty())
return
Local<T>();
243
#
endif
244
return
Local
<T>(T::Cast(*that));
245
}
246
247
/**
248
* Calling this is equivalent to Local<S>::Cast().
249
* In particular, this is only valid if the handle actually refers to a value
250
* of the target type.
251
*/
252
template
<
class
S>
253
V8_INLINE
Local
<S>
As
()
const
{
254
return
Local
<S>::Cast(*
this
);
255
}
256
257
/**
258
* Create a local handle for the content of another handle.
259
* The referee is kept alive by the local handle even when
260
* the original handle is destroyed/disposed.
261
*/
262
V8_INLINE
static
Local
<T>
New
(
Isolate
* isolate,
Local
<T> that) {
263
return
New(isolate, that.val_);
264
}
265
266
V8_INLINE
static
Local
<T>
New
(
Isolate
* isolate,
267
const
PersistentBase
<T>& that) {
268
return
New(isolate, that.val_);
269
}
270
271
V8_INLINE
static
Local
<T>
New
(
Isolate
* isolate,
272
const
BasicTracedReference
<T>& that) {
273
return
New(isolate, *that);
274
}
275
276
private
:
277
friend
class
TracedReferenceBase
;
278
friend
class
Utils;
279
template
<
class
F>
280
friend
class
Eternal
;
281
template
<
class
F>
282
friend
class
PersistentBase
;
283
template
<
class
F,
class
M>
284
friend
class
Persistent
;
285
template
<
class
F>
286
friend
class
Local
;
287
template
<
class
F>
288
friend
class
MaybeLocal
;
289
template
<
class
F>
290
friend
class
FunctionCallbackInfo
;
291
template
<
class
F>
292
friend
class
PropertyCallbackInfo
;
293
friend
class
String
;
294
friend
class
Object
;
295
friend
class
Context
;
296
friend
class
Isolate
;
297
friend
class
Private
;
298
template
<
class
F>
299
friend
class
internal
::
CustomArguments
;
300
friend
Local
<
Primitive
>
Undefined
(
Isolate
* isolate);
301
friend
Local
<
Primitive
>
Null
(
Isolate
* isolate);
302
friend
Local
<
Boolean
>
True
(
Isolate
* isolate);
303
friend
Local
<
Boolean
>
False
(
Isolate
* isolate);
304
friend
class
HandleScope
;
305
friend
class
EscapableHandleScope
;
306
template
<
class
F1,
class
F2,
class
F3>
307
friend
class
PersistentValueMapBase
;
308
template
<
class
F1,
class
F2>
309
friend
class
PersistentValueVector
;
310
template
<
class
F>
311
friend
class
ReturnValue
;
312
template
<
class
F>
313
friend
class
Traced
;
314
template
<
class
F>
315
friend
class
TracedGlobal
;
316
template
<
class
F>
317
friend
class
BasicTracedReference
;
318
template
<
class
F>
319
friend
class
TracedReference
;
320
321
explicit
V8_INLINE
Local(T* that) : val_(that) {}
322
V8_INLINE
static
Local
<T> New(
Isolate
* isolate, T* that) {
323
if
(that ==
nullptr
)
return
Local
<T>();
324
T* that_ptr = that;
325
internal
::
Address
* p =
reinterpret_cast
<
internal
::
Address
*>(that_ptr);
326
return
Local
<T>(
reinterpret_cast
<T*>(
HandleScope
::
CreateHandle
(
327
reinterpret_cast
<
internal
::Isolate*>(isolate)
,
*p
)
));
328
}
329
T* val_;
330
};
331
332
#
if
!
defined
(
V8_IMMINENT_DEPRECATION_WARNINGS
)
333
// Handle is an alias for Local for historical reasons.
334
template
<
class
T>
335
using
Handle =
Local
<T>;
336
#
endif
337
338
/**
339
* A MaybeLocal<> is a wrapper around Local<> that enforces a check whether
340
* the Local<> is empty before it can be used.
341
*
342
* If an API method returns a MaybeLocal<>, the API method can potentially fail
343
* either because an exception is thrown, or because an exception is pending,
344
* e.g. because a previous API call threw an exception that hasn't been caught
345
* yet, or because a TerminateExecution exception was thrown. In that case, an
346
* empty MaybeLocal is returned.
347
*/
348
template
<
class
T>
349
class
MaybeLocal
{
350
public
:
351
V8_INLINE
MaybeLocal
() : val_(
nullptr
) {}
352
template
<
class
S>
353
V8_INLINE
MaybeLocal
(
Local
<S> that) : val_(
reinterpret_cast
<T*>(*that)) {
354
static_assert
(std::is_base_of<T, S>::value,
"type check"
);
355
}
356
357
V8_INLINE
bool
IsEmpty
()
const
{
return
val_ ==
nullptr
; }
358
359
/**
360
* Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty,
361
* |false| is returned and |out| is left untouched.
362
*/
363
template
<
class
S>
364
V8_WARN_UNUSED_RESULT
V8_INLINE
bool
ToLocal
(
Local
<S>* out)
const
{
365
out->val_ =
IsEmpty
(
)
?
nullptr
:
this
->val_;
366
return
!
IsEmpty
(
)
;
367
}
368
369
/**
370
* Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty,
371
* V8 will crash the process.
372
*/
373
V8_INLINE
Local
<T>
ToLocalChecked
() {
374
if
(
V8_UNLIKELY
(val_ ==
nullptr
))
api_internal
::
ToLocalEmpty
(
)
;
375
return
Local
<T>(val_);
376
}
377
378
/**
379
* Converts this MaybeLocal<> to a Local<>, using a default value if this
380
* MaybeLocal<> is empty.
381
*/
382
template
<
class
S>
383
V8_INLINE
Local
<S>
FromMaybe
(
Local
<S> default_value)
const
{
384
return
IsEmpty
(
)
? default_value :
Local
<S>(val_);
385
}
386
387
private
:
388
T* val_;
389
};
390
391
/**
392
* A HandleScope which first allocates a handle in the current scope
393
* which will be later filled with the escape value.
394
*/
395
class
V8_EXPORT
V8_NODISCARD
EscapableHandleScope
:
public
HandleScope
{
396
public
:
397
explicit
EscapableHandleScope
(
Isolate
* isolate);
398
V8_INLINE
~
EscapableHandleScope
() =
default
;
399
400
/**
401
* Pushes the value into the previous scope and returns a handle to it.
402
* Cannot be called twice.
403
*/
404
template
<
class
T>
405
V8_INLINE
Local
<T>
Escape
(
Local
<T> value) {
406
internal
::
Address
* slot =
407
Escape(
reinterpret_cast
<
internal
::
Address
*>(*value));
408
return
Local
<T>(
reinterpret_cast
<T*>(slot));
409
}
410
411
template
<
class
T>
412
V8_INLINE
MaybeLocal
<T>
EscapeMaybe
(
MaybeLocal
<T> value) {
413
return
Escape(value.FromMaybe(
Local
<T>()));
414
}
415
416
EscapableHandleScope
(
const
EscapableHandleScope
&) =
delete
;
417
void
operator
=(
const
EscapableHandleScope
&) =
delete
;
418
419
private
:
420
// Declaring operator new and delete as deleted is not spec compliant.
421
// Therefore declare them private instead to disable dynamic alloc
422
void
* operator
new
(size_t size);
423
void
* operator
new
[](size_t size);
424
void
operator
delete
(
void
*, size_t);
425
void
operator
delete
[](
void
*, size_t);
426
427
internal
::
Address
* Escape(
internal
::
Address
* escape_value);
428
internal
::
Address
* escape_slot_;
429
};
430
431
/**
432
* A SealHandleScope acts like a handle scope in which no handle allocations
433
* are allowed. It can be useful for debugging handle leaks.
434
* Handles can be allocated within inner normal HandleScopes.
435
*/
436
class
V8_EXPORT
V8_NODISCARD
SealHandleScope
{
437
public
:
438
explicit
SealHandleScope
(
Isolate
* isolate);
439
~
SealHandleScope
();
440
441
SealHandleScope
(
const
SealHandleScope
&) =
delete
;
442
void
operator
=(
const
SealHandleScope
&) =
delete
;
443
444
private
:
445
// Declaring operator new and delete as deleted is not spec compliant.
446
// Therefore declare them private instead to disable dynamic alloc
447
void
* operator
new
(size_t size);
448
void
* operator
new
[](size_t size);
449
void
operator
delete
(
void
*, size_t);
450
void
operator
delete
[](
void
*, size_t);
451
452
internal
::Isolate*
const
isolate_;
453
internal
::
Address
* prev_limit_;
454
int
prev_sealed_level_;
455
};
456
457
}
// namespace v8
458
459
#
endif
// INCLUDE_V8_LOCAL_HANDLE_H_
include
v8-local-handle.h
Generated on Tue May 24 2022 19:29:00 for v8 by
1.9.1