Commit e8adbe78 authored by verwaest's avatar verwaest Committed by Commit bot

Reflect.construct / Proxies: Fall back to intrinsicDefaultProto for non-instance prototypes

Error still to be done, since that's not yet available in the bootstrapper.

BUG=v8:3900, v8:3931, v8:1543, v8:3330
LOG=n

Review URL: https://codereview.chromium.org/1499923002

Cr-Commit-Position: refs/heads/master@{#32662}
parent 931f99b1
......@@ -1028,6 +1028,16 @@ static void SimpleInstallFunction(Handle<JSObject> base, Handle<Name> name,
}
static void InstallWithIntrinsicDefaultProto(Isolate* isolate,
Handle<JSFunction> function,
int context_index) {
Handle<Smi> index(Smi::FromInt(context_index), isolate);
JSObject::AddProperty(
function, isolate->factory()->native_context_index_symbol(), index, NONE);
isolate->native_context()->set(context_index, *function);
}
// This is only called if we are not using snapshots. The equivalent
// work in the snapshot case is done in HookUpGlobalObject.
void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
......@@ -1058,14 +1068,18 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<JSObject> global(native_context()->global_object());
// Install global Function object
Handle<JSFunction> function_function =
InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize,
empty_function, Builtins::kIllegal);
function_function->initial_map()->set_is_callable();
function_function->initial_map()->set_is_constructor(true);
function_function->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
{ // Install global Function object
Handle<JSFunction> function_function =
InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize,
empty_function, Builtins::kIllegal);
function_function->initial_map()->set_is_callable();
function_function->initial_map()->set_is_constructor(true);
function_function->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
InstallWithIntrinsicDefaultProto(isolate, function_function,
Context::FUNCTION_FUNCTION_INDEX);
}
{ // --- A r r a y ---
Handle<JSFunction> array_function =
......@@ -1098,11 +1112,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
initial_map->AppendDescriptor(&d);
}
// array_function is used internally. JS code creating array object should
// search for the 'Array' property on the global object and use that one
// as the constructor. 'Array' property on a global object can be
// overwritten by JS code.
native_context()->set_array_function(*array_function);
InstallWithIntrinsicDefaultProto(isolate, array_function,
Context::ARRAY_FUNCTION_INDEX);
// Cache the array maps, needed by ArrayConstructorStub
CacheInitialJSArrayMaps(native_context(), initial_map);
......@@ -1125,7 +1136,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize,
isolate->initial_object_prototype(),
Builtins::kIllegal);
native_context()->set_number_function(*number_fun);
InstallWithIntrinsicDefaultProto(isolate, number_fun,
Context::NUMBER_FUNCTION_INDEX);
number_fun->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
}
......@@ -1135,7 +1147,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize,
isolate->initial_object_prototype(),
Builtins::kIllegal);
native_context()->set_boolean_function(*boolean_fun);
InstallWithIntrinsicDefaultProto(isolate, boolean_fun,
Context::BOOLEAN_FUNCTION_INDEX);
}
{ // --- S t r i n g ---
......@@ -1146,7 +1159,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
*isolate->builtins()->StringConstructor_ConstructStub());
string_fun->shared()->DontAdaptArguments();
string_fun->shared()->set_length(1);
native_context()->set_string_function(*string_fun);
InstallWithIntrinsicDefaultProto(isolate, string_fun,
Context::STRING_FUNCTION_INDEX);
Handle<Map> string_map =
Handle<Map>(native_context()->string_function()->initial_map());
......@@ -1181,6 +1195,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<JSFunction> date_fun = InstallFunction(
global, "Date", JS_DATE_TYPE, JSDate::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
InstallWithIntrinsicDefaultProto(isolate, date_fun,
Context::DATE_FUNCTION_INDEX);
date_fun->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
}
......@@ -1191,7 +1207,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
isolate->initial_object_prototype(),
Builtins::kIllegal);
native_context()->set_regexp_function(*regexp_fun);
InstallWithIntrinsicDefaultProto(isolate, regexp_fun,
Context::REGEXP_FUNCTION_INDEX);
regexp_fun->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
......@@ -1253,15 +1270,17 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
JSArrayBuffer::kSizeWithInternalFields,
isolate->initial_object_prototype(),
Builtins::kIllegal);
native_context()->set_array_buffer_fun(*array_buffer_fun);
InstallWithIntrinsicDefaultProto(isolate, array_buffer_fun,
Context::ARRAY_BUFFER_FUN_INDEX);
}
{ // -- T y p e d A r r a y s
#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
{ \
Handle<JSFunction> fun; \
InstallTypedArray(#Type "Array", TYPE##_ELEMENTS, &fun); \
native_context()->set_##type##_array_fun(*fun); \
#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
{ \
Handle<JSFunction> fun; \
InstallTypedArray(#Type "Array", TYPE##_ELEMENTS, &fun); \
InstallWithIntrinsicDefaultProto(isolate, fun, \
Context::TYPE##_ARRAY_FUN_INDEX); \
}
TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
#undef INSTALL_TYPED_ARRAY
......@@ -1272,7 +1291,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
JSDataView::kSizeWithInternalFields,
isolate->initial_object_prototype(),
Builtins::kIllegal);
native_context()->set_data_view_fun(*data_view_fun);
InstallWithIntrinsicDefaultProto(isolate, data_view_fun,
Context::DATA_VIEW_FUN_INDEX);
data_view_fun->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
}
......@@ -1281,14 +1301,16 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<JSFunction> js_map_fun = InstallFunction(
global, "Map", JS_MAP_TYPE, JSMap::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
native_context()->set_js_map_fun(*js_map_fun);
InstallWithIntrinsicDefaultProto(isolate, js_map_fun,
Context::JS_MAP_FUN_INDEX);
}
{ // -- S e t
Handle<JSFunction> js_set_fun = InstallFunction(
global, "Set", JS_SET_TYPE, JSSet::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
native_context()->set_js_set_fun(*js_set_fun);
InstallWithIntrinsicDefaultProto(isolate, js_set_fun,
Context::JS_SET_FUN_INDEX);
}
{ // -- I t e r a t o r R e s u l t
......@@ -1313,12 +1335,21 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
native_context()->set_iterator_result_map(*map);
}
// -- W e a k M a p
InstallFunction(global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
// -- W e a k S e t
InstallFunction(global, "WeakSet", JS_WEAK_SET_TYPE, JSWeakSet::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
{ // -- W e a k M a p
Handle<JSFunction> js_weak_map_fun = InstallFunction(
global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
InstallWithIntrinsicDefaultProto(isolate, js_weak_map_fun,
Context::JS_WEAK_MAP_FUN_INDEX);
}
{ // -- W e a k S e t
Handle<JSFunction> js_weak_set_fun = InstallFunction(
global, "WeakSet", JS_WEAK_SET_TYPE, JSWeakSet::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
InstallWithIntrinsicDefaultProto(isolate, js_weak_set_fun,
Context::JS_WEAK_SET_FUN_INDEX);
}
{ // --- sloppy arguments map
// Make sure we can recognize argument objects at runtime.
......@@ -1776,6 +1807,9 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
generator_function_function->initial_map()->set_is_constructor(true);
generator_function_function->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
InstallWithIntrinsicDefaultProto(
isolate, generator_function_function,
Context::GENERATOR_FUNCTION_FUNCTION_INDEX);
}
{ // -- S e t I t e r a t o r
......
......@@ -176,6 +176,7 @@ enum BindingFlags {
V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \
V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
error_message_for_code_gen_from_strings) \
V(ERRORS_THROWN_INDEX, Smi, errors_thrown) \
......@@ -186,6 +187,9 @@ enum BindingFlags {
V(FLOAT32X4_FUNCTION_INDEX, JSFunction, float32x4_function) \
V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \
V(FUNCTION_CACHE_INDEX, ObjectHashTable, function_cache) \
V(FUNCTION_FUNCTION_INDEX, JSFunction, function_function) \
V(GENERATOR_FUNCTION_FUNCTION_INDEX, JSFunction, \
generator_function_function) \
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, generator_object_prototype_map) \
V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \
V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
......@@ -204,6 +208,8 @@ enum BindingFlags {
V(JS_OBJECT_STRONG_MAP_INDEX, Map, js_object_strong_map) \
V(JS_SET_FUN_INDEX, JSFunction, js_set_fun) \
V(JS_SET_MAP_INDEX, Map, js_set_map) \
V(JS_WEAK_MAP_FUN_INDEX, JSFunction, js_weak_map_fun) \
V(JS_WEAK_SET_FUN_INDEX, JSFunction, js_weak_set_fun) \
V(MAP_CACHE_INDEX, Object, map_cache) \
V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \
V(STRING_ITERATOR_MAP_INDEX, Map, string_iterator_map) \
......
......@@ -364,7 +364,8 @@ namespace internal {
V(stack_trace_symbol) \
V(string_iterator_iterated_string_symbol) \
V(string_iterator_next_index_symbol) \
V(uninitialized_symbol)
V(uninitialized_symbol) \
V(native_context_index_symbol)
#define PUBLIC_SYMBOL_LIST(V) \
V(has_instance_symbol, Symbol.hasInstance) \
......
......@@ -4801,7 +4801,7 @@ MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
// static
MaybeHandle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
DCHECK(function->map()->is_constructor());
return handle(function->context()->native_context());
}
......@@ -12744,13 +12744,21 @@ MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
prototype = handle(function->prototype(), isolate);
}
// If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
// correct realm. Rather than directly fetching the .prototype, we fetch the
// constructor that points to the .prototype. This relies on
// constructor.prototype being FROZEN for those constructors.
if (!prototype->IsJSReceiver()) {
Handle<Context> context;
ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
JSReceiver::GetFunctionRealm(new_target), Map);
DCHECK(context->IsNativeContext());
// TODO(verwaest): Use the intrinsicDefaultProto instead.
prototype = handle(context->initial_object_prototype(), isolate);
Handle<Object> maybe_index = JSReceiver::GetDataProperty(
constructor, isolate->factory()->native_context_index_symbol());
int index = maybe_index->IsSmi() ? Smi::cast(*maybe_index)->value()
: Context::OBJECT_FUNCTION_INDEX;
Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)));
prototype = handle(realm_constructor->prototype(), isolate);
}
Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
......
......@@ -7234,7 +7234,7 @@ class JSFunction: public JSObject {
inline JSObject* global_proxy();
inline Context* native_context();
static MaybeHandle<Context> GetFunctionRealm(Handle<JSFunction> function);
static Handle<Context> GetFunctionRealm(Handle<JSFunction> function);
// [code]: The generated code object for this function. Executed
// when the function is invoked, e.g. foo() or new foo(). See
......
......@@ -284,3 +284,94 @@
assertTrue(o.__proto__ === g.prototype);
assertTrue(o.__proto__ !== f.prototype);
})();
(function () {
var realm1 = Realm.create();
var realm2 = Realm.create();
var well_known_intrinsic_constructors = [
"Array",
"ArrayBuffer",
"Boolean",
["DataView", [new ArrayBuffer()]],
"Date",
// "Error",
// "EvalError",
"Float32Array",
"Float64Array",
"Function",
"((function*(){}).constructor)", // GeneratorFunction
"Int8Array",
"Int16Array",
"Int32Array",
"Map",
"Number",
"Object",
// "Promise",
// "RangeError",
// "ReferenceError",
"RegExp",
"Set",
"String",
// "SyntaxError",
// %TypedArray%?
// "TypeError",
"Uint8Array",
"Uint8ClampedArray",
"Uint16Array",
"Uint32Array",
// "URIError",
"WeakMap",
"WeakSet"
];
function getname(v) {
return typeof v === "string" ? v : v[0];
}
function getargs(v) {
return typeof v === "string" ? [] : v[1];
}
function test_intrinsic_prototype(name) {
var own = Realm.eval(realm1, name);
// Ensure that constructor.prototype is non-writable, non-configurable.
var desc = Object.getOwnPropertyDescriptor(own, "prototype");
assertFalse(desc.configurable, name);
assertFalse(desc.writable, name);
}
for (var intrinsic of well_known_intrinsic_constructors) {
test_intrinsic_prototype(getname(intrinsic));
}
function function_with_non_instance_prototype(realm) {
var f = Realm.eval(realm, "(function(){})");
f.prototype = 1;
return f;
}
function test_intrinsic_default(realm, name, args, convert) {
var own = Realm.eval(realm1, name);
var other = Realm.eval(realm, name);
var o = Reflect.construct(
convert(own), args, function_with_non_instance_prototype(realm));
// Ensure the intrisicDefaultProto is fetched from the correct realm.
assertTrue(realm == realm1 || o.__proto__ !== own.prototype, [...arguments]);
assertTrue(o.__proto__ === other.prototype, [...arguments]);
}
function test_all(test, convert) {
for (var intrinsic of well_known_intrinsic_constructors) {
for (var realm of [realm1, realm2]) {
test(realm, getname(intrinsic), getargs(intrinsic), convert);
}
}
}
test_all(test_intrinsic_default, (v)=>v);
test_all(test_intrinsic_default,
(v)=>{ "use strict"; return class extends v {}});
})();
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