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