v8 14.1.146 (node 25.0.0)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
v8-context.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_CONTEXT_H_
6#define INCLUDE_V8_CONTEXT_H_
7
8#include <stdint.h>
9
10#include <vector>
11
12#include "v8-data.h" // NOLINT(build/include_directory)
13#include "v8-local-handle.h" // NOLINT(build/include_directory)
14#include "v8-maybe.h" // NOLINT(build/include_directory)
15#include "v8-snapshot.h" // NOLINT(build/include_directory)
16#include "v8config.h" // NOLINT(build/include_directory)
17
18namespace v8 {
19
20class Function;
21class MicrotaskQueue;
22class Object;
23class ObjectTemplate;
24class Value;
25class String;
26
27/**
28 * A container for extension names.
29 */
31 public:
32 ExtensionConfiguration() : name_count_(0), names_(nullptr) {}
33 ExtensionConfiguration(int name_count, const char* names[])
34 : name_count_(name_count), names_(names) {}
35
36 const char** begin() const { return &names_[0]; }
37 const char** end() const { return &names_[name_count_]; }
38
39 private:
40 const int name_count_;
41 const char** names_;
42};
43
44/**
45 * A sandboxed execution context with its own set of built-in objects
46 * and functions.
47 */
48class V8_EXPORT Context : public Data {
49 public:
50 /**
51 * Returns the global proxy object.
52 *
53 * Global proxy object is a thin wrapper whose prototype points to actual
54 * context's global object with the properties like Object, etc. This is done
55 * that way for security reasons (for more details see
56 * https://wiki.mozilla.org/Gecko:SplitWindow).
57 *
58 * Please note that changes to global proxy object prototype most probably
59 * would break VM---v8 expects only global object as a prototype of global
60 * proxy object.
61 */
63
64 /**
65 * Detaches the global object from its context before
66 * the global object can be reused to create a new context.
67 */
69
70 /**
71 * Creates a new context and returns a handle to the newly allocated
72 * context.
73 *
74 * \param isolate The isolate in which to create the context.
75 *
76 * \param extensions An optional extension configuration containing
77 * the extensions to be installed in the newly created context.
78 *
79 * \param global_template An optional object template from which the
80 * global object for the newly created context will be created.
81 *
82 * \param global_object An optional global object to be reused for
83 * the newly created context. This global object must have been
84 * created by a previous call to Context::New with the same global
85 * template. The state of the global object will be completely reset
86 * and only object identify will remain.
87 *
88 * \param internal_fields_deserializer An optional callback used
89 * to deserialize fields set by
90 * v8::Object::SetAlignedPointerInInternalField() in wrapper objects
91 * from the default context snapshot. It should match the
92 * SerializeInternalFieldsCallback() used by
93 * v8::SnapshotCreator::SetDefaultContext() when the default context
94 * snapshot is created. It does not need to be configured if the default
95 * context snapshot contains no wrapper objects with pointer internal
96 * fields, or if no custom startup snapshot is configured
97 * in the v8::CreateParams used to create the isolate.
98 *
99 * \param microtask_queue An optional microtask queue used to manage
100 * the microtasks created in this context. If not set the per-isolate
101 * default microtask queue would be used.
102 *
103 * \param context_data_deserializer An optional callback used
104 * to deserialize embedder data set by
105 * v8::Context::SetAlignedPointerInEmbedderData() in the default
106 * context from the default context snapshot. It does not need to be
107 * configured if the default context snapshot contains no pointer embedder
108 * data, or if no custom startup snapshot is configured in the
109 * v8::CreateParams used to create the isolate.
110 *
111 * \param api_wrapper_deserializer An optional callback used to deserialize
112 * API wrapper objects that was initially set with v8::Object::Wrap() and then
113 * serialized using SerializeAPIWrapperCallback.
114 */
116 Isolate* isolate, ExtensionConfiguration* extensions = nullptr,
117 MaybeLocal<ObjectTemplate> global_template = MaybeLocal<ObjectTemplate>(),
118 MaybeLocal<Value> global_object = MaybeLocal<Value>(),
119 DeserializeInternalFieldsCallback internal_fields_deserializer =
121 MicrotaskQueue* microtask_queue = nullptr,
122 DeserializeContextDataCallback context_data_deserializer =
124 DeserializeAPIWrapperCallback api_wrapper_deserializer =
126
127 /**
128 * Create a new context from a (non-default) context snapshot. There
129 * is no way to provide a global object template since we do not create
130 * a new global object from template, but we can reuse a global object.
131 *
132 * \param isolate See v8::Context::New().
133 *
134 * \param context_snapshot_index The index of the context snapshot to
135 * deserialize from. Use v8::Context::New() for the default snapshot.
136 *
137 * \param internal_fields_deserializer An optional callback used
138 * to deserialize fields set by
139 * v8::Object::SetAlignedPointerInInternalField() in wrapper objects
140 * from the default context snapshot. It does not need to be
141 * configured if there are no wrapper objects with no internal
142 * pointer fields in the default context snapshot or if no startup
143 * snapshot is configured when the isolate is created.
144 *
145 * \param extensions See v8::Context::New().
146 *
147 * \param global_object See v8::Context::New().
148 *
149 * \param internal_fields_deserializer Similar to
150 * internal_fields_deserializer in v8::Context::New() but applies to
151 * the context specified by the context_snapshot_index.
152 *
153 * \param microtask_queue See v8::Context::New().
154 *
155 * \param context_data_deserializer Similar to
156 * context_data_deserializer in v8::Context::New() but applies to
157 * the context specified by the context_snapshot_index.
158 *
159 *\param api_wrapper_deserializer Similar to api_wrapper_deserializer in
160 * v8::Context::New() but applies to the context specified by the
161 * context_snapshot_index.
162 */
164 Isolate* isolate, size_t context_snapshot_index,
165 DeserializeInternalFieldsCallback internal_fields_deserializer =
167 ExtensionConfiguration* extensions = nullptr,
168 MaybeLocal<Value> global_object = MaybeLocal<Value>(),
169 MicrotaskQueue* microtask_queue = nullptr,
170 DeserializeContextDataCallback context_data_deserializer =
172 DeserializeAPIWrapperCallback api_wrapper_deserializer =
174
175 /**
176 * Returns an global object that isn't backed by an actual context.
177 *
178 * The global template needs to have access checks with handlers installed.
179 * If an existing global object is passed in, the global object is detached
180 * from its context.
181 *
182 * Note that this is different from a detached context where all accesses to
183 * the global proxy will fail. Instead, the access check handlers are invoked.
184 *
185 * It is also not possible to detach an object returned by this method.
186 * Instead, the access check handlers need to return nothing to achieve the
187 * same effect.
188 *
189 * It is possible, however, to create a new context from the global object
190 * returned by this method.
191 */
193 Isolate* isolate, Local<ObjectTemplate> global_template,
194 MaybeLocal<Value> global_object = MaybeLocal<Value>());
195
196 /**
197 * Sets the security token for the context. To access an object in
198 * another context, the security tokens must match.
199 */
201
202 /** Restores the security token to the default value. */
204
205 /** Returns the security token of this context.*/
207
208 /**
209 * Enter this context. After entering a context, all code compiled
210 * and run is compiled and run in this context. If another context
211 * is already entered, this old context is saved so it can be
212 * restored when the new context is exited.
213 */
214 void Enter();
215
216 /**
217 * Exit this context. Exiting the current context restores the
218 * context that was in place when entering the current context.
219 */
220 void Exit();
221
222 /**
223 * Delegate to help with Deep freezing embedder-specific objects (such as
224 * JSApiObjects) that can not be frozen natively.
225 */
227 public:
228 /**
229 * Performs embedder-specific operations to freeze the provided embedder
230 * object. The provided object *will* be frozen by DeepFreeze after this
231 * function returns, so only embedder-specific objects need to be frozen.
232 * This function *may not* create new JS objects or perform JS allocations.
233 * Any v8 objects reachable from the provided embedder object that should
234 * also be considered for freezing should be added to the children_out
235 * parameter. Returns true if the operation completed successfully.
236 */
238 Local<Object> obj, LocalVector<Object>& children_out) = 0;
239 };
240
241 /**
242 * Attempts to recursively freeze all objects reachable from this context.
243 * Some objects (generators, iterators, non-const closures) can not be frozen
244 * and will cause this method to throw an error. An optional delegate can be
245 * provided to help freeze embedder-specific objects.
246 *
247 * Freezing occurs in two steps:
248 * 1. "Marking" where we iterate through all objects reachable by this
249 * context, accumulating a list of objects that need to be frozen and
250 * looking for objects that can't be frozen. This step is separated because
251 * it is more efficient when we can assume there is no garbage collection.
252 * 2. "Freezing" where we go through the list of objects and freezing them.
253 * This effectively requires copying them so it may trigger garbage
254 * collection.
255 */
256 Maybe<void> DeepFreeze(DeepFreezeDelegate* delegate = nullptr);
257
258 /** Returns the isolate associated with a current context. */
260 "Use Isolate::GetCurrent() instead, which is guaranteed to return the "
261 "same isolate since https://crrev.com/c/6458560.")
262 Isolate* GetIsolate();
263
264 /** Returns the microtask queue associated with a current context. */
266
267 /** Sets the microtask queue associated with the current context. */
269
270 /**
271 * The field at kDebugIdIndex used to be reserved for the inspector.
272 * It now serves no purpose.
273 */
275
276 /**
277 * Return the number of fields allocated for embedder data.
278 */
280
281 /**
282 * Gets the embedder data with the given index, which must have been set by a
283 * previous call to SetEmbedderData with the same index.
284 */
286
287 /**
288 * Gets the binding object used by V8 extras. Extra natives get a reference
289 * to this object and can use it to "export" functionality by adding
290 * properties. Extra natives can also "import" functionality by accessing
291 * properties added by the embedder using the V8 API.
292 */
294
295 /**
296 * Sets the embedder data with the given index, growing the data as
297 * needed. Note that index 0 currently has a special meaning for Chrome's
298 * debugger.
299 */
300 void SetEmbedderData(int index, Local<Value> value);
301
302 /**
303 * Gets a 2-byte-aligned native pointer from the embedder data with the given
304 * index, which must have been set by a previous call to
305 * SetAlignedPointerInEmbedderData with the same index. Note that index 0
306 * currently has a special meaning for Chrome's debugger.
307 */
309 int index);
311
312 /**
313 * Sets a 2-byte-aligned native pointer in the embedder data with the given
314 * index, growing the data as needed. Note that index 0 currently has a
315 * special meaning for Chrome's debugger.
316 */
318 "Use SetAlignedPointerInEmbedderData with EmbedderDataTypeTag parameter "
319 "instead.")
320 void SetAlignedPointerInEmbedderData(int index, void* value);
321
322 void SetAlignedPointerInEmbedderData(int index, void* value,
323 EmbedderDataTypeTag slot);
324
325 /**
326 * Control whether code generation from strings is allowed. Calling
327 * this method with false will disable 'eval' and the 'Function'
328 * constructor for code running in this context. If 'eval' or the
329 * 'Function' constructor are used an exception will be thrown.
330 *
331 * If code generation from strings is not allowed the
332 * V8::ModifyCodeGenerationFromStringsCallback callback will be invoked if
333 * set before blocking the call to 'eval' or the 'Function'
334 * constructor. If that callback returns true, the call will be
335 * allowed, otherwise an exception will be thrown. If no callback is
336 * set an exception will be thrown.
337 */
339
340 /**
341 * Returns true if code generation from strings is allowed for the context.
342 * For more details see AllowCodeGenerationFromStrings(bool) documentation.
343 */
345
346 /**
347 * Sets the error description for the exception that is thrown when
348 * code generation from strings is not allowed and 'eval' or the 'Function'
349 * constructor are called.
350 */
352
353 /**
354 * Sets the error description for the exception that is thrown when
355 * wasm code generation is not allowed.
356 */
358
359 /**
360 * Return data that was previously attached to the context snapshot via
361 * SnapshotCreator, and removes the reference to it.
362 * Repeated call with the same index returns an empty MaybeLocal.
363 */
364 template <class T>
366
367 /**
368 * If callback is set, abort any attempt to execute JavaScript in this
369 * context, call the specified callback, and throw an exception.
370 * To unset abort, pass nullptr as callback.
371 */
372 using AbortScriptExecutionCallback = void (*)(Isolate* isolate,
373 Local<Context> context);
374 void SetAbortScriptExecution(AbortScriptExecutionCallback callback);
375
376 /**
377 * Set or clear hooks to be invoked for promise lifecycle operations.
378 * To clear a hook, set it to an empty v8::Function. Each function will
379 * receive the observed promise as the first argument. If a chaining
380 * operation is used on a promise, the init will additionally receive
381 * the parent promise as the second argument.
382 */
383 void SetPromiseHooks(Local<Function> init_hook, Local<Function> before_hook,
384 Local<Function> after_hook,
385 Local<Function> resolve_hook);
386
388 /**
389 * Stack-allocated class which sets the execution context for all
390 * operations executed within a local scope.
391 */
393 public:
394 explicit V8_INLINE Scope(Local<Context> context) : context_(context) {
395 context_->Enter();
396 }
397 V8_INLINE ~Scope() { context_->Exit(); }
398
399 private:
400 Local<Context> context_;
401 };
402
403 /**
404 * Stack-allocated class to support the backup incumbent settings object
405 * stack.
406 * https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
407 */
408 class V8_EXPORT V8_NODISCARD BackupIncumbentScope final {
409 public:
410 /**
411 * |backup_incumbent_context| is pushed onto the backup incumbent settings
412 * object stack.
413 */
414 explicit BackupIncumbentScope(Local<Context> backup_incumbent_context);
416
417 private:
418 friend class internal::Isolate;
419
420 uintptr_t JSStackComparableAddressPrivate() const {
421 return js_stack_comparable_address_;
422 }
423
424 Local<Context> backup_incumbent_context_;
425 uintptr_t js_stack_comparable_address_ = 0;
426 const BackupIncumbentScope* prev_ = nullptr;
427 };
428
429 V8_INLINE static Context* Cast(Data* data);
430
431 private:
432 friend class Value;
433 friend class Script;
434 friend class Object;
435 friend class Function;
436
437 static void CheckCast(Data* obj);
438
439 internal::ValueHelper::InternalRepresentationType GetDataFromSnapshotOnce(
440 size_t index);
441 Local<Value> SlowGetEmbedderData(int index);
442 void* SlowGetAlignedPointerFromEmbedderData(int index);
443};
444
445// --- Implementation ---
446
448#ifndef V8_ENABLE_CHECKS
449 using A = internal::Address;
450 using I = internal::Internals;
451 A ctx = internal::ValueHelper::ValueAsAddress(this);
452 A embedder_data =
454 int value_offset =
456 A value = I::ReadRawField<A>(embedder_data, value_offset);
457#ifdef V8_COMPRESS_POINTERS
458 // We read the full pointer value and then decompress it in order to avoid
459 // dealing with potential endiannes issues.
460 value = I::DecompressTaggedField(embedder_data, static_cast<uint32_t>(value));
461#endif
462
463 auto* isolate = I::GetCurrentIsolate();
464 return Local<Value>::New(isolate, value);
465#else
466 return SlowGetEmbedderData(index);
467#endif
468}
469
471#if !defined(V8_ENABLE_CHECKS)
472 using A = internal::Address;
473 using I = internal::Internals;
474 A ctx = internal::ValueHelper::ValueAsAddress(this);
475 A embedder_data =
477 int value_offset = I::kEmbedderDataArrayHeaderSize +
478 (I::kEmbedderDataSlotSize * index) +
480 return reinterpret_cast<void*>(
481 I::ReadExternalPointerField<{internal::kFirstEmbedderDataTag,
483 isolate, embedder_data, value_offset));
484#else
485 return SlowGetAlignedPointerFromEmbedderData(index);
486#endif
487}
488
490#if !defined(V8_ENABLE_CHECKS)
491 using A = internal::Address;
492 using I = internal::Internals;
493 A ctx = internal::ValueHelper::ValueAsAddress(this);
494 A embedder_data =
496 int value_offset = I::kEmbedderDataArrayHeaderSize +
497 (I::kEmbedderDataSlotSize * index) +
500 return reinterpret_cast<void*>(
501 I::ReadExternalPointerField<{internal::kFirstEmbedderDataTag,
503 isolate, embedder_data, value_offset));
504#else
505 return SlowGetAlignedPointerFromEmbedderData(index);
506#endif
507}
508
509template <class T>
511 if (auto repr = GetDataFromSnapshotOnce(index);
512 repr != internal::ValueHelper::kEmpty) {
513 internal::PerformCastCheck(internal::ValueHelper::ReprAsValue<T>(repr));
514 return Local<T>::FromRepr(repr);
515 }
516 return {};
517}
518
520#ifdef V8_ENABLE_CHECKS
521 CheckCast(data);
522#endif
523 return static_cast<Context*>(data);
524}
525
526} // namespace v8
527
528#endif // INCLUDE_V8_CONTEXT_H_
BackupIncumbentScope(Local< Context > backup_incumbent_context)
virtual bool FreezeEmbedderObjectAndGetChildren(Local< Object > obj, LocalVector< Object > &children_out)=0
V8_INLINE ~Scope()
Definition v8-context.h:397
V8_INLINE Scope(Local< Context > context)
Definition v8-context.h:394
void SetEmbedderData(int index, Local< Value > value)
void * value
Definition v8-context.h:320
V8_INLINE Local< Value > GetEmbedderData(int index)
Definition v8-context.h:447
static MaybeLocal< Object > NewRemoteContext(Isolate *isolate, Local< ObjectTemplate > global_template, MaybeLocal< Value > global_object=MaybeLocal< Value >())
Local< Object > GetExtrasBindingObject()
Local< Object > Global()
bool IsCodeGenerationFromStringsAllowed() const
V8_INLINE void * GetAlignedPointerFromEmbedderData(int index)
Definition v8-context.h:489
void SetAlignedPointerInEmbedderData(int index, void *value, EmbedderDataTypeTag slot)
Local< Value > GetSecurityToken()
static MaybeLocal< Context > FromSnapshot(Isolate *isolate, size_t context_snapshot_index, DeserializeInternalFieldsCallback internal_fields_deserializer=DeserializeInternalFieldsCallback(), ExtensionConfiguration *extensions=nullptr, MaybeLocal< Value > global_object=MaybeLocal< Value >(), MicrotaskQueue *microtask_queue=nullptr, DeserializeContextDataCallback context_data_deserializer=DeserializeContextDataCallback(), DeserializeAPIWrapperCallback api_wrapper_deserializer=DeserializeAPIWrapperCallback())
void DetachGlobal()
void Enter()
void SetAbortScriptExecution(AbortScriptExecutionCallback callback)
V8_INLINE MaybeLocal< T > GetDataFromSnapshotOnce(size_t index)
void AllowCodeGenerationFromStrings(bool allow)
void SetErrorMessageForCodeGenerationFromStrings(Local< String > message)
void UseDefaultSecurityToken()
void SetMicrotaskQueue(MicrotaskQueue *queue)
MicrotaskQueue * GetMicrotaskQueue()
Maybe< void > DeepFreeze(DeepFreezeDelegate *delegate=nullptr)
V8_INLINE void * GetAlignedPointerFromEmbedderData(Isolate *isolate, int index)
Definition v8-context.h:470
void SetErrorMessageForWasmCodeGeneration(Local< String > message)
static V8_INLINE Context * Cast(Data *data)
Definition v8-context.h:519
void SetSecurityToken(Local< Value > token)
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=nullptr, MaybeLocal< ObjectTemplate > global_template=MaybeLocal< ObjectTemplate >(), MaybeLocal< Value > global_object=MaybeLocal< Value >(), DeserializeInternalFieldsCallback internal_fields_deserializer=DeserializeInternalFieldsCallback(), MicrotaskQueue *microtask_queue=nullptr, DeserializeContextDataCallback context_data_deserializer=DeserializeContextDataCallback(), DeserializeAPIWrapperCallback api_wrapper_deserializer=DeserializeAPIWrapperCallback())
bool HasTemplateLiteralObject(Local< Value > object)
void SetPromiseHooks(Local< Function > init_hook, Local< Function > before_hook, Local< Function > after_hook, Local< Function > resolve_hook)
uint32_t GetNumberOfEmbedderDataFields()
const char ** begin() const
Definition v8-context.h:36
ExtensionConfiguration(int name_count, const char *names[])
Definition v8-context.h:33
const char ** end() const
Definition v8-context.h:37
friend class Local
friend class MaybeLocal
static const int kNativeContextEmbedderDataOffset
static const int kEmbedderDataArrayHeaderSize
static const int kEmbedderDataSlotExternalPointerOffset
static V8_INLINE v8::Isolate * GetCurrentIsolateForSandbox()
static const int kEmbedderDataSlotSize
static V8_INLINE Address ReadTaggedPointerField(Address heap_object_ptr, int offset)
static V8_EXPORT v8::Isolate * GetCurrentIsolate()
static constexpr InternalRepresentationType kEmpty
uintptr_t Address
Definition v8-internal.h:52
DeserializeAPIWrapperCallback(CallbackFunction function=nullptr, void *data=nullptr)
DeserializeContextDataCallback(CallbackFunction function=nullptr, void *data_arg=nullptr)
DeserializeInternalFieldsCallback(CallbackFunction function=nullptr, void *data_arg=nullptr)
Definition v8-snapshot.h:94
#define V8_EXPORT
Definition v8config.h:860
#define V8_INLINE
Definition v8config.h:513
#define V8_DEPRECATE_SOON(message)
Definition v8config.h:627
#define V8_DEPRECATED(message)
Definition v8config.h:619
#define V8_NODISCARD
Definition v8config.h:706