1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/api-natives.h" 6 7 #include "src/api.h" 8 #include "src/isolate-inl.h" 9 #include "src/lookup.h" 10 #include "src/messages.h" 11 12 namespace v8 { 13 namespace internal { 14 15 16 namespace { 17 18 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, 19 Handle<ObjectTemplateInfo> data, 20 Handle<JSReceiver> new_target, 21 bool is_hidden_prototype); 22 23 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, 24 Handle<FunctionTemplateInfo> data, 25 Handle<Name> name = Handle<Name>()); 26 27 28 MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, 29 Handle<Name> name = Handle<Name>()) { 30 if (data->IsFunctionTemplateInfo()) { 31 return InstantiateFunction(isolate, 32 Handle<FunctionTemplateInfo>::cast(data), name); 33 } else if (data->IsObjectTemplateInfo()) { 34 return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data), 35 Handle<JSReceiver>(), false); 36 } else { 37 return data; 38 } 39 } 40 41 MaybeHandle<Object> DefineAccessorProperty( 42 Isolate* isolate, Handle<JSObject> object, Handle<Name> name, 43 Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes, 44 bool force_instantiate) { 45 DCHECK(!getter->IsFunctionTemplateInfo() || 46 !FunctionTemplateInfo::cast(*getter)->do_not_cache()); 47 DCHECK(!setter->IsFunctionTemplateInfo() || 48 !FunctionTemplateInfo::cast(*setter)->do_not_cache()); 49 if (force_instantiate) { 50 if (getter->IsFunctionTemplateInfo()) { 51 ASSIGN_RETURN_ON_EXCEPTION( 52 isolate, getter, 53 InstantiateFunction(isolate, 54 Handle<FunctionTemplateInfo>::cast(getter)), 55 Object); 56 } 57 if (setter->IsFunctionTemplateInfo()) { 58 ASSIGN_RETURN_ON_EXCEPTION( 59 isolate, setter, 60 InstantiateFunction(isolate, 61 Handle<FunctionTemplateInfo>::cast(setter)), 62 Object); 63 } 64 } 65 RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter, 66 setter, attributes), 67 Object); 68 return object; 69 } 70 71 72 MaybeHandle<Object> DefineDataProperty(Isolate* isolate, 73 Handle<JSObject> object, 74 Handle<Name> name, 75 Handle<Object> prop_data, 76 PropertyAttributes attributes) { 77 Handle<Object> value; 78 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, 79 Instantiate(isolate, prop_data, name), Object); 80 81 LookupIterator it = LookupIterator::PropertyOrElement( 82 isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 83 84 #ifdef DEBUG 85 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 86 DCHECK(maybe.IsJust()); 87 if (it.IsFound()) { 88 THROW_NEW_ERROR( 89 isolate, 90 NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name), 91 Object); 92 } 93 #endif 94 95 MAYBE_RETURN_NULL( 96 Object::AddDataProperty(&it, value, attributes, Object::THROW_ON_ERROR, 97 Object::CERTAINLY_NOT_STORE_FROM_KEYED)); 98 return value; 99 } 100 101 102 void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) { 103 Handle<Map> old_map(object->map()); 104 // Copy map so it won't interfere constructor's initial map. 105 Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks"); 106 new_map->set_is_access_check_needed(false); 107 JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map); 108 } 109 110 111 void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) { 112 Handle<Map> old_map(object->map()); 113 // Copy map so it won't interfere constructor's initial map. 114 Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks"); 115 new_map->set_is_access_check_needed(true); 116 JSObject::MigrateToMap(object, new_map); 117 } 118 119 120 class AccessCheckDisableScope { 121 public: 122 AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj) 123 : isolate_(isolate), 124 disabled_(obj->map()->is_access_check_needed()), 125 obj_(obj) { 126 if (disabled_) { 127 DisableAccessChecks(isolate_, obj_); 128 } 129 } 130 ~AccessCheckDisableScope() { 131 if (disabled_) { 132 EnableAccessChecks(isolate_, obj_); 133 } 134 } 135 136 private: 137 Isolate* isolate_; 138 const bool disabled_; 139 Handle<JSObject> obj_; 140 }; 141 142 143 Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) { 144 Handle<Context> native_context = isolate->native_context(); 145 DCHECK(!native_context.is_null()); 146 switch (intrinsic) { 147 #define GET_INTRINSIC_VALUE(name, iname) \ 148 case v8::k##name: \ 149 return native_context->iname(); 150 V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE) 151 #undef GET_INTRINSIC_VALUE 152 } 153 return nullptr; 154 } 155 156 // Returns parent function template or null. 157 FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) { 158 Object* parent = data->parent_template(); 159 return parent->IsUndefined(data->GetIsolate()) 160 ? nullptr 161 : FunctionTemplateInfo::cast(parent); 162 } 163 164 // Starting from given object template's constructor walk up the inheritance 165 // chain till a function template that has an instance template is found. 166 ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) { 167 Object* maybe_ctor = data->constructor(); 168 Isolate* isolate = data->GetIsolate(); 169 if (maybe_ctor->IsUndefined(isolate)) return nullptr; 170 FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor); 171 while (true) { 172 ctor = GetParent(ctor); 173 if (ctor == nullptr) return nullptr; 174 Object* maybe_obj = ctor->instance_template(); 175 if (!maybe_obj->IsUndefined(isolate)) { 176 return ObjectTemplateInfo::cast(maybe_obj); 177 } 178 } 179 } 180 181 template <typename TemplateInfoT> 182 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, 183 Handle<TemplateInfoT> data, 184 bool is_hidden_prototype) { 185 HandleScope scope(isolate); 186 // Disable access checks while instantiating the object. 187 AccessCheckDisableScope access_check_scope(isolate, obj); 188 189 // Walk the inheritance chain and copy all accessors to current object. 190 int max_number_of_properties = 0; 191 TemplateInfoT* info = *data; 192 while (info != nullptr) { 193 if (!info->property_accessors()->IsUndefined(isolate)) { 194 Object* props = info->property_accessors(); 195 if (!props->IsUndefined(isolate)) { 196 Handle<Object> props_handle(props, isolate); 197 NeanderArray props_array(props_handle); 198 max_number_of_properties += props_array.length(); 199 } 200 } 201 info = GetParent(info); 202 } 203 204 if (max_number_of_properties > 0) { 205 int valid_descriptors = 0; 206 // Use a temporary FixedArray to accumulate unique accessors. 207 Handle<FixedArray> array = 208 isolate->factory()->NewFixedArray(max_number_of_properties); 209 210 info = *data; 211 while (info != nullptr) { 212 // Accumulate accessors. 213 if (!info->property_accessors()->IsUndefined(isolate)) { 214 Handle<Object> props(info->property_accessors(), isolate); 215 valid_descriptors = 216 AccessorInfo::AppendUnique(props, array, valid_descriptors); 217 } 218 info = GetParent(info); 219 } 220 221 // Install accumulated accessors. 222 for (int i = 0; i < valid_descriptors; i++) { 223 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i))); 224 JSObject::SetAccessor(obj, accessor).Assert(); 225 } 226 } 227 228 auto property_list = handle(data->property_list(), isolate); 229 if (property_list->IsUndefined(isolate)) return obj; 230 // TODO(dcarney): just use a FixedArray here. 231 NeanderArray properties(property_list); 232 if (properties.length() == 0) return obj; 233 234 int i = 0; 235 for (int c = 0; c < data->number_of_properties(); c++) { 236 auto name = handle(Name::cast(properties.get(i++)), isolate); 237 auto bit = handle(properties.get(i++), isolate); 238 if (bit->IsSmi()) { 239 PropertyDetails details(Smi::cast(*bit)); 240 PropertyAttributes attributes = details.attributes(); 241 PropertyKind kind = details.kind(); 242 243 if (kind == kData) { 244 auto prop_data = handle(properties.get(i++), isolate); 245 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, 246 prop_data, attributes), 247 JSObject); 248 } else { 249 auto getter = handle(properties.get(i++), isolate); 250 auto setter = handle(properties.get(i++), isolate); 251 RETURN_ON_EXCEPTION( 252 isolate, DefineAccessorProperty(isolate, obj, name, getter, setter, 253 attributes, is_hidden_prototype), 254 JSObject); 255 } 256 } else { 257 // Intrinsic data property --- Get appropriate value from the current 258 // context. 259 PropertyDetails details(Smi::cast(properties.get(i++))); 260 PropertyAttributes attributes = details.attributes(); 261 DCHECK_EQ(kData, details.kind()); 262 263 v8::Intrinsic intrinsic = 264 static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value()); 265 auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate); 266 267 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, 268 prop_data, attributes), 269 JSObject); 270 } 271 } 272 return obj; 273 } 274 275 void CacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number, 276 Handle<JSObject> object) { 277 auto cache = isolate->template_instantiations_cache(); 278 auto new_cache = 279 UnseededNumberDictionary::AtNumberPut(cache, serial_number, object); 280 isolate->native_context()->set_template_instantiations_cache(*new_cache); 281 } 282 283 void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) { 284 auto cache = isolate->template_instantiations_cache(); 285 int entry = cache->FindEntry(serial_number); 286 DCHECK(entry != UnseededNumberDictionary::kNotFound); 287 Handle<Object> result = 288 UnseededNumberDictionary::DeleteProperty(cache, entry); 289 USE(result); 290 DCHECK(result->IsTrue(isolate)); 291 auto new_cache = UnseededNumberDictionary::Shrink(cache, entry); 292 isolate->native_context()->set_template_instantiations_cache(*new_cache); 293 } 294 295 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, 296 Handle<ObjectTemplateInfo> info, 297 Handle<JSReceiver> new_target, 298 bool is_hidden_prototype) { 299 Handle<JSFunction> constructor; 300 uint32_t serial_number = 301 static_cast<uint32_t>(Smi::cast(info->serial_number())->value()); 302 if (!new_target.is_null()) { 303 if (new_target->IsJSFunction() && 304 JSFunction::cast(*new_target)->shared()->function_data() == 305 info->constructor() && 306 JSFunction::cast(*new_target)->context()->native_context() == 307 isolate->context()->native_context()) { 308 constructor = Handle<JSFunction>::cast(new_target); 309 } else { 310 // Disable caching for subclass instantiation. 311 serial_number = 0; 312 } 313 } 314 // Fast path. 315 Handle<JSObject> result; 316 if (serial_number) { 317 // Probe cache. 318 auto cache = isolate->template_instantiations_cache(); 319 int entry = cache->FindEntry(serial_number); 320 if (entry != UnseededNumberDictionary::kNotFound) { 321 Object* boilerplate = cache->ValueAt(entry); 322 result = handle(JSObject::cast(boilerplate), isolate); 323 return isolate->factory()->CopyJSObject(result); 324 } 325 } 326 // Enter a new scope. Recursion could otherwise create a lot of handles. 327 HandleScope scope(isolate); 328 329 if (constructor.is_null()) { 330 Handle<Object> cons(info->constructor(), isolate); 331 if (cons->IsUndefined(isolate)) { 332 constructor = isolate->object_function(); 333 } else { 334 auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons); 335 ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor, 336 InstantiateFunction(isolate, cons_templ), 337 JSObject); 338 } 339 340 if (new_target.is_null()) new_target = constructor; 341 } 342 343 Handle<JSObject> object; 344 ASSIGN_RETURN_ON_EXCEPTION(isolate, object, 345 JSObject::New(constructor, new_target), JSObject); 346 ASSIGN_RETURN_ON_EXCEPTION( 347 isolate, result, 348 ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); 349 // TODO(dcarney): is this necessary? 350 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); 351 352 if (serial_number) { 353 CacheTemplateInstantiation(isolate, serial_number, result); 354 result = isolate->factory()->CopyJSObject(result); 355 } 356 return scope.CloseAndEscape(result); 357 } 358 359 360 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, 361 Handle<FunctionTemplateInfo> data, 362 Handle<Name> name) { 363 uint32_t serial_number = 364 static_cast<uint32_t>(Smi::cast(data->serial_number())->value()); 365 if (serial_number) { 366 // Probe cache. 367 auto cache = isolate->template_instantiations_cache(); 368 int entry = cache->FindEntry(serial_number); 369 if (entry != UnseededNumberDictionary::kNotFound) { 370 Object* element = cache->ValueAt(entry); 371 return handle(JSFunction::cast(element), isolate); 372 } 373 } 374 // Enter a new scope. Recursion could otherwise create a lot of handles. 375 HandleScope scope(isolate); 376 Handle<JSObject> prototype; 377 if (!data->remove_prototype()) { 378 auto prototype_templ = handle(data->prototype_template(), isolate); 379 if (prototype_templ->IsUndefined(isolate)) { 380 prototype = isolate->factory()->NewJSObject(isolate->object_function()); 381 } else { 382 ASSIGN_RETURN_ON_EXCEPTION( 383 isolate, prototype, 384 InstantiateObject(isolate, 385 Handle<ObjectTemplateInfo>::cast(prototype_templ), 386 Handle<JSReceiver>(), data->hidden_prototype()), 387 JSFunction); 388 } 389 auto parent = handle(data->parent_template(), isolate); 390 if (!parent->IsUndefined(isolate)) { 391 Handle<JSFunction> parent_instance; 392 ASSIGN_RETURN_ON_EXCEPTION( 393 isolate, parent_instance, 394 InstantiateFunction(isolate, 395 Handle<FunctionTemplateInfo>::cast(parent)), 396 JSFunction); 397 // TODO(dcarney): decide what to do here. 398 Handle<Object> parent_prototype; 399 ASSIGN_RETURN_ON_EXCEPTION( 400 isolate, parent_prototype, 401 JSObject::GetProperty(parent_instance, 402 isolate->factory()->prototype_string()), 403 JSFunction); 404 MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false, 405 Object::THROW_ON_ERROR), 406 MaybeHandle<JSFunction>()); 407 } 408 } 409 auto function = ApiNatives::CreateApiFunction( 410 isolate, data, prototype, ApiNatives::JavaScriptObjectType); 411 if (!name.is_null() && name->IsString()) { 412 function->shared()->set_name(*name); 413 } 414 if (serial_number) { 415 // Cache the function. 416 CacheTemplateInstantiation(isolate, serial_number, function); 417 } 418 auto result = 419 ConfigureInstance(isolate, function, data, data->hidden_prototype()); 420 if (result.is_null()) { 421 // Uncache on error. 422 if (serial_number) { 423 UncacheTemplateInstantiation(isolate, serial_number); 424 } 425 return MaybeHandle<JSFunction>(); 426 } 427 return scope.CloseAndEscape(function); 428 } 429 430 431 class InvokeScope { 432 public: 433 explicit InvokeScope(Isolate* isolate) 434 : isolate_(isolate), save_context_(isolate) {} 435 ~InvokeScope() { 436 bool has_exception = isolate_->has_pending_exception(); 437 if (has_exception) { 438 isolate_->ReportPendingMessages(); 439 } else { 440 isolate_->clear_pending_message(); 441 } 442 } 443 444 private: 445 Isolate* isolate_; 446 SaveContext save_context_; 447 }; 448 449 450 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ, 451 int length, Handle<Object>* data) { 452 auto list = handle(templ->property_list(), isolate); 453 if (list->IsUndefined(isolate)) { 454 list = NeanderArray(isolate).value(); 455 templ->set_property_list(*list); 456 } 457 templ->set_number_of_properties(templ->number_of_properties() + 1); 458 NeanderArray array(list); 459 for (int i = 0; i < length; i++) { 460 Handle<Object> value = 461 data[i].is_null() 462 ? Handle<Object>::cast(isolate->factory()->undefined_value()) 463 : data[i]; 464 array.add(isolate, value); 465 } 466 } 467 468 } // namespace 469 470 471 MaybeHandle<JSFunction> ApiNatives::InstantiateFunction( 472 Handle<FunctionTemplateInfo> data) { 473 Isolate* isolate = data->GetIsolate(); 474 InvokeScope invoke_scope(isolate); 475 return ::v8::internal::InstantiateFunction(isolate, data); 476 } 477 478 MaybeHandle<JSObject> ApiNatives::InstantiateObject( 479 Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) { 480 Isolate* isolate = data->GetIsolate(); 481 InvokeScope invoke_scope(isolate); 482 return ::v8::internal::InstantiateObject(isolate, data, new_target, false); 483 } 484 485 486 void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info, 487 Handle<Name> name, Handle<Object> value, 488 PropertyAttributes attributes) { 489 const int kSize = 3; 490 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); 491 auto details_handle = handle(details.AsSmi(), isolate); 492 Handle<Object> data[kSize] = {name, details_handle, value}; 493 AddPropertyToPropertyList(isolate, info, kSize, data); 494 } 495 496 497 void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info, 498 Handle<Name> name, v8::Intrinsic intrinsic, 499 PropertyAttributes attributes) { 500 const int kSize = 4; 501 auto value = handle(Smi::FromInt(intrinsic), isolate); 502 auto intrinsic_marker = isolate->factory()->true_value(); 503 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); 504 auto details_handle = handle(details.AsSmi(), isolate); 505 Handle<Object> data[kSize] = {name, intrinsic_marker, details_handle, value}; 506 AddPropertyToPropertyList(isolate, info, kSize, data); 507 } 508 509 510 void ApiNatives::AddAccessorProperty(Isolate* isolate, 511 Handle<TemplateInfo> info, 512 Handle<Name> name, 513 Handle<FunctionTemplateInfo> getter, 514 Handle<FunctionTemplateInfo> setter, 515 PropertyAttributes attributes) { 516 const int kSize = 4; 517 PropertyDetails details(attributes, ACCESSOR, 0, PropertyCellType::kNoCell); 518 auto details_handle = handle(details.AsSmi(), isolate); 519 Handle<Object> data[kSize] = {name, details_handle, getter, setter}; 520 AddPropertyToPropertyList(isolate, info, kSize, data); 521 } 522 523 524 void ApiNatives::AddNativeDataProperty(Isolate* isolate, 525 Handle<TemplateInfo> info, 526 Handle<AccessorInfo> property) { 527 auto list = handle(info->property_accessors(), isolate); 528 if (list->IsUndefined(isolate)) { 529 list = NeanderArray(isolate).value(); 530 info->set_property_accessors(*list); 531 } 532 NeanderArray array(list); 533 array.add(isolate, property); 534 } 535 536 537 Handle<JSFunction> ApiNatives::CreateApiFunction( 538 Isolate* isolate, Handle<FunctionTemplateInfo> obj, 539 Handle<Object> prototype, ApiInstanceType instance_type) { 540 Handle<SharedFunctionInfo> shared = 541 FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj); 542 Handle<JSFunction> result = 543 isolate->factory()->NewFunctionFromSharedFunctionInfo( 544 shared, isolate->native_context()); 545 546 if (obj->remove_prototype()) { 547 result->set_map(*isolate->sloppy_function_without_prototype_map()); 548 DCHECK(prototype.is_null()); 549 DCHECK(result->shared()->IsApiFunction()); 550 DCHECK(!result->has_initial_map()); 551 DCHECK(!result->has_prototype()); 552 DCHECK(!result->IsConstructor()); 553 return result; 554 } 555 556 // Down from here is only valid for API functions that can be used as a 557 // constructor (don't set the "remove prototype" flag). 558 559 if (obj->read_only_prototype()) { 560 result->set_map(*isolate->sloppy_function_with_readonly_prototype_map()); 561 } 562 563 if (prototype->IsTheHole(isolate)) { 564 prototype = isolate->factory()->NewFunctionPrototype(result); 565 } else { 566 JSObject::AddProperty(Handle<JSObject>::cast(prototype), 567 isolate->factory()->constructor_string(), result, 568 DONT_ENUM); 569 } 570 571 int internal_field_count = 0; 572 if (!obj->instance_template()->IsUndefined(isolate)) { 573 Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>( 574 ObjectTemplateInfo::cast(obj->instance_template())); 575 internal_field_count = 576 Smi::cast(instance_template->internal_field_count())->value(); 577 } 578 579 // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing 580 // JSObject::GetHeaderSize. 581 int instance_size = kPointerSize * internal_field_count; 582 InstanceType type; 583 switch (instance_type) { 584 case JavaScriptObjectType: 585 if (!obj->needs_access_check() && 586 obj->named_property_handler()->IsUndefined(isolate) && 587 obj->indexed_property_handler()->IsUndefined(isolate)) { 588 type = JS_API_OBJECT_TYPE; 589 } else { 590 type = JS_SPECIAL_API_OBJECT_TYPE; 591 } 592 instance_size += JSObject::kHeaderSize; 593 break; 594 case GlobalObjectType: 595 type = JS_GLOBAL_OBJECT_TYPE; 596 instance_size += JSGlobalObject::kSize; 597 break; 598 case GlobalProxyType: 599 type = JS_GLOBAL_PROXY_TYPE; 600 instance_size += JSGlobalProxy::kSize; 601 break; 602 default: 603 UNREACHABLE(); 604 type = JS_OBJECT_TYPE; // Keep the compiler happy. 605 break; 606 } 607 608 Handle<Map> map = 609 isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS); 610 JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype)); 611 612 // Mark as undetectable if needed. 613 if (obj->undetectable()) { 614 map->set_is_undetectable(); 615 } 616 617 // Mark as needs_access_check if needed. 618 if (obj->needs_access_check()) { 619 map->set_is_access_check_needed(true); 620 } 621 622 // Set interceptor information in the map. 623 if (!obj->named_property_handler()->IsUndefined(isolate)) { 624 map->set_has_named_interceptor(); 625 } 626 if (!obj->indexed_property_handler()->IsUndefined(isolate)) { 627 map->set_has_indexed_interceptor(); 628 } 629 630 // Mark instance as callable in the map. 631 if (!obj->instance_call_handler()->IsUndefined(isolate)) { 632 map->set_is_callable(); 633 map->set_is_constructor(true); 634 } 635 636 return result; 637 } 638 639 } // namespace internal 640 } // namespace v8 641