v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
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 "v8-data.h" // NOLINT(build/include_directory)
11 #include "v8-local-handle.h" // NOLINT(build/include_directory)
12 #include "v8-snapshot.h" // NOLINT(build/include_directory)
13 #include "v8config.h" // NOLINT(build/include_directory)
14 
15 namespace v8 {
16 
17 class Function;
18 class MicrotaskQueue;
19 class Object;
20 class ObjectTemplate;
21 class Value;
22 class String;
23 
24 /**
25  * A container for extension names.
26  */
28  public:
29  ExtensionConfiguration() : name_count_(0), names_(nullptr) {}
30  ExtensionConfiguration(int name_count, const char* names[])
31  : name_count_(name_count), names_(names) {}
32 
33  const char** begin() const { return &names_[0]; }
34  const char** end() const { return &names_[name_count_]; }
35 
36  private:
37  const int name_count_;
38  const char** names_;
39 };
40 
41 /**
42  * A sandboxed execution context with its own set of built-in objects
43  * and functions.
44  */
45 class V8_EXPORT Context : public Data {
46  public:
47  /**
48  * Returns the global proxy object.
49  *
50  * Global proxy object is a thin wrapper whose prototype points to actual
51  * context's global object with the properties like Object, etc. This is done
52  * that way for security reasons (for more details see
53  * https://wiki.mozilla.org/Gecko:SplitWindow).
54  *
55  * Please note that changes to global proxy object prototype most probably
56  * would break VM---v8 expects only global object as a prototype of global
57  * proxy object.
58  */
60 
61  /**
62  * Detaches the global object from its context before
63  * the global object can be reused to create a new context.
64  */
65  void DetachGlobal();
66 
67  /**
68  * Creates a new context and returns a handle to the newly allocated
69  * context.
70  *
71  * \param isolate The isolate in which to create the context.
72  *
73  * \param extensions An optional extension configuration containing
74  * the extensions to be installed in the newly created context.
75  *
76  * \param global_template An optional object template from which the
77  * global object for the newly created context will be created.
78  *
79  * \param global_object An optional global object to be reused for
80  * the newly created context. This global object must have been
81  * created by a previous call to Context::New with the same global
82  * template. The state of the global object will be completely reset
83  * and only object identify will remain.
84  */
85  static Local<Context> New(
86  Isolate* isolate, ExtensionConfiguration* extensions = nullptr,
88  MaybeLocal<Value> global_object = MaybeLocal<Value>(),
89  DeserializeInternalFieldsCallback internal_fields_deserializer =
91  MicrotaskQueue* microtask_queue = nullptr);
92 
93  /**
94  * Create a new context from a (non-default) context snapshot. There
95  * is no way to provide a global object template since we do not create
96  * a new global object from template, but we can reuse a global object.
97  *
98  * \param isolate See v8::Context::New.
99  *
100  * \param context_snapshot_index The index of the context snapshot to
101  * deserialize from. Use v8::Context::New for the default snapshot.
102  *
103  * \param embedder_fields_deserializer Optional callback to deserialize
104  * internal fields. It should match the SerializeInternalFieldCallback used
105  * to serialize.
106  *
107  * \param extensions See v8::Context::New.
108  *
109  * \param global_object See v8::Context::New.
110  */
112  Isolate* isolate, size_t context_snapshot_index,
113  DeserializeInternalFieldsCallback embedder_fields_deserializer =
115  ExtensionConfiguration* extensions = nullptr,
116  MaybeLocal<Value> global_object = MaybeLocal<Value>(),
117  MicrotaskQueue* microtask_queue = nullptr);
118 
119  /**
120  * Returns an global object that isn't backed by an actual context.
121  *
122  * The global template needs to have access checks with handlers installed.
123  * If an existing global object is passed in, the global object is detached
124  * from its context.
125  *
126  * Note that this is different from a detached context where all accesses to
127  * the global proxy will fail. Instead, the access check handlers are invoked.
128  *
129  * It is also not possible to detach an object returned by this method.
130  * Instead, the access check handlers need to return nothing to achieve the
131  * same effect.
132  *
133  * It is possible, however, to create a new context from the global object
134  * returned by this method.
135  */
137  Isolate* isolate, Local<ObjectTemplate> global_template,
138  MaybeLocal<Value> global_object = MaybeLocal<Value>());
139 
140  /**
141  * Sets the security token for the context. To access an object in
142  * another context, the security tokens must match.
143  */
145 
146  /** Restores the security token to the default value. */
148 
149  /** Returns the security token of this context.*/
151 
152  /**
153  * Enter this context. After entering a context, all code compiled
154  * and run is compiled and run in this context. If another context
155  * is already entered, this old context is saved so it can be
156  * restored when the new context is exited.
157  */
158  void Enter();
159 
160  /**
161  * Exit this context. Exiting the current context restores the
162  * context that was in place when entering the current context.
163  */
164  void Exit();
165 
166  /** Returns the isolate associated with a current context. */
168 
169  /** Returns the microtask queue associated with a current context. */
171 
172  /**
173  * The field at kDebugIdIndex used to be reserved for the inspector.
174  * It now serves no purpose.
175  */
177 
178  /**
179  * Return the number of fields allocated for embedder data.
180  */
182 
183  /**
184  * Gets the embedder data with the given index, which must have been set by a
185  * previous call to SetEmbedderData with the same index.
186  */
187  V8_INLINE Local<Value> GetEmbedderData(int index);
188 
189  /**
190  * Gets the binding object used by V8 extras. Extra natives get a reference
191  * to this object and can use it to "export" functionality by adding
192  * properties. Extra natives can also "import" functionality by accessing
193  * properties added by the embedder using the V8 API.
194  */
196 
197  /**
198  * Sets the embedder data with the given index, growing the data as
199  * needed. Note that index 0 currently has a special meaning for Chrome's
200  * debugger.
201  */
202  void SetEmbedderData(int index, Local<Value> value);
203 
204  /**
205  * Gets a 2-byte-aligned native pointer from the embedder data with the given
206  * index, which must have been set by a previous call to
207  * SetAlignedPointerInEmbedderData with the same index. Note that index 0
208  * currently has a special meaning for Chrome's debugger.
209  */
211 
212  /**
213  * Sets a 2-byte-aligned native pointer in the embedder data with the given
214  * index, growing the data as needed. Note that index 0 currently has a
215  * special meaning for Chrome's debugger.
216  */
217  void SetAlignedPointerInEmbedderData(int index, void* value);
218 
219  /**
220  * Control whether code generation from strings is allowed. Calling
221  * this method with false will disable 'eval' and the 'Function'
222  * constructor for code running in this context. If 'eval' or the
223  * 'Function' constructor are used an exception will be thrown.
224  *
225  * If code generation from strings is not allowed the
226  * V8::AllowCodeGenerationFromStrings callback will be invoked if
227  * set before blocking the call to 'eval' or the 'Function'
228  * constructor. If that callback returns true, the call will be
229  * allowed, otherwise an exception will be thrown. If no callback is
230  * set an exception will be thrown.
231  */
233 
234  /**
235  * Returns true if code generation from strings is allowed for the context.
236  * For more details see AllowCodeGenerationFromStrings(bool) documentation.
237  */
239 
240  /**
241  * Sets the error description for the exception that is thrown when
242  * code generation from strings is not allowed and 'eval' or the 'Function'
243  * constructor are called.
244  */
246 
247  /**
248  * Return data that was previously attached to the context snapshot via
249  * SnapshotCreator, and removes the reference to it.
250  * Repeated call with the same index returns an empty MaybeLocal.
251  */
252  template <class T>
254 
255  /**
256  * If callback is set, abort any attempt to execute JavaScript in this
257  * context, call the specified callback, and throw an exception.
258  * To unset abort, pass nullptr as callback.
259  */
260  using AbortScriptExecutionCallback = void (*)(Isolate* isolate,
261  Local<Context> context);
262  void SetAbortScriptExecution(AbortScriptExecutionCallback callback);
263 
264  /**
265  * Returns the value that was set or restored by
266  * SetContinuationPreservedEmbedderData(), if any.
267  */
269 
270  /**
271  * Sets a value that will be stored on continuations and reset while the
272  * continuation runs.
273  */
275 
276  /**
277  * Set or clear hooks to be invoked for promise lifecycle operations.
278  * To clear a hook, set it to an empty v8::Function. Each function will
279  * receive the observed promise as the first argument. If a chaining
280  * operation is used on a promise, the init will additionally receive
281  * the parent promise as the second argument.
282  */
283  void SetPromiseHooks(Local<Function> init_hook, Local<Function> before_hook,
284  Local<Function> after_hook,
285  Local<Function> resolve_hook);
286 
287  /**
288  * Stack-allocated class which sets the execution context for all
289  * operations executed within a local scope.
290  */
292  public:
293  explicit V8_INLINE Scope(Local<Context> context) : context_(context) {
294  context_->Enter();
295  }
296  V8_INLINE ~Scope() { context_->Exit(); }
297 
298  private:
299  Local<Context> context_;
300  };
301 
302  /**
303  * Stack-allocated class to support the backup incumbent settings object
304  * stack.
305  * https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
306  */
307  class V8_EXPORT V8_NODISCARD BackupIncumbentScope final {
308  public:
309  /**
310  * |backup_incumbent_context| is pushed onto the backup incumbent settings
311  * object stack.
312  */
313  explicit BackupIncumbentScope(Local<Context> backup_incumbent_context);
315 
316  private:
317  friend class internal::Isolate;
318 
319  uintptr_t JSStackComparableAddressPrivate() const {
320  return js_stack_comparable_address_;
321  }
322 
323  Local<Context> backup_incumbent_context_;
324  uintptr_t js_stack_comparable_address_ = 0;
325  const BackupIncumbentScope* prev_ = nullptr;
326  };
327 
328  V8_INLINE static Context* Cast(Data* data);
329 
330  private:
331  friend class Value;
332  friend class Script;
333  friend class Object;
334  friend class Function;
335 
336  static void CheckCast(Data* obj);
337 
338  internal::Address* GetDataFromSnapshotOnce(size_t index);
339  Local<Value> SlowGetEmbedderData(int index);
340  void* SlowGetAlignedPointerFromEmbedderData(int index);
341 };
342 
343 // --- Implementation ---
344 
346 #ifndef V8_ENABLE_CHECKS
347  using A = internal::Address;
348  using I = internal::Internals;
349  A ctx = *reinterpret_cast<const A*>(this);
350  A embedder_data =
352  int value_offset =
354  A value = I::ReadRawField<A>(embedder_data, value_offset);
355 #ifdef V8_COMPRESS_POINTERS
356  // We read the full pointer value and then decompress it in order to avoid
357  // dealing with potential endiannes issues.
358  value =
359  I::DecompressTaggedAnyField(embedder_data, static_cast<uint32_t>(value));
360 #endif
362  *reinterpret_cast<A*>(this));
363  A* result = HandleScope::CreateHandle(isolate, value);
364  return Local<Value>(reinterpret_cast<Value*>(result));
365 #else
366  return SlowGetEmbedderData(index);
367 #endif
368 }
369 
371 #if !defined(V8_ENABLE_CHECKS)
372  using A = internal::Address;
373  using I = internal::Internals;
374  A ctx = *reinterpret_cast<const A*>(this);
375  A embedder_data =
377  int value_offset =
379 #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
380  value_offset += I::kEmbedderDataSlotRawPayloadOffset;
381 #endif
382  internal::Isolate* isolate = I::GetIsolateForSandbox(ctx);
383  return reinterpret_cast<void*>(
384  I::ReadExternalPointerField(isolate, embedder_data, value_offset,
386 #else
387  return SlowGetAlignedPointerFromEmbedderData(index);
388 #endif
389 }
390 
391 template <class T>
393  T* data = reinterpret_cast<T*>(GetDataFromSnapshotOnce(index));
394  if (data) internal::PerformCastCheck(data);
395  return Local<T>(data);
396 }
397 
399 #ifdef V8_ENABLE_CHECKS
400  CheckCast(data);
401 #endif
402  return static_cast<Context*>(data);
403 }
404 
405 } // namespace v8
406 
407 #endif // INCLUDE_V8_CONTEXT_H_