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/v8.h"
      6 #include "src/accessors.h"
      7 
      8 #include "src/compiler.h"
      9 #include "src/contexts.h"
     10 #include "src/deoptimizer.h"
     11 #include "src/execution.h"
     12 #include "src/factory.h"
     13 #include "src/frames-inl.h"
     14 #include "src/isolate.h"
     15 #include "src/list-inl.h"
     16 #include "src/property-details.h"
     17 #include "src/api.h"
     18 
     19 namespace v8 {
     20 namespace internal {
     21 
     22 
     23 // We have a slight impedance mismatch between the external API and the way we
     24 // use callbacks internally: Externally, callbacks can only be used with
     25 // v8::Object, but internally we even have callbacks on entities which are
     26 // higher in the hierarchy, so we can only return i::Object here, not
     27 // i::JSObject.
     28 Handle<Object> GetThisFrom(const v8::PropertyCallbackInfo<v8::Value>& info) {
     29   return Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
     30 }
     31 
     32 
     33 Handle<AccessorInfo> Accessors::MakeAccessor(
     34     Isolate* isolate,
     35     Handle<String> name,
     36     AccessorGetterCallback getter,
     37     AccessorSetterCallback setter,
     38     PropertyAttributes attributes) {
     39   Factory* factory = isolate->factory();
     40   Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
     41   info->set_property_attributes(attributes);
     42   info->set_all_can_read(false);
     43   info->set_all_can_write(false);
     44   info->set_name(*name);
     45   Handle<Object> get = v8::FromCData(isolate, getter);
     46   Handle<Object> set = v8::FromCData(isolate, setter);
     47   info->set_getter(*get);
     48   info->set_setter(*set);
     49   return info;
     50 }
     51 
     52 
     53 Handle<ExecutableAccessorInfo> Accessors::CloneAccessor(
     54     Isolate* isolate,
     55     Handle<ExecutableAccessorInfo> accessor) {
     56   Factory* factory = isolate->factory();
     57   Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
     58   info->set_name(accessor->name());
     59   info->set_flag(accessor->flag());
     60   info->set_expected_receiver_type(accessor->expected_receiver_type());
     61   info->set_getter(accessor->getter());
     62   info->set_setter(accessor->setter());
     63   info->set_data(accessor->data());
     64   return info;
     65 }
     66 
     67 
     68 template <class C>
     69 static C* FindInstanceOf(Isolate* isolate, Object* obj) {
     70   for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype(isolate)) {
     71     if (Is<C>(cur)) return C::cast(cur);
     72   }
     73   return NULL;
     74 }
     75 
     76 
     77 static V8_INLINE bool CheckForName(Handle<String> name,
     78                                    Handle<String> property_name,
     79                                    int offset,
     80                                    int* object_offset) {
     81   if (String::Equals(name, property_name)) {
     82     *object_offset = offset;
     83     return true;
     84   }
     85   return false;
     86 }
     87 
     88 
     89 // Returns true for properties that are accessors to object fields.
     90 // If true, *object_offset contains offset of object field.
     91 template <class T>
     92 bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
     93                                         Handle<String> name,
     94                                         int* object_offset) {
     95   Isolate* isolate = name->GetIsolate();
     96 
     97   if (type->Is(T::String())) {
     98     return CheckForName(name, isolate->factory()->length_string(),
     99                         String::kLengthOffset, object_offset);
    100   }
    101 
    102   if (!type->IsClass()) return false;
    103   Handle<Map> map = type->AsClass()->Map();
    104 
    105   switch (map->instance_type()) {
    106     case JS_ARRAY_TYPE:
    107       return
    108         CheckForName(name, isolate->factory()->length_string(),
    109                      JSArray::kLengthOffset, object_offset);
    110     case JS_TYPED_ARRAY_TYPE:
    111       return
    112         CheckForName(name, isolate->factory()->length_string(),
    113                      JSTypedArray::kLengthOffset, object_offset) ||
    114         CheckForName(name, isolate->factory()->byte_length_string(),
    115                      JSTypedArray::kByteLengthOffset, object_offset) ||
    116         CheckForName(name, isolate->factory()->byte_offset_string(),
    117                      JSTypedArray::kByteOffsetOffset, object_offset);
    118     case JS_ARRAY_BUFFER_TYPE:
    119       return
    120         CheckForName(name, isolate->factory()->byte_length_string(),
    121                      JSArrayBuffer::kByteLengthOffset, object_offset);
    122     case JS_DATA_VIEW_TYPE:
    123       return
    124         CheckForName(name, isolate->factory()->byte_length_string(),
    125                      JSDataView::kByteLengthOffset, object_offset) ||
    126         CheckForName(name, isolate->factory()->byte_offset_string(),
    127                      JSDataView::kByteOffsetOffset, object_offset);
    128     default:
    129       return false;
    130   }
    131 }
    132 
    133 
    134 template
    135 bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
    136                                               Handle<String> name,
    137                                               int* object_offset);
    138 
    139 
    140 template
    141 bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
    142                                                   Handle<String> name,
    143                                                   int* object_offset);
    144 
    145 
    146 //
    147 // Accessors::ArrayLength
    148 //
    149 
    150 
    151 // The helper function will 'flatten' Number objects.
    152 Handle<Object> Accessors::FlattenNumber(Isolate* isolate,
    153                                         Handle<Object> value) {
    154   if (value->IsNumber() || !value->IsJSValue()) return value;
    155   Handle<JSValue> wrapper = Handle<JSValue>::cast(value);
    156   ASSERT(wrapper->GetIsolate()->context()->native_context()->number_function()->
    157       has_initial_map());
    158   if (wrapper->map() ==
    159       isolate->context()->native_context()->number_function()->initial_map()) {
    160     return handle(wrapper->value(), isolate);
    161   }
    162 
    163   return value;
    164 }
    165 
    166 
    167 void Accessors::ArrayLengthGetter(
    168     v8::Local<v8::String> name,
    169     const v8::PropertyCallbackInfo<v8::Value>& info) {
    170   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    171   DisallowHeapAllocation no_allocation;
    172   HandleScope scope(isolate);
    173   Object* object = *GetThisFrom(info);
    174   // Traverse the prototype chain until we reach an array.
    175   JSArray* holder = FindInstanceOf<JSArray>(isolate, object);
    176   Object* result;
    177   if (holder != NULL) {
    178     result = holder->length();
    179   } else {
    180     result = Smi::FromInt(0);
    181   }
    182   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
    183 }
    184 
    185 
    186 void Accessors::ArrayLengthSetter(
    187     v8::Local<v8::String> name,
    188     v8::Local<v8::Value> val,
    189     const v8::PropertyCallbackInfo<void>& info) {
    190   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    191   HandleScope scope(isolate);
    192   Handle<JSObject> object = Handle<JSObject>::cast(
    193       Utils::OpenHandle(*info.This()));
    194   Handle<Object> value = Utils::OpenHandle(*val);
    195   // This means one of the object's prototypes is a JSArray and the
    196   // object does not have a 'length' property.  Calling SetProperty
    197   // causes an infinite loop.
    198   if (!object->IsJSArray()) {
    199     MaybeHandle<Object> maybe_result =
    200         JSObject::SetOwnPropertyIgnoreAttributes(
    201             object, isolate->factory()->length_string(), value, NONE);
    202     maybe_result.Check();
    203     return;
    204   }
    205 
    206   value = FlattenNumber(isolate, value);
    207 
    208   Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
    209   MaybeHandle<Object> maybe;
    210   Handle<Object> uint32_v;
    211   maybe = Execution::ToUint32(isolate, value);
    212   if (!maybe.ToHandle(&uint32_v)) {
    213     isolate->OptionalRescheduleException(false);
    214     return;
    215   }
    216   Handle<Object> number_v;
    217   maybe = Execution::ToNumber(isolate, value);
    218   if (!maybe.ToHandle(&number_v)) {
    219     isolate->OptionalRescheduleException(false);
    220     return;
    221   }
    222 
    223   if (uint32_v->Number() == number_v->Number()) {
    224     maybe = JSArray::SetElementsLength(array_handle, uint32_v);
    225     maybe.Check();
    226     return;
    227   }
    228 
    229   isolate->ScheduleThrow(
    230       *isolate->factory()->NewRangeError("invalid_array_length",
    231                                          HandleVector<Object>(NULL, 0)));
    232 }
    233 
    234 
    235 Handle<AccessorInfo> Accessors::ArrayLengthInfo(
    236       Isolate* isolate, PropertyAttributes attributes) {
    237   return MakeAccessor(isolate,
    238                       isolate->factory()->length_string(),
    239                       &ArrayLengthGetter,
    240                       &ArrayLengthSetter,
    241                       attributes);
    242 }
    243 
    244 
    245 
    246 //
    247 // Accessors::StringLength
    248 //
    249 
    250 void Accessors::StringLengthGetter(
    251     v8::Local<v8::String> name,
    252     const v8::PropertyCallbackInfo<v8::Value>& info) {
    253   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    254   DisallowHeapAllocation no_allocation;
    255   HandleScope scope(isolate);
    256   Object* value = *GetThisFrom(info);
    257   Object* result;
    258   if (value->IsJSValue()) value = JSValue::cast(value)->value();
    259   if (value->IsString()) {
    260     result = Smi::FromInt(String::cast(value)->length());
    261   } else {
    262     // If object is not a string we return 0 to be compatible with WebKit.
    263     // Note: Firefox returns the length of ToString(object).
    264     result = Smi::FromInt(0);
    265   }
    266   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
    267 }
    268 
    269 
    270 void Accessors::StringLengthSetter(
    271     v8::Local<v8::String> name,
    272     v8::Local<v8::Value> value,
    273     const v8::PropertyCallbackInfo<void>& info) {
    274   UNREACHABLE();
    275 }
    276 
    277 
    278 Handle<AccessorInfo> Accessors::StringLengthInfo(
    279       Isolate* isolate, PropertyAttributes attributes) {
    280   return MakeAccessor(isolate,
    281                       isolate->factory()->length_string(),
    282                       &StringLengthGetter,
    283                       &StringLengthSetter,
    284                       attributes);
    285 }
    286 
    287 
    288 //
    289 // Accessors::ScriptColumnOffset
    290 //
    291 
    292 
    293 void Accessors::ScriptColumnOffsetGetter(
    294     v8::Local<v8::String> name,
    295     const v8::PropertyCallbackInfo<v8::Value>& info) {
    296   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    297   DisallowHeapAllocation no_allocation;
    298   HandleScope scope(isolate);
    299   Object* object = *Utils::OpenHandle(*info.This());
    300   Object* res = Script::cast(JSValue::cast(object)->value())->column_offset();
    301   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
    302 }
    303 
    304 
    305 void Accessors::ScriptColumnOffsetSetter(
    306     v8::Local<v8::String> name,
    307     v8::Local<v8::Value> value,
    308     const v8::PropertyCallbackInfo<void>& info) {
    309   UNREACHABLE();
    310 }
    311 
    312 
    313 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
    314       Isolate* isolate, PropertyAttributes attributes) {
    315   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    316         STATIC_ASCII_VECTOR("column_offset")));
    317   return MakeAccessor(isolate,
    318                       name,
    319                       &ScriptColumnOffsetGetter,
    320                       &ScriptColumnOffsetSetter,
    321                       attributes);
    322 }
    323 
    324 
    325 //
    326 // Accessors::ScriptId
    327 //
    328 
    329 
    330 void Accessors::ScriptIdGetter(
    331     v8::Local<v8::String> name,
    332     const v8::PropertyCallbackInfo<v8::Value>& info) {
    333   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    334   DisallowHeapAllocation no_allocation;
    335   HandleScope scope(isolate);
    336   Object* object = *Utils::OpenHandle(*info.This());
    337   Object* id = Script::cast(JSValue::cast(object)->value())->id();
    338   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
    339 }
    340 
    341 
    342 void Accessors::ScriptIdSetter(
    343     v8::Local<v8::String> name,
    344     v8::Local<v8::Value> value,
    345     const v8::PropertyCallbackInfo<void>& info) {
    346   UNREACHABLE();
    347 }
    348 
    349 
    350 Handle<AccessorInfo> Accessors::ScriptIdInfo(
    351       Isolate* isolate, PropertyAttributes attributes) {
    352   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    353         STATIC_ASCII_VECTOR("id")));
    354   return MakeAccessor(isolate,
    355                       name,
    356                       &ScriptIdGetter,
    357                       &ScriptIdSetter,
    358                       attributes);
    359 }
    360 
    361 
    362 //
    363 // Accessors::ScriptName
    364 //
    365 
    366 
    367 void Accessors::ScriptNameGetter(
    368     v8::Local<v8::String> name,
    369     const v8::PropertyCallbackInfo<v8::Value>& info) {
    370   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    371   DisallowHeapAllocation no_allocation;
    372   HandleScope scope(isolate);
    373   Object* object = *Utils::OpenHandle(*info.This());
    374   Object* source = Script::cast(JSValue::cast(object)->value())->name();
    375   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
    376 }
    377 
    378 
    379 void Accessors::ScriptNameSetter(
    380     v8::Local<v8::String> name,
    381     v8::Local<v8::Value> value,
    382     const v8::PropertyCallbackInfo<void>& info) {
    383   UNREACHABLE();
    384 }
    385 
    386 
    387 Handle<AccessorInfo> Accessors::ScriptNameInfo(
    388       Isolate* isolate, PropertyAttributes attributes) {
    389   return MakeAccessor(isolate,
    390                       isolate->factory()->name_string(),
    391                       &ScriptNameGetter,
    392                       &ScriptNameSetter,
    393                       attributes);
    394 }
    395 
    396 
    397 //
    398 // Accessors::ScriptSource
    399 //
    400 
    401 
    402 void Accessors::ScriptSourceGetter(
    403     v8::Local<v8::String> name,
    404     const v8::PropertyCallbackInfo<v8::Value>& info) {
    405   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    406   DisallowHeapAllocation no_allocation;
    407   HandleScope scope(isolate);
    408   Object* object = *Utils::OpenHandle(*info.This());
    409   Object* source = Script::cast(JSValue::cast(object)->value())->source();
    410   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
    411 }
    412 
    413 
    414 void Accessors::ScriptSourceSetter(
    415     v8::Local<v8::String> name,
    416     v8::Local<v8::Value> value,
    417     const v8::PropertyCallbackInfo<void>& info) {
    418   UNREACHABLE();
    419 }
    420 
    421 
    422 Handle<AccessorInfo> Accessors::ScriptSourceInfo(
    423       Isolate* isolate, PropertyAttributes attributes) {
    424   return MakeAccessor(isolate,
    425                       isolate->factory()->source_string(),
    426                       &ScriptSourceGetter,
    427                       &ScriptSourceSetter,
    428                       attributes);
    429 }
    430 
    431 
    432 //
    433 // Accessors::ScriptLineOffset
    434 //
    435 
    436 
    437 void Accessors::ScriptLineOffsetGetter(
    438     v8::Local<v8::String> name,
    439     const v8::PropertyCallbackInfo<v8::Value>& info) {
    440   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    441   DisallowHeapAllocation no_allocation;
    442   HandleScope scope(isolate);
    443   Object* object = *Utils::OpenHandle(*info.This());
    444   Object* res = Script::cast(JSValue::cast(object)->value())->line_offset();
    445   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
    446 }
    447 
    448 
    449 void Accessors::ScriptLineOffsetSetter(
    450     v8::Local<v8::String> name,
    451     v8::Local<v8::Value> value,
    452     const v8::PropertyCallbackInfo<void>& info) {
    453   UNREACHABLE();
    454 }
    455 
    456 
    457 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
    458       Isolate* isolate, PropertyAttributes attributes) {
    459   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    460         STATIC_ASCII_VECTOR("line_offset")));
    461   return MakeAccessor(isolate,
    462                       name,
    463                       &ScriptLineOffsetGetter,
    464                       &ScriptLineOffsetSetter,
    465                       attributes);
    466 }
    467 
    468 
    469 //
    470 // Accessors::ScriptType
    471 //
    472 
    473 
    474 void Accessors::ScriptTypeGetter(
    475     v8::Local<v8::String> name,
    476     const v8::PropertyCallbackInfo<v8::Value>& info) {
    477   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    478   DisallowHeapAllocation no_allocation;
    479   HandleScope scope(isolate);
    480   Object* object = *Utils::OpenHandle(*info.This());
    481   Object* res = Script::cast(JSValue::cast(object)->value())->type();
    482   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
    483 }
    484 
    485 
    486 void Accessors::ScriptTypeSetter(
    487     v8::Local<v8::String> name,
    488     v8::Local<v8::Value> value,
    489     const v8::PropertyCallbackInfo<void>& info) {
    490   UNREACHABLE();
    491 }
    492 
    493 
    494 Handle<AccessorInfo> Accessors::ScriptTypeInfo(
    495       Isolate* isolate, PropertyAttributes attributes) {
    496   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    497         STATIC_ASCII_VECTOR("type")));
    498   return MakeAccessor(isolate,
    499                       name,
    500                       &ScriptTypeGetter,
    501                       &ScriptTypeSetter,
    502                       attributes);
    503 }
    504 
    505 
    506 //
    507 // Accessors::ScriptCompilationType
    508 //
    509 
    510 
    511 void Accessors::ScriptCompilationTypeGetter(
    512     v8::Local<v8::String> name,
    513     const v8::PropertyCallbackInfo<v8::Value>& info) {
    514   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    515   DisallowHeapAllocation no_allocation;
    516   HandleScope scope(isolate);
    517   Object* object = *Utils::OpenHandle(*info.This());
    518   Object* res = Smi::FromInt(
    519       Script::cast(JSValue::cast(object)->value())->compilation_type());
    520   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
    521 }
    522 
    523 
    524 void Accessors::ScriptCompilationTypeSetter(
    525     v8::Local<v8::String> name,
    526     v8::Local<v8::Value> value,
    527     const v8::PropertyCallbackInfo<void>& info) {
    528   UNREACHABLE();
    529 }
    530 
    531 
    532 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
    533       Isolate* isolate, PropertyAttributes attributes) {
    534   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    535         STATIC_ASCII_VECTOR("compilation_type")));
    536   return MakeAccessor(isolate,
    537                       name,
    538                       &ScriptCompilationTypeGetter,
    539                       &ScriptCompilationTypeSetter,
    540                       attributes);
    541 }
    542 
    543 
    544 //
    545 // Accessors::ScriptGetLineEnds
    546 //
    547 
    548 
    549 void Accessors::ScriptLineEndsGetter(
    550     v8::Local<v8::String> name,
    551     const v8::PropertyCallbackInfo<v8::Value>& info) {
    552   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    553   HandleScope scope(isolate);
    554   Handle<Object> object = Utils::OpenHandle(*info.This());
    555   Handle<Script> script(
    556       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
    557   Script::InitLineEnds(script);
    558   ASSERT(script->line_ends()->IsFixedArray());
    559   Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
    560   // We do not want anyone to modify this array from JS.
    561   ASSERT(*line_ends == isolate->heap()->empty_fixed_array() ||
    562          line_ends->map() == isolate->heap()->fixed_cow_array_map());
    563   Handle<JSArray> js_array =
    564       isolate->factory()->NewJSArrayWithElements(line_ends);
    565   info.GetReturnValue().Set(Utils::ToLocal(js_array));
    566 }
    567 
    568 
    569 void Accessors::ScriptLineEndsSetter(
    570     v8::Local<v8::String> name,
    571     v8::Local<v8::Value> value,
    572     const v8::PropertyCallbackInfo<void>& info) {
    573   UNREACHABLE();
    574 }
    575 
    576 
    577 Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
    578       Isolate* isolate, PropertyAttributes attributes) {
    579   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    580         STATIC_ASCII_VECTOR("line_ends")));
    581   return MakeAccessor(isolate,
    582                       name,
    583                       &ScriptLineEndsGetter,
    584                       &ScriptLineEndsSetter,
    585                       attributes);
    586 }
    587 
    588 
    589 //
    590 // Accessors::ScriptGetContextData
    591 //
    592 
    593 
    594 void Accessors::ScriptContextDataGetter(
    595     v8::Local<v8::String> name,
    596     const v8::PropertyCallbackInfo<v8::Value>& info) {
    597   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    598   DisallowHeapAllocation no_allocation;
    599   HandleScope scope(isolate);
    600   Object* object = *Utils::OpenHandle(*info.This());
    601   Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
    602   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
    603 }
    604 
    605 
    606 void Accessors::ScriptContextDataSetter(
    607     v8::Local<v8::String> name,
    608     v8::Local<v8::Value> value,
    609     const v8::PropertyCallbackInfo<void>& info) {
    610   UNREACHABLE();
    611 }
    612 
    613 
    614 Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
    615       Isolate* isolate, PropertyAttributes attributes) {
    616   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    617         STATIC_ASCII_VECTOR("context_data")));
    618   return MakeAccessor(isolate,
    619                       name,
    620                       &ScriptContextDataGetter,
    621                       &ScriptContextDataSetter,
    622                       attributes);
    623 }
    624 
    625 
    626 //
    627 // Accessors::ScriptGetEvalFromScript
    628 //
    629 
    630 
    631 void Accessors::ScriptEvalFromScriptGetter(
    632     v8::Local<v8::String> name,
    633     const v8::PropertyCallbackInfo<v8::Value>& info) {
    634   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    635   HandleScope scope(isolate);
    636   Handle<Object> object = Utils::OpenHandle(*info.This());
    637   Handle<Script> script(
    638       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
    639   Handle<Object> result = isolate->factory()->undefined_value();
    640   if (!script->eval_from_shared()->IsUndefined()) {
    641     Handle<SharedFunctionInfo> eval_from_shared(
    642         SharedFunctionInfo::cast(script->eval_from_shared()));
    643     if (eval_from_shared->script()->IsScript()) {
    644       Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
    645       result = Script::GetWrapper(eval_from_script);
    646     }
    647   }
    648 
    649   info.GetReturnValue().Set(Utils::ToLocal(result));
    650 }
    651 
    652 
    653 void Accessors::ScriptEvalFromScriptSetter(
    654     v8::Local<v8::String> name,
    655     v8::Local<v8::Value> value,
    656     const v8::PropertyCallbackInfo<void>& info) {
    657   UNREACHABLE();
    658 }
    659 
    660 
    661 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
    662       Isolate* isolate, PropertyAttributes attributes) {
    663   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    664         STATIC_ASCII_VECTOR("eval_from_script")));
    665   return MakeAccessor(isolate,
    666                       name,
    667                       &ScriptEvalFromScriptGetter,
    668                       &ScriptEvalFromScriptSetter,
    669                       attributes);
    670 }
    671 
    672 
    673 //
    674 // Accessors::ScriptGetEvalFromScriptPosition
    675 //
    676 
    677 
    678 void Accessors::ScriptEvalFromScriptPositionGetter(
    679     v8::Local<v8::String> name,
    680     const v8::PropertyCallbackInfo<v8::Value>& info) {
    681   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    682   HandleScope scope(isolate);
    683   Handle<Object> object = Utils::OpenHandle(*info.This());
    684   Handle<Script> script(
    685       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
    686   Handle<Object> result = isolate->factory()->undefined_value();
    687   if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
    688     Handle<Code> code(SharedFunctionInfo::cast(
    689         script->eval_from_shared())->code());
    690     result = Handle<Object>(
    691         Smi::FromInt(code->SourcePosition(code->instruction_start() +
    692                      script->eval_from_instructions_offset()->value())),
    693         isolate);
    694   }
    695   info.GetReturnValue().Set(Utils::ToLocal(result));
    696 }
    697 
    698 
    699 void Accessors::ScriptEvalFromScriptPositionSetter(
    700     v8::Local<v8::String> name,
    701     v8::Local<v8::Value> value,
    702     const v8::PropertyCallbackInfo<void>& info) {
    703   UNREACHABLE();
    704 }
    705 
    706 
    707 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
    708       Isolate* isolate, PropertyAttributes attributes) {
    709   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    710         STATIC_ASCII_VECTOR("eval_from_script_position")));
    711   return MakeAccessor(isolate,
    712                       name,
    713                       &ScriptEvalFromScriptPositionGetter,
    714                       &ScriptEvalFromScriptPositionSetter,
    715                       attributes);
    716 }
    717 
    718 
    719 //
    720 // Accessors::ScriptGetEvalFromFunctionName
    721 //
    722 
    723 
    724 void Accessors::ScriptEvalFromFunctionNameGetter(
    725     v8::Local<v8::String> name,
    726     const v8::PropertyCallbackInfo<v8::Value>& info) {
    727   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    728   HandleScope scope(isolate);
    729   Handle<Object> object = Utils::OpenHandle(*info.This());
    730   Handle<Script> script(
    731       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
    732   Handle<Object> result;
    733   Handle<SharedFunctionInfo> shared(
    734       SharedFunctionInfo::cast(script->eval_from_shared()));
    735   // Find the name of the function calling eval.
    736   if (!shared->name()->IsUndefined()) {
    737     result = Handle<Object>(shared->name(), isolate);
    738   } else {
    739     result = Handle<Object>(shared->inferred_name(), isolate);
    740   }
    741   info.GetReturnValue().Set(Utils::ToLocal(result));
    742 }
    743 
    744 
    745 void Accessors::ScriptEvalFromFunctionNameSetter(
    746     v8::Local<v8::String> name,
    747     v8::Local<v8::Value> value,
    748     const v8::PropertyCallbackInfo<void>& info) {
    749   UNREACHABLE();
    750 }
    751 
    752 
    753 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
    754       Isolate* isolate, PropertyAttributes attributes) {
    755   Handle<String> name(isolate->factory()->InternalizeOneByteString(
    756         STATIC_ASCII_VECTOR("eval_from_function_name")));
    757   return MakeAccessor(isolate,
    758                       name,
    759                       &ScriptEvalFromFunctionNameGetter,
    760                       &ScriptEvalFromFunctionNameSetter,
    761                       attributes);
    762 }
    763 
    764 
    765 //
    766 // Accessors::FunctionPrototype
    767 //
    768 
    769 static Handle<Object> GetFunctionPrototype(Isolate* isolate,
    770                                            Handle<Object> receiver) {
    771   Handle<JSFunction> function;
    772   {
    773     DisallowHeapAllocation no_allocation;
    774     JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, *receiver);
    775     if (function_raw == NULL) return isolate->factory()->undefined_value();
    776     while (!function_raw->should_have_prototype()) {
    777       function_raw = FindInstanceOf<JSFunction>(isolate,
    778                                                 function_raw->GetPrototype());
    779       // There has to be one because we hit the getter.
    780       ASSERT(function_raw != NULL);
    781     }
    782     function = Handle<JSFunction>(function_raw, isolate);
    783   }
    784 
    785   if (!function->has_prototype()) {
    786     Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
    787     JSFunction::SetPrototype(function, proto);
    788   }
    789   return Handle<Object>(function->prototype(), isolate);
    790 }
    791 
    792 
    793 static Handle<Object> SetFunctionPrototype(Isolate* isolate,
    794                                            Handle<JSObject> receiver,
    795                                            Handle<Object> value) {
    796   Handle<JSFunction> function;
    797   {
    798     DisallowHeapAllocation no_allocation;
    799     JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, *receiver);
    800     if (function_raw == NULL) return isolate->factory()->undefined_value();
    801     function = Handle<JSFunction>(function_raw, isolate);
    802   }
    803 
    804   if (!function->should_have_prototype()) {
    805     // Since we hit this accessor, object will have no prototype property.
    806     MaybeHandle<Object> maybe_result =
    807         JSObject::SetOwnPropertyIgnoreAttributes(
    808             receiver, isolate->factory()->prototype_string(), value, NONE);
    809     return maybe_result.ToHandleChecked();
    810   }
    811 
    812   Handle<Object> old_value;
    813   bool is_observed = *function == *receiver && function->map()->is_observed();
    814   if (is_observed) {
    815     if (function->has_prototype())
    816       old_value = handle(function->prototype(), isolate);
    817     else
    818       old_value = isolate->factory()->NewFunctionPrototype(function);
    819   }
    820 
    821   JSFunction::SetPrototype(function, value);
    822   ASSERT(function->prototype() == *value);
    823 
    824   if (is_observed && !old_value->SameValue(*value)) {
    825     JSObject::EnqueueChangeRecord(
    826         function, "update", isolate->factory()->prototype_string(), old_value);
    827   }
    828 
    829   return function;
    830 }
    831 
    832 
    833 Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
    834   return GetFunctionPrototype(function->GetIsolate(), function);
    835 }
    836 
    837 
    838 Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
    839                                                Handle<Object> prototype) {
    840   ASSERT(function->should_have_prototype());
    841   Isolate* isolate = function->GetIsolate();
    842   return SetFunctionPrototype(isolate, function, prototype);
    843 }
    844 
    845 
    846 void Accessors::FunctionPrototypeGetter(
    847     v8::Local<v8::String> name,
    848     const v8::PropertyCallbackInfo<v8::Value>& info) {
    849   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    850   HandleScope scope(isolate);
    851   Handle<Object> object = GetThisFrom(info);
    852   Handle<Object> result = GetFunctionPrototype(isolate, object);
    853   info.GetReturnValue().Set(Utils::ToLocal(result));
    854 }
    855 
    856 
    857 void Accessors::FunctionPrototypeSetter(
    858     v8::Local<v8::String> name,
    859     v8::Local<v8::Value> val,
    860     const v8::PropertyCallbackInfo<void>& info) {
    861   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    862   HandleScope scope(isolate);
    863   Handle<JSObject> object =
    864       Handle<JSObject>::cast(Utils::OpenHandle(*info.This()));
    865   Handle<Object> value = Utils::OpenHandle(*val);
    866 
    867   SetFunctionPrototype(isolate, object, value);
    868 }
    869 
    870 
    871 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
    872       Isolate* isolate, PropertyAttributes attributes) {
    873   return MakeAccessor(isolate,
    874                       isolate->factory()->prototype_string(),
    875                       &FunctionPrototypeGetter,
    876                       &FunctionPrototypeSetter,
    877                       attributes);
    878 }
    879 
    880 
    881 //
    882 // Accessors::FunctionLength
    883 //
    884 
    885 
    886 void Accessors::FunctionLengthGetter(
    887     v8::Local<v8::String> name,
    888     const v8::PropertyCallbackInfo<v8::Value>& info) {
    889   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    890   HandleScope scope(isolate);
    891   Handle<Object> object = GetThisFrom(info);
    892   MaybeHandle<JSFunction> maybe_function;
    893 
    894   {
    895     DisallowHeapAllocation no_allocation;
    896     JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
    897     if (function != NULL) maybe_function = Handle<JSFunction>(function);
    898   }
    899 
    900   int length = 0;
    901   Handle<JSFunction> function;
    902   if (maybe_function.ToHandle(&function)) {
    903     if (function->shared()->is_compiled()) {
    904       length = function->shared()->length();
    905     } else {
    906       // If the function isn't compiled yet, the length is not computed
    907       // correctly yet. Compile it now and return the right length.
    908       if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) {
    909         length = function->shared()->length();
    910       }
    911       if (isolate->has_pending_exception()) {
    912         isolate->OptionalRescheduleException(false);
    913       }
    914     }
    915   }
    916   Handle<Object> result(Smi::FromInt(length), isolate);
    917   info.GetReturnValue().Set(Utils::ToLocal(result));
    918 }
    919 
    920 
    921 void Accessors::FunctionLengthSetter(
    922     v8::Local<v8::String> name,
    923     v8::Local<v8::Value> val,
    924     const v8::PropertyCallbackInfo<void>& info) {
    925   // Do nothing.
    926 }
    927 
    928 
    929 Handle<AccessorInfo> Accessors::FunctionLengthInfo(
    930       Isolate* isolate, PropertyAttributes attributes) {
    931   return MakeAccessor(isolate,
    932                       isolate->factory()->length_string(),
    933                       &FunctionLengthGetter,
    934                       &FunctionLengthSetter,
    935                       attributes);
    936 }
    937 
    938 
    939 //
    940 // Accessors::FunctionName
    941 //
    942 
    943 
    944 void Accessors::FunctionNameGetter(
    945     v8::Local<v8::String> name,
    946     const v8::PropertyCallbackInfo<v8::Value>& info) {
    947   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
    948   HandleScope scope(isolate);
    949   Handle<Object> object = GetThisFrom(info);
    950   MaybeHandle<JSFunction> maybe_function;
    951 
    952   {
    953     DisallowHeapAllocation no_allocation;
    954     JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
    955     if (function != NULL) maybe_function = Handle<JSFunction>(function);
    956   }
    957 
    958   Handle<JSFunction> function;
    959   Handle<Object> result;
    960   if (maybe_function.ToHandle(&function)) {
    961     result = Handle<Object>(function->shared()->name(), isolate);
    962   } else {
    963     result = isolate->factory()->undefined_value();
    964   }
    965   info.GetReturnValue().Set(Utils::ToLocal(result));
    966 }
    967 
    968 
    969 void Accessors::FunctionNameSetter(
    970     v8::Local<v8::String> name,
    971     v8::Local<v8::Value> val,
    972     const v8::PropertyCallbackInfo<void>& info) {
    973   // Do nothing.
    974 }
    975 
    976 
    977 Handle<AccessorInfo> Accessors::FunctionNameInfo(
    978       Isolate* isolate, PropertyAttributes attributes) {
    979   return MakeAccessor(isolate,
    980                       isolate->factory()->name_string(),
    981                       &FunctionNameGetter,
    982                       &FunctionNameSetter,
    983                       attributes);
    984 }
    985 
    986 
    987 //
    988 // Accessors::FunctionArguments
    989 //
    990 
    991 
    992 static Handle<Object> ArgumentsForInlinedFunction(
    993     JavaScriptFrame* frame,
    994     Handle<JSFunction> inlined_function,
    995     int inlined_frame_index) {
    996   Isolate* isolate = inlined_function->GetIsolate();
    997   Factory* factory = isolate->factory();
    998   SlotRefValueBuilder slot_refs(
    999       frame,
   1000       inlined_frame_index,
   1001       inlined_function->shared()->formal_parameter_count());
   1002 
   1003   int args_count = slot_refs.args_length();
   1004   Handle<JSObject> arguments =
   1005       factory->NewArgumentsObject(inlined_function, args_count);
   1006   Handle<FixedArray> array = factory->NewFixedArray(args_count);
   1007   slot_refs.Prepare(isolate);
   1008   for (int i = 0; i < args_count; ++i) {
   1009     Handle<Object> value = slot_refs.GetNext(isolate, 0);
   1010     array->set(i, *value);
   1011   }
   1012   slot_refs.Finish(isolate);
   1013   arguments->set_elements(*array);
   1014 
   1015   // Return the freshly allocated arguments object.
   1016   return arguments;
   1017 }
   1018 
   1019 
   1020 static int FindFunctionInFrame(JavaScriptFrame* frame,
   1021                                Handle<JSFunction> function) {
   1022   DisallowHeapAllocation no_allocation;
   1023   List<JSFunction*> functions(2);
   1024   frame->GetFunctions(&functions);
   1025   for (int i = functions.length() - 1; i >= 0; i--) {
   1026     if (functions[i] == *function) return i;
   1027   }
   1028   return -1;
   1029 }
   1030 
   1031 
   1032 Handle<Object> GetFunctionArguments(Isolate* isolate,
   1033                                     Handle<JSFunction> function) {
   1034   if (function->shared()->native()) return isolate->factory()->null_value();
   1035 
   1036   // Find the top invocation of the function by traversing frames.
   1037   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
   1038     JavaScriptFrame* frame = it.frame();
   1039     int function_index = FindFunctionInFrame(frame, function);
   1040     if (function_index < 0) continue;
   1041 
   1042     if (function_index > 0) {
   1043       // The function in question was inlined.  Inlined functions have the
   1044       // correct number of arguments and no allocated arguments object, so
   1045       // we can construct a fresh one by interpreting the function's
   1046       // deoptimization input data.
   1047       return ArgumentsForInlinedFunction(frame, function, function_index);
   1048     }
   1049 
   1050     if (!frame->is_optimized()) {
   1051       // If there is an arguments variable in the stack, we return that.
   1052       Handle<ScopeInfo> scope_info(function->shared()->scope_info());
   1053       int index = scope_info->StackSlotIndex(
   1054           isolate->heap()->arguments_string());
   1055       if (index >= 0) {
   1056         Handle<Object> arguments(frame->GetExpression(index), isolate);
   1057         if (!arguments->IsArgumentsMarker()) return arguments;
   1058       }
   1059     }
   1060 
   1061     // If there is no arguments variable in the stack or we have an
   1062     // optimized frame, we find the frame that holds the actual arguments
   1063     // passed to the function.
   1064     it.AdvanceToArgumentsFrame();
   1065     frame = it.frame();
   1066 
   1067     // Get the number of arguments and construct an arguments object
   1068     // mirror for the right frame.
   1069     const int length = frame->ComputeParametersCount();
   1070     Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
   1071         function, length);
   1072     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
   1073 
   1074     // Copy the parameters to the arguments object.
   1075     ASSERT(array->length() == length);
   1076     for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
   1077     arguments->set_elements(*array);
   1078 
   1079     // Return the freshly allocated arguments object.
   1080     return arguments;
   1081   }
   1082 
   1083   // No frame corresponding to the given function found. Return null.
   1084   return isolate->factory()->null_value();
   1085 }
   1086 
   1087 
   1088 Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
   1089   return GetFunctionArguments(function->GetIsolate(), function);
   1090 }
   1091 
   1092 
   1093 void Accessors::FunctionArgumentsGetter(
   1094     v8::Local<v8::String> name,
   1095     const v8::PropertyCallbackInfo<v8::Value>& info) {
   1096   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   1097   HandleScope scope(isolate);
   1098   Handle<Object> object = GetThisFrom(info);
   1099   MaybeHandle<JSFunction> maybe_function;
   1100 
   1101   {
   1102     DisallowHeapAllocation no_allocation;
   1103     JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
   1104     if (function != NULL) maybe_function = Handle<JSFunction>(function);
   1105   }
   1106 
   1107   Handle<JSFunction> function;
   1108   Handle<Object> result;
   1109   if (maybe_function.ToHandle(&function)) {
   1110     result = GetFunctionArguments(isolate, function);
   1111   } else {
   1112     result = isolate->factory()->undefined_value();
   1113   }
   1114   info.GetReturnValue().Set(Utils::ToLocal(result));
   1115 }
   1116 
   1117 
   1118 void Accessors::FunctionArgumentsSetter(
   1119     v8::Local<v8::String> name,
   1120     v8::Local<v8::Value> val,
   1121     const v8::PropertyCallbackInfo<void>& info) {
   1122   // Do nothing.
   1123 }
   1124 
   1125 
   1126 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
   1127       Isolate* isolate, PropertyAttributes attributes) {
   1128   return MakeAccessor(isolate,
   1129                       isolate->factory()->arguments_string(),
   1130                       &FunctionArgumentsGetter,
   1131                       &FunctionArgumentsSetter,
   1132                       attributes);
   1133 }
   1134 
   1135 
   1136 //
   1137 // Accessors::FunctionCaller
   1138 //
   1139 
   1140 
   1141 static inline bool AllowAccessToFunction(Context* current_context,
   1142                                          JSFunction* function) {
   1143   return current_context->HasSameSecurityTokenAs(function->context());
   1144 }
   1145 
   1146 
   1147 class FrameFunctionIterator {
   1148  public:
   1149   FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
   1150       : isolate_(isolate),
   1151         frame_iterator_(isolate),
   1152         functions_(2),
   1153         index_(0) {
   1154     GetFunctions();
   1155   }
   1156   JSFunction* next() {
   1157     while (true) {
   1158       if (functions_.length() == 0) return NULL;
   1159       JSFunction* next_function = functions_[index_];
   1160       index_--;
   1161       if (index_ < 0) {
   1162         GetFunctions();
   1163       }
   1164       // Skip functions from other origins.
   1165       if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
   1166       return next_function;
   1167     }
   1168   }
   1169 
   1170   // Iterate through functions until the first occurence of 'function'.
   1171   // Returns true if 'function' is found, and false if the iterator ends
   1172   // without finding it.
   1173   bool Find(JSFunction* function) {
   1174     JSFunction* next_function;
   1175     do {
   1176       next_function = next();
   1177       if (next_function == function) return true;
   1178     } while (next_function != NULL);
   1179     return false;
   1180   }
   1181 
   1182  private:
   1183   void GetFunctions() {
   1184     functions_.Rewind(0);
   1185     if (frame_iterator_.done()) return;
   1186     JavaScriptFrame* frame = frame_iterator_.frame();
   1187     frame->GetFunctions(&functions_);
   1188     ASSERT(functions_.length() > 0);
   1189     frame_iterator_.Advance();
   1190     index_ = functions_.length() - 1;
   1191   }
   1192   Isolate* isolate_;
   1193   JavaScriptFrameIterator frame_iterator_;
   1194   List<JSFunction*> functions_;
   1195   int index_;
   1196 };
   1197 
   1198 
   1199 MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
   1200                                    Handle<JSFunction> function) {
   1201   DisallowHeapAllocation no_allocation;
   1202   FrameFunctionIterator it(isolate, no_allocation);
   1203   if (function->shared()->native()) {
   1204     return MaybeHandle<JSFunction>();
   1205   }
   1206   // Find the function from the frames.
   1207   if (!it.Find(*function)) {
   1208     // No frame corresponding to the given function found. Return null.
   1209     return MaybeHandle<JSFunction>();
   1210   }
   1211   // Find previously called non-toplevel function.
   1212   JSFunction* caller;
   1213   do {
   1214     caller = it.next();
   1215     if (caller == NULL) return MaybeHandle<JSFunction>();
   1216   } while (caller->shared()->is_toplevel());
   1217 
   1218   // If caller is a built-in function and caller's caller is also built-in,
   1219   // use that instead.
   1220   JSFunction* potential_caller = caller;
   1221   while (potential_caller != NULL && potential_caller->IsBuiltin()) {
   1222     caller = potential_caller;
   1223     potential_caller = it.next();
   1224   }
   1225   if (!caller->shared()->native() && potential_caller != NULL) {
   1226     caller = potential_caller;
   1227   }
   1228   // If caller is bound, return null. This is compatible with JSC, and
   1229   // allows us to make bound functions use the strict function map
   1230   // and its associated throwing caller and arguments.
   1231   if (caller->shared()->bound()) {
   1232     return MaybeHandle<JSFunction>();
   1233   }
   1234   // Censor if the caller is not a sloppy mode function.
   1235   // Change from ES5, which used to throw, see:
   1236   // https://bugs.ecmascript.org/show_bug.cgi?id=310
   1237   if (caller->shared()->strict_mode() == STRICT) {
   1238     return MaybeHandle<JSFunction>();
   1239   }
   1240   // Don't return caller from another security context.
   1241   if (!AllowAccessToFunction(isolate->context(), caller)) {
   1242     return MaybeHandle<JSFunction>();
   1243   }
   1244   return Handle<JSFunction>(caller);
   1245 }
   1246 
   1247 
   1248 void Accessors::FunctionCallerGetter(
   1249     v8::Local<v8::String> name,
   1250     const v8::PropertyCallbackInfo<v8::Value>& info) {
   1251   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   1252   HandleScope scope(isolate);
   1253   Handle<Object> object = GetThisFrom(info);
   1254   MaybeHandle<JSFunction> maybe_function;
   1255   {
   1256     DisallowHeapAllocation no_allocation;
   1257     JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
   1258     if (function != NULL) maybe_function = Handle<JSFunction>(function);
   1259   }
   1260   Handle<JSFunction> function;
   1261   Handle<Object> result;
   1262   if (maybe_function.ToHandle(&function)) {
   1263     MaybeHandle<JSFunction> maybe_caller;
   1264     maybe_caller = FindCaller(isolate, function);
   1265     Handle<JSFunction> caller;
   1266     if (maybe_caller.ToHandle(&caller)) {
   1267       result = caller;
   1268     } else {
   1269       result = isolate->factory()->null_value();
   1270     }
   1271   } else {
   1272     result = isolate->factory()->undefined_value();
   1273   }
   1274   info.GetReturnValue().Set(Utils::ToLocal(result));
   1275 }
   1276 
   1277 
   1278 void Accessors::FunctionCallerSetter(
   1279     v8::Local<v8::String> name,
   1280     v8::Local<v8::Value> val,
   1281     const v8::PropertyCallbackInfo<void>& info) {
   1282   // Do nothing.
   1283 }
   1284 
   1285 
   1286 Handle<AccessorInfo> Accessors::FunctionCallerInfo(
   1287       Isolate* isolate, PropertyAttributes attributes) {
   1288   return MakeAccessor(isolate,
   1289                       isolate->factory()->caller_string(),
   1290                       &FunctionCallerGetter,
   1291                       &FunctionCallerSetter,
   1292                       attributes);
   1293 }
   1294 
   1295 
   1296 //
   1297 // Accessors::MakeModuleExport
   1298 //
   1299 
   1300 static void ModuleGetExport(
   1301     v8::Local<v8::String> property,
   1302     const v8::PropertyCallbackInfo<v8::Value>& info) {
   1303   JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
   1304   Context* context = Context::cast(instance->context());
   1305   ASSERT(context->IsModuleContext());
   1306   int slot = info.Data()->Int32Value();
   1307   Object* value = context->get(slot);
   1308   Isolate* isolate = instance->GetIsolate();
   1309   if (value->IsTheHole()) {
   1310     Handle<String> name = v8::Utils::OpenHandle(*property);
   1311     isolate->ScheduleThrow(
   1312         *isolate->factory()->NewReferenceError("not_defined",
   1313                                                HandleVector(&name, 1)));
   1314     return;
   1315   }
   1316   info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
   1317 }
   1318 
   1319 
   1320 static void ModuleSetExport(
   1321     v8::Local<v8::String> property,
   1322     v8::Local<v8::Value> value,
   1323     const v8::PropertyCallbackInfo<v8::Value>& info) {
   1324   JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
   1325   Context* context = Context::cast(instance->context());
   1326   ASSERT(context->IsModuleContext());
   1327   int slot = info.Data()->Int32Value();
   1328   Object* old_value = context->get(slot);
   1329   if (old_value->IsTheHole()) {
   1330     Handle<String> name = v8::Utils::OpenHandle(*property);
   1331     Isolate* isolate = instance->GetIsolate();
   1332     isolate->ScheduleThrow(
   1333         *isolate->factory()->NewReferenceError("not_defined",
   1334                                                HandleVector(&name, 1)));
   1335     return;
   1336   }
   1337   context->set(slot, *v8::Utils::OpenHandle(*value));
   1338 }
   1339 
   1340 
   1341 Handle<AccessorInfo> Accessors::MakeModuleExport(
   1342     Handle<String> name,
   1343     int index,
   1344     PropertyAttributes attributes) {
   1345   Isolate* isolate = name->GetIsolate();
   1346   Factory* factory = isolate->factory();
   1347   Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
   1348   info->set_property_attributes(attributes);
   1349   info->set_all_can_read(true);
   1350   info->set_all_can_write(true);
   1351   info->set_name(*name);
   1352   info->set_data(Smi::FromInt(index));
   1353   Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport);
   1354   Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport);
   1355   info->set_getter(*getter);
   1356   if (!(attributes & ReadOnly)) info->set_setter(*setter);
   1357   return info;
   1358 }
   1359 
   1360 
   1361 } }  // namespace v8::internal
   1362