diff --git a/include/v8.h b/include/v8.h index 3dafc49c27..c4256efbec 100644 --- a/include/v8.h +++ b/include/v8.h @@ -4921,6 +4921,7 @@ class V8_EXPORT External : public Value { F(ArrayProto_forEach, array_for_each_iterator) \ F(ArrayProto_keys, array_keys_iterator) \ F(ArrayProto_values, array_values_iterator) \ + F(ErrorPrototype, initial_error_prototype) \ F(IteratorPrototype, initial_iterator_prototype) enum Intrinsic { diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 819bb947a3..bda60456ef 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1170,6 +1170,7 @@ static void InstallError(Isolate* isolate, Handle global, SimpleInstallFunction(prototype, factory->toString_string(), Builtins::kErrorPrototypeToString, 0, true); isolate->native_context()->set_error_to_string(*to_string_fun); + isolate->native_context()->set_initial_error_prototype(*prototype); } else { DCHECK(isolate->native_context()->error_to_string()->IsJSFunction()); diff --git a/src/contexts.h b/src/contexts.h index 82a685fbbe..9064043855 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -254,6 +254,7 @@ enum ContextLookupFlags { V(INITIAL_ARRAY_ITERATOR_PROTOTYPE_MAP_INDEX, Map, \ initial_array_iterator_prototype_map) \ V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \ + V(INITIAL_ERROR_PROTOTYPE_INDEX, JSObject, initial_error_prototype) \ V(INITIAL_GENERATOR_PROTOTYPE_INDEX, JSObject, initial_generator_prototype) \ V(INITIAL_ASYNC_GENERATOR_PROTOTYPE_INDEX, JSObject, \ initial_async_generator_prototype) \ diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 607c8e7fd4..da71038270 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -26215,6 +26215,76 @@ TEST(TemplateIteratorPrototypeIntrinsics) { } } +TEST(TemplateErrorPrototypeIntrinsics) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + LocalContext env; + + // Object templates. + { + Local object_template = v8::ObjectTemplate::New(isolate); + object_template->SetIntrinsicDataProperty(v8_str("error_proto"), + v8::kErrorPrototype); + Local object = + object_template->NewInstance(env.local()).ToLocalChecked(); + CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust()); + ExpectTrue("obj.error_proto === Error.prototype"); + Local error = v8::Exception::Error(v8_str("error message")); + CHECK(env->Global()->Set(env.local(), v8_str("err"), error).FromJust()); + ExpectTrue("obj.error_proto === Object.getPrototypeOf(err)"); + } + // Setting %ErrorPrototype% on the function object's prototype template. + { + Local func_template = v8::FunctionTemplate::New(isolate); + func_template->PrototypeTemplate()->SetIntrinsicDataProperty( + v8_str("error_proto"), v8::kErrorPrototype); + Local func1 = + func_template->GetFunction(env.local()).ToLocalChecked(); + CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust()); + Local func2 = + func_template->GetFunction(env.local()).ToLocalChecked(); + CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust()); + ExpectTrue("func1.prototype.error_proto === Error.prototype"); + ExpectTrue("func2.prototype.error_proto === Error.prototype"); + ExpectTrue("func1.prototype.error_proto === func2.prototype.error_proto"); + + Local instance1 = func1->NewInstance(env.local()).ToLocalChecked(); + CHECK(env->Global() + ->Set(env.local(), v8_str("instance1"), instance1) + .FromJust()); + ExpectFalse("instance1.hasOwnProperty('error_proto')"); + ExpectTrue("'error_proto' in instance1.__proto__"); + ExpectTrue("instance1.error_proto === Error.prototype"); + } + // Put %ErrorPrototype% in a function object's inheritance chain. + { + Local parent_template = + v8::FunctionTemplate::New(isolate); + parent_template->RemovePrototype(); // Remove so there is no name clash. + parent_template->SetIntrinsicDataProperty(v8_str("prototype"), + v8::kErrorPrototype); + Local func_template = v8::FunctionTemplate::New(isolate); + func_template->Inherit(parent_template); + + Local func = + func_template->GetFunction(env.local()).ToLocalChecked(); + CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust()); + ExpectTrue("func.prototype.__proto__ === Error.prototype"); + + Local func_instance = + func->NewInstance(env.local()).ToLocalChecked(); + CHECK(env->Global() + ->Set(env.local(), v8_str("instance"), func_instance) + .FromJust()); + ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype"); + // Now let's check if %ErrorPrototype% properties are in the instance. + ExpectTrue("'constructor' in instance"); + ExpectTrue("'message' in instance"); + ExpectTrue("'name' in instance"); + ExpectTrue("'toString' in instance"); + } +} + TEST(ObjectTemplateArrayProtoIntrinsics) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate);