Commit 892591e1 authored by Vicky Kontoura's avatar Vicky Kontoura Committed by V8 LUCI CQ

[web snapshot] Introduce an ExplicitRealmScope in d8

This CL introduces an ExplicitRealmScope in d8 for entering an existing
Realm on demand.

Bug: v8:11525, v8:11706
Change-Id: I3b556aed85fc615bb5efbd4a072e075534617258
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2936602
Commit-Queue: Vicky Kontoura <vkont@google.com>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74946}
parent 928da809
...@@ -1517,6 +1517,24 @@ PerIsolateData::RealmScope::~RealmScope() { ...@@ -1517,6 +1517,24 @@ PerIsolateData::RealmScope::~RealmScope() {
delete[] data_->realms_; delete[] data_->realms_;
} }
PerIsolateData::ExplicitRealmScope::ExplicitRealmScope(PerIsolateData* data,
int index)
: data_(data), index_(index) {
realm_ = Local<Context>::New(data->isolate_, data->realms_[index_]);
realm_->Enter();
previous_index_ = data->realm_current_;
data->realm_current_ = data->realm_switch_ = index_;
}
PerIsolateData::ExplicitRealmScope::~ExplicitRealmScope() {
realm_->Exit();
data_->realm_current_ = data_->realm_switch_ = previous_index_;
}
Local<Context> PerIsolateData::ExplicitRealmScope::context() const {
return realm_;
}
int PerIsolateData::RealmFind(Local<Context> context) { int PerIsolateData::RealmFind(Local<Context> context) {
for (int i = 0; i < realm_count_; ++i) { for (int i = 0; i < realm_count_; ++i) {
if (realms_[i] == context) return i; if (realms_[i] == context) return i;
...@@ -1783,18 +1801,15 @@ void Shell::RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -1783,18 +1801,15 @@ void Shell::RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
.ToLocal(&script)) { .ToLocal(&script)) {
return; return;
} }
Local<Context> realm = Local<Context>::New(isolate, data->realms_[index]);
realm->Enter();
int previous_index = data->realm_current_;
data->realm_current_ = data->realm_switch_ = index;
Local<Value> result; Local<Value> result;
if (!script->BindToCurrentContext()->Run(realm).ToLocal(&result)) { {
realm->Exit(); PerIsolateData::ExplicitRealmScope realm_scope(data, index);
data->realm_current_ = data->realm_switch_ = previous_index; if (!script->BindToCurrentContext()
return; ->Run(realm_scope.context())
.ToLocal(&result)) {
return;
}
} }
realm->Exit();
data->realm_current_ = data->realm_switch_ = previous_index;
args.GetReturnValue().Set(result); args.GetReturnValue().Set(result);
} }
...@@ -1841,23 +1856,17 @@ void Shell::RealmTakeWebSnapshot( ...@@ -1841,23 +1856,17 @@ void Shell::RealmTakeWebSnapshot(
} }
exports->Set(isolate, i, str); exports->Set(isolate, i, str);
} }
// Enter the realm. // Take the snapshot in the specified Realm.
Local<Context> realm = Local<Context>::New(isolate, data->realms_[index]);
realm->Enter();
int previous_index = data->realm_current_;
data->realm_current_ = data->realm_switch_ = index;
// Take the snapshot.
i::WebSnapshotSerializer serializer(isolate);
auto snapshot_data_shared = std::make_shared<i::WebSnapshotData>(); auto snapshot_data_shared = std::make_shared<i::WebSnapshotData>();
if (!serializer.TakeSnapshot(realm, exports, *snapshot_data_shared)) { {
realm->Exit(); PerIsolateData::ExplicitRealmScope realm_scope(data, index);
data->realm_current_ = data->realm_switch_ = previous_index; i::WebSnapshotSerializer serializer(isolate);
args.GetReturnValue().Set(Undefined(isolate)); if (!serializer.TakeSnapshot(realm_scope.context(), exports,
return; *snapshot_data_shared)) {
args.GetReturnValue().Set(Undefined(isolate));
return;
}
} }
// Exit the realm.
realm->Exit();
data->realm_current_ = data->realm_switch_ = previous_index;
// Create a snapshot object and store the WebSnapshotData as an embedder // Create a snapshot object and store the WebSnapshotData as an embedder
// field. TODO(v8:11525): Use methods on global Snapshot objects with // field. TODO(v8:11525): Use methods on global Snapshot objects with
// signature checks. // signature checks.
...@@ -1869,7 +1878,8 @@ void Shell::RealmTakeWebSnapshot( ...@@ -1869,7 +1878,8 @@ void Shell::RealmTakeWebSnapshot(
Local<ObjectTemplate> snapshot_template = Local<ObjectTemplate> snapshot_template =
data->GetSnapshotObjectCtor()->InstanceTemplate(); data->GetSnapshotObjectCtor()->InstanceTemplate();
Local<Object> snapshot_instance = Local<Object> snapshot_instance =
snapshot_template->NewInstance(realm).ToLocalChecked(); snapshot_template->NewInstance(isolate->GetCurrentContext())
.ToLocalChecked();
snapshot_instance->SetInternalField(0, shapshot_data); snapshot_instance->SetInternalField(0, shapshot_data);
args.GetReturnValue().Set(snapshot_instance); args.GetReturnValue().Set(snapshot_instance);
} }
...@@ -1899,18 +1909,14 @@ void Shell::RealmUseWebSnapshot( ...@@ -1899,18 +1909,14 @@ void Shell::RealmUseWebSnapshot(
i::Handle<i::Managed<i::WebSnapshotData>>::cast(snapshot_data_handle); i::Handle<i::Managed<i::WebSnapshotData>>::cast(snapshot_data_handle);
std::shared_ptr<i::WebSnapshotData> snapshot_data_shared = std::shared_ptr<i::WebSnapshotData> snapshot_data_shared =
snapshot_data_managed->get(); snapshot_data_managed->get();
// Enter the realm. // Deserialize the snapshot in the specified Realm.
Local<Context> realm = Local<Context>::New(isolate, data->realms_[index]); {
realm->Enter(); PerIsolateData::ExplicitRealmScope realm_scope(data, index);
int previous_index = data->realm_current_; i::WebSnapshotDeserializer deserializer(isolate);
data->realm_current_ = data->realm_switch_ = index; bool success = deserializer.UseWebSnapshot(
// Deserialize the snapshot. snapshot_data_shared->buffer, snapshot_data_shared->buffer_size);
i::WebSnapshotDeserializer deserializer(isolate); args.GetReturnValue().Set(success);
bool success = deserializer.UseWebSnapshot(snapshot_data_shared->buffer, }
snapshot_data_shared->buffer_size);
args.GetReturnValue().Set(success);
realm->Exit();
data->realm_current_ = data->realm_switch_ = previous_index;
} }
void Shell::LogGetAndStop(const v8::FunctionCallbackInfo<v8::Value>& args) { void Shell::LogGetAndStop(const v8::FunctionCallbackInfo<v8::Value>& args) {
......
...@@ -254,6 +254,22 @@ class PerIsolateData { ...@@ -254,6 +254,22 @@ class PerIsolateData {
PerIsolateData* data_; PerIsolateData* data_;
}; };
// Contrary to RealmScope (which creates a new Realm), ExplicitRealmScope
// allows for entering an existing Realm, as specified by its index.
class V8_NODISCARD ExplicitRealmScope {
public:
explicit ExplicitRealmScope(PerIsolateData* data, int index);
~ExplicitRealmScope();
Local<Context> context() const;
private:
PerIsolateData* data_;
Local<Context> realm_;
int index_;
int previous_index_;
};
inline void SetTimeout(Local<Function> callback, Local<Context> context); inline void SetTimeout(Local<Function> callback, Local<Context> context);
inline MaybeLocal<Function> GetTimeoutCallback(); inline MaybeLocal<Function> GetTimeoutCallback();
inline MaybeLocal<Context> GetTimeoutContext(); inline MaybeLocal<Context> GetTimeoutContext();
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function TestExplicitRealmScope() {
const r1 = Realm.create();
Realm.eval(r1, 'globalThis.foo = 42;');
const foo1 = Realm.eval(r1, 'globalThis.foo;');
assertEquals(42, foo1);
const r2 = Realm.create();
const foo2 = Realm.eval(r2, 'globalThis.foo;');
assertEquals(undefined, foo2);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment