[runtime] Mark old JSGlobalProxy's map as unstable when an iframe navigates away.
This CL also introduces Realm.navigate(i). BUG=chromium:683667 Change-Id: I9227292ea3a575f34367e82fc6297d234d3eecae Reviewed-on: https://chromium-review.googlesource.com/447638 Commit-Queue: Igor Sheludko <ishell@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#43494}
This commit is contained in:
parent
497dff7809
commit
1c7f83980e
59
src/d8.cc
59
src/d8.cc
@ -857,20 +857,24 @@ void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
}
|
||||
|
||||
MaybeLocal<Context> Shell::CreateRealm(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args, int index,
|
||||
v8::MaybeLocal<Value> global_object) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
TryCatch try_catch(isolate);
|
||||
PerIsolateData* data = PerIsolateData::Get(isolate);
|
||||
Global<Context>* old_realms = data->realms_;
|
||||
int index = data->realm_count_;
|
||||
data->realms_ = new Global<Context>[++data->realm_count_];
|
||||
for (int i = 0; i < index; ++i) {
|
||||
data->realms_[i].Reset(isolate, old_realms[i]);
|
||||
old_realms[i].Reset();
|
||||
if (index < 0) {
|
||||
Global<Context>* old_realms = data->realms_;
|
||||
index = data->realm_count_;
|
||||
data->realms_ = new Global<Context>[++data->realm_count_];
|
||||
for (int i = 0; i < index; ++i) {
|
||||
data->realms_[i].Reset(isolate, old_realms[i]);
|
||||
old_realms[i].Reset();
|
||||
}
|
||||
delete[] old_realms;
|
||||
}
|
||||
delete[] old_realms;
|
||||
Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
|
||||
Local<Context> context = Context::New(isolate, NULL, global_template);
|
||||
Local<Context> context =
|
||||
Context::New(isolate, NULL, global_template, global_object);
|
||||
if (context.IsEmpty()) {
|
||||
DCHECK(try_catch.HasCaught());
|
||||
try_catch.ReThrow();
|
||||
@ -882,10 +886,20 @@ MaybeLocal<Context> Shell::CreateRealm(
|
||||
return context;
|
||||
}
|
||||
|
||||
void Shell::DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
int index) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
PerIsolateData* data = PerIsolateData::Get(isolate);
|
||||
DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
|
||||
data->realms_[index].Reset();
|
||||
isolate->ContextDisposedNotification();
|
||||
isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
|
||||
}
|
||||
|
||||
// Realm.create() creates a new realm with a distinct security token
|
||||
// and returns its index.
|
||||
void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
CreateRealm(args);
|
||||
CreateRealm(args, -1, v8::MaybeLocal<Value>());
|
||||
}
|
||||
|
||||
// Realm.createAllowCrossRealmAccess() creates a new realm with the same
|
||||
@ -893,12 +907,26 @@ void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
void Shell::RealmCreateAllowCrossRealmAccess(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Local<Context> context;
|
||||
if (CreateRealm(args).ToLocal(&context)) {
|
||||
if (CreateRealm(args, -1, v8::MaybeLocal<Value>()).ToLocal(&context)) {
|
||||
context->SetSecurityToken(
|
||||
args.GetIsolate()->GetEnteredContext()->GetSecurityToken());
|
||||
}
|
||||
}
|
||||
|
||||
// Realm.navigate(i) creates a new realm with a distinct security token
|
||||
// in place of realm i.
|
||||
void Shell::RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
PerIsolateData* data = PerIsolateData::Get(isolate);
|
||||
int index = data->RealmIndexOrThrow(args, 0);
|
||||
if (index == -1) return;
|
||||
|
||||
Local<Context> context = Local<Context>::New(isolate, data->realms_[index]);
|
||||
v8::MaybeLocal<Value> global_object = context->Global();
|
||||
DisposeRealm(args, index);
|
||||
CreateRealm(args, index, global_object);
|
||||
}
|
||||
|
||||
// Realm.dispose(i) disposes the reference to the realm i.
|
||||
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
@ -910,10 +938,7 @@ void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Throw(args.GetIsolate(), "Invalid realm index");
|
||||
return;
|
||||
}
|
||||
DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
|
||||
data->realms_[index].Reset();
|
||||
isolate->ContextDisposedNotification();
|
||||
isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
|
||||
DisposeRealm(args, index);
|
||||
}
|
||||
|
||||
|
||||
@ -1480,6 +1505,10 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
|
||||
NewStringType::kNormal)
|
||||
.ToLocalChecked(),
|
||||
FunctionTemplate::New(isolate, RealmCreateAllowCrossRealmAccess));
|
||||
realm_template->Set(
|
||||
String::NewFromUtf8(isolate, "navigate", NewStringType::kNormal)
|
||||
.ToLocalChecked(),
|
||||
FunctionTemplate::New(isolate, RealmNavigate));
|
||||
realm_template->Set(
|
||||
String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
|
||||
.ToLocalChecked(),
|
||||
|
6
src/d8.h
6
src/d8.h
@ -377,6 +377,7 @@ class Shell : public i::AllStatic {
|
||||
static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RealmCreateAllowCrossRealmAccess(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
@ -475,7 +476,10 @@ class Shell : public i::AllStatic {
|
||||
static bool SetOptions(int argc, char* argv[]);
|
||||
static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
|
||||
static MaybeLocal<Context> CreateRealm(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args, int index,
|
||||
v8::MaybeLocal<Value> global_object);
|
||||
static void DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
int index);
|
||||
static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Context> context,
|
||||
const std::string& file_name);
|
||||
};
|
||||
|
@ -2330,6 +2330,7 @@ void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
|
||||
map->set_is_prototype_map(true);
|
||||
}
|
||||
JSObject::NotifyMapChange(old_map, map, isolate());
|
||||
old_map->NotifyLeafMapLayoutChange();
|
||||
|
||||
// Check that the already allocated object has the same size and type as
|
||||
// objects allocated using the constructor.
|
||||
|
@ -6270,6 +6270,11 @@ class Map: public HeapObject {
|
||||
Handle<Map> split_map, Handle<DescriptorArray> descriptors,
|
||||
Handle<LayoutDescriptor> full_layout_descriptor);
|
||||
|
||||
// Fires when the layout of an object with a leaf map changes.
|
||||
// This includes adding transitions to the leaf map or changing
|
||||
// the descriptor array.
|
||||
inline void NotifyLeafMapLayoutChange();
|
||||
|
||||
private:
|
||||
// Returns the map that this (root) map transitions to if its elements_kind
|
||||
// is changed to |elements_kind|, or |nullptr| if no such map is cached yet.
|
||||
@ -6323,11 +6328,6 @@ class Map: public HeapObject {
|
||||
Handle<Map> map, ElementsKind elements_kind, int modify_index,
|
||||
PropertyKind kind, PropertyAttributes attributes, const char* reason);
|
||||
|
||||
// Fires when the layout of an object with a leaf map changes.
|
||||
// This includes adding transitions to the leaf map or changing
|
||||
// the descriptor array.
|
||||
inline void NotifyLeafMapLayoutChange();
|
||||
|
||||
void DeprecateTransitionTree();
|
||||
|
||||
void ReplaceDescriptors(DescriptorArray* new_descriptors,
|
||||
|
14
test/mjsunit/regress/regress-crbug-683667.js
Normal file
14
test/mjsunit/regress/regress-crbug-683667.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Flags: --expose-gc --verify-heap
|
||||
|
||||
var realm = Realm.create();
|
||||
var g = Realm.global(realm);
|
||||
var obj = {x: 0, g: g};
|
||||
|
||||
// Navigation will replace JSGlobalObject behind the JSGlobalProxy g and
|
||||
// therefore will change the g's map. The old map must be marked as non-stable.
|
||||
Realm.navigate(realm);
|
||||
gc();
|
Loading…
Reference in New Issue
Block a user