1 // Copyright 2012 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/accessors.h" 6 7 #include "src/api.h" 8 #include "src/contexts.h" 9 #include "src/deoptimizer.h" 10 #include "src/execution.h" 11 #include "src/factory.h" 12 #include "src/frames-inl.h" 13 #include "src/isolate-inl.h" 14 #include "src/list-inl.h" 15 #include "src/messages.h" 16 #include "src/property-details.h" 17 #include "src/prototype.h" 18 19 namespace v8 { 20 namespace internal { 21 22 Handle<AccessorInfo> Accessors::MakeAccessor( 23 Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter, 24 AccessorNameBooleanSetterCallback setter, PropertyAttributes attributes) { 25 Factory* factory = isolate->factory(); 26 Handle<AccessorInfo> info = factory->NewAccessorInfo(); 27 info->set_property_attributes(attributes); 28 info->set_all_can_read(false); 29 info->set_all_can_write(false); 30 info->set_is_special_data_property(true); 31 info->set_is_sloppy(false); 32 info->set_replace_on_access(false); 33 name = factory->InternalizeName(name); 34 info->set_name(*name); 35 Handle<Object> get = v8::FromCData(isolate, getter); 36 if (setter == nullptr) setter = &ReconfigureToDataProperty; 37 Handle<Object> set = v8::FromCData(isolate, setter); 38 info->set_getter(*get); 39 info->set_setter(*set); 40 Address redirected = info->redirected_getter(); 41 if (redirected != nullptr) { 42 Handle<Object> js_get = v8::FromCData(isolate, redirected); 43 info->set_js_getter(*js_get); 44 } 45 return info; 46 } 47 48 49 static V8_INLINE bool CheckForName(Handle<Name> name, 50 Handle<String> property_name, 51 int offset, 52 int* object_offset) { 53 if (Name::Equals(name, property_name)) { 54 *object_offset = offset; 55 return true; 56 } 57 return false; 58 } 59 60 61 // Returns true for properties that are accessors to object fields. 62 // If true, *object_offset contains offset of object field. 63 bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name, 64 int* object_offset) { 65 Isolate* isolate = name->GetIsolate(); 66 67 switch (map->instance_type()) { 68 case JS_ARRAY_TYPE: 69 return 70 CheckForName(name, isolate->factory()->length_string(), 71 JSArray::kLengthOffset, object_offset); 72 default: 73 if (map->instance_type() < FIRST_NONSTRING_TYPE) { 74 return CheckForName(name, isolate->factory()->length_string(), 75 String::kLengthOffset, object_offset); 76 } 77 78 return false; 79 } 80 } 81 82 83 namespace { 84 85 MUST_USE_RESULT MaybeHandle<Object> ReplaceAccessorWithDataProperty( 86 Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder, 87 Handle<Name> name, Handle<Object> value) { 88 LookupIterator it(receiver, name, holder, 89 LookupIterator::OWN_SKIP_INTERCEPTOR); 90 // Skip any access checks we might hit. This accessor should never hit in a 91 // situation where the caller does not have access. 92 if (it.state() == LookupIterator::ACCESS_CHECK) { 93 CHECK(it.HasAccess()); 94 it.Next(); 95 } 96 DCHECK(holder.is_identical_to(it.GetHolder<JSObject>())); 97 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); 98 it.ReconfigureDataProperty(value, it.property_attributes()); 99 return value; 100 } 101 102 } // namespace 103 104 void Accessors::ReconfigureToDataProperty( 105 v8::Local<v8::Name> key, v8::Local<v8::Value> val, 106 const v8::PropertyCallbackInfo<v8::Boolean>& info) { 107 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 108 HandleScope scope(isolate); 109 Handle<Object> receiver = Utils::OpenHandle(*info.This()); 110 Handle<JSObject> holder = 111 Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder())); 112 Handle<Name> name = Utils::OpenHandle(*key); 113 Handle<Object> value = Utils::OpenHandle(*val); 114 MaybeHandle<Object> result = 115 ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value); 116 if (result.is_null()) { 117 isolate->OptionalRescheduleException(false); 118 } else { 119 info.GetReturnValue().Set(true); 120 } 121 } 122 123 // 124 // Accessors::ArgumentsIterator 125 // 126 127 128 void Accessors::ArgumentsIteratorGetter( 129 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 130 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 131 DisallowHeapAllocation no_allocation; 132 HandleScope scope(isolate); 133 Object* result = isolate->native_context()->array_values_iterator(); 134 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); 135 } 136 137 138 Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo( 139 Isolate* isolate, PropertyAttributes attributes) { 140 Handle<Name> name = isolate->factory()->iterator_symbol(); 141 return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, nullptr, 142 attributes); 143 } 144 145 146 // 147 // Accessors::ArrayLength 148 // 149 150 151 void Accessors::ArrayLengthGetter( 152 v8::Local<v8::Name> name, 153 const v8::PropertyCallbackInfo<v8::Value>& info) { 154 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 155 RuntimeCallTimerScope timer( 156 isolate, &RuntimeCallStats::AccessorNameGetterCallback_ArrayLength); 157 DisallowHeapAllocation no_allocation; 158 HandleScope scope(isolate); 159 JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder())); 160 Object* result = holder->length(); 161 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); 162 } 163 164 void Accessors::ArrayLengthSetter( 165 v8::Local<v8::Name> name, v8::Local<v8::Value> val, 166 const v8::PropertyCallbackInfo<v8::Boolean>& info) { 167 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 168 HandleScope scope(isolate); 169 170 Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder()); 171 Handle<JSArray> array = Handle<JSArray>::cast(object); 172 Handle<Object> length_obj = Utils::OpenHandle(*val); 173 174 uint32_t length = 0; 175 if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) { 176 isolate->OptionalRescheduleException(false); 177 return; 178 } 179 180 JSArray::SetLength(array, length); 181 182 uint32_t actual_new_len = 0; 183 CHECK(array->length()->ToArrayLength(&actual_new_len)); 184 // Fail if there were non-deletable elements. 185 if (actual_new_len != length) { 186 if (info.ShouldThrowOnError()) { 187 Factory* factory = isolate->factory(); 188 isolate->Throw(*factory->NewTypeError( 189 MessageTemplate::kStrictDeleteProperty, 190 factory->NewNumberFromUint(actual_new_len - 1), array)); 191 isolate->OptionalRescheduleException(false); 192 } else { 193 info.GetReturnValue().Set(false); 194 } 195 } else { 196 info.GetReturnValue().Set(true); 197 } 198 } 199 200 201 Handle<AccessorInfo> Accessors::ArrayLengthInfo( 202 Isolate* isolate, PropertyAttributes attributes) { 203 return MakeAccessor(isolate, 204 isolate->factory()->length_string(), 205 &ArrayLengthGetter, 206 &ArrayLengthSetter, 207 attributes); 208 } 209 210 // 211 // Accessors::ModuleNamespaceEntry 212 // 213 214 void Accessors::ModuleNamespaceEntryGetter( 215 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 216 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 217 HandleScope scope(isolate); 218 JSModuleNamespace* holder = 219 JSModuleNamespace::cast(*Utils::OpenHandle(*info.Holder())); 220 Handle<Object> result; 221 if (!holder->GetExport(Handle<String>::cast(Utils::OpenHandle(*name))) 222 .ToHandle(&result)) { 223 isolate->OptionalRescheduleException(false); 224 } else { 225 info.GetReturnValue().Set(Utils::ToLocal(result)); 226 } 227 } 228 229 void Accessors::ModuleNamespaceEntrySetter( 230 v8::Local<v8::Name> name, v8::Local<v8::Value> val, 231 const v8::PropertyCallbackInfo<v8::Boolean>& info) { 232 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 233 HandleScope scope(isolate); 234 Factory* factory = isolate->factory(); 235 Handle<JSModuleNamespace> holder = 236 Handle<JSModuleNamespace>::cast(Utils::OpenHandle(*info.Holder())); 237 238 if (info.ShouldThrowOnError()) { 239 isolate->Throw(*factory->NewTypeError( 240 MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name), 241 i::Object::TypeOf(isolate, holder), holder)); 242 isolate->OptionalRescheduleException(false); 243 } else { 244 info.GetReturnValue().Set(false); 245 } 246 } 247 248 Handle<AccessorInfo> Accessors::ModuleNamespaceEntryInfo( 249 Isolate* isolate, Handle<String> name, PropertyAttributes attributes) { 250 return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter, 251 &ModuleNamespaceEntrySetter, attributes); 252 } 253 254 255 // 256 // Accessors::StringLength 257 // 258 259 void Accessors::StringLengthGetter( 260 v8::Local<v8::Name> name, 261 const v8::PropertyCallbackInfo<v8::Value>& info) { 262 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 263 RuntimeCallTimerScope timer( 264 isolate, &RuntimeCallStats::AccessorNameGetterCallback_StringLength); 265 DisallowHeapAllocation no_allocation; 266 HandleScope scope(isolate); 267 268 // We have a slight impedance mismatch between the external API and the way we 269 // use callbacks internally: Externally, callbacks can only be used with 270 // v8::Object, but internally we have callbacks on entities which are higher 271 // in the hierarchy, in this case for String values. 272 273 Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This())); 274 if (!value->IsString()) { 275 // Not a string value. That means that we either got a String wrapper or 276 // a Value with a String wrapper in its prototype chain. 277 value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value(); 278 } 279 Object* result = Smi::FromInt(String::cast(value)->length()); 280 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate))); 281 } 282 283 284 Handle<AccessorInfo> Accessors::StringLengthInfo( 285 Isolate* isolate, PropertyAttributes attributes) { 286 return MakeAccessor(isolate, isolate->factory()->length_string(), 287 &StringLengthGetter, nullptr, attributes); 288 } 289 290 291 // 292 // Accessors::ScriptColumnOffset 293 // 294 295 296 void Accessors::ScriptColumnOffsetGetter( 297 v8::Local<v8::Name> name, 298 const v8::PropertyCallbackInfo<v8::Value>& info) { 299 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 300 DisallowHeapAllocation no_allocation; 301 HandleScope scope(isolate); 302 Object* object = *Utils::OpenHandle(*info.Holder()); 303 Object* res = Smi::FromInt( 304 Script::cast(JSValue::cast(object)->value())->column_offset()); 305 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 306 } 307 308 309 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo( 310 Isolate* isolate, PropertyAttributes attributes) { 311 Handle<String> name(isolate->factory()->InternalizeOneByteString( 312 STATIC_CHAR_VECTOR("column_offset"))); 313 return MakeAccessor(isolate, name, &ScriptColumnOffsetGetter, nullptr, 314 attributes); 315 } 316 317 318 // 319 // Accessors::ScriptId 320 // 321 322 323 void Accessors::ScriptIdGetter( 324 v8::Local<v8::Name> name, 325 const v8::PropertyCallbackInfo<v8::Value>& info) { 326 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 327 DisallowHeapAllocation no_allocation; 328 HandleScope scope(isolate); 329 Object* object = *Utils::OpenHandle(*info.Holder()); 330 Object* id = Smi::FromInt(Script::cast(JSValue::cast(object)->value())->id()); 331 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate))); 332 } 333 334 335 Handle<AccessorInfo> Accessors::ScriptIdInfo( 336 Isolate* isolate, PropertyAttributes attributes) { 337 Handle<String> name( 338 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id"))); 339 return MakeAccessor(isolate, name, &ScriptIdGetter, nullptr, attributes); 340 } 341 342 343 // 344 // Accessors::ScriptName 345 // 346 347 348 void Accessors::ScriptNameGetter( 349 v8::Local<v8::Name> name, 350 const v8::PropertyCallbackInfo<v8::Value>& info) { 351 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 352 DisallowHeapAllocation no_allocation; 353 HandleScope scope(isolate); 354 Object* object = *Utils::OpenHandle(*info.Holder()); 355 Object* source = Script::cast(JSValue::cast(object)->value())->name(); 356 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate))); 357 } 358 359 360 Handle<AccessorInfo> Accessors::ScriptNameInfo( 361 Isolate* isolate, PropertyAttributes attributes) { 362 return MakeAccessor(isolate, isolate->factory()->name_string(), 363 &ScriptNameGetter, nullptr, attributes); 364 } 365 366 367 // 368 // Accessors::ScriptSource 369 // 370 371 372 void Accessors::ScriptSourceGetter( 373 v8::Local<v8::Name> name, 374 const v8::PropertyCallbackInfo<v8::Value>& info) { 375 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 376 DisallowHeapAllocation no_allocation; 377 HandleScope scope(isolate); 378 Object* object = *Utils::OpenHandle(*info.Holder()); 379 Object* source = Script::cast(JSValue::cast(object)->value())->source(); 380 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate))); 381 } 382 383 384 Handle<AccessorInfo> Accessors::ScriptSourceInfo( 385 Isolate* isolate, PropertyAttributes attributes) { 386 return MakeAccessor(isolate, isolate->factory()->source_string(), 387 &ScriptSourceGetter, nullptr, attributes); 388 } 389 390 391 // 392 // Accessors::ScriptLineOffset 393 // 394 395 396 void Accessors::ScriptLineOffsetGetter( 397 v8::Local<v8::Name> name, 398 const v8::PropertyCallbackInfo<v8::Value>& info) { 399 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 400 DisallowHeapAllocation no_allocation; 401 HandleScope scope(isolate); 402 Object* object = *Utils::OpenHandle(*info.Holder()); 403 Object* res = 404 Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset()); 405 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 406 } 407 408 409 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo( 410 Isolate* isolate, PropertyAttributes attributes) { 411 Handle<String> name(isolate->factory()->InternalizeOneByteString( 412 STATIC_CHAR_VECTOR("line_offset"))); 413 return MakeAccessor(isolate, name, &ScriptLineOffsetGetter, nullptr, 414 attributes); 415 } 416 417 418 // 419 // Accessors::ScriptType 420 // 421 422 423 void Accessors::ScriptTypeGetter( 424 v8::Local<v8::Name> name, 425 const v8::PropertyCallbackInfo<v8::Value>& info) { 426 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 427 DisallowHeapAllocation no_allocation; 428 HandleScope scope(isolate); 429 Object* object = *Utils::OpenHandle(*info.Holder()); 430 Object* res = 431 Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type()); 432 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 433 } 434 435 436 Handle<AccessorInfo> Accessors::ScriptTypeInfo( 437 Isolate* isolate, PropertyAttributes attributes) { 438 Handle<String> name( 439 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type"))); 440 return MakeAccessor(isolate, name, &ScriptTypeGetter, nullptr, attributes); 441 } 442 443 444 // 445 // Accessors::ScriptCompilationType 446 // 447 448 449 void Accessors::ScriptCompilationTypeGetter( 450 v8::Local<v8::Name> name, 451 const v8::PropertyCallbackInfo<v8::Value>& info) { 452 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 453 DisallowHeapAllocation no_allocation; 454 HandleScope scope(isolate); 455 Object* object = *Utils::OpenHandle(*info.Holder()); 456 Object* res = Smi::FromInt( 457 Script::cast(JSValue::cast(object)->value())->compilation_type()); 458 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 459 } 460 461 462 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo( 463 Isolate* isolate, PropertyAttributes attributes) { 464 Handle<String> name(isolate->factory()->InternalizeOneByteString( 465 STATIC_CHAR_VECTOR("compilation_type"))); 466 return MakeAccessor(isolate, name, &ScriptCompilationTypeGetter, nullptr, 467 attributes); 468 } 469 470 471 // 472 // Accessors::ScriptSourceUrl 473 // 474 475 476 void Accessors::ScriptSourceUrlGetter( 477 v8::Local<v8::Name> name, 478 const v8::PropertyCallbackInfo<v8::Value>& info) { 479 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 480 DisallowHeapAllocation no_allocation; 481 HandleScope scope(isolate); 482 Object* object = *Utils::OpenHandle(*info.Holder()); 483 Object* url = Script::cast(JSValue::cast(object)->value())->source_url(); 484 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate))); 485 } 486 487 488 Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo( 489 Isolate* isolate, PropertyAttributes attributes) { 490 return MakeAccessor(isolate, isolate->factory()->source_url_string(), 491 &ScriptSourceUrlGetter, nullptr, attributes); 492 } 493 494 495 // 496 // Accessors::ScriptSourceMappingUrl 497 // 498 499 500 void Accessors::ScriptSourceMappingUrlGetter( 501 v8::Local<v8::Name> name, 502 const v8::PropertyCallbackInfo<v8::Value>& info) { 503 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 504 DisallowHeapAllocation no_allocation; 505 HandleScope scope(isolate); 506 Object* object = *Utils::OpenHandle(*info.Holder()); 507 Object* url = 508 Script::cast(JSValue::cast(object)->value())->source_mapping_url(); 509 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate))); 510 } 511 512 513 Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo( 514 Isolate* isolate, PropertyAttributes attributes) { 515 return MakeAccessor(isolate, isolate->factory()->source_mapping_url_string(), 516 &ScriptSourceMappingUrlGetter, nullptr, attributes); 517 } 518 519 520 // 521 // Accessors::ScriptIsEmbedderDebugScript 522 // 523 524 525 void Accessors::ScriptIsEmbedderDebugScriptGetter( 526 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 527 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 528 DisallowHeapAllocation no_allocation; 529 HandleScope scope(isolate); 530 Object* object = *Utils::OpenHandle(*info.Holder()); 531 bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value()) 532 ->origin_options() 533 .IsEmbedderDebugScript(); 534 Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script); 535 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 536 } 537 538 539 Handle<AccessorInfo> Accessors::ScriptIsEmbedderDebugScriptInfo( 540 Isolate* isolate, PropertyAttributes attributes) { 541 Handle<String> name(isolate->factory()->InternalizeOneByteString( 542 STATIC_CHAR_VECTOR("is_debugger_script"))); 543 return MakeAccessor(isolate, name, &ScriptIsEmbedderDebugScriptGetter, 544 nullptr, attributes); 545 } 546 547 548 // 549 // Accessors::ScriptGetContextData 550 // 551 552 553 void Accessors::ScriptContextDataGetter( 554 v8::Local<v8::Name> name, 555 const v8::PropertyCallbackInfo<v8::Value>& info) { 556 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 557 DisallowHeapAllocation no_allocation; 558 HandleScope scope(isolate); 559 Object* object = *Utils::OpenHandle(*info.Holder()); 560 Object* res = Script::cast(JSValue::cast(object)->value())->context_data(); 561 info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate))); 562 } 563 564 565 Handle<AccessorInfo> Accessors::ScriptContextDataInfo( 566 Isolate* isolate, PropertyAttributes attributes) { 567 Handle<String> name(isolate->factory()->InternalizeOneByteString( 568 STATIC_CHAR_VECTOR("context_data"))); 569 return MakeAccessor(isolate, name, &ScriptContextDataGetter, nullptr, 570 attributes); 571 } 572 573 574 // 575 // Accessors::ScriptGetEvalFromScript 576 // 577 578 579 void Accessors::ScriptEvalFromScriptGetter( 580 v8::Local<v8::Name> name, 581 const v8::PropertyCallbackInfo<v8::Value>& info) { 582 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 583 HandleScope scope(isolate); 584 Handle<Object> object = Utils::OpenHandle(*info.Holder()); 585 Handle<Script> script( 586 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 587 Handle<Object> result = isolate->factory()->undefined_value(); 588 if (!script->eval_from_shared()->IsUndefined(isolate)) { 589 Handle<SharedFunctionInfo> eval_from_shared( 590 SharedFunctionInfo::cast(script->eval_from_shared())); 591 if (eval_from_shared->script()->IsScript()) { 592 Handle<Script> eval_from_script(Script::cast(eval_from_shared->script())); 593 result = Script::GetWrapper(eval_from_script); 594 } 595 } 596 597 info.GetReturnValue().Set(Utils::ToLocal(result)); 598 } 599 600 601 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo( 602 Isolate* isolate, PropertyAttributes attributes) { 603 Handle<String> name(isolate->factory()->InternalizeOneByteString( 604 STATIC_CHAR_VECTOR("eval_from_script"))); 605 return MakeAccessor(isolate, name, &ScriptEvalFromScriptGetter, nullptr, 606 attributes); 607 } 608 609 610 // 611 // Accessors::ScriptGetEvalFromScriptPosition 612 // 613 614 615 void Accessors::ScriptEvalFromScriptPositionGetter( 616 v8::Local<v8::Name> name, 617 const v8::PropertyCallbackInfo<v8::Value>& info) { 618 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 619 HandleScope scope(isolate); 620 Handle<Object> object = Utils::OpenHandle(*info.Holder()); 621 Handle<Script> script( 622 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 623 Handle<Object> result = isolate->factory()->undefined_value(); 624 if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) { 625 result = Handle<Object>(Smi::FromInt(script->GetEvalPosition()), isolate); 626 } 627 info.GetReturnValue().Set(Utils::ToLocal(result)); 628 } 629 630 631 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo( 632 Isolate* isolate, PropertyAttributes attributes) { 633 Handle<String> name(isolate->factory()->InternalizeOneByteString( 634 STATIC_CHAR_VECTOR("eval_from_script_position"))); 635 return MakeAccessor(isolate, name, &ScriptEvalFromScriptPositionGetter, 636 nullptr, attributes); 637 } 638 639 640 // 641 // Accessors::ScriptGetEvalFromFunctionName 642 // 643 644 645 void Accessors::ScriptEvalFromFunctionNameGetter( 646 v8::Local<v8::Name> name, 647 const v8::PropertyCallbackInfo<v8::Value>& info) { 648 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 649 HandleScope scope(isolate); 650 Handle<Object> object = Utils::OpenHandle(*info.Holder()); 651 Handle<Script> script( 652 Script::cast(Handle<JSValue>::cast(object)->value()), isolate); 653 Handle<Object> result = isolate->factory()->undefined_value(); 654 if (!script->eval_from_shared()->IsUndefined(isolate)) { 655 Handle<SharedFunctionInfo> shared( 656 SharedFunctionInfo::cast(script->eval_from_shared())); 657 // Find the name of the function calling eval. 658 if (!shared->name()->IsUndefined(isolate)) { 659 result = Handle<Object>(shared->name(), isolate); 660 } else { 661 result = Handle<Object>(shared->inferred_name(), isolate); 662 } 663 } 664 info.GetReturnValue().Set(Utils::ToLocal(result)); 665 } 666 667 668 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo( 669 Isolate* isolate, PropertyAttributes attributes) { 670 Handle<String> name(isolate->factory()->InternalizeOneByteString( 671 STATIC_CHAR_VECTOR("eval_from_function_name"))); 672 return MakeAccessor(isolate, name, &ScriptEvalFromFunctionNameGetter, nullptr, 673 attributes); 674 } 675 676 677 // 678 // Accessors::FunctionPrototype 679 // 680 681 static Handle<Object> GetFunctionPrototype(Isolate* isolate, 682 Handle<JSFunction> function) { 683 if (!function->has_prototype()) { 684 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function); 685 JSFunction::SetPrototype(function, proto); 686 } 687 return Handle<Object>(function->prototype(), isolate); 688 } 689 690 691 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype( 692 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) { 693 JSFunction::SetPrototype(function, value); 694 DCHECK(function->prototype() == *value); 695 return function; 696 } 697 698 699 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function, 700 Handle<Object> prototype) { 701 DCHECK(function->IsConstructor()); 702 Isolate* isolate = function->GetIsolate(); 703 return SetFunctionPrototype(isolate, function, prototype); 704 } 705 706 707 void Accessors::FunctionPrototypeGetter( 708 v8::Local<v8::Name> name, 709 const v8::PropertyCallbackInfo<v8::Value>& info) { 710 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 711 RuntimeCallTimerScope timer( 712 isolate, &RuntimeCallStats::AccessorNameGetterCallback_FunctionPrototype); 713 HandleScope scope(isolate); 714 Handle<JSFunction> function = 715 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 716 Handle<Object> result = GetFunctionPrototype(isolate, function); 717 info.GetReturnValue().Set(Utils::ToLocal(result)); 718 } 719 720 void Accessors::FunctionPrototypeSetter( 721 v8::Local<v8::Name> name, v8::Local<v8::Value> val, 722 const v8::PropertyCallbackInfo<v8::Boolean>& info) { 723 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 724 HandleScope scope(isolate); 725 Handle<Object> value = Utils::OpenHandle(*val); 726 Handle<JSFunction> object = 727 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 728 if (SetFunctionPrototype(isolate, object, value).is_null()) { 729 isolate->OptionalRescheduleException(false); 730 } else { 731 info.GetReturnValue().Set(true); 732 } 733 } 734 735 736 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo( 737 Isolate* isolate, PropertyAttributes attributes) { 738 return MakeAccessor(isolate, 739 isolate->factory()->prototype_string(), 740 &FunctionPrototypeGetter, 741 &FunctionPrototypeSetter, 742 attributes); 743 } 744 745 746 // 747 // Accessors::FunctionLength 748 // 749 750 751 void Accessors::FunctionLengthGetter( 752 v8::Local<v8::Name> name, 753 const v8::PropertyCallbackInfo<v8::Value>& info) { 754 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 755 HandleScope scope(isolate); 756 Handle<JSFunction> function = 757 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 758 Handle<Object> result; 759 if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) { 760 result = handle(Smi::kZero, isolate); 761 isolate->OptionalRescheduleException(false); 762 } 763 764 info.GetReturnValue().Set(Utils::ToLocal(result)); 765 } 766 767 Handle<AccessorInfo> Accessors::FunctionLengthInfo( 768 Isolate* isolate, PropertyAttributes attributes) { 769 return MakeAccessor(isolate, isolate->factory()->length_string(), 770 &FunctionLengthGetter, &ReconfigureToDataProperty, 771 attributes); 772 } 773 774 775 // 776 // Accessors::FunctionName 777 // 778 779 780 void Accessors::FunctionNameGetter( 781 v8::Local<v8::Name> name, 782 const v8::PropertyCallbackInfo<v8::Value>& info) { 783 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 784 HandleScope scope(isolate); 785 Handle<JSFunction> function = 786 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 787 Handle<Object> result = JSFunction::GetName(isolate, function); 788 info.GetReturnValue().Set(Utils::ToLocal(result)); 789 } 790 791 Handle<AccessorInfo> Accessors::FunctionNameInfo( 792 Isolate* isolate, PropertyAttributes attributes) { 793 return MakeAccessor(isolate, isolate->factory()->name_string(), 794 &FunctionNameGetter, &ReconfigureToDataProperty, 795 attributes); 796 } 797 798 799 // 800 // Accessors::FunctionArguments 801 // 802 803 804 static Handle<Object> ArgumentsForInlinedFunction( 805 JavaScriptFrame* frame, 806 Handle<JSFunction> inlined_function, 807 int inlined_frame_index) { 808 Isolate* isolate = inlined_function->GetIsolate(); 809 Factory* factory = isolate->factory(); 810 811 TranslatedState translated_values(frame); 812 translated_values.Prepare(false, frame->fp()); 813 814 int argument_count = 0; 815 TranslatedFrame* translated_frame = 816 translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index, 817 &argument_count); 818 TranslatedFrame::iterator iter = translated_frame->begin(); 819 820 // Skip the function. 821 iter++; 822 823 // Skip the receiver. 824 iter++; 825 argument_count--; 826 827 Handle<JSObject> arguments = 828 factory->NewArgumentsObject(inlined_function, argument_count); 829 Handle<FixedArray> array = factory->NewFixedArray(argument_count); 830 bool should_deoptimize = false; 831 for (int i = 0; i < argument_count; ++i) { 832 // If we materialize any object, we should deopt because we might alias 833 // an object that was eliminated by escape analysis. 834 should_deoptimize = should_deoptimize || iter->IsMaterializedObject(); 835 Handle<Object> value = iter->GetValue(); 836 array->set(i, *value); 837 iter++; 838 } 839 arguments->set_elements(*array); 840 841 if (should_deoptimize) { 842 translated_values.StoreMaterializedValuesAndDeopt(); 843 } 844 845 // Return the freshly allocated arguments object. 846 return arguments; 847 } 848 849 850 static int FindFunctionInFrame(JavaScriptFrame* frame, 851 Handle<JSFunction> function) { 852 DisallowHeapAllocation no_allocation; 853 List<JSFunction*> functions(2); 854 frame->GetFunctions(&functions); 855 for (int i = functions.length() - 1; i >= 0; i--) { 856 if (functions[i] == *function) return i; 857 } 858 return -1; 859 } 860 861 862 namespace { 863 864 Handle<Object> GetFunctionArguments(Isolate* isolate, 865 Handle<JSFunction> function) { 866 // Find the top invocation of the function by traversing frames. 867 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { 868 JavaScriptFrame* frame = it.frame(); 869 int function_index = FindFunctionInFrame(frame, function); 870 if (function_index < 0) continue; 871 872 if (function_index > 0) { 873 // The function in question was inlined. Inlined functions have the 874 // correct number of arguments and no allocated arguments object, so 875 // we can construct a fresh one by interpreting the function's 876 // deoptimization input data. 877 return ArgumentsForInlinedFunction(frame, function, function_index); 878 } 879 880 // Find the frame that holds the actual arguments passed to the function. 881 it.AdvanceToArgumentsFrame(); 882 frame = it.frame(); 883 884 // Get the number of arguments and construct an arguments object 885 // mirror for the right frame. 886 const int length = frame->ComputeParametersCount(); 887 Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject( 888 function, length); 889 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); 890 891 // Copy the parameters to the arguments object. 892 DCHECK(array->length() == length); 893 for (int i = 0; i < length; i++) { 894 Object* value = frame->GetParameter(i); 895 if (value->IsTheHole(isolate)) { 896 // Generators currently use holes as dummy arguments when resuming. We 897 // must not leak those. 898 DCHECK(IsResumableFunction(function->shared()->kind())); 899 value = isolate->heap()->undefined_value(); 900 } 901 array->set(i, value); 902 } 903 arguments->set_elements(*array); 904 905 // Return the freshly allocated arguments object. 906 return arguments; 907 } 908 909 // No frame corresponding to the given function found. Return null. 910 return isolate->factory()->null_value(); 911 } 912 913 } // namespace 914 915 916 Handle<JSObject> Accessors::FunctionGetArguments(Handle<JSFunction> function) { 917 Handle<Object> arguments = 918 GetFunctionArguments(function->GetIsolate(), function); 919 CHECK(arguments->IsJSObject()); 920 return Handle<JSObject>::cast(arguments); 921 } 922 923 924 void Accessors::FunctionArgumentsGetter( 925 v8::Local<v8::Name> name, 926 const v8::PropertyCallbackInfo<v8::Value>& info) { 927 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 928 HandleScope scope(isolate); 929 Handle<JSFunction> function = 930 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 931 Handle<Object> result = 932 function->shared()->native() 933 ? Handle<Object>::cast(isolate->factory()->null_value()) 934 : GetFunctionArguments(isolate, function); 935 info.GetReturnValue().Set(Utils::ToLocal(result)); 936 } 937 938 939 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo( 940 Isolate* isolate, PropertyAttributes attributes) { 941 return MakeAccessor(isolate, isolate->factory()->arguments_string(), 942 &FunctionArgumentsGetter, nullptr, attributes); 943 } 944 945 946 // 947 // Accessors::FunctionCaller 948 // 949 950 951 static inline bool AllowAccessToFunction(Context* current_context, 952 JSFunction* function) { 953 return current_context->HasSameSecurityTokenAs(function->context()); 954 } 955 956 957 class FrameFunctionIterator { 958 public: 959 FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise) 960 : isolate_(isolate), 961 frame_iterator_(isolate), 962 functions_(2), 963 index_(0) { 964 GetFunctions(); 965 } 966 JSFunction* next() { 967 while (true) { 968 if (functions_.length() == 0) return NULL; 969 JSFunction* next_function = functions_[index_]; 970 index_--; 971 if (index_ < 0) { 972 GetFunctions(); 973 } 974 // Skip functions from other origins. 975 if (!AllowAccessToFunction(isolate_->context(), next_function)) continue; 976 return next_function; 977 } 978 } 979 980 // Iterate through functions until the first occurence of 'function'. 981 // Returns true if 'function' is found, and false if the iterator ends 982 // without finding it. 983 bool Find(JSFunction* function) { 984 JSFunction* next_function; 985 do { 986 next_function = next(); 987 if (next_function == function) return true; 988 } while (next_function != NULL); 989 return false; 990 } 991 992 private: 993 void GetFunctions() { 994 functions_.Rewind(0); 995 if (frame_iterator_.done()) return; 996 JavaScriptFrame* frame = frame_iterator_.frame(); 997 frame->GetFunctions(&functions_); 998 DCHECK(functions_.length() > 0); 999 frame_iterator_.Advance(); 1000 index_ = functions_.length() - 1; 1001 } 1002 Isolate* isolate_; 1003 JavaScriptFrameIterator frame_iterator_; 1004 List<JSFunction*> functions_; 1005 int index_; 1006 }; 1007 1008 1009 MaybeHandle<JSFunction> FindCaller(Isolate* isolate, 1010 Handle<JSFunction> function) { 1011 DisallowHeapAllocation no_allocation; 1012 FrameFunctionIterator it(isolate, no_allocation); 1013 if (function->shared()->native()) { 1014 return MaybeHandle<JSFunction>(); 1015 } 1016 // Find the function from the frames. 1017 if (!it.Find(*function)) { 1018 // No frame corresponding to the given function found. Return null. 1019 return MaybeHandle<JSFunction>(); 1020 } 1021 // Find previously called non-toplevel function. 1022 JSFunction* caller; 1023 do { 1024 caller = it.next(); 1025 if (caller == NULL) return MaybeHandle<JSFunction>(); 1026 } while (caller->shared()->is_toplevel()); 1027 1028 // If caller is a built-in function and caller's caller is also built-in, 1029 // use that instead. 1030 JSFunction* potential_caller = caller; 1031 while (potential_caller != NULL && potential_caller->shared()->IsBuiltin()) { 1032 caller = potential_caller; 1033 potential_caller = it.next(); 1034 } 1035 if (!caller->shared()->native() && potential_caller != NULL) { 1036 caller = potential_caller; 1037 } 1038 // Censor if the caller is not a sloppy mode function. 1039 // Change from ES5, which used to throw, see: 1040 // https://bugs.ecmascript.org/show_bug.cgi?id=310 1041 if (is_strict(caller->shared()->language_mode())) { 1042 return MaybeHandle<JSFunction>(); 1043 } 1044 // Don't return caller from another security context. 1045 if (!AllowAccessToFunction(isolate->context(), caller)) { 1046 return MaybeHandle<JSFunction>(); 1047 } 1048 return Handle<JSFunction>(caller); 1049 } 1050 1051 1052 void Accessors::FunctionCallerGetter( 1053 v8::Local<v8::Name> name, 1054 const v8::PropertyCallbackInfo<v8::Value>& info) { 1055 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1056 HandleScope scope(isolate); 1057 Handle<JSFunction> function = 1058 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); 1059 Handle<Object> result; 1060 MaybeHandle<JSFunction> maybe_caller; 1061 maybe_caller = FindCaller(isolate, function); 1062 Handle<JSFunction> caller; 1063 if (maybe_caller.ToHandle(&caller)) { 1064 result = caller; 1065 } else { 1066 result = isolate->factory()->null_value(); 1067 } 1068 info.GetReturnValue().Set(Utils::ToLocal(result)); 1069 } 1070 1071 1072 Handle<AccessorInfo> Accessors::FunctionCallerInfo( 1073 Isolate* isolate, PropertyAttributes attributes) { 1074 return MakeAccessor(isolate, isolate->factory()->caller_string(), 1075 &FunctionCallerGetter, nullptr, attributes); 1076 } 1077 1078 1079 // 1080 // Accessors::BoundFunctionLength 1081 // 1082 1083 void Accessors::BoundFunctionLengthGetter( 1084 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 1085 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1086 RuntimeCallTimerScope timer( 1087 isolate, 1088 &RuntimeCallStats::AccessorNameGetterCallback_BoundFunctionLength); 1089 HandleScope scope(isolate); 1090 Handle<JSBoundFunction> function = 1091 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder())); 1092 1093 Handle<Smi> target_length; 1094 Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()), 1095 isolate); 1096 if (!JSFunction::GetLength(isolate, target).ToHandle(&target_length)) { 1097 target_length = handle(Smi::kZero, isolate); 1098 isolate->OptionalRescheduleException(false); 1099 return; 1100 } 1101 1102 int bound_length = function->bound_arguments()->length(); 1103 int length = Max(0, target_length->value() - bound_length); 1104 1105 Handle<Object> result(Smi::FromInt(length), isolate); 1106 info.GetReturnValue().Set(Utils::ToLocal(result)); 1107 } 1108 1109 Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo( 1110 Isolate* isolate, PropertyAttributes attributes) { 1111 return MakeAccessor(isolate, isolate->factory()->length_string(), 1112 &BoundFunctionLengthGetter, &ReconfigureToDataProperty, 1113 attributes); 1114 } 1115 1116 // 1117 // Accessors::BoundFunctionName 1118 // 1119 1120 void Accessors::BoundFunctionNameGetter( 1121 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { 1122 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1123 RuntimeCallTimerScope timer( 1124 isolate, &RuntimeCallStats::AccessorNameGetterCallback_BoundFunctionName); 1125 HandleScope scope(isolate); 1126 Handle<JSBoundFunction> function = 1127 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder())); 1128 Handle<Object> result; 1129 if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) { 1130 isolate->OptionalRescheduleException(false); 1131 return; 1132 } 1133 info.GetReturnValue().Set(Utils::ToLocal(result)); 1134 } 1135 1136 Handle<AccessorInfo> Accessors::BoundFunctionNameInfo( 1137 Isolate* isolate, PropertyAttributes attributes) { 1138 return MakeAccessor(isolate, isolate->factory()->name_string(), 1139 &BoundFunctionNameGetter, &ReconfigureToDataProperty, 1140 attributes); 1141 } 1142 1143 // 1144 // Accessors::ErrorStack 1145 // 1146 1147 namespace { 1148 1149 MaybeHandle<JSReceiver> ClearInternalStackTrace(Isolate* isolate, 1150 Handle<JSObject> error) { 1151 RETURN_ON_EXCEPTION( 1152 isolate, 1153 JSReceiver::SetProperty(error, isolate->factory()->stack_trace_symbol(), 1154 isolate->factory()->undefined_value(), STRICT), 1155 JSReceiver); 1156 return error; 1157 } 1158 1159 bool IsAccessor(Handle<Object> receiver, Handle<Name> name, 1160 Handle<JSObject> holder) { 1161 LookupIterator it(receiver, name, holder, 1162 LookupIterator::OWN_SKIP_INTERCEPTOR); 1163 // Skip any access checks we might hit. This accessor should never hit in a 1164 // situation where the caller does not have access. 1165 if (it.state() == LookupIterator::ACCESS_CHECK) { 1166 CHECK(it.HasAccess()); 1167 it.Next(); 1168 } 1169 return (it.state() == LookupIterator::ACCESSOR); 1170 } 1171 1172 } // namespace 1173 1174 void Accessors::ErrorStackGetter( 1175 v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) { 1176 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1177 HandleScope scope(isolate); 1178 Handle<JSObject> holder = 1179 Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder())); 1180 1181 // Retrieve the structured stack trace. 1182 1183 Handle<Object> stack_trace; 1184 Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol(); 1185 MaybeHandle<Object> maybe_stack_trace = 1186 JSObject::GetProperty(holder, stack_trace_symbol); 1187 if (!maybe_stack_trace.ToHandle(&stack_trace) || 1188 stack_trace->IsUndefined(isolate)) { 1189 Handle<Object> result = isolate->factory()->undefined_value(); 1190 info.GetReturnValue().Set(Utils::ToLocal(result)); 1191 return; 1192 } 1193 1194 // Format it, clear the internal structured trace and reconfigure as a data 1195 // property. 1196 1197 Handle<Object> formatted_stack_trace; 1198 if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace) 1199 .ToHandle(&formatted_stack_trace)) { 1200 isolate->OptionalRescheduleException(false); 1201 return; 1202 } 1203 1204 MaybeHandle<Object> result = ClearInternalStackTrace(isolate, holder); 1205 if (result.is_null()) { 1206 isolate->OptionalRescheduleException(false); 1207 return; 1208 } 1209 1210 // If stack is still an accessor (this could have changed in the meantime 1211 // since FormatStackTrace can execute arbitrary JS), replace it with a data 1212 // property. 1213 Handle<Object> receiver = Utils::OpenHandle(*info.This()); 1214 Handle<Name> name = Utils::OpenHandle(*key); 1215 if (IsAccessor(receiver, name, holder)) { 1216 result = ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, 1217 formatted_stack_trace); 1218 if (result.is_null()) { 1219 isolate->OptionalRescheduleException(false); 1220 return; 1221 } 1222 } else { 1223 // The stack property has been modified in the meantime. 1224 if (!JSObject::GetProperty(holder, name).ToHandle(&formatted_stack_trace)) { 1225 isolate->OptionalRescheduleException(false); 1226 return; 1227 } 1228 } 1229 1230 v8::Local<v8::Value> value = Utils::ToLocal(formatted_stack_trace); 1231 info.GetReturnValue().Set(value); 1232 } 1233 1234 void Accessors::ErrorStackSetter( 1235 v8::Local<v8::Name> name, v8::Local<v8::Value> val, 1236 const v8::PropertyCallbackInfo<v8::Boolean>& info) { 1237 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); 1238 HandleScope scope(isolate); 1239 Handle<JSObject> obj = 1240 Handle<JSObject>::cast(Utils::OpenHandle(*info.This())); 1241 1242 // Clear internal properties to avoid memory leaks. 1243 Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol(); 1244 if (JSReceiver::HasOwnProperty(obj, stack_trace_symbol).FromMaybe(false)) { 1245 ClearInternalStackTrace(isolate, obj); 1246 } 1247 1248 Accessors::ReconfigureToDataProperty(name, val, info); 1249 } 1250 1251 Handle<AccessorInfo> Accessors::ErrorStackInfo(Isolate* isolate, 1252 PropertyAttributes attributes) { 1253 Handle<AccessorInfo> info = 1254 MakeAccessor(isolate, isolate->factory()->stack_string(), 1255 &ErrorStackGetter, &ErrorStackSetter, attributes); 1256 return info; 1257 } 1258 1259 } // namespace internal 1260 } // namespace v8 1261