[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
47
src/d8.cc
47
src/d8.cc
@ -857,20 +857,24 @@ void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MaybeLocal<Context> Shell::CreateRealm(
|
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();
|
Isolate* isolate = args.GetIsolate();
|
||||||
TryCatch try_catch(isolate);
|
TryCatch try_catch(isolate);
|
||||||
PerIsolateData* data = PerIsolateData::Get(isolate);
|
PerIsolateData* data = PerIsolateData::Get(isolate);
|
||||||
|
if (index < 0) {
|
||||||
Global<Context>* old_realms = data->realms_;
|
Global<Context>* old_realms = data->realms_;
|
||||||
int index = data->realm_count_;
|
index = data->realm_count_;
|
||||||
data->realms_ = new Global<Context>[++data->realm_count_];
|
data->realms_ = new Global<Context>[++data->realm_count_];
|
||||||
for (int i = 0; i < index; ++i) {
|
for (int i = 0; i < index; ++i) {
|
||||||
data->realms_[i].Reset(isolate, old_realms[i]);
|
data->realms_[i].Reset(isolate, old_realms[i]);
|
||||||
old_realms[i].Reset();
|
old_realms[i].Reset();
|
||||||
}
|
}
|
||||||
delete[] old_realms;
|
delete[] old_realms;
|
||||||
|
}
|
||||||
Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
|
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()) {
|
if (context.IsEmpty()) {
|
||||||
DCHECK(try_catch.HasCaught());
|
DCHECK(try_catch.HasCaught());
|
||||||
try_catch.ReThrow();
|
try_catch.ReThrow();
|
||||||
@ -882,10 +886,20 @@ MaybeLocal<Context> Shell::CreateRealm(
|
|||||||
return context;
|
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
|
// Realm.create() creates a new realm with a distinct security token
|
||||||
// and returns its index.
|
// and returns its index.
|
||||||
void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
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
|
// 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(
|
void Shell::RealmCreateAllowCrossRealmAccess(
|
||||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||||
Local<Context> context;
|
Local<Context> context;
|
||||||
if (CreateRealm(args).ToLocal(&context)) {
|
if (CreateRealm(args, -1, v8::MaybeLocal<Value>()).ToLocal(&context)) {
|
||||||
context->SetSecurityToken(
|
context->SetSecurityToken(
|
||||||
args.GetIsolate()->GetEnteredContext()->GetSecurityToken());
|
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.
|
// Realm.dispose(i) disposes the reference to the realm i.
|
||||||
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||||
Isolate* isolate = args.GetIsolate();
|
Isolate* isolate = args.GetIsolate();
|
||||||
@ -910,10 +938,7 @@ void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||||||
Throw(args.GetIsolate(), "Invalid realm index");
|
Throw(args.GetIsolate(), "Invalid realm index");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
|
DisposeRealm(args, index);
|
||||||
data->realms_[index].Reset();
|
|
||||||
isolate->ContextDisposedNotification();
|
|
||||||
isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1480,6 +1505,10 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
|
|||||||
NewStringType::kNormal)
|
NewStringType::kNormal)
|
||||||
.ToLocalChecked(),
|
.ToLocalChecked(),
|
||||||
FunctionTemplate::New(isolate, RealmCreateAllowCrossRealmAccess));
|
FunctionTemplate::New(isolate, RealmCreateAllowCrossRealmAccess));
|
||||||
|
realm_template->Set(
|
||||||
|
String::NewFromUtf8(isolate, "navigate", NewStringType::kNormal)
|
||||||
|
.ToLocalChecked(),
|
||||||
|
FunctionTemplate::New(isolate, RealmNavigate));
|
||||||
realm_template->Set(
|
realm_template->Set(
|
||||||
String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
|
String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
|
||||||
.ToLocalChecked(),
|
.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 RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void RealmGlobal(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 RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
|
static void RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void RealmCreateAllowCrossRealmAccess(
|
static void RealmCreateAllowCrossRealmAccess(
|
||||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void RealmDispose(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 bool SetOptions(int argc, char* argv[]);
|
||||||
static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
|
static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
|
||||||
static MaybeLocal<Context> CreateRealm(
|
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,
|
static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Context> context,
|
||||||
const std::string& file_name);
|
const std::string& file_name);
|
||||||
};
|
};
|
||||||
|
@ -2330,6 +2330,7 @@ void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
|
|||||||
map->set_is_prototype_map(true);
|
map->set_is_prototype_map(true);
|
||||||
}
|
}
|
||||||
JSObject::NotifyMapChange(old_map, map, isolate());
|
JSObject::NotifyMapChange(old_map, map, isolate());
|
||||||
|
old_map->NotifyLeafMapLayoutChange();
|
||||||
|
|
||||||
// Check that the already allocated object has the same size and type as
|
// Check that the already allocated object has the same size and type as
|
||||||
// objects allocated using the constructor.
|
// objects allocated using the constructor.
|
||||||
|
@ -6270,6 +6270,11 @@ class Map: public HeapObject {
|
|||||||
Handle<Map> split_map, Handle<DescriptorArray> descriptors,
|
Handle<Map> split_map, Handle<DescriptorArray> descriptors,
|
||||||
Handle<LayoutDescriptor> full_layout_descriptor);
|
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:
|
private:
|
||||||
// Returns the map that this (root) map transitions to if its elements_kind
|
// 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.
|
// 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,
|
Handle<Map> map, ElementsKind elements_kind, int modify_index,
|
||||||
PropertyKind kind, PropertyAttributes attributes, const char* reason);
|
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 DeprecateTransitionTree();
|
||||||
|
|
||||||
void ReplaceDescriptors(DescriptorArray* new_descriptors,
|
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