| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e774de1 commit 254cb1c
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,6 +17,7 @@ namespace { | |||
| 17 | 17 | ||
| 18 | 18 | MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | |
| 19 | 19 | Handle<ObjectTemplateInfo> data, | |
| 20 | + Handle<JSReceiver> new_target, | ||
| 20 | 21 | bool is_hidden_prototype); | |
| 21 | 22 | ||
| 22 | 23 | MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | |
@@ -31,7 +32,7 @@ MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, | |||
| 31 | 32 | Handle<FunctionTemplateInfo>::cast(data), name); | |
| 32 | 33 | } else if (data->IsObjectTemplateInfo()) { | |
| 33 | 34 | return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data), | |
| 34 | - false); | ||
| 35 | + Handle<JSReceiver>(), false); | ||
| 35 | 36 | } else { | |
| 36 | 37 | return data; | |
| 37 | 38 | } | |
@@ -288,11 +289,25 @@ void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) { | |||
| 288 | 289 | ||
| 289 | 290 | MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | |
| 290 | 291 | Handle<ObjectTemplateInfo> info, | |
| 292 | + Handle<JSReceiver> new_target, | ||
| 291 | 293 | bool is_hidden_prototype) { | |
| 292 | - // Fast path. | ||
| 293 | - Handle<JSObject> result; | ||
| 294 | + Handle<JSFunction> constructor; | ||
| 294 | 295 | uint32_t serial_number = | |
| 295 | 296 | static_cast<uint32_t>(Smi::cast(info->serial_number())->value()); | |
| 297 | + if (!new_target.is_null()) { | ||
| 298 | + if (new_target->IsJSFunction() && | ||
| 299 | + JSFunction::cast(*new_target)->shared()->function_data() == | ||
| 300 | + info->constructor() && | ||
| 301 | + JSFunction::cast(*new_target)->context()->native_context() == | ||
| 302 | + isolate->context()->native_context()) { | ||
| 303 | + constructor = Handle<JSFunction>::cast(new_target); | ||
| 304 | + } else { | ||
| 305 | + // Disable caching for subclass instantiation. | ||
| 306 | + serial_number = 0; | ||
| 307 | + } | ||
| 308 | + } | ||
| 309 | + // Fast path. | ||
| 310 | + Handle<JSObject> result; | ||
| 296 | 311 | if (serial_number) { | |
| 297 | 312 | // Probe cache. | |
| 298 | 313 | auto cache = isolate->template_instantiations_cache(); | |
@@ -305,20 +320,27 @@ MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | |||
| 305 | 320 | } | |
| 306 | 321 | // Enter a new scope. Recursion could otherwise create a lot of handles. | |
| 307 | 322 | HandleScope scope(isolate); | |
| 308 | - auto constructor = handle(info->constructor(), isolate); | ||
| 309 | - Handle<JSFunction> cons; | ||
| 310 | - if (constructor->IsUndefined()) { | ||
| 311 | - cons = isolate->object_function(); | ||
| 312 | - } else { | ||
| 313 | - auto cons_templ = Handle<FunctionTemplateInfo>::cast(constructor); | ||
| 314 | - ASSIGN_RETURN_ON_EXCEPTION( | ||
| 315 | - isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction); | ||
| 323 | + | ||
| 324 | + if (constructor.is_null()) { | ||
| 325 | + Handle<Object> cons(info->constructor(), isolate); | ||
| 326 | + if (cons->IsUndefined()) { | ||
| 327 | + constructor = isolate->object_function(); | ||
| 328 | + } else { | ||
| 329 | + auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons); | ||
| 330 | + ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor, | ||
| 331 | + InstantiateFunction(isolate, cons_templ), | ||
| 332 | + JSObject); | ||
| 333 | + } | ||
| 334 | + | ||
| 335 | + if (new_target.is_null()) new_target = constructor; | ||
| 316 | 336 | } | |
| 317 | - auto object = isolate->factory()->NewJSObject(cons); | ||
| 337 | + | ||
| 338 | + Handle<JSObject> object; | ||
| 339 | + ASSIGN_RETURN_ON_EXCEPTION(isolate, object, | ||
| 340 | + JSObject::New(constructor, new_target), JSObject); | ||
| 318 | 341 | ASSIGN_RETURN_ON_EXCEPTION( | |
| 319 | 342 | isolate, result, | |
| 320 | - ConfigureInstance(isolate, object, info, is_hidden_prototype), | ||
| 321 | - JSFunction); | ||
| 343 | + ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); | ||
| 322 | 344 | // TODO(dcarney): is this necessary? | |
| 323 | 345 | JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); | |
| 324 | 346 | ||
@@ -356,7 +378,7 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | |||
| 356 | 378 | isolate, prototype, | |
| 357 | 379 | InstantiateObject(isolate, | |
| 358 | 380 | Handle<ObjectTemplateInfo>::cast(prototype_templ), | |
| 359 | - data->hidden_prototype()), | ||
| 381 | + Handle<JSReceiver>(), data->hidden_prototype()), | ||
| 360 | 382 | JSFunction); | |
| 361 | 383 | } | |
| 362 | 384 | auto parent = handle(data->parent_template(), isolate); | |
@@ -448,12 +470,11 @@ MaybeHandle<JSFunction> ApiNatives::InstantiateFunction( | |||
| 448 | 470 | return ::v8::internal::InstantiateFunction(isolate, data); | |
| 449 | 471 | } | |
| 450 | 472 | ||
| 451 | - | ||
| 452 | 473 | MaybeHandle<JSObject> ApiNatives::InstantiateObject( | |
| 453 | - Handle<ObjectTemplateInfo> data) { | ||
| 474 | + Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) { | ||
| 454 | 475 | Isolate* isolate = data->GetIsolate(); | |
| 455 | 476 | InvokeScope invoke_scope(isolate); | |
| 456 | - return ::v8::internal::InstantiateObject(isolate, data, false); | ||
| 477 | + return ::v8::internal::InstantiateObject(isolate, data, new_target, false); | ||
| 457 | 478 | } | |
| 458 | 479 | ||
| 459 | 480 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,7 +23,8 @@ class ApiNatives { | |||
| 23 | 23 | Handle<FunctionTemplateInfo> data); | |
| 24 | 24 | ||
| 25 | 25 | MUST_USE_RESULT static MaybeHandle<JSObject> InstantiateObject( | |
| 26 | - Handle<ObjectTemplateInfo> data); | ||
| 26 | + Handle<ObjectTemplateInfo> data, | ||
| 27 | + Handle<JSReceiver> new_target = Handle<JSReceiver>()); | ||
| 27 | 28 | ||
| 28 | 29 | enum ApiInstanceType { | |
| 29 | 30 | JavaScriptObjectType, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4262,9 +4262,11 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( | |||
| 4262 | 4262 | } | |
| 4263 | 4263 | Handle<ObjectTemplateInfo> instance_template( | |
| 4264 | 4264 | ObjectTemplateInfo::cast(fun_data->instance_template()), isolate); | |
| 4265 | - ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver, | ||
| 4266 | - ApiNatives::InstantiateObject(instance_template), | ||
| 4267 | - Object); | ||
| 4265 | + ASSIGN_RETURN_ON_EXCEPTION( | ||
| 4266 | + isolate, receiver, | ||
| 4267 | + ApiNatives::InstantiateObject(instance_template, | ||
| 4268 | + Handle<JSReceiver>::cast(new_target)), | ||
| 4269 | + Object); | ||
| 4268 | 4270 | args[0] = *receiver; | |
| 4269 | 4271 | DCHECK_EQ(*receiver, *args.receiver()); | |
| 4270 | 4272 | } else { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13080,50 +13080,51 @@ namespace { | |||
| 13080 | 13080 | ||
| 13081 | 13081 | bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { | |
| 13082 | 13082 | switch (instance_type) { | |
| 13083 | - case JS_OBJECT_TYPE: | ||
| 13084 | - case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | ||
| 13085 | - case JS_GENERATOR_OBJECT_TYPE: | ||
| 13086 | - case JS_MODULE_TYPE: | ||
| 13087 | - case JS_VALUE_TYPE: | ||
| 13088 | - case JS_DATE_TYPE: | ||
| 13089 | - case JS_ARRAY_TYPE: | ||
| 13090 | - case JS_MESSAGE_OBJECT_TYPE: | ||
| 13091 | 13083 | case JS_ARRAY_BUFFER_TYPE: | |
| 13092 | - case JS_TYPED_ARRAY_TYPE: | ||
| 13084 | + case JS_ARRAY_TYPE: | ||
| 13085 | + case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | ||
| 13093 | 13086 | case JS_DATA_VIEW_TYPE: | |
| 13094 | - case JS_SET_TYPE: | ||
| 13087 | + case JS_DATE_TYPE: | ||
| 13088 | + case JS_FUNCTION_TYPE: | ||
| 13089 | + case JS_GENERATOR_OBJECT_TYPE: | ||
| 13090 | + case JS_MAP_ITERATOR_TYPE: | ||
| 13095 | 13091 | case JS_MAP_TYPE: | |
| 13092 | + case JS_MESSAGE_OBJECT_TYPE: | ||
| 13093 | + case JS_MODULE_TYPE: | ||
| 13094 | + case JS_OBJECT_TYPE: | ||
| 13095 | + case JS_PROMISE_TYPE: | ||
| 13096 | + case JS_REGEXP_TYPE: | ||
| 13096 | 13097 | case JS_SET_ITERATOR_TYPE: | |
| 13097 | - case JS_MAP_ITERATOR_TYPE: | ||
| 13098 | + case JS_SET_TYPE: | ||
| 13099 | + case JS_SPECIAL_API_OBJECT_TYPE: | ||
| 13100 | + case JS_TYPED_ARRAY_TYPE: | ||
| 13101 | + case JS_VALUE_TYPE: | ||
| 13098 | 13102 | case JS_WEAK_MAP_TYPE: | |
| 13099 | 13103 | case JS_WEAK_SET_TYPE: | |
| 13100 | - case JS_PROMISE_TYPE: | ||
| 13101 | - case JS_REGEXP_TYPE: | ||
| 13102 | - case JS_FUNCTION_TYPE: | ||
| 13103 | 13104 | return true; | |
| 13104 | 13105 | ||
| 13105 | - case JS_BOUND_FUNCTION_TYPE: | ||
| 13106 | - case JS_PROXY_TYPE: | ||
| 13107 | - case JS_GLOBAL_PROXY_TYPE: | ||
| 13108 | - case JS_GLOBAL_OBJECT_TYPE: | ||
| 13106 | + case BYTECODE_ARRAY_TYPE: | ||
| 13107 | + case BYTE_ARRAY_TYPE: | ||
| 13108 | + case CELL_TYPE: | ||
| 13109 | + case CODE_TYPE: | ||
| 13110 | + case FILLER_TYPE: | ||
| 13109 | 13111 | case FIXED_ARRAY_TYPE: | |
| 13110 | 13112 | case FIXED_DOUBLE_ARRAY_TYPE: | |
| 13111 | - case ODDBALL_TYPE: | ||
| 13112 | 13113 | case FOREIGN_TYPE: | |
| 13113 | - case MAP_TYPE: | ||
| 13114 | - case CODE_TYPE: | ||
| 13115 | - case CELL_TYPE: | ||
| 13116 | - case PROPERTY_CELL_TYPE: | ||
| 13117 | - case WEAK_CELL_TYPE: | ||
| 13118 | - case SYMBOL_TYPE: | ||
| 13119 | - case BYTECODE_ARRAY_TYPE: | ||
| 13114 | + case FREE_SPACE_TYPE: | ||
| 13120 | 13115 | case HEAP_NUMBER_TYPE: | |
| 13116 | + case JS_BOUND_FUNCTION_TYPE: | ||
| 13117 | + case JS_GLOBAL_OBJECT_TYPE: | ||
| 13118 | + case JS_GLOBAL_PROXY_TYPE: | ||
| 13119 | + case JS_PROXY_TYPE: | ||
| 13120 | + case MAP_TYPE: | ||
| 13121 | 13121 | case MUTABLE_HEAP_NUMBER_TYPE: | |
| 13122 | - case SIMD128_VALUE_TYPE: | ||
| 13123 | - case FILLER_TYPE: | ||
| 13124 | - case BYTE_ARRAY_TYPE: | ||
| 13125 | - case FREE_SPACE_TYPE: | ||
| 13122 | + case ODDBALL_TYPE: | ||
| 13123 | + case PROPERTY_CELL_TYPE: | ||
| 13126 | 13124 | case SHARED_FUNCTION_INFO_TYPE: | |
| 13125 | + case SIMD128_VALUE_TYPE: | ||
| 13126 | + case SYMBOL_TYPE: | ||
| 13127 | + case WEAK_CELL_TYPE: | ||
| 13127 | 13128 | ||
| 13128 | 13129 | #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
| 13129 | 13130 | case FIXED_##TYPE##_ARRAY_TYPE: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2142,6 +2142,95 @@ THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) { | |||
| 2142 | 2142 | Constructor_GetFunction_New); | |
| 2143 | 2143 | } | |
| 2144 | 2144 | ||
| 2145 | + THREADED_TEST(TestObjectTemplateClassInheritance) { | ||
| 2146 | + LocalContext env; | ||
| 2147 | + v8::Isolate* isolate = CcTest::isolate(); | ||
| 2148 | + v8::HandleScope scope(isolate); | ||
| 2149 | + | ||
| 2150 | + Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate); | ||
| 2151 | + fun_A->SetClassName(v8_str("A")); | ||
| 2152 | + | ||
| 2153 | + Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate(); | ||
| 2154 | + templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk); | ||
| 2155 | + templ_A->SetNativeDataProperty(v8_str("rino"), GetRino); | ||
| 2156 | + | ||
| 2157 | + Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate); | ||
| 2158 | + v8::Local<v8::String> class_name = v8_str("B"); | ||
| 2159 | + fun_B->SetClassName(class_name); | ||
| 2160 | + fun_B->Inherit(fun_A); | ||
| 2161 | + | ||
| 2162 | + v8::Local<v8::String> subclass_name = v8_str("C"); | ||
| 2163 | + v8::Local<v8::Object> b_proto; | ||
| 2164 | + v8::Local<v8::Object> c_proto; | ||
| 2165 | + // Perform several iterations to make sure the cache doesn't break | ||
| 2166 | + // subclassing. | ||
| 2167 | + for (int i = 0; i < 3; i++) { | ||
| 2168 | + Local<v8::Function> function_B = | ||
| 2169 | + fun_B->GetFunction(env.local()).ToLocalChecked(); | ||
| 2170 | + if (i == 0) { | ||
| 2171 | + CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust()); | ||
| 2172 | + CompileRun("class C extends B {}"); | ||
| 2173 | + b_proto = | ||
| 2174 | + CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked(); | ||
| 2175 | + c_proto = | ||
| 2176 | + CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked(); | ||
| 2177 | + CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust()); | ||
| 2178 | + } | ||
| 2179 | + Local<v8::Object> instance = | ||
| 2180 | + CompileRun("new C()")->ToObject(env.local()).ToLocalChecked(); | ||
| 2181 | + CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust()); | ||
| 2182 | + | ||
| 2183 | + CHECK(subclass_name->StrictEquals(instance->GetConstructorName())); | ||
| 2184 | + CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust()); | ||
| 2185 | + | ||
| 2186 | + CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust()); | ||
| 2187 | + CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust()); | ||
| 2188 | + } | ||
| 2189 | + } | ||
| 2190 | + | ||
| 2191 | + static void NamedPropertyGetterWhichReturns42( | ||
| 2192 | + Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { | ||
| 2193 | + info.GetReturnValue().Set(v8_num(42)); | ||
| 2194 | + } | ||
| 2195 | + | ||
| 2196 | + THREADED_TEST(TestObjectTemplateReflectConstruct) { | ||
| 2197 | + LocalContext env; | ||
| 2198 | + v8::Isolate* isolate = CcTest::isolate(); | ||
| 2199 | + v8::HandleScope scope(isolate); | ||
| 2200 | + | ||
| 2201 | + Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate); | ||
| 2202 | + fun_B->InstanceTemplate()->SetHandler( | ||
| 2203 | + v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42)); | ||
| 2204 | + v8::Local<v8::String> class_name = v8_str("B"); | ||
| 2205 | + fun_B->SetClassName(class_name); | ||
| 2206 | + | ||
| 2207 | + v8::Local<v8::String> subclass_name = v8_str("C"); | ||
| 2208 | + v8::Local<v8::Object> b_proto; | ||
| 2209 | + v8::Local<v8::Object> c_proto; | ||
| 2210 | + // Perform several iterations to make sure the cache doesn't break | ||
| 2211 | + // subclassing. | ||
| 2212 | + for (int i = 0; i < 3; i++) { | ||
| 2213 | + Local<v8::Function> function_B = | ||
| 2214 | + fun_B->GetFunction(env.local()).ToLocalChecked(); | ||
| 2215 | + if (i == 0) { | ||
| 2216 | + CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust()); | ||
| 2217 | + CompileRun("function C() {}"); | ||
| 2218 | + c_proto = | ||
| 2219 | + CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked(); | ||
| 2220 | + } | ||
| 2221 | + Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)") | ||
| 2222 | + ->ToObject(env.local()) | ||
| 2223 | + .ToLocalChecked(); | ||
| 2224 | + CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust()); | ||
| 2225 | + | ||
| 2226 | + CHECK(subclass_name->StrictEquals(instance->GetConstructorName())); | ||
| 2227 | + CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust()); | ||
| 2228 | + | ||
| 2229 | + CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust()); | ||
| 2230 | + CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust()); | ||
| 2231 | + } | ||
| 2232 | + } | ||
| 2233 | + | ||
| 2145 | 2234 | static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 2146 | 2235 | ApiTestFuzzer::Fuzz(); | |
| 2147 | 2236 | args.GetReturnValue().Set(v8_num(17.2)); | |
@@ -18765,12 +18854,6 @@ TEST(SetterOnConstructorPrototype) { | |||
| 18765 | 18854 | } | |
| 18766 | 18855 | ||
| 18767 | 18856 | ||
| 18768 | - static void NamedPropertyGetterWhichReturns42( | ||
| 18769 | - Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { | ||
| 18770 | - info.GetReturnValue().Set(v8_num(42)); | ||
| 18771 | - } | ||
| 18772 | - | ||
| 18773 | - | ||
| 18774 | 18857 | static void NamedPropertySetterWhichSetsYOnThisTo23( | |
| 18775 | 18858 | Local<Name> name, Local<Value> value, | |
| 18776 | 18859 | const v8::PropertyCallbackInfo<v8::Value>& info) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments