GeezerVison is showing github.com — src: retrieve binding data from the context · nodejs/node@a292630
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: src/README.md +15-9Lines changed: 15 additions & 9 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -400,16 +400,23 @@ NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, Initialize) | 400 | 400 |
| 401 | 401 | Some internal bindings, such as the HTTP parser, maintain internal state that | 402 | 402 | only affects that particular binding. In that case, one common way to store | 403 | | -that state is through the use of `Environment::BindingScope`, which gives all | 404 | | -new functions created within it access to an object for storing such state. | | 403 | +that state is through the use of `Environment::AddBindingData`, which gives | | 404 | +binding functions access to an object for storing such state. | 405 | 405 | That object is always a [`BaseObject`][]. | 406 | 406 |
| | 407 | +Its class needs to have a static `binding_data_name` field that based on a | | 408 | +constant string, in order to disambiguate it from other classes of this type, | | 409 | +and which could e.g. match the binding’s name (in the example above, that would | | 410 | +be `cares_wrap`). | | 411 | +
| 407 | 412 | ```c++ | 408 | 413 | // In the HTTP parser source code file: | 409 | 414 | class BindingData : public BaseObject { | 410 | 415 | public: | 411 | 416 | BindingData(Environment* env, Local<Object> obj) : BaseObject(env, obj) {} | 412 | 417 |
| | 418 | + static constexpr FastStringKey binding_data_name { "http_parser" }; | | 419 | +
| 413 | 420 | std::vector<char> parser_buffer; | 414 | 421 | bool parser_buffer_in_use = false; | 415 | 422 |
| @@ -418,22 +425,21 @@ class BindingData : public BaseObject { | 418 | 425 |
| 419 | 426 | // Available for binding functions, e.g. the HTTP Parser constructor: | 420 | 427 | static void New(const FunctionCallbackInfo<Value>& args) { | 421 | | - BindingData* binding_data = Unwrap<BindingData>(args.Data()); | | 428 | + BindingData* binding_data = Environment::GetBindingData<BindingData>(args); | 422 | 429 | new Parser(binding_data, args.This()); | 423 | 430 | } | 424 | 431 |
| 425 | | -// ... because the initialization function told the Environment to use this | 426 | | -// BindingData class for all functions created by it: | | 432 | +// ... because the initialization function told the Environment to store the | | 433 | +// BindingData object: | 427 | 434 | void InitializeHttpParser(Local<Object> target, | 428 | 435 | Local<Value> unused, | 429 | 436 | Local<Context> context, | 430 | 437 | void* priv) { | 431 | 438 | Environment* env = Environment::GetCurrent(context); | 432 | | - Environment::BindingScope<BindingData> binding_scope(env); | 433 | | - if (!binding_scope) return; | 434 | | - BindingData* binding_data = binding_scope.data; | | 439 | + BindingData* const binding_data = | | 440 | + env->AddBindingData<BindingData>(context, target); | | 441 | + if (binding_data == nullptr) return; | 435 | 442 |
| 436 | | - // Created within the Environment::BindingScope | 437 | 443 | Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New); | 438 | 444 | ... | 439 | 445 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/env-inl.h +41-37Lines changed: 41 additions & 37 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -287,6 +287,10 @@ inline void Environment::AssignToContext(v8::Local<v8::Context> context, | 287 | 287 | // Used by Environment::GetCurrent to know that we are on a node context. | 288 | 288 | context->SetAlignedPointerInEmbedderData( | 289 | 289 | ContextEmbedderIndex::kContextTag, Environment::kNodeContextTagPtr); | | 290 | + // Used to retrieve bindings | | 291 | + context->SetAlignedPointerInEmbedderData( | | 292 | + ContextEmbedderIndex::kBindingListIndex, &(this->bindings_)); | | 293 | + | 290 | 294 | #if HAVE_INSPECTOR | 291 | 295 | inspector_agent()->ContextCreated(context, info); | 292 | 296 | #endif // HAVE_INSPECTOR | @@ -318,55 +322,55 @@ inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) { | 318 | 322 |
| 319 | 323 | inline Environment* Environment::GetCurrent( | 320 | 324 | const v8::FunctionCallbackInfo<v8::Value>& info) { | 321 | | - return GetFromCallbackData(info.Data()); | | 325 | + return GetCurrent(info.GetIsolate()->GetCurrentContext()); | 322 | 326 | } | 323 | 327 |
| 324 | 328 | template <typename T> | 325 | 329 | inline Environment* Environment::GetCurrent( | 326 | 330 | const v8::PropertyCallbackInfo<T>& info) { | 327 | | - return GetFromCallbackData(info.Data()); | | 331 | + return GetCurrent(info.GetIsolate()->GetCurrentContext()); | 328 | 332 | } | 329 | 333 |
| 330 | | -Environment* Environment::GetFromCallbackData(v8::Local<v8::Value> val) { | 331 | | - DCHECK(val->IsObject()); | 332 | | - v8::Local<v8::Object> obj = val.As<v8::Object>(); | 333 | | - DCHECK_GE(obj->InternalFieldCount(), | 334 | | - BaseObject::kInternalFieldCount); | 335 | | - Environment* env = Unwrap<BaseObject>(obj)->env(); | 336 | | - DCHECK(env->as_callback_data_template()->HasInstance(obj)); | 337 | | - return env; | | 334 | +template <typename T, typename U> | | 335 | +inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo<U>& info) { | | 336 | + return GetBindingData<T>(info.GetIsolate()->GetCurrentContext()); | 338 | 337 | } | 339 | 338 |
| 340 | 339 | template <typename T> | 341 | | -Environment::BindingScope<T>::BindingScope(Environment* env) : env(env) { | 342 | | - v8::Local<v8::Object> callback_data; | 343 | | - if (!env->MakeBindingCallbackData<T>().ToLocal(&callback_data)) | 344 | | - return; | 345 | | - data = Unwrap<T>(callback_data); | 346 | | - | 347 | | - // No nesting allowed currently. | 348 | | - CHECK_EQ(env->current_callback_data(), env->as_callback_data()); | 349 | | - env->set_current_callback_data(callback_data); | | 340 | +inline T* Environment::GetBindingData( | | 341 | + const v8::FunctionCallbackInfo<v8::Value>& info) { | | 342 | + return GetBindingData<T>(info.GetIsolate()->GetCurrentContext()); | 350 | 343 | } | 351 | 344 |
| 352 | 345 | template <typename T> | 353 | | -Environment::BindingScope<T>::~BindingScope() { | 354 | | - env->set_current_callback_data(env->as_callback_data()); | | 346 | +inline T* Environment::GetBindingData(v8::Local<v8::Context> context) { | | 347 | + BindingDataStore* map = static_cast<BindingDataStore*>( | | 348 | + context->GetAlignedPointerFromEmbedderData( | | 349 | + ContextEmbedderIndex::kBindingListIndex)); | | 350 | + DCHECK_NOT_NULL(map); | | 351 | + auto it = map->find(T::binding_data_name); | | 352 | + if (UNLIKELY(it == map->end())) return nullptr; | | 353 | + T* result = static_cast<T*>(it->second.get()); | | 354 | + DCHECK_NOT_NULL(result); | | 355 | + DCHECK_EQ(result->env(), GetCurrent(context)); | | 356 | + return result; | 355 | 357 | } | 356 | 358 |
| 357 | 359 | template <typename T> | 358 | | -v8::MaybeLocal<v8::Object> Environment::MakeBindingCallbackData() { | 359 | | - v8::Local<v8::Function> ctor; | 360 | | - v8::Local<v8::Object> obj; | 361 | | - if (!as_callback_data_template()->GetFunction(context()).ToLocal(&ctor) || | 362 | | - !ctor->NewInstance(context()).ToLocal(&obj)) { | 363 | | - return v8::MaybeLocal<v8::Object>(); | 364 | | - } | 365 | | - T* data = new T(this, obj); | | 360 | +inline T* Environment::AddBindingData( | | 361 | + v8::Local<v8::Context> context, | | 362 | + v8::Local<v8::Object> target) { | | 363 | + DCHECK_EQ(GetCurrent(context), this); | 366 | 364 | // This won't compile if T is not a BaseObject subclass. | 367 | | - CHECK_EQ(data, static_cast<BaseObject*>(data)); | 368 | | - data->MakeWeak(); | 369 | | - return obj; | | 365 | + BaseObjectPtr<T> item = MakeDetachedBaseObject<T>(this, target); | | 366 | + BindingDataStore* map = static_cast<BindingDataStore*>( | | 367 | + context->GetAlignedPointerFromEmbedderData( | | 368 | + ContextEmbedderIndex::kBindingListIndex)); | | 369 | + DCHECK_NOT_NULL(map); | | 370 | + auto result = map->emplace(T::binding_data_name, item); | | 371 | + CHECK(result.second); | | 372 | + DCHECK_EQ(GetBindingData<T>(context), item.get()); | | 373 | + return item.get(); | 370 | 374 | } | 371 | 375 |
| 372 | 376 | inline Environment* Environment::GetThreadLocalEnv() { | @@ -1077,8 +1081,7 @@ inline v8::Local<v8::FunctionTemplate> | 1077 | 1081 | v8::Local<v8::Signature> signature, | 1078 | 1082 | v8::ConstructorBehavior behavior, | 1079 | 1083 | v8::SideEffectType side_effect_type) { | 1080 | | - v8::Local<v8::Object> external = current_callback_data(); | 1081 | | - return v8::FunctionTemplate::New(isolate(), callback, external, | | 1084 | + return v8::FunctionTemplate::New(isolate(), callback, v8::Local<v8::Value>(), | 1082 | 1085 | signature, 0, behavior, side_effect_type); | 1083 | 1086 | } | 1084 | 1087 |
| @@ -1270,9 +1273,10 @@ void Environment::set_process_exit_handler( | 1270 | 1273 | ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) | 1271 | 1274 | #undef V | 1272 | 1275 |
| 1273 | | - inline v8::Local<v8::Context> Environment::context() const { | 1274 | | - return PersistentToLocal::Strong(context_); | 1275 | | - } | | 1276 | +v8::Local<v8::Context> Environment::context() const { | | 1277 | + return PersistentToLocal::Strong(context_); | | 1278 | +} | | 1279 | + | 1276 | 1280 | } // namespace node | 1277 | 1281 |
| 1278 | 1282 | // These two files depend on each other. Including base_object-inl.h after this | |
Collapse file Copy file name to clipboardExpand all lines: src/env.cc +4-14Lines changed: 4 additions & 14 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -261,29 +261,17 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() { | 261 | 261 | USE(cb->Call(env_->context(), Undefined(isolate), arraysize(args), args)); | 262 | 262 | } | 263 | 263 |
| 264 | | -class NoBindingData : public BaseObject { | 265 | | - public: | 266 | | - NoBindingData(Environment* env, Local<Object> obj) : BaseObject(env, obj) {} | 267 | | - | 268 | | - SET_NO_MEMORY_INFO() | 269 | | - SET_MEMORY_INFO_NAME(NoBindingData) | 270 | | - SET_SELF_SIZE(NoBindingData) | 271 | | -}; | 272 | | - | 273 | 264 | void Environment::CreateProperties() { | 274 | 265 | HandleScope handle_scope(isolate_); | 275 | 266 | Local<Context> ctx = context(); | | 267 | + | 276 | 268 | { | 277 | 269 | Context::Scope context_scope(ctx); | 278 | 270 | Local<FunctionTemplate> templ = FunctionTemplate::New(isolate()); | 279 | 271 | templ->InstanceTemplate()->SetInternalFieldCount( | 280 | 272 | BaseObject::kInternalFieldCount); | 281 | | - set_as_callback_data_template(templ); | 282 | 273 |
| 283 | | - Local<Object> obj = MakeBindingCallbackData<NoBindingData>() | 284 | | - .ToLocalChecked(); | 285 | | - set_as_callback_data(obj); | 286 | | - set_current_callback_data(obj); | | 274 | + set_binding_data_ctor_template(templ); | 287 | 275 | } | 288 | 276 |
| 289 | 277 | // Store primordials setup by the per-context script in the environment. | @@ -674,6 +662,8 @@ void Environment::RunCleanup() { | 674 | 662 | started_cleanup_ = true; | 675 | 663 | TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | 676 | 664 | "RunCleanup", this); | | 665 | + bindings_.clear(); | | 666 | + initial_base_object_count_ = 0; | 677 | 667 | CleanupHandles(); | 678 | 668 |
| 679 | 669 | while (!cleanup_hooks_.empty()) { | |
Collapse file Copy file name to clipboardExpand all lines: src/env.h +17-18Lines changed: 17 additions & 18 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -390,9 +390,9 @@ constexpr size_t kFsStatsBufferLength = | 390 | 390 | V(zero_return_string, "ZERO_RETURN") | 391 | 391 |
| 392 | 392 | #define ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V) \ | 393 | | - V(as_callback_data_template, v8::FunctionTemplate) \ | 394 | 393 | V(async_wrap_ctor_template, v8::FunctionTemplate) \ | 395 | 394 | V(async_wrap_object_ctor_template, v8::FunctionTemplate) \ | | 395 | + V(binding_data_ctor_template, v8::FunctionTemplate) \ | 396 | 396 | V(compiled_fn_entry_template, v8::ObjectTemplate) \ | 397 | 397 | V(dir_instance_template, v8::ObjectTemplate) \ | 398 | 398 | V(fd_constructor_template, v8::ObjectTemplate) \ | @@ -420,7 +420,6 @@ constexpr size_t kFsStatsBufferLength = | 420 | 420 | V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) | 421 | 421 |
| 422 | 422 | #define ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \ | 423 | | - V(as_callback_data, v8::Object) \ | 424 | 423 | V(async_hooks_after_function, v8::Function) \ | 425 | 424 | V(async_hooks_before_function, v8::Function) \ | 426 | 425 | V(async_hooks_binding, v8::Object) \ | @@ -429,7 +428,6 @@ constexpr size_t kFsStatsBufferLength = | 429 | 428 | V(async_hooks_promise_resolve_function, v8::Function) \ | 430 | 429 | V(buffer_prototype_object, v8::Object) \ | 431 | 430 | V(crypto_key_object_constructor, v8::Function) \ | 432 | | - V(current_callback_data, v8::Object) \ | 433 | 431 | V(domain_callback, v8::Function) \ | 434 | 432 | V(domexception_function, v8::Function) \ | 435 | 433 | V(enhance_fatal_stack_after_inspector, v8::Function) \ | @@ -864,25 +862,24 @@ class Environment : public MemoryRetainer { | 864 | 862 | static inline Environment* GetCurrent( | 865 | 863 | const v8::PropertyCallbackInfo<T>& info); | 866 | 864 |
| 867 | | - static inline Environment* GetFromCallbackData(v8::Local<v8::Value> val); | 868 | | - | 869 | 865 | // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside | 870 | 866 | // this scope can access the created T* object using | 871 | | - // Unwrap<T>(args.Data()) later. | | 867 | + // GetBindingData<T>(args) later. | 872 | 868 | template <typename T> | 873 | | - struct BindingScope { | 874 | | - explicit inline BindingScope(Environment* env); | 875 | | - inline ~BindingScope(); | 876 | | - | 877 | | - T* data = nullptr; | 878 | | - Environment* env; | 879 | | - | 880 | | - inline operator bool() const { return data != nullptr; } | 881 | | - inline bool operator !() const { return data == nullptr; } | 882 | | - }; | 883 | | - | | 869 | + T* AddBindingData(v8::Local<v8::Context> context, | | 870 | + v8::Local<v8::Object> target); | | 871 | + template <typename T, typename U> | | 872 | + static inline T* GetBindingData(const v8::PropertyCallbackInfo<U>& info); | 884 | 873 | template <typename T> | 885 | | - inline v8::MaybeLocal<v8::Object> MakeBindingCallbackData(); | | 874 | + static inline T* GetBindingData( | | 875 | + const v8::FunctionCallbackInfo<v8::Value>& info); | | 876 | + template <typename T> | | 877 | + static inline T* GetBindingData(v8::Local<v8::Context> context); | | 878 | + | | 879 | + typedef std::unordered_map< | | 880 | + FastStringKey, | | 881 | + BaseObjectPtr<BaseObject>, | | 882 | + FastStringKey::Hash> BindingDataStore; | 886 | 883 |
| 887 | 884 | static uv_key_t thread_local_env; | 888 | 885 | static inline Environment* GetThreadLocalEnv(); | @@ -1425,6 +1422,8 @@ class Environment : public MemoryRetainer { | 1425 | 1422 | void RequestInterruptFromV8(); | 1426 | 1423 | static void CheckImmediate(uv_check_t* handle); | 1427 | 1424 |
| | 1425 | + BindingDataStore bindings_; | | 1426 | + | 1428 | 1427 | // Use an unordered_set, so that we have efficient insertion and removal. | 1429 | 1428 | std::unordered_set<CleanupHookCallback, | 1430 | 1429 | CleanupHookCallback::Hash, | |
Collapse file Copy file name to clipboardExpand all lines: src/fs_event_wrap.cc +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -108,7 +108,7 @@ void FSEventWrap::Initialize(Local<Object> target, | 108 | 108 | Local<FunctionTemplate> get_initialized_templ = | 109 | 109 | FunctionTemplate::New(env->isolate(), | 110 | 110 | GetInitialized, | 111 | | - env->current_callback_data(), | | 111 | + Local<Value>(), | 112 | 112 | Signature::New(env->isolate(), t)); | 113 | 113 |
| 114 | 114 | t->PrototypeTemplate()->SetAccessorProperty( | |
Collapse file Copy file name to clipboardExpand all lines: src/node.cc +1-2Lines changed: 1 addition & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -331,8 +331,7 @@ MaybeLocal<Value> Environment::BootstrapNode() { | 331 | 331 |
| 332 | 332 | Local<String> env_string = FIXED_ONE_BYTE_STRING(isolate_, "env"); | 333 | 333 | Local<Object> env_var_proxy; | 334 | | - if (!CreateEnvVarProxy(context(), isolate_, current_callback_data()) | 335 | | - .ToLocal(&env_var_proxy) || | | 334 | + if (!CreateEnvVarProxy(context(), isolate_).ToLocal(&env_var_proxy) || | 336 | 335 | process_object()->Set(context(), env_string, env_var_proxy).IsNothing()) { | 337 | 336 | return MaybeLocal<Value>(); | 338 | 337 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/node_binding.cc +5-1Lines changed: 5 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -230,6 +230,7 @@ namespace node { | 230 | 230 |
| 231 | 231 | using v8::Context; | 232 | 232 | using v8::Exception; | | 233 | +using v8::Function; | 233 | 234 | using v8::FunctionCallbackInfo; | 234 | 235 | using v8::Local; | 235 | 236 | using v8::NewStringType; | @@ -556,8 +557,11 @@ inline struct node_module* FindModule(struct node_module* list, | 556 | 557 | static Local<Object> InitModule(Environment* env, | 557 | 558 | node_module* mod, | 558 | 559 | Local<String> module) { | 559 | | - Local<Object> exports = Object::New(env->isolate()); | 560 | 560 | // Internal bindings don't have a "module" object, only exports. | | 561 | + Local<Function> ctor = env->binding_data_ctor_template() | | 562 | + ->GetFunction(env->context()) | | 563 | + .ToLocalChecked(); | | 564 | + Local<Object> exports = ctor->NewInstance(env->context()).ToLocalChecked(); | 561 | 565 | CHECK_NULL(mod->nm_register_func); | 562 | 566 | CHECK_NOT_NULL(mod->nm_context_register_func); | 563 | 567 | Local<Value> unused = Undefined(env->isolate()); | |
Collapse file Copy file name to clipboardExpand all lines: src/node_context_data.h +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -25,11 +25,16 @@ namespace node { | 25 | 25 | #define NODE_CONTEXT_TAG 35 | 26 | 26 | #endif | 27 | 27 |
| | 28 | +#ifndef NODE_BINDING_LIST | | 29 | +#define NODE_BINDING_LIST_INDEX 36 | | 30 | +#endif | | 31 | + | 28 | 32 | enum ContextEmbedderIndex { | 29 | 33 | kEnvironment = NODE_CONTEXT_EMBEDDER_DATA_INDEX, | 30 | 34 | kSandboxObject = NODE_CONTEXT_SANDBOX_OBJECT_INDEX, | 31 | 35 | kAllowWasmCodeGeneration = NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX, | 32 | 36 | kContextTag = NODE_CONTEXT_TAG, | | 37 | + kBindingListIndex = NODE_BINDING_LIST_INDEX | 33 | 38 | }; | 34 | 39 |
| 35 | 40 | } // namespace node | |
Collapse file Copy file name to clipboardExpand all lines: src/node_crypto.cc +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -505,7 +505,7 @@ void SecureContext::Initialize(Environment* env, Local<Object> target) { | 505 | 505 | Local<FunctionTemplate> ctx_getter_templ = | 506 | 506 | FunctionTemplate::New(env->isolate(), | 507 | 507 | CtxGetter, | 508 | | - env->current_callback_data(), | | 508 | + Local<Value>(), | 509 | 509 | Signature::New(env->isolate(), t)); | 510 | 510 |
| 511 | 511 |
| @@ -5103,7 +5103,7 @@ void DiffieHellman::Initialize(Environment* env, Local<Object> target) { | 5103 | 5103 | Local<FunctionTemplate> verify_error_getter_templ = | 5104 | 5104 | FunctionTemplate::New(env->isolate(), | 5105 | 5105 | DiffieHellman::VerifyErrorGetter, | 5106 | | - env->current_callback_data(), | | 5106 | + Local<Value>(), | 5107 | 5107 | Signature::New(env->isolate(), t), | 5108 | 5108 | /* length */ 0, | 5109 | 5109 | ConstructorBehavior::kThrow, | |
Collapse file Copy file name to clipboardExpand all lines: src/node_env_var.cc +2-4Lines changed: 2 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -377,13 +377,11 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) { | 377 | 377 | env->env_vars()->Enumerate(env->isolate())); | 378 | 378 | } | 379 | 379 |
| 380 | | -MaybeLocal<Object> CreateEnvVarProxy(Local<Context> context, | 381 | | - Isolate* isolate, | 382 | | - Local<Object> data) { | | 380 | +MaybeLocal<Object> CreateEnvVarProxy(Local<Context> context, Isolate* isolate) { | 383 | 381 | EscapableHandleScope scope(isolate); | 384 | 382 | Local<ObjectTemplate> env_proxy_template = ObjectTemplate::New(isolate); | 385 | 383 | env_proxy_template->SetHandler(NamedPropertyHandlerConfiguration( | 386 | | - EnvGetter, EnvSetter, EnvQuery, EnvDeleter, EnvEnumerator, data, | | 384 | + EnvGetter, EnvSetter, EnvQuery, EnvDeleter, EnvEnumerator, Local<Value>(), | 387 | 385 | PropertyHandlerFlags::kHasNoSideEffect)); | 388 | 386 | return scope.EscapeMaybe(env_proxy_template->NewInstance(context)); | 389 | 387 | } | |
|