123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- // Copyright 2021 the V8 project authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef INCLUDE_V8_CONTEXT_H_
- #define INCLUDE_V8_CONTEXT_H_
- #include <stdint.h>
- #include "v8-data.h" // NOLINT(build/include_directory)
- #include "v8-local-handle.h" // NOLINT(build/include_directory)
- #include "v8-snapshot.h" // NOLINT(build/include_directory)
- #include "v8config.h" // NOLINT(build/include_directory)
- namespace v8 {
- class Function;
- class MicrotaskQueue;
- class Object;
- class ObjectTemplate;
- class Value;
- class String;
- /**
- * A container for extension names.
- */
- class V8_EXPORT ExtensionConfiguration {
- public:
- ExtensionConfiguration() : name_count_(0), names_(nullptr) {}
- ExtensionConfiguration(int name_count, const char* names[])
- : name_count_(name_count), names_(names) {}
- const char** begin() const { return &names_[0]; }
- const char** end() const { return &names_[name_count_]; }
- private:
- const int name_count_;
- const char** names_;
- };
- /**
- * A sandboxed execution context with its own set of built-in objects
- * and functions.
- */
- class V8_EXPORT Context : public Data {
- public:
- /**
- * Returns the global proxy object.
- *
- * Global proxy object is a thin wrapper whose prototype points to actual
- * context's global object with the properties like Object, etc. This is done
- * that way for security reasons (for more details see
- * https://wiki.mozilla.org/Gecko:SplitWindow).
- *
- * Please note that changes to global proxy object prototype most probably
- * would break VM---v8 expects only global object as a prototype of global
- * proxy object.
- */
- Local<Object> Global();
- /**
- * Detaches the global object from its context before
- * the global object can be reused to create a new context.
- */
- void DetachGlobal();
- /**
- * Creates a new context and returns a handle to the newly allocated
- * context.
- *
- * \param isolate The isolate in which to create the context.
- *
- * \param extensions An optional extension configuration containing
- * the extensions to be installed in the newly created context.
- *
- * \param global_template An optional object template from which the
- * global object for the newly created context will be created.
- *
- * \param global_object An optional global object to be reused for
- * the newly created context. This global object must have been
- * created by a previous call to Context::New with the same global
- * template. The state of the global object will be completely reset
- * and only object identify will remain.
- */
- 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);
- /**
- * Create a new context from a (non-default) context snapshot. There
- * is no way to provide a global object template since we do not create
- * a new global object from template, but we can reuse a global object.
- *
- * \param isolate See v8::Context::New.
- *
- * \param context_snapshot_index The index of the context snapshot to
- * deserialize from. Use v8::Context::New for the default snapshot.
- *
- * \param embedder_fields_deserializer Optional callback to deserialize
- * internal fields. It should match the SerializeInternalFieldCallback used
- * to serialize.
- *
- * \param extensions See v8::Context::New.
- *
- * \param global_object See v8::Context::New.
- */
- static MaybeLocal<Context> FromSnapshot(
- Isolate* isolate, size_t context_snapshot_index,
- DeserializeInternalFieldsCallback embedder_fields_deserializer =
- DeserializeInternalFieldsCallback(),
- ExtensionConfiguration* extensions = nullptr,
- MaybeLocal<Value> global_object = MaybeLocal<Value>(),
- MicrotaskQueue* microtask_queue = nullptr);
- /**
- * Returns an global object that isn't backed by an actual context.
- *
- * The global template needs to have access checks with handlers installed.
- * If an existing global object is passed in, the global object is detached
- * from its context.
- *
- * Note that this is different from a detached context where all accesses to
- * the global proxy will fail. Instead, the access check handlers are invoked.
- *
- * It is also not possible to detach an object returned by this method.
- * Instead, the access check handlers need to return nothing to achieve the
- * same effect.
- *
- * It is possible, however, to create a new context from the global object
- * returned by this method.
- */
- static MaybeLocal<Object> NewRemoteContext(
- Isolate* isolate, Local<ObjectTemplate> global_template,
- MaybeLocal<Value> global_object = MaybeLocal<Value>());
- /**
- * Sets the security token for the context. To access an object in
- * another context, the security tokens must match.
- */
- void SetSecurityToken(Local<Value> token);
- /** Restores the security token to the default value. */
- void UseDefaultSecurityToken();
- /** Returns the security token of this context.*/
- Local<Value> GetSecurityToken();
- /**
- * Enter this context. After entering a context, all code compiled
- * and run is compiled and run in this context. If another context
- * is already entered, this old context is saved so it can be
- * restored when the new context is exited.
- */
- void Enter();
- /**
- * Exit this context. Exiting the current context restores the
- * context that was in place when entering the current context.
- */
- void Exit();
- /** Returns the isolate associated with a current context. */
- Isolate* GetIsolate();
- /** Returns the microtask queue associated with a current context. */
- MicrotaskQueue* GetMicrotaskQueue();
- /**
- * The field at kDebugIdIndex used to be reserved for the inspector.
- * It now serves no purpose.
- */
- enum EmbedderDataFields { kDebugIdIndex = 0 };
- /**
- * Return the number of fields allocated for embedder data.
- */
- uint32_t GetNumberOfEmbedderDataFields();
- /**
- * Gets the embedder data with the given index, which must have been set by a
- * previous call to SetEmbedderData with the same index.
- */
- V8_INLINE Local<Value> GetEmbedderData(int index);
- /**
- * Gets the binding object used by V8 extras. Extra natives get a reference
- * to this object and can use it to "export" functionality by adding
- * properties. Extra natives can also "import" functionality by accessing
- * properties added by the embedder using the V8 API.
- */
- Local<Object> GetExtrasBindingObject();
- /**
- * Sets the embedder data with the given index, growing the data as
- * needed. Note that index 0 currently has a special meaning for Chrome's
- * debugger.
- */
- void SetEmbedderData(int index, Local<Value> value);
- /**
- * Gets a 2-byte-aligned native pointer from the embedder data with the given
- * index, which must have been set by a previous call to
- * SetAlignedPointerInEmbedderData with the same index. Note that index 0
- * currently has a special meaning for Chrome's debugger.
- */
- V8_INLINE void* GetAlignedPointerFromEmbedderData(int index);
- /**
- * Sets a 2-byte-aligned native pointer in the embedder data with the given
- * index, growing the data as needed. Note that index 0 currently has a
- * special meaning for Chrome's debugger.
- */
- void SetAlignedPointerInEmbedderData(int index, void* value);
- /**
- * Control whether code generation from strings is allowed. Calling
- * this method with false will disable 'eval' and the 'Function'
- * constructor for code running in this context. If 'eval' or the
- * 'Function' constructor are used an exception will be thrown.
- *
- * If code generation from strings is not allowed the
- * V8::AllowCodeGenerationFromStrings callback will be invoked if
- * set before blocking the call to 'eval' or the 'Function'
- * constructor. If that callback returns true, the call will be
- * allowed, otherwise an exception will be thrown. If no callback is
- * set an exception will be thrown.
- */
- void AllowCodeGenerationFromStrings(bool allow);
- /**
- * Returns true if code generation from strings is allowed for the context.
- * For more details see AllowCodeGenerationFromStrings(bool) documentation.
- */
- bool IsCodeGenerationFromStringsAllowed() const;
- /**
- * Sets the error description for the exception that is thrown when
- * code generation from strings is not allowed and 'eval' or the 'Function'
- * constructor are called.
- */
- void SetErrorMessageForCodeGenerationFromStrings(Local<String> message);
- /**
- * Return data that was previously attached to the context snapshot via
- * SnapshotCreator, and removes the reference to it.
- * Repeated call with the same index returns an empty MaybeLocal.
- */
- template <class T>
- V8_INLINE MaybeLocal<T> GetDataFromSnapshotOnce(size_t index);
- /**
- * If callback is set, abort any attempt to execute JavaScript in this
- * context, call the specified callback, and throw an exception.
- * To unset abort, pass nullptr as callback.
- */
- using AbortScriptExecutionCallback = void (*)(Isolate* isolate,
- Local<Context> context);
- void SetAbortScriptExecution(AbortScriptExecutionCallback callback);
- /**
- * Returns the value that was set or restored by
- * SetContinuationPreservedEmbedderData(), if any.
- */
- Local<Value> GetContinuationPreservedEmbedderData() const;
- /**
- * Sets a value that will be stored on continuations and reset while the
- * continuation runs.
- */
- void SetContinuationPreservedEmbedderData(Local<Value> context);
- /**
- * Set or clear hooks to be invoked for promise lifecycle operations.
- * To clear a hook, set it to an empty v8::Function. Each function will
- * receive the observed promise as the first argument. If a chaining
- * operation is used on a promise, the init will additionally receive
- * the parent promise as the second argument.
- */
- void SetPromiseHooks(Local<Function> init_hook, Local<Function> before_hook,
- Local<Function> after_hook,
- Local<Function> resolve_hook);
- /**
- * Stack-allocated class which sets the execution context for all
- * operations executed within a local scope.
- */
- class V8_NODISCARD Scope {
- public:
- explicit V8_INLINE Scope(Local<Context> context) : context_(context) {
- context_->Enter();
- }
- V8_INLINE ~Scope() { context_->Exit(); }
- private:
- Local<Context> context_;
- };
- /**
- * Stack-allocated class to support the backup incumbent settings object
- * stack.
- * https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
- */
- class V8_EXPORT V8_NODISCARD BackupIncumbentScope final {
- public:
- /**
- * |backup_incumbent_context| is pushed onto the backup incumbent settings
- * object stack.
- */
- explicit BackupIncumbentScope(Local<Context> backup_incumbent_context);
- ~BackupIncumbentScope();
- private:
- friend class internal::Isolate;
- uintptr_t JSStackComparableAddressPrivate() const {
- return js_stack_comparable_address_;
- }
- Local<Context> backup_incumbent_context_;
- uintptr_t js_stack_comparable_address_ = 0;
- const BackupIncumbentScope* prev_ = nullptr;
- };
- V8_INLINE static Context* Cast(Data* data);
- private:
- friend class Value;
- friend class Script;
- friend class Object;
- friend class Function;
- static void CheckCast(Data* obj);
- internal::Address* GetDataFromSnapshotOnce(size_t index);
- Local<Value> SlowGetEmbedderData(int index);
- void* SlowGetAlignedPointerFromEmbedderData(int index);
- };
- // --- Implementation ---
- Local<Value> Context::GetEmbedderData(int index) {
- #ifndef V8_ENABLE_CHECKS
- using A = internal::Address;
- using I = internal::Internals;
- A ctx = *reinterpret_cast<const A*>(this);
- A embedder_data =
- I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
- int value_offset =
- I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
- A value = I::ReadRawField<A>(embedder_data, value_offset);
- #ifdef V8_COMPRESS_POINTERS
- // We read the full pointer value and then decompress it in order to avoid
- // dealing with potential endiannes issues.
- value =
- I::DecompressTaggedAnyField(embedder_data, static_cast<uint32_t>(value));
- #endif
- internal::Isolate* isolate = internal::IsolateFromNeverReadOnlySpaceObject(
- *reinterpret_cast<A*>(this));
- A* result = HandleScope::CreateHandle(isolate, value);
- return Local<Value>(reinterpret_cast<Value*>(result));
- #else
- return SlowGetEmbedderData(index);
- #endif
- }
- void* Context::GetAlignedPointerFromEmbedderData(int index) {
- #if !defined(V8_ENABLE_CHECKS)
- using A = internal::Address;
- using I = internal::Internals;
- A ctx = *reinterpret_cast<const A*>(this);
- A embedder_data =
- I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
- int value_offset =
- I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
- #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
- value_offset += I::kEmbedderDataSlotRawPayloadOffset;
- #endif
- internal::Isolate* isolate = I::GetIsolateForSandbox(ctx);
- return reinterpret_cast<void*>(
- I::ReadExternalPointerField(isolate, embedder_data, value_offset,
- internal::kEmbedderDataSlotPayloadTag));
- #else
- return SlowGetAlignedPointerFromEmbedderData(index);
- #endif
- }
- template <class T>
- MaybeLocal<T> Context::GetDataFromSnapshotOnce(size_t index) {
- T* data = reinterpret_cast<T*>(GetDataFromSnapshotOnce(index));
- if (data) internal::PerformCastCheck(data);
- return Local<T>(data);
- }
- Context* Context::Cast(v8::Data* data) {
- #ifdef V8_ENABLE_CHECKS
- CheckCast(data);
- #endif
- return static_cast<Context*>(data);
- }
- } // namespace v8
- #endif // INCLUDE_V8_CONTEXT_H_
|