![]() |
|
|||
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_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |