Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-09 09:13:47

0001 // Copyright 2021 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
0004 
0005 #ifndef INCLUDE_V8_CONTEXT_H_
0006 #define INCLUDE_V8_CONTEXT_H_
0007 
0008 #include <stdint.h>
0009 
0010 #include <vector>
0011 
0012 #include "v8-data.h"          // NOLINT(build/include_directory)
0013 #include "v8-local-handle.h"  // NOLINT(build/include_directory)
0014 #include "v8-maybe.h"         // NOLINT(build/include_directory)
0015 #include "v8-snapshot.h"      // NOLINT(build/include_directory)
0016 #include "v8config.h"         // NOLINT(build/include_directory)
0017 
0018 namespace v8 {
0019 
0020 class Function;
0021 class MicrotaskQueue;
0022 class Object;
0023 class ObjectTemplate;
0024 class Value;
0025 class String;
0026 
0027 /**
0028  * A container for extension names.
0029  */
0030 class V8_EXPORT ExtensionConfiguration {
0031  public:
0032   ExtensionConfiguration() : name_count_(0), names_(nullptr) {}
0033   ExtensionConfiguration(int name_count, const char* names[])
0034       : name_count_(name_count), names_(names) {}
0035 
0036   const char** begin() const { return &names_[0]; }
0037   const char** end() const { return &names_[name_count_]; }
0038 
0039  private:
0040   const int name_count_;
0041   const char** names_;
0042 };
0043 
0044 /**
0045  * A sandboxed execution context with its own set of built-in objects
0046  * and functions.
0047  */
0048 class V8_EXPORT Context : public Data {
0049  public:
0050   /**
0051    * Returns the global proxy object.
0052    *
0053    * Global proxy object is a thin wrapper whose prototype points to actual
0054    * context's global object with the properties like Object, etc. This is done
0055    * that way for security reasons (for more details see
0056    * https://wiki.mozilla.org/Gecko:SplitWindow).
0057    *
0058    * Please note that changes to global proxy object prototype most probably
0059    * would break VM---v8 expects only global object as a prototype of global
0060    * proxy object.
0061    */
0062   Local<Object> Global();
0063 
0064   /**
0065    * Detaches the global object from its context before
0066    * the global object can be reused to create a new context.
0067    */
0068   void DetachGlobal();
0069 
0070   /**
0071    * Creates a new context and returns a handle to the newly allocated
0072    * context.
0073    *
0074    * \param isolate The isolate in which to create the context.
0075    *
0076    * \param extensions An optional extension configuration containing
0077    * the extensions to be installed in the newly created context.
0078    *
0079    * \param global_template An optional object template from which the
0080    * global object for the newly created context will be created.
0081    *
0082    * \param global_object An optional global object to be reused for
0083    * the newly created context. This global object must have been
0084    * created by a previous call to Context::New with the same global
0085    * template. The state of the global object will be completely reset
0086    * and only object identify will remain.
0087    *
0088    * \param internal_fields_deserializer An optional callback used
0089    * to deserialize fields set by
0090    * v8::Object::SetAlignedPointerInInternalField() in wrapper objects
0091    * from the default context snapshot. It should match the
0092    * SerializeInternalFieldsCallback() used by
0093    * v8::SnapshotCreator::SetDefaultContext() when the default context
0094    * snapshot is created. It does not need to be configured if the default
0095    * context snapshot contains no wrapper objects with pointer internal
0096    * fields, or if no custom startup snapshot is configured
0097    * in the v8::CreateParams used to create the isolate.
0098    *
0099    * \param microtask_queue An optional microtask queue used to manage
0100    * the microtasks created in this context. If not set the per-isolate
0101    * default microtask queue would be used.
0102    *
0103    * \param context_data_deserializer An optional callback used
0104    * to deserialize embedder data set by
0105    * v8::Context::SetAlignedPointerInEmbedderData() in the default
0106    * context from the default context snapshot. It does not need to be
0107    * configured if the default context snapshot contains no pointer embedder
0108    * data, or if no custom startup snapshot is configured in the
0109    * v8::CreateParams used to create the isolate.
0110    *
0111    * \param api_wrapper_deserializer An optional callback used to deserialize
0112    * API wrapper objects that was initially set with v8::Object::Wrap() and then
0113    * serialized using SerializeAPIWrapperCallback.
0114    */
0115   static Local<Context> New(
0116       Isolate* isolate, ExtensionConfiguration* extensions = nullptr,
0117       MaybeLocal<ObjectTemplate> global_template = MaybeLocal<ObjectTemplate>(),
0118       MaybeLocal<Value> global_object = MaybeLocal<Value>(),
0119       DeserializeInternalFieldsCallback internal_fields_deserializer =
0120           DeserializeInternalFieldsCallback(),
0121       MicrotaskQueue* microtask_queue = nullptr,
0122       DeserializeContextDataCallback context_data_deserializer =
0123           DeserializeContextDataCallback(),
0124       DeserializeAPIWrapperCallback api_wrapper_deserializer =
0125           DeserializeAPIWrapperCallback());
0126 
0127   /**
0128    * Create a new context from a (non-default) context snapshot. There
0129    * is no way to provide a global object template since we do not create
0130    * a new global object from template, but we can reuse a global object.
0131    *
0132    * \param isolate See v8::Context::New().
0133    *
0134    * \param context_snapshot_index The index of the context snapshot to
0135    * deserialize from. Use v8::Context::New() for the default snapshot.
0136    *
0137    * \param internal_fields_deserializer An optional callback used
0138    * to deserialize fields set by
0139    * v8::Object::SetAlignedPointerInInternalField() in wrapper objects
0140    * from the default context snapshot. It does not need to be
0141    * configured if there are no wrapper objects with no internal
0142    * pointer fields in the default context snapshot or if no startup
0143    * snapshot is configured when the isolate is created.
0144    *
0145    * \param extensions See v8::Context::New().
0146    *
0147    * \param global_object See v8::Context::New().
0148    *
0149    * \param internal_fields_deserializer Similar to
0150    * internal_fields_deserializer in v8::Context::New() but applies to
0151    * the context specified by the context_snapshot_index.
0152    *
0153    * \param microtask_queue  See v8::Context::New().
0154    *
0155    * \param context_data_deserializer  Similar to
0156    * context_data_deserializer in v8::Context::New() but applies to
0157    * the context specified by the context_snapshot_index.
0158    *
0159    *\param api_wrapper_deserializer Similar to api_wrapper_deserializer in
0160    * v8::Context::New() but applies to the context specified by the
0161    * context_snapshot_index.
0162    */
0163   static MaybeLocal<Context> FromSnapshot(
0164       Isolate* isolate, size_t context_snapshot_index,
0165       DeserializeInternalFieldsCallback internal_fields_deserializer =
0166           DeserializeInternalFieldsCallback(),
0167       ExtensionConfiguration* extensions = nullptr,
0168       MaybeLocal<Value> global_object = MaybeLocal<Value>(),
0169       MicrotaskQueue* microtask_queue = nullptr,
0170       DeserializeContextDataCallback context_data_deserializer =
0171           DeserializeContextDataCallback(),
0172       DeserializeAPIWrapperCallback api_wrapper_deserializer =
0173           DeserializeAPIWrapperCallback());
0174 
0175   /**
0176    * Returns an global object that isn't backed by an actual context.
0177    *
0178    * The global template needs to have access checks with handlers installed.
0179    * If an existing global object is passed in, the global object is detached
0180    * from its context.
0181    *
0182    * Note that this is different from a detached context where all accesses to
0183    * the global proxy will fail. Instead, the access check handlers are invoked.
0184    *
0185    * It is also not possible to detach an object returned by this method.
0186    * Instead, the access check handlers need to return nothing to achieve the
0187    * same effect.
0188    *
0189    * It is possible, however, to create a new context from the global object
0190    * returned by this method.
0191    */
0192   static MaybeLocal<Object> NewRemoteContext(
0193       Isolate* isolate, Local<ObjectTemplate> global_template,
0194       MaybeLocal<Value> global_object = MaybeLocal<Value>());
0195 
0196   /**
0197    * Sets the security token for the context.  To access an object in
0198    * another context, the security tokens must match.
0199    */
0200   void SetSecurityToken(Local<Value> token);
0201 
0202   /** Restores the security token to the default value. */
0203   void UseDefaultSecurityToken();
0204 
0205   /** Returns the security token of this context.*/
0206   Local<Value> GetSecurityToken();
0207 
0208   /**
0209    * Enter this context.  After entering a context, all code compiled
0210    * and run is compiled and run in this context.  If another context
0211    * is already entered, this old context is saved so it can be
0212    * restored when the new context is exited.
0213    */
0214   void Enter();
0215 
0216   /**
0217    * Exit this context.  Exiting the current context restores the
0218    * context that was in place when entering the current context.
0219    */
0220   void Exit();
0221 
0222   /**
0223    * Delegate to help with Deep freezing embedder-specific objects (such as
0224    * JSApiObjects) that can not be frozen natively.
0225    */
0226   class DeepFreezeDelegate {
0227    public:
0228     /**
0229      * Performs embedder-specific operations to freeze the provided embedder
0230      * object. The provided object *will* be frozen by DeepFreeze after this
0231      * function returns, so only embedder-specific objects need to be frozen.
0232      * This function *may not* create new JS objects or perform JS allocations.
0233      * Any v8 objects reachable from the provided embedder object that should
0234      * also be considered for freezing should be added to the children_out
0235      * parameter. Returns true if the operation completed successfully.
0236      */
0237     virtual bool FreezeEmbedderObjectAndGetChildren(
0238         Local<Object> obj, LocalVector<Object>& children_out) = 0;
0239   };
0240 
0241   /**
0242    * Attempts to recursively freeze all objects reachable from this context.
0243    * Some objects (generators, iterators, non-const closures) can not be frozen
0244    * and will cause this method to throw an error. An optional delegate can be
0245    * provided to help freeze embedder-specific objects.
0246    *
0247    * Freezing occurs in two steps:
0248    * 1. "Marking" where we iterate through all objects reachable by this
0249    *    context, accumulating a list of objects that need to be frozen and
0250    *    looking for objects that can't be frozen. This step is separated because
0251    *    it is more efficient when we can assume there is no garbage collection.
0252    * 2. "Freezing" where we go through the list of objects and freezing them.
0253    *    This effectively requires copying them so it may trigger garbage
0254    *    collection.
0255    */
0256   Maybe<void> DeepFreeze(DeepFreezeDelegate* delegate = nullptr);
0257 
0258   /** Returns the microtask queue associated with a current context. */
0259   MicrotaskQueue* GetMicrotaskQueue();
0260 
0261   /** Sets the microtask queue associated with the current context. */
0262   void SetMicrotaskQueue(MicrotaskQueue* queue);
0263 
0264   /**
0265    * The field at kDebugIdIndex used to be reserved for the inspector.
0266    * It now serves no purpose.
0267    */
0268   enum EmbedderDataFields { kDebugIdIndex = 0 };
0269 
0270   /**
0271    * Return the number of fields allocated for embedder data.
0272    */
0273   uint32_t GetNumberOfEmbedderDataFields();
0274 
0275   /**
0276    * Gets the embedder data with the given index, which must have been set by a
0277    * previous call to SetEmbedderData with the same index.
0278    */
0279   V8_INLINE Local<Data> GetEmbedderDataV2(int index);
0280 
0281   /**
0282    * Sets the embedder data with the given index, growing the data as
0283    * needed. Note that index 0 currently has a special meaning for Chrome's
0284    * debugger.
0285    */
0286   void SetEmbedderDataV2(int index, Local<Data> value);
0287 
0288   /**
0289    * Gets the embedder data with the given index, which must have been set by a
0290    * previous call to SetEmbedderData with the same index.
0291    */
0292   V8_DEPRECATE_SOON("Use GetEmbedderDataV2 instead")
0293   V8_INLINE Local<Value> GetEmbedderData(int index);
0294 
0295   /**
0296    * Gets the binding object used by V8 extras. Extra natives get a reference
0297    * to this object and can use it to "export" functionality by adding
0298    * properties. Extra natives can also "import" functionality by accessing
0299    * properties added by the embedder using the V8 API.
0300    */
0301   Local<Object> GetExtrasBindingObject();
0302 
0303   /**
0304    * Sets the embedder data with the given index, growing the data as
0305    * needed. Note that index 0 currently has a special meaning for Chrome's
0306    * debugger.
0307    */
0308   V8_DEPRECATE_SOON("Use SetEmbedderDataV2 instead")
0309   void SetEmbedderData(int index, Local<Value> value);
0310 
0311   /**
0312    * Gets a 2-byte-aligned native pointer from the embedder data with the given
0313    * index, which must have been set by a previous call to
0314    * SetAlignedPointerInEmbedderData with the same index. Note that index 0
0315    * currently has a special meaning for Chrome's debugger.
0316    */
0317   V8_INLINE void* GetAlignedPointerFromEmbedderData(Isolate* isolate, int index,
0318                                                     EmbedderDataTypeTag tag);
0319   V8_INLINE void* GetAlignedPointerFromEmbedderData(int index,
0320                                                     EmbedderDataTypeTag tag);
0321 
0322   V8_DEPRECATED(
0323       "Use GetAlignedPointerFromEmbedderData with EmbedderDataTypeTag "
0324       "parameter instead.")
0325   V8_INLINE void* GetAlignedPointerFromEmbedderData(Isolate* isolate,
0326                                                     int index) {
0327     return GetAlignedPointerFromEmbedderData(isolate, index,
0328                                              kEmbedderDataTypeTagDefault);
0329   }
0330 
0331   V8_DEPRECATED(
0332       "Use GetAlignedPointerFromEmbedderData with EmbedderDataTypeTag "
0333       "parameter instead.")
0334   V8_INLINE void* GetAlignedPointerFromEmbedderData(int index) {
0335     return GetAlignedPointerFromEmbedderData(index,
0336                                              kEmbedderDataTypeTagDefault);
0337   }
0338 
0339   void SetAlignedPointerInEmbedderData(int index, void* value,
0340                                        EmbedderDataTypeTag tag);
0341 
0342   /**
0343    * Sets a 2-byte-aligned native pointer in the embedder data with the given
0344    * index, growing the data as needed. Note that index 0 currently has a
0345    * special meaning for Chrome's debugger.
0346    */
0347   V8_DEPRECATED(
0348       "Use SetAlignedPointerInEmbedderData with EmbedderDataTypeTag parameter "
0349       "instead.")
0350   void SetAlignedPointerInEmbedderData(int index, void* value) {
0351     SetAlignedPointerInEmbedderData(index, value, kEmbedderDataTypeTagDefault);
0352   }
0353 
0354   /**
0355    * Control whether code generation from strings is allowed. Calling
0356    * this method with false will disable 'eval' and the 'Function'
0357    * constructor for code running in this context. If 'eval' or the
0358    * 'Function' constructor are used an exception will be thrown.
0359    *
0360    * If code generation from strings is not allowed the
0361    * V8::ModifyCodeGenerationFromStringsCallback callback will be invoked if
0362    * set before blocking the call to 'eval' or the 'Function'
0363    * constructor. If that callback returns true, the call will be
0364    * allowed, otherwise an exception will be thrown. If no callback is
0365    * set an exception will be thrown.
0366    */
0367   void AllowCodeGenerationFromStrings(bool allow);
0368 
0369   /**
0370    * Returns true if code generation from strings is allowed for the context.
0371    * For more details see AllowCodeGenerationFromStrings(bool) documentation.
0372    */
0373   bool IsCodeGenerationFromStringsAllowed() const;
0374 
0375   /**
0376    * Sets the error description for the exception that is thrown when
0377    * code generation from strings is not allowed and 'eval' or the 'Function'
0378    * constructor are called.
0379    */
0380   void SetErrorMessageForCodeGenerationFromStrings(Local<String> message);
0381 
0382   /**
0383    * Sets the error description for the exception that is thrown when
0384    * wasm code generation is not allowed.
0385    */
0386   void SetErrorMessageForWasmCodeGeneration(Local<String> message);
0387 
0388   /**
0389    * Return data that was previously attached to the context snapshot via
0390    * SnapshotCreator, and removes the reference to it.
0391    * Repeated call with the same index returns an empty MaybeLocal.
0392    */
0393   template <class T>
0394   V8_INLINE MaybeLocal<T> GetDataFromSnapshotOnce(size_t index);
0395 
0396   /**
0397    * If callback is set, abort any attempt to execute JavaScript in this
0398    * context, call the specified callback, and throw an exception.
0399    * To unset abort, pass nullptr as callback.
0400    */
0401   using AbortScriptExecutionCallback = void (*)(Isolate* isolate,
0402                                                 Local<Context> context);
0403   void SetAbortScriptExecution(AbortScriptExecutionCallback callback);
0404 
0405   /**
0406    * Set or clear hooks to be invoked for promise lifecycle operations.
0407    * To clear a hook, set it to an empty v8::Function. Each function will
0408    * receive the observed promise as the first argument. If a chaining
0409    * operation is used on a promise, the init will additionally receive
0410    * the parent promise as the second argument.
0411    */
0412   void SetPromiseHooks(Local<Function> init_hook, Local<Function> before_hook,
0413                        Local<Function> after_hook,
0414                        Local<Function> resolve_hook);
0415 
0416   bool HasTemplateLiteralObject(Local<Value> object);
0417   /**
0418    * Stack-allocated class which sets the execution context for all
0419    * operations executed within a local scope.
0420    */
0421   class V8_NODISCARD Scope {
0422    public:
0423     explicit V8_INLINE Scope(Local<Context> context) : context_(context) {
0424       context_->Enter();
0425     }
0426     V8_INLINE ~Scope() { context_->Exit(); }
0427 
0428    private:
0429     Local<Context> context_;
0430   };
0431 
0432   /**
0433    * Stack-allocated class to support the backup incumbent settings object
0434    * stack.
0435    * https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
0436    */
0437   class V8_EXPORT V8_NODISCARD BackupIncumbentScope final {
0438    public:
0439     /**
0440      * |backup_incumbent_context| is pushed onto the backup incumbent settings
0441      * object stack.
0442      */
0443     explicit BackupIncumbentScope(Local<Context> backup_incumbent_context);
0444     ~BackupIncumbentScope();
0445 
0446    private:
0447     friend class internal::Isolate;
0448 
0449     uintptr_t JSStackComparableAddressPrivate() const {
0450       return js_stack_comparable_address_;
0451     }
0452 
0453     Local<Context> backup_incumbent_context_;
0454     uintptr_t js_stack_comparable_address_ = 0;
0455     const BackupIncumbentScope* prev_ = nullptr;
0456   };
0457 
0458   V8_INLINE static Context* Cast(Data* data);
0459 
0460  private:
0461   friend class Value;
0462   friend class Script;
0463   friend class Object;
0464   friend class Function;
0465 
0466   static void CheckCast(Data* obj);
0467 
0468   internal::ValueHelper::InternalRepresentationType GetDataFromSnapshotOnce(
0469       size_t index);
0470   Local<Value> SlowGetEmbedderData(int index);
0471   Local<Data> SlowGetEmbedderDataV2(int index);
0472   void* SlowGetAlignedPointerFromEmbedderData(int index,
0473                                               EmbedderDataTypeTag tag);
0474 };
0475 
0476 // --- Implementation ---
0477 
0478 Local<Value> Context::GetEmbedderData(int index) {
0479 #ifndef V8_ENABLE_CHECKS
0480   using A = internal::Address;
0481   using I = internal::Internals;
0482   A ctx = internal::ValueHelper::ValueAsAddress(this);
0483   A embedder_data =
0484       I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
0485   int value_offset =
0486       I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
0487   A value = I::ReadRawField<A>(embedder_data, value_offset);
0488 #ifdef V8_COMPRESS_POINTERS
0489   // We read the full pointer value and then decompress it in order to avoid
0490   // dealing with potential endianness issues.
0491   value = I::DecompressTaggedField(embedder_data, static_cast<uint32_t>(value));
0492 #endif
0493 
0494   auto* isolate = I::GetCurrentIsolate();
0495   return Local<Value>::New(isolate, value);
0496 #else
0497   return SlowGetEmbedderData(index);
0498 #endif
0499 }
0500 
0501 V8_INLINE Local<Data> Context::GetEmbedderDataV2(int index) {
0502 #ifndef V8_ENABLE_CHECKS
0503   using A = internal::Address;
0504   using I = internal::Internals;
0505   A ctx = internal::ValueHelper::ValueAsAddress(this);
0506   A embedder_data =
0507       I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
0508   int value_offset =
0509       I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
0510   A value = I::ReadRawField<A>(embedder_data, value_offset);
0511 #ifdef V8_COMPRESS_POINTERS
0512   // We read the full pointer value and then decompress it in order to avoid
0513   // dealing with potential endianness issues.
0514   value = I::DecompressTaggedField(embedder_data, static_cast<uint32_t>(value));
0515 #endif
0516 
0517   auto* isolate = I::GetCurrentIsolate();
0518   return Local<Data>::New(isolate, value);
0519 #else
0520   return SlowGetEmbedderDataV2(index);
0521 #endif
0522 }
0523 
0524 void* Context::GetAlignedPointerFromEmbedderData(Isolate* isolate, int index,
0525                                                  EmbedderDataTypeTag tag) {
0526 #if !defined(V8_ENABLE_CHECKS)
0527   using A = internal::Address;
0528   using I = internal::Internals;
0529   A ctx = internal::ValueHelper::ValueAsAddress(this);
0530   A embedder_data =
0531       I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
0532   int value_offset = I::kEmbedderDataArrayHeaderSize +
0533                      (I::kEmbedderDataSlotSize * index) +
0534                      I::kEmbedderDataSlotExternalPointerOffset;
0535   return reinterpret_cast<void*>(I::ReadExternalPointerField(
0536       isolate, embedder_data, value_offset, ToExternalPointerTag(tag)));
0537 #else
0538   return SlowGetAlignedPointerFromEmbedderData(index, tag);
0539 #endif
0540 }
0541 
0542 void* Context::GetAlignedPointerFromEmbedderData(int index,
0543                                                  EmbedderDataTypeTag tag) {
0544 #if !defined(V8_ENABLE_CHECKS)
0545   using A = internal::Address;
0546   using I = internal::Internals;
0547   A ctx = internal::ValueHelper::ValueAsAddress(this);
0548   A embedder_data =
0549       I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
0550   int value_offset = I::kEmbedderDataArrayHeaderSize +
0551                      (I::kEmbedderDataSlotSize * index) +
0552                      I::kEmbedderDataSlotExternalPointerOffset;
0553   Isolate* isolate = I::GetCurrentIsolateForSandbox();
0554   return reinterpret_cast<void*>(I::ReadExternalPointerField(
0555       isolate, embedder_data, value_offset, ToExternalPointerTag(tag)));
0556 #else
0557   return SlowGetAlignedPointerFromEmbedderData(index, tag);
0558 #endif
0559 }
0560 
0561 template <class T>
0562 MaybeLocal<T> Context::GetDataFromSnapshotOnce(size_t index) {
0563   if (auto repr = GetDataFromSnapshotOnce(index);
0564       repr != internal::ValueHelper::kEmpty) {
0565     internal::PerformCastCheck(internal::ValueHelper::ReprAsValue<T>(repr));
0566     return Local<T>::FromRepr(repr);
0567   }
0568   return {};
0569 }
0570 
0571 Context* Context::Cast(v8::Data* data) {
0572 #ifdef V8_ENABLE_CHECKS
0573   CheckCast(data);
0574 #endif
0575   return static_cast<Context*>(data);
0576 }
0577 
0578 }  // namespace v8
0579 
0580 #endif  // INCLUDE_V8_CONTEXT_H_