Skip to content

Commit

Permalink
fixup! src: introduce node::Realm
Browse files Browse the repository at this point in the history
  • Loading branch information
legendecas committed Aug 11, 2022
1 parent 3179ee1 commit 730654c
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 28 deletions.
6 changes: 6 additions & 0 deletions src/base_object-inl.h
Expand Up @@ -32,6 +32,12 @@

namespace node {

// static
v8::Local<v8::FunctionTemplate> 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;
Expand Down
5 changes: 4 additions & 1 deletion src/base_object.h
Expand Up @@ -31,6 +31,7 @@
namespace node {

class Environment;
class IsolateData;
template <typename T, bool kIsWeak>
class BaseObjectPtrImpl;

Expand Down Expand Up @@ -109,8 +110,10 @@ class BaseObject : public MemoryRetainer {
// a BaseObjectPtr to this object.
inline void Detach();

static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
static inline v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
Environment* env);
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
IsolateData* isolate_data);

// Interface for transferring BaseObject instances using the .postMessage()
// method of MessagePorts (and, by extension, Workers).
Expand Down
3 changes: 2 additions & 1 deletion src/env-inl.h
Expand Up @@ -620,11 +620,12 @@ inline bool Environment::has_run_bootstrapping_code() const {

inline void Environment::DoneBootstrapping() {
CHECK(has_run_bootstrapping_code());
// TODO(legendecas): distinguish base objects with realms.

// 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.

// TODO(legendecas): track base objects by realms instead of environments.
base_object_created_by_bootstrap_ = base_object_count_;
}

Expand Down
38 changes: 15 additions & 23 deletions src/env.cc
Expand Up @@ -428,7 +428,13 @@ void IsolateData::CreateProperties() {
NODE_ASYNC_PROVIDER_TYPES(V)
#undef V

// TODO(legendecas): eagerly create per isolate templates.
Local<FunctionTemplate> templ = FunctionTemplate::New(isolate());
templ->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
templ->Inherit(BaseObject::GetConstructorTemplate(this));
set_binding_data_ctor_template(templ);

// TODO(legendecas): eagerly create more per-isolate templates.
}

IsolateData::IsolateData(Isolate* isolate,
Expand Down Expand Up @@ -578,17 +584,6 @@ std::unique_ptr<v8::BackingStore> Environment::release_managed_buffer(
return bs;
}

void Environment::CreateProperties() {
HandleScope handle_scope(isolate_);

Local<FunctionTemplate> templ = FunctionTemplate::New(isolate());
templ->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
templ->Inherit(BaseObject::GetConstructorTemplate(this));

set_binding_data_ctor_template(templ);
}

std::string GetExecPath(const std::vector<std::string>& argv) {
char exec_path_buf[2 * PATH_MAX];
size_t exec_path_len = sizeof(exec_path_buf);
Expand Down Expand Up @@ -725,15 +720,10 @@ Environment::Environment(IsolateData* isolate_data,
void Environment::InitializeMainContext(Local<Context> context,
const EnvSerializeInfo* env_info) {
principal_realm_ = std::make_unique<Realm>(
isolate_data_,
this,
context,
env_info == nullptr ? nullptr : &env_info->principal_realm);
isolate_data_, this, context, MAYBE_FIELD_PTR(env_info, principal_realm));
AssignToContext(context, ContextInfo(""));
if (env_info != nullptr) {
DeserializeProperties(env_info);
} else {
CreateProperties();
}

if (!options_->force_async_hooks_checks) {
Expand Down Expand Up @@ -2015,12 +2005,14 @@ bool BaseObject::IsRootNode() const {
return !persistent_handle_.IsWeak();
}

Local<FunctionTemplate> BaseObject::GetConstructorTemplate(Environment* env) {
Local<FunctionTemplate> tmpl = env->base_object_ctor_template();
Local<FunctionTemplate> BaseObject::GetConstructorTemplate(
IsolateData* isolate_data) {
Local<FunctionTemplate> tmpl = isolate_data->base_object_ctor_template();
if (tmpl.IsEmpty()) {
tmpl = NewFunctionTemplate(env->isolate(), nullptr);
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BaseObject"));
env->set_base_object_ctor_template(tmpl);
tmpl = NewFunctionTemplate(isolate_data->isolate(), nullptr);
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(isolate_data->isolate(), "BaseObject"));
isolate_data->set_base_object_ctor_template(tmpl);
}
return tmpl;
}
Expand Down
6 changes: 5 additions & 1 deletion src/env.h
Expand Up @@ -590,6 +590,11 @@ struct SnapshotData {
SnapshotData() = default;
};

/**
* Environment is a per-isolate data structure that represents an execution
* environment. Each environment has a principal realm. An environment can
* create multiple subsidiary synthetic realms.
*/
class Environment : public MemoryRetainer {
public:
Environment(const Environment&) = delete;
Expand All @@ -604,7 +609,6 @@ class Environment : public MemoryRetainer {
void MemoryInfo(MemoryTracker* tracker) const override;

EnvSerializeInfo Serialize(v8::SnapshotCreator* creator);
void CreateProperties();
void DeserializeProperties(const EnvSerializeInfo* info);

void PrintInfoForSnapshotIfDebug();
Expand Down
8 changes: 6 additions & 2 deletions src/node_realm.cc
Expand Up @@ -41,6 +41,9 @@ void Realm::MemoryInfo(MemoryTracker* tracker) const {
tracker->TrackField(#PropertyName, PropertyName());
PER_REALM_STRONG_PERSISTENT_VALUES(V)
#undef V

tracker->TrackField("isolate_data", isolate_data_);
tracker->TrackField("env", env_);
}

void Realm::CreateProperties() {
Expand Down Expand Up @@ -280,12 +283,13 @@ MaybeLocal<Value> Realm::RunBootstrapping() {
return MaybeLocal<Value>();
}

// TODO(legendecas): distinguish req_wrap and handle_wrap with realms.

// Make sure that no request or handle is created during bootstrap -
// if necessary those should be done in pre-execution.
// Usually, doing so would trigger the checks present in the ReqWrap and
// HandleWrap classes, so this is only a consistency check.

// TODO(legendecas): track req_wrap and handle_wrap by realms instead of
// environments.
CHECK(env_->req_wrap_queue()->IsEmpty());
CHECK(env_->handle_wrap_queue()->IsEmpty());

Expand Down
16 changes: 16 additions & 0 deletions src/node_realm.h
Expand Up @@ -10,6 +10,22 @@

namespace node {

/**
* node::Realm is a container for a set of JavaScript objects and functions
* that associated with a particular global environment.
*
* An ECMAScript realm (https://tc39.es/ecma262/#sec-code-realms) representing
* a global environment in which script is run. Each ECMAScript realm comes
* with a global object and a set of intrinsic objects. An ECMAScript realm has
* a [[HostDefined]] field, which contains the node::Realm object.
*
* Realm can be a principal realm or a synthetic realm. A principal realm is
* created with an Environment as its principal global environment to evaluate
* scripts. A synthetic realm is created with JS APIs like ShadowRealm.
*
* Native bindings and builtin modules can be evaluated in either a principal
* realm or a synthetic realm.
*/
class Realm : public MemoryRetainer {
public:
static inline Realm* GetCurrent(v8::Isolate* isolate);
Expand Down

0 comments on commit 730654c

Please sign in to comment.