diff --git a/node.gyp b/node.gyp index 0e28b14cbfc073..949e2599556368 100644 --- a/node.gyp +++ b/node.gyp @@ -525,6 +525,7 @@ 'src/node_process_events.cc', 'src/node_process_methods.cc', 'src/node_process_object.cc', + 'src/node_realm.cc', 'src/node_report.cc', 'src/node_report_module.cc', 'src/node_report_utils.cc', @@ -585,6 +586,7 @@ 'src/connection_wrap.h', 'src/debug_utils.h', 'src/debug_utils-inl.h', + 'src/env_properties.h', 'src/env.h', 'src/env-inl.h', 'src/handle_wrap.h', @@ -632,6 +634,8 @@ 'src/node_platform.h', 'src/node_process.h', 'src/node_process-inl.h', + 'src/node_realm.h', + 'src/node_realm-inl.h', 'src/node_report.h', 'src/node_revert.h', 'src/node_root_certs.h', diff --git a/src/api/environment.cc b/src/api/environment.cc index d4d89f9d56cd58..b8f2e41aeabc80 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -5,6 +5,7 @@ #include "node_internals.h" #include "node_options-inl.h" #include "node_platform.h" +#include "node_realm-inl.h" #include "node_shadow_realm.h" #include "node_v8_platform-inl.h" #include "node_wasm_web_api.h" @@ -378,7 +379,7 @@ Environment* CreateEnvironment( } #endif - if (env->RunBootstrapping().IsEmpty()) { + if (env->principal_realm()->RunBootstrapping().IsEmpty()) { FreeEnvironment(env); return nullptr; } @@ -453,11 +454,13 @@ MaybeLocal LoadEnvironment( builtins::BuiltinLoader::Add( name.c_str(), UnionBytes(**main_utf16, main_utf16->length())); env->set_main_utf16(std::move(main_utf16)); + Realm* realm = env->principal_realm(); + // Arguments must match the parameters specified in // BuiltinLoader::LookupAndCompile(). - std::vector> args = {env->process_object(), - env->builtin_module_require()}; - return ExecuteBootstrapper(env, name.c_str(), &args); + std::vector> args = {realm->process_object(), + realm->builtin_module_require()}; + return realm->ExecuteBootstrapper(name.c_str(), &args); }); } diff --git a/src/base_object-inl.h b/src/base_object-inl.h index e27de6ef32e8b3..c5560f66bffb04 100644 --- a/src/base_object-inl.h +++ b/src/base_object-inl.h @@ -32,6 +32,12 @@ namespace node { +// static +v8::Local BaseObject::GetConstructorTemplate( + Environment* env) { + return BaseObject::GetConstructorTemplate(env->isolate_data()); +} + void BaseObject::Detach() { CHECK_GT(pointer_data()->strong_ptr_count, 0); pointer_data()->is_detached = true; diff --git a/src/base_object.h b/src/base_object.h index 8dd988903aece5..2d1dffed361599 100644 --- a/src/base_object.h +++ b/src/base_object.h @@ -31,6 +31,7 @@ namespace node { class Environment; +class IsolateData; template class BaseObjectPtrImpl; @@ -113,8 +114,10 @@ class BaseObject : public MemoryRetainer { // a BaseObjectPtr to this object. inline void Detach(); - static v8::Local GetConstructorTemplate( + static inline v8::Local GetConstructorTemplate( Environment* env); + static v8::Local GetConstructorTemplate( + IsolateData* isolate_data); // Interface for transferring BaseObject instances using the .postMessage() // method of MessagePorts (and, by extension, Workers). diff --git a/src/env-inl.h b/src/env-inl.h index c121b1bc885928..e04c0c2cf179e3 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -31,6 +31,7 @@ #include "node_context_data.h" #include "node_internals.h" #include "node_perf_common.h" +#include "node_realm-inl.h" #include "util-inl.h" #include "uv.h" #include "v8.h" @@ -614,15 +615,7 @@ inline void Environment::set_can_call_into_js(bool can_call_into_js) { } inline bool Environment::has_run_bootstrapping_code() const { - return has_run_bootstrapping_code_; -} - -inline void Environment::DoneBootstrapping() { - has_run_bootstrapping_code_ = true; - // This adjusts the return value of base_object_created_after_bootstrap() so - // that tests that check the count do not have to account for internally - // created BaseObjects. - base_object_created_by_bootstrap_ = base_object_count_; + return principal_realm_->has_run_bootstrapping_code(); } inline bool Environment::has_serialized_options() const { @@ -805,14 +798,18 @@ void Environment::modify_base_object_count(int64_t delta) { base_object_count_ += delta; } -int64_t Environment::base_object_created_after_bootstrap() const { - return base_object_count_ - base_object_created_by_bootstrap_; -} - int64_t Environment::base_object_count() const { return base_object_count_; } +inline void Environment::set_base_object_created_by_bootstrap(int64_t count) { + base_object_created_by_bootstrap_ = base_object_count_; +} + +int64_t Environment::base_object_created_after_bootstrap() const { + return base_object_count_ - base_object_created_by_bootstrap_; +} + void Environment::set_main_utf16(std::unique_ptr str) { CHECK(!main_utf16_); main_utf16_ = std::move(str); @@ -877,16 +874,22 @@ void Environment::set_process_exit_handler( #define V(PropertyName, TypeName) \ inline v8::Local Environment::PropertyName() const { \ - return PersistentToLocal::Strong(PropertyName##_); \ + DCHECK_NOT_NULL(principal_realm_); \ + return principal_realm_->PropertyName(); \ } \ inline void Environment::set_##PropertyName(v8::Local value) { \ - PropertyName##_.Reset(isolate(), value); \ + DCHECK_NOT_NULL(principal_realm_); \ + principal_realm_->set_##PropertyName(value); \ } - ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) + PER_REALM_STRONG_PERSISTENT_VALUES(V) #undef V v8::Local Environment::context() const { - return PersistentToLocal::Strong(context_); + return principal_realm()->context(); +} + +Realm* Environment::principal_realm() const { + return principal_realm_.get(); } inline void Environment::set_heap_snapshot_near_heap_limit(uint32_t limit) { diff --git a/src/env.cc b/src/env.cc index ba637a5863af0e..43cce236ebf95a 100644 --- a/src/env.cc +++ b/src/env.cc @@ -448,6 +448,12 @@ void IsolateData::CreateProperties() { #undef V // TODO(legendecas): eagerly create per isolate templates. + Local templ = FunctionTemplate::New(isolate()); + templ->InstanceTemplate()->SetInternalFieldCount( + BaseObject::kInternalFieldCount); + templ->Inherit(BaseObject::GetConstructorTemplate(this)); + set_binding_data_ctor_template(templ); + set_contextify_global_template( contextify::ContextifyContext::CreateGlobalTemplate(isolate_)); } @@ -502,6 +508,10 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() { return; } + if (env_->principal_realm() == nullptr) { + return; + } + bool async_hooks_enabled = (*(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( TRACING_CATEGORY_NODE1(async_hooks)))) != 0; @@ -517,9 +527,11 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() { } void Environment::AssignToContext(Local context, + Realm* realm, const ContextInfo& info) { context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kEnvironment, this); + context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm, realm); // Used to retrieve bindings context->SetAlignedPointerInEmbedderData( ContextEmbedderIndex::kBindingListIndex, &(this->bindings_)); @@ -594,56 +606,6 @@ std::unique_ptr Environment::release_managed_buffer( return bs; } -void Environment::CreateProperties() { - HandleScope handle_scope(isolate_); - Local ctx = context(); - - { - Context::Scope context_scope(ctx); - Local templ = FunctionTemplate::New(isolate()); - templ->InstanceTemplate()->SetInternalFieldCount( - BaseObject::kInternalFieldCount); - templ->Inherit(BaseObject::GetConstructorTemplate(this)); - - set_binding_data_ctor_template(templ); - } - - // Store primordials setup by the per-context script in the environment. - Local per_context_bindings = - GetPerContextExports(ctx).ToLocalChecked(); - Local primordials = - per_context_bindings->Get(ctx, primordials_string()).ToLocalChecked(); - CHECK(primordials->IsObject()); - set_primordials(primordials.As()); - - Local prototype_string = - FIXED_ONE_BYTE_STRING(isolate(), "prototype"); - -#define V(EnvPropertyName, PrimordialsPropertyName) \ - { \ - Local ctor = \ - primordials.As() \ - ->Get(ctx, \ - FIXED_ONE_BYTE_STRING(isolate(), PrimordialsPropertyName)) \ - .ToLocalChecked(); \ - CHECK(ctor->IsObject()); \ - Local prototype = \ - ctor.As()->Get(ctx, prototype_string).ToLocalChecked(); \ - CHECK(prototype->IsObject()); \ - set_##EnvPropertyName(prototype.As()); \ - } - - V(primordials_safe_map_prototype_object, "SafeMap"); - V(primordials_safe_set_prototype_object, "SafeSet"); - V(primordials_safe_weak_map_prototype_object, "SafeWeakMap"); - V(primordials_safe_weak_set_prototype_object, "SafeWeakSet"); -#undef V - - Local process_object = - node::CreateProcessObject(this).FromMaybe(Local()); - set_process_object(process_object); -} - std::string GetExecPath(const std::vector& argv) { char exec_path_buf[2 * PATH_MAX]; size_t exec_path_len = sizeof(exec_path_buf); @@ -781,12 +743,11 @@ Environment::Environment(IsolateData* isolate_data, void Environment::InitializeMainContext(Local context, const EnvSerializeInfo* env_info) { - context_.Reset(context->GetIsolate(), context); - AssignToContext(context, ContextInfo("")); + principal_realm_ = std::make_unique( + this, context, MAYBE_FIELD_PTR(env_info, principal_realm)); + AssignToContext(context, principal_realm_.get(), ContextInfo("")); if (env_info != nullptr) { DeserializeProperties(env_info); - } else { - CreateProperties(); } if (!options_->force_async_hooks_checks) { @@ -811,6 +772,9 @@ void Environment::InitializeMainContext(Local context, } Environment::~Environment() { + HandleScope handle_scope(isolate()); + Local ctx = context(); + if (Environment** interrupt_data = interrupt_data_.load()) { // There are pending RequestInterrupt() callbacks. Tell them not to run, // then force V8 to run interrupts by compiling and running an empty script @@ -818,9 +782,8 @@ Environment::~Environment() { *interrupt_data = nullptr; Isolate::AllowJavascriptExecutionScope allow_js_here(isolate()); - HandleScope handle_scope(isolate()); TryCatch try_catch(isolate()); - Context::Scope context_scope(context()); + Context::Scope context_scope(ctx); #ifdef DEBUG bool consistency_check = false; @@ -830,8 +793,8 @@ Environment::~Environment() { #endif Local