Home | History | Annotate | Download | only in src
      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