Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:05:23

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   static Local<Context> New(
0112       Isolate* isolate, ExtensionConfiguration* extensions = nullptr,
0113       MaybeLocal<ObjectTemplate> global_template = MaybeLocal<ObjectTemplate>(),
0114       MaybeLocal<Value> global_object = MaybeLocal<Value>(),
0115       DeserializeInternalFieldsCallback internal_fields_deserializer =
0116           DeserializeInternalFieldsCallback(),
0117       MicrotaskQueue* microtask_queue = nullptr,
0118       DeserializeContextDataCallback context_data_deserializer =
0119           DeserializeContextDataCallback());
0120 
0121   /**
0122    * Create a new context from a (non-default) context snapshot. There
0123    * is no way to provide a global object template since we do not create
0124    * a new global object from template, but we can reuse a global object.
0125    *
0126    * \param isolate See v8::Context::New.
0127    *
0128    * \param context_snapshot_index The index of the context snapshot to
0129    * deserialize from. Use v8::Context::New for the default snapshot.
0130    *
0131    * \param internal_fields_deserializer An optional callback used
0132    * to deserialize fields set by
0133    * v8::Object::SetAlignedPointerInInternalField() in wrapper objects
0134    * from the default context snapshot. It does not need to be
0135    * configured if there are no wrapper objects with no internal
0136    * pointer fields in the default context snapshot or if no startup
0137    * snapshot is configured when the isolate is created.
0138    *
0139    * \param extensions See v8::Context::New.
0140    *
0141    * \param global_object See v8::Context::New.
0142    *
0143    * \param internal_fields_deserializer Similar to
0144    * internal_fields_deserializer in v8::Context::New but applies to
0145    * the context specified by the context_snapshot_index.
0146    *
0147    * \param microtask_queue  See v8::Context::New.
0148    *
0149    * \param context_data_deserializer  Similar to
0150    * context_data_deserializer in v8::Context::New but applies to
0151    * the context specified by the context_snapshot_index.
0152    */
0153   static MaybeLocal<Context> FromSnapshot(
0154       Isolate* isolate, size_t context_snapshot_index,
0155       DeserializeInternalFieldsCallback internal_fields_deserializer =
0156           DeserializeInternalFieldsCallback(),
0157       ExtensionConfiguration* extensions = nullptr,
0158       MaybeLocal<Value> global_object = MaybeLocal<Value>(),
0159       MicrotaskQueue* microtask_queue = nullptr,
0160       DeserializeContextDataCallback context_data_deserializer =
0161           DeserializeContextDataCallback());
0162 
0163   /**
0164    * Returns an global object that isn't backed by an actual context.
0165    *
0166    * The global template needs to have access checks with handlers installed.
0167    * If an existing global object is passed in, the global object is detached
0168    * from its context.
0169    *
0170    * Note that this is different from a detached context where all accesses to
0171    * the global proxy will fail. Instead, the access check handlers are invoked.
0172    *
0173    * It is also not possible to detach an object returned by this method.
0174    * Instead, the access check handlers need to return nothing to achieve the
0175    * same effect.
0176    *
0177    * It is possible, however, to create a new context from the global object
0178    * returned by this method.
0179    */
0180   static MaybeLocal<Object> NewRemoteContext(
0181       Isolate* isolate, Local<ObjectTemplate> global_template,
0182       MaybeLocal<Value> global_object = MaybeLocal<Value>());
0183 
0184   /**
0185    * Sets the security token for the context.  To access an object in
0186    * another context, the security tokens must match.
0187    */
0188   void SetSecurityToken(Local<Value> token);
0189 
0190   /** Restores the security token to the default value. */
0191   void UseDefaultSecurityToken();
0192 
0193   /** Returns the security token of this context.*/
0194   Local<Value> GetSecurityToken();
0195 
0196   /**
0197    * Enter this context.  After entering a context, all code compiled
0198    * and run is compiled and run in this context.  If another context
0199    * is already entered, this old context is saved so it can be
0200    * restored when the new context is exited.
0201    */
0202   void Enter();
0203 
0204   /**
0205    * Exit this context.  Exiting the current context restores the
0206    * context that was in place when entering the current context.
0207    */
0208   void Exit();
0209 
0210   /**
0211    * Delegate to help with Deep freezing embedder-specific objects (such as
0212    * JSApiObjects) that can not be frozen natively.
0213    */
0214   class DeepFreezeDelegate {
0215    public:
0216     /**
0217      * Performs embedder-specific operations to freeze the provided embedder
0218      * object. The provided object *will* be frozen by DeepFreeze after this
0219      * function returns, so only embedder-specific objects need to be frozen.
0220      * This function *may not* create new JS objects or perform JS allocations.
0221      * Any v8 objects reachable from the provided embedder object that should
0222      * also be considered for freezing should be added to the children_out
0223      * parameter. Returns true if the operation completed successfully.
0224      */
0225     virtual bool FreezeEmbedderObjectAndGetChildren(
0226         Local<Object> obj, LocalVector<Object>& children_out) = 0;
0227   };
0228 
0229   /**
0230    * Attempts to recursively freeze all objects reachable from this context.
0231    * Some objects (generators, iterators, non-const closures) can not be frozen
0232    * and will cause this method to throw an error. An optional delegate can be
0233    * provided to help freeze embedder-specific objects.
0234    *
0235    * Freezing occurs in two steps:
0236    * 1. "Marking" where we iterate through all objects reachable by this
0237    *    context, accumulating a list of objects that need to be frozen and
0238    *    looking for objects that can't be frozen. This step is separated because
0239    *    it is more efficient when we can assume there is no garbage collection.
0240    * 2. "Freezing" where we go through the list of objects and freezing them.
0241    *    This effectively requires copying them so it may trigger garbage
0242    *    collection.
0243    */
0244   Maybe<void> DeepFreeze(DeepFreezeDelegate* delegate = nullptr);
0245 
0246   /** Returns the isolate associated with a current context. */
0247   Isolate* GetIsolate();
0248 
0249   /** Returns the microtask queue associated with a current context. */
0250   MicrotaskQueue* GetMicrotaskQueue();
0251 
0252   /** Sets the microtask queue associated with the current context. */
0253   void SetMicrotaskQueue(MicrotaskQueue* queue);
0254 
0255   /**
0256    * The field at kDebugIdIndex used to be reserved for the inspector.
0257    * It now serves no purpose.
0258    */
0259   enum EmbedderDataFields { kDebugIdIndex = 0 };
0260 
0261   /**
0262    * Return the number of fields allocated for embedder data.
0263    */
0264   uint32_t GetNumberOfEmbedderDataFields();
0265 
0266   /**
0267    * Gets the embedder data with the given index, which must have been set by a
0268    * previous call to SetEmbedderData with the same index.
0269    */
0270   V8_INLINE Local<Value> GetEmbedderData(int index);
0271 
0272   /**
0273    * Gets the binding object used by V8 extras. Extra natives get a reference
0274    * to this object and can use it to "export" functionality by adding
0275    * properties. Extra natives can also "import" functionality by accessing
0276    * properties added by the embedder using the V8 API.
0277    */
0278   Local<Object> GetExtrasBindingObject();
0279 
0280   /**
0281    * Sets the embedder data with the given index, growing the data as
0282    * needed. Note that index 0 currently has a special meaning for Chrome's
0283    * debugger.
0284    */
0285   void SetEmbedderData(int index, Local<Value> value);
0286 
0287   /**
0288    * Gets a 2-byte-aligned native pointer from the embedder data with the given
0289    * index, which must have been set by a previous call to
0290    * SetAlignedPointerInEmbedderData with the same index. Note that index 0
0291    * currently has a special meaning for Chrome's debugger.
0292    */
0293   V8_INLINE void* GetAlignedPointerFromEmbedderData(int index);
0294 
0295   /**
0296    * Sets a 2-byte-aligned native pointer in the embedder data with the given
0297    * index, growing the data as needed. Note that index 0 currently has a
0298    * special meaning for Chrome's debugger.
0299    */
0300   void SetAlignedPointerInEmbedderData(int index, void* value);
0301 
0302   /**
0303    * Control whether code generation from strings is allowed. Calling
0304    * this method with false will disable 'eval' and the 'Function'
0305    * constructor for code running in this context. If 'eval' or the
0306    * 'Function' constructor are used an exception will be thrown.
0307    *
0308    * If code generation from strings is not allowed the
0309    * V8::AllowCodeGenerationFromStrings callback will be invoked if
0310    * set before blocking the call to 'eval' or the 'Function'
0311    * constructor. If that callback returns true, the call will be
0312    * allowed, otherwise an exception will be thrown. If no callback is
0313    * set an exception will be thrown.
0314    */
0315   void AllowCodeGenerationFromStrings(bool allow);
0316 
0317   /**
0318    * Returns true if code generation from strings is allowed for the context.
0319    * For more details see AllowCodeGenerationFromStrings(bool) documentation.
0320    */
0321   bool IsCodeGenerationFromStringsAllowed() const;
0322 
0323   /**
0324    * Sets the error description for the exception that is thrown when
0325    * code generation from strings is not allowed and 'eval' or the 'Function'
0326    * constructor are called.
0327    */
0328   void SetErrorMessageForCodeGenerationFromStrings(Local<String> message);
0329 
0330   /**
0331    * Sets the error description for the exception that is thrown when
0332    * wasm code generation is not allowed.
0333    */
0334   void SetErrorMessageForWasmCodeGeneration(Local<String> message);
0335 
0336   /**
0337    * Return data that was previously attached to the context snapshot via
0338    * SnapshotCreator, and removes the reference to it.
0339    * Repeated call with the same index returns an empty MaybeLocal.
0340    */
0341   template <class T>
0342   V8_INLINE MaybeLocal<T> GetDataFromSnapshotOnce(size_t index);
0343 
0344   /**
0345    * If callback is set, abort any attempt to execute JavaScript in this
0346    * context, call the specified callback, and throw an exception.
0347    * To unset abort, pass nullptr as callback.
0348    */
0349   using AbortScriptExecutionCallback = void (*)(Isolate* isolate,
0350                                                 Local<Context> context);
0351   void SetAbortScriptExecution(AbortScriptExecutionCallback callback);
0352 
0353   /**
0354    * Set or clear hooks to be invoked for promise lifecycle operations.
0355    * To clear a hook, set it to an empty v8::Function. Each function will
0356    * receive the observed promise as the first argument. If a chaining
0357    * operation is used on a promise, the init will additionally receive
0358    * the parent promise as the second argument.
0359    */
0360   void SetPromiseHooks(Local<Function> init_hook, Local<Function> before_hook,
0361                        Local<Function> after_hook,
0362                        Local<Function> resolve_hook);
0363 
0364   bool HasTemplateLiteralObject(Local<Value> object);
0365   /**
0366    * Stack-allocated class which sets the execution context for all
0367    * operations executed within a local scope.
0368    */
0369   class V8_NODISCARD Scope {
0370    public:
0371     explicit V8_INLINE Scope(Local<Context> context) : context_(context) {
0372       context_->Enter();
0373     }
0374     V8_INLINE ~Scope() { context_->Exit(); }
0375 
0376    private:
0377     Local<Context> context_;
0378   };
0379 
0380   /**
0381    * Stack-allocated class to support the backup incumbent settings object
0382    * stack.
0383    * https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
0384    */
0385   class V8_EXPORT V8_NODISCARD BackupIncumbentScope final {
0386    public:
0387     /**
0388      * |backup_incumbent_context| is pushed onto the backup incumbent settings
0389      * object stack.
0390      */
0391     explicit BackupIncumbentScope(Local<Context> backup_incumbent_context);
0392     ~BackupIncumbentScope();
0393 
0394    private:
0395     friend class internal::Isolate;
0396 
0397     uintptr_t JSStackComparableAddressPrivate() const {
0398       return js_stack_comparable_address_;
0399     }
0400 
0401     Local<Context> backup_incumbent_context_;
0402     uintptr_t js_stack_comparable_address_ = 0;
0403     const BackupIncumbentScope* prev_ = nullptr;
0404   };
0405 
0406   V8_INLINE static Context* Cast(Data* data);
0407 
0408  private:
0409   friend class Value;
0410   friend class Script;
0411   friend class Object;
0412   friend class Function;
0413 
0414   static void CheckCast(Data* obj);
0415 
0416   internal::Address* GetDataFromSnapshotOnce(size_t index);
0417   Local<Value> SlowGetEmbedderData(int index);
0418   void* SlowGetAlignedPointerFromEmbedderData(int index);
0419 };
0420 
0421 // --- Implementation ---
0422 
0423 Local<Value> Context::GetEmbedderData(int index) {
0424 #ifndef V8_ENABLE_CHECKS
0425   using A = internal::Address;
0426   using I = internal::Internals;
0427   A ctx = internal::ValueHelper::ValueAsAddress(this);
0428   A embedder_data =
0429       I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
0430   int value_offset =
0431       I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
0432   A value = I::ReadRawField<A>(embedder_data, value_offset);
0433 #ifdef V8_COMPRESS_POINTERS
0434   // We read the full pointer value and then decompress it in order to avoid
0435   // dealing with potential endiannes issues.
0436   value = I::DecompressTaggedField(embedder_data, static_cast<uint32_t>(value));
0437 #endif
0438 
0439   auto isolate = reinterpret_cast<v8::Isolate*>(
0440       internal::IsolateFromNeverReadOnlySpaceObject(ctx));
0441   return Local<Value>::New(isolate, value);
0442 #else
0443   return SlowGetEmbedderData(index);
0444 #endif
0445 }
0446 
0447 void* Context::GetAlignedPointerFromEmbedderData(int index) {
0448 #if !defined(V8_ENABLE_CHECKS)
0449   using A = internal::Address;
0450   using I = internal::Internals;
0451   A ctx = internal::ValueHelper::ValueAsAddress(this);
0452   A embedder_data =
0453       I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
0454   int value_offset = I::kEmbedderDataArrayHeaderSize +
0455                      (I::kEmbedderDataSlotSize * index) +
0456                      I::kEmbedderDataSlotExternalPointerOffset;
0457   Isolate* isolate = I::GetIsolateForSandbox(ctx);
0458   return reinterpret_cast<void*>(
0459       I::ReadExternalPointerField<internal::kEmbedderDataSlotPayloadTag>(
0460           isolate, embedder_data, value_offset));
0461 #else
0462   return SlowGetAlignedPointerFromEmbedderData(index);
0463 #endif
0464 }
0465 
0466 template <class T>
0467 MaybeLocal<T> Context::GetDataFromSnapshotOnce(size_t index) {
0468   if (auto slot = GetDataFromSnapshotOnce(index); slot) {
0469     internal::PerformCastCheck(
0470         internal::ValueHelper::SlotAsValue<T, false>(slot));
0471     return Local<T>::FromSlot(slot);
0472   }
0473   return {};
0474 }
0475 
0476 Context* Context::Cast(v8::Data* data) {
0477 #ifdef V8_ENABLE_CHECKS
0478   CheckCast(data);
0479 #endif
0480   return static_cast<Context*>(data);
0481 }
0482 
0483 }  // namespace v8
0484 
0485 #endif  // INCLUDE_V8_CONTEXT_H_