Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.2k
src: make realm binding data store weak#47688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -5,6 +5,7 @@ | ||
| namespace node{ | ||
| namespace shadow_realm{ | ||
| using v8::Context; | ||
| using v8::EscapableHandleScope; | ||
| using v8::HandleScope; | ||
| using v8::Local; | ||
| using v8::MaybeLocal; | ||
| @@ -15,7 +16,6 @@ using TryCatchScope = node::errors::TryCatchScope; | ||
| // static | ||
| ShadowRealm* ShadowRealm::New(Environment* env){ | ||
| ShadowRealm* realm = new ShadowRealm(env); | ||
| env->AssignToContext(realm->context(), realm, ContextInfo("")); | ||
| // We do not expect the realm bootstrapping to throw any | ||
| // exceptions. If it does, exit the current Node.js instance. | ||
| @@ -31,39 +31,62 @@ ShadowRealm* ShadowRealm::New(Environment* env){ | ||
| MaybeLocal<Context> HostCreateShadowRealmContextCallback( | ||
| Local<Context> initiator_context){ | ||
| Environment* env = Environment::GetCurrent(initiator_context); | ||
| EscapableHandleScope scope(env->isolate()); | ||
| ShadowRealm* realm = ShadowRealm::New(env); | ||
| if (realm != nullptr){ | ||
| return realm->context(); | ||
| return scope.Escape(realm->context()); | ||
| } | ||
| return MaybeLocal<Context>(); | ||
| } | ||
| // static | ||
| void ShadowRealm::WeakCallback(const v8::WeakCallbackInfo<ShadowRealm>& data){ | ||
| ShadowRealm* realm = data.GetParameter(); | ||
| realm->context_.Reset(); | ||
| // Yield to pending weak callbacks before deleting the realm. | ||
| // This is necessary to avoid cleaning up base objects before their scheduled | ||
| // weak callbacks are invoked, which can lead to accessing to v8 apis during | ||
| // the first pass of the weak callback. | ||
| realm->env()->SetImmediate([realm](Environment* env){delete realm}); | ||
Member
| ||
| // Remove the cleanup hook to avoid deleting the realm again. | ||
| realm->env()->RemoveCleanupHook(DeleteMe, realm); | ||
| } | ||
| // static | ||
| void ShadowRealm::DeleteMe(void* data){ | ||
| ShadowRealm* realm = static_cast<ShadowRealm*>(data); | ||
| // Clear the context handle to avoid invoking the weak callback again. | ||
| // Also, the context internal slots are cleared and the context is no longer | ||
| // reference to the realm. | ||
| delete realm; | ||
| } | ||
| ShadowRealm::ShadowRealm(Environment* env) | ||
| : Realm(env, NewContext(env->isolate()), kShadowRealm){ | ||
| env->TrackShadowRealm(this); | ||
| context_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); | ||
| CreateProperties(); | ||
| env->TrackShadowRealm(this); | ||
| env->AddCleanupHook(DeleteMe, this); | ||
| } | ||
| ShadowRealm::~ShadowRealm(){ | ||
| while (HasCleanupHooks()){ | ||
| RunCleanup(); | ||
| } | ||
| if (env_ != nullptr){ | ||
| env_->UntrackShadowRealm(this); | ||
| env_->UntrackShadowRealm(this); | ||
| if (context_.IsEmpty()){ | ||
| // This most likely happened because the weak callback cleared it. | ||
| return; | ||
| } | ||
| } | ||
| void ShadowRealm::OnEnvironmentDestruct(){ | ||
| CHECK_NOT_NULL(env_); | ||
| env_ = nullptr; // This means that the shadow realm has out-lived the | ||
| // environment. | ||
| { | ||
| HandleScope handle_scope(isolate()); | ||
| env_->UnassignFromContext(context()); | ||
| } | ||
| } | ||
| v8::Local<v8::Context> ShadowRealm::context() const{ | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test that creates a bunch of shadow realms and then generates a heap snapshot? I think that's how I ran into the shadow realms outliving shadow realms issue and is why this is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a new test
test/pummel/test-heapdump-shadow-realm.js.