Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 #include "accessors.h"
     30 
     31 #include "contexts.h"
     32 #include "deoptimizer.h"
     33 #include "execution.h"
     34 #include "factory.h"
     35 #include "frames-inl.h"
     36 #include "isolate.h"
     37 #include "list-inl.h"
     38 #include "property-details.h"
     39 
     40 namespace v8 {
     41 namespace internal {
     42 
     43 
     44 template <class C>
     45 static C* FindInstanceOf(Isolate* isolate, Object* obj) {
     46   for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype(isolate)) {
     47     if (Is<C>(cur)) return C::cast(cur);
     48   }
     49   return NULL;
     50 }
     51 
     52 
     53 // Entry point that never should be called.
     54 MaybeObject* Accessors::IllegalSetter(JSObject*, Object*, void*) {
     55   UNREACHABLE();
     56   return NULL;
     57 }
     58 
     59 
     60 Object* Accessors::IllegalGetAccessor(Object* object, void*) {
     61   UNREACHABLE();
     62   return object;
     63 }
     64 
     65 
     66 MaybeObject* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) {
     67   // According to ECMA-262, section 8.6.2.2, page 28, setting
     68   // read-only properties must be silently ignored.
     69   return value;
     70 }
     71 
     72 
     73 //
     74 // Accessors::ArrayLength
     75 //
     76 
     77 
     78 MaybeObject* Accessors::ArrayGetLength(Object* object, void*) {
     79   // Traverse the prototype chain until we reach an array.
     80   JSArray* holder = FindInstanceOf<JSArray>(Isolate::Current(), object);
     81   return holder == NULL ? Smi::FromInt(0) : holder->length();
     82 }
     83 
     84 
     85 // The helper function will 'flatten' Number objects.
     86 Object* Accessors::FlattenNumber(Object* value) {
     87   if (value->IsNumber() || !value->IsJSValue()) return value;
     88   JSValue* wrapper = JSValue::cast(value);
     89   ASSERT(Isolate::Current()->context()->native_context()->number_function()->
     90       has_initial_map());
     91   Map* number_map = Isolate::Current()->context()->native_context()->
     92       number_function()->initial_map();
     93   if (wrapper->map() == number_map) return wrapper->value();
     94   return value;
     95 }
     96 
     97 
     98 MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
     99   Isolate* isolate = object->GetIsolate();
    100 
    101   // This means one of the object's prototypes is a JSArray and the
    102   // object does not have a 'length' property.  Calling SetProperty
    103   // causes an infinite loop.
    104   if (!object->IsJSArray()) {
    105     return object->SetLocalPropertyIgnoreAttributes(
    106         isolate->heap()->length_string(), value, NONE);
    107   }
    108 
    109   value = FlattenNumber(value);
    110 
    111   // Need to call methods that may trigger GC.
    112   HandleScope scope(isolate);
    113 
    114   // Protect raw pointers.
    115   Handle<JSArray> array_handle(JSArray::cast(object), isolate);
    116   Handle<Object> value_handle(value, isolate);
    117 
    118   bool has_exception;
    119   Handle<Object> uint32_v = Execution::ToUint32(value_handle, &has_exception);
    120   if (has_exception) return Failure::Exception();
    121   Handle<Object> number_v = Execution::ToNumber(value_handle, &has_exception);
    122   if (has_exception) return Failure::Exception();
    123 
    124   if (uint32_v->Number() == number_v->Number()) {
    125     return array_handle->SetElementsLength(*uint32_v);
    126   }
    127   return isolate->Throw(
    128       *isolate->factory()->NewRangeError("invalid_array_length",
    129                                          HandleVector<Object>(NULL, 0)));
    130 }
    131 
    132 
    133 const AccessorDescriptor Accessors::ArrayLength = {
    134   ArrayGetLength,
    135   ArraySetLength,
    136   0
    137 };
    138 
    139 
    140 //
    141 // Accessors::StringLength
    142 //
    143 
    144 
    145 MaybeObject* Accessors::StringGetLength(Object* object, void*) {
    146   Object* value = object;
    147   if (object->IsJSValue()) value = JSValue::cast(object)->value();
    148   if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
    149   // If object is not a string we return 0 to be compatible with WebKit.
    150   // Note: Firefox returns the length of ToString(object).
    151   return Smi::FromInt(0);
    152 }
    153 
    154 
    155 const AccessorDescriptor Accessors::StringLength = {
    156   StringGetLength,
    157   IllegalSetter,
    158   0
    159 };
    160 
    161 
    162 //
    163 // Accessors::ScriptSource
    164 //
    165 
    166 
    167 MaybeObject* Accessors::ScriptGetSource(Object* object, void*) {
    168   Object* script = JSValue::cast(object)->value();
    169   return Script::cast(script)->source();
    170 }
    171 
    172 
    173 const AccessorDescriptor Accessors::ScriptSource = {
    174   ScriptGetSource,
    175   IllegalSetter,
    176   0
    177 };
    178 
    179 
    180 //
    181 // Accessors::ScriptName
    182 //
    183 
    184 
    185 MaybeObject* Accessors::ScriptGetName(Object* object, void*) {
    186   Object* script = JSValue::cast(object)->value();
    187   return Script::cast(script)->name();
    188 }
    189 
    190 
    191 const AccessorDescriptor Accessors::ScriptName = {
    192   ScriptGetName,
    193   IllegalSetter,
    194   0
    195 };
    196 
    197 
    198 //
    199 // Accessors::ScriptId
    200 //
    201 
    202 
    203 MaybeObject* Accessors::ScriptGetId(Object* object, void*) {
    204   Object* script = JSValue::cast(object)->value();
    205   return Script::cast(script)->id();
    206 }
    207 
    208 
    209 const AccessorDescriptor Accessors::ScriptId = {
    210   ScriptGetId,
    211   IllegalSetter,
    212   0
    213 };
    214 
    215 
    216 //
    217 // Accessors::ScriptLineOffset
    218 //
    219 
    220 
    221 MaybeObject* Accessors::ScriptGetLineOffset(Object* object, void*) {
    222   Object* script = JSValue::cast(object)->value();
    223   return Script::cast(script)->line_offset();
    224 }
    225 
    226 
    227 const AccessorDescriptor Accessors::ScriptLineOffset = {
    228   ScriptGetLineOffset,
    229   IllegalSetter,
    230   0
    231 };
    232 
    233 
    234 //
    235 // Accessors::ScriptColumnOffset
    236 //
    237 
    238 
    239 MaybeObject* Accessors::ScriptGetColumnOffset(Object* object, void*) {
    240   Object* script = JSValue::cast(object)->value();
    241   return Script::cast(script)->column_offset();
    242 }
    243 
    244 
    245 const AccessorDescriptor Accessors::ScriptColumnOffset = {
    246   ScriptGetColumnOffset,
    247   IllegalSetter,
    248   0
    249 };
    250 
    251 
    252 //
    253 // Accessors::ScriptData
    254 //
    255 
    256 
    257 MaybeObject* Accessors::ScriptGetData(Object* object, void*) {
    258   Object* script = JSValue::cast(object)->value();
    259   return Script::cast(script)->data();
    260 }
    261 
    262 
    263 const AccessorDescriptor Accessors::ScriptData = {
    264   ScriptGetData,
    265   IllegalSetter,
    266   0
    267 };
    268 
    269 
    270 //
    271 // Accessors::ScriptType
    272 //
    273 
    274 
    275 MaybeObject* Accessors::ScriptGetType(Object* object, void*) {
    276   Object* script = JSValue::cast(object)->value();
    277   return Script::cast(script)->type();
    278 }
    279 
    280 
    281 const AccessorDescriptor Accessors::ScriptType = {
    282   ScriptGetType,
    283   IllegalSetter,
    284   0
    285 };
    286 
    287 
    288 //
    289 // Accessors::ScriptCompilationType
    290 //
    291 
    292 
    293 MaybeObject* Accessors::ScriptGetCompilationType(Object* object, void*) {
    294   Object* script = JSValue::cast(object)->value();
    295   return Smi::FromInt(Script::cast(script)->compilation_type());
    296 }
    297 
    298 
    299 const AccessorDescriptor Accessors::ScriptCompilationType = {
    300   ScriptGetCompilationType,
    301   IllegalSetter,
    302   0
    303 };
    304 
    305 
    306 //
    307 // Accessors::ScriptGetLineEnds
    308 //
    309 
    310 
    311 MaybeObject* Accessors::ScriptGetLineEnds(Object* object, void*) {
    312   JSValue* wrapper = JSValue::cast(object);
    313   Isolate* isolate = wrapper->GetIsolate();
    314   HandleScope scope(isolate);
    315   Handle<Script> script(Script::cast(wrapper->value()), isolate);
    316   InitScriptLineEnds(script);
    317   ASSERT(script->line_ends()->IsFixedArray());
    318   Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
    319   // We do not want anyone to modify this array from JS.
    320   ASSERT(*line_ends == isolate->heap()->empty_fixed_array() ||
    321          line_ends->map() == isolate->heap()->fixed_cow_array_map());
    322   Handle<JSArray> js_array =
    323       isolate->factory()->NewJSArrayWithElements(line_ends);
    324   return *js_array;
    325 }
    326 
    327 
    328 const AccessorDescriptor Accessors::ScriptLineEnds = {
    329   ScriptGetLineEnds,
    330   IllegalSetter,
    331   0
    332 };
    333 
    334 
    335 //
    336 // Accessors::ScriptGetContextData
    337 //
    338 
    339 
    340 MaybeObject* Accessors::ScriptGetContextData(Object* object, void*) {
    341   Object* script = JSValue::cast(object)->value();
    342   return Script::cast(script)->context_data();
    343 }
    344 
    345 
    346 const AccessorDescriptor Accessors::ScriptContextData = {
    347   ScriptGetContextData,
    348   IllegalSetter,
    349   0
    350 };
    351 
    352 
    353 //
    354 // Accessors::ScriptGetEvalFromScript
    355 //
    356 
    357 
    358 MaybeObject* Accessors::ScriptGetEvalFromScript(Object* object, void*) {
    359   Object* script = JSValue::cast(object)->value();
    360   if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
    361     Handle<SharedFunctionInfo> eval_from_shared(
    362         SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
    363 
    364     if (eval_from_shared->script()->IsScript()) {
    365       Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
    366       return *GetScriptWrapper(eval_from_script);
    367     }
    368   }
    369   return HEAP->undefined_value();
    370 }
    371 
    372 
    373 const AccessorDescriptor Accessors::ScriptEvalFromScript = {
    374   ScriptGetEvalFromScript,
    375   IllegalSetter,
    376   0
    377 };
    378 
    379 
    380 //
    381 // Accessors::ScriptGetEvalFromScriptPosition
    382 //
    383 
    384 
    385 MaybeObject* Accessors::ScriptGetEvalFromScriptPosition(Object* object, void*) {
    386   Script* raw_script = Script::cast(JSValue::cast(object)->value());
    387   HandleScope scope(raw_script->GetIsolate());
    388   Handle<Script> script(raw_script);
    389 
    390   // If this is not a script compiled through eval there is no eval position.
    391   if (script->compilation_type() != Script::COMPILATION_TYPE_EVAL) {
    392     return script->GetHeap()->undefined_value();
    393   }
    394 
    395   // Get the function from where eval was called and find the source position
    396   // from the instruction offset.
    397   Handle<Code> code(SharedFunctionInfo::cast(
    398       script->eval_from_shared())->code());
    399   return Smi::FromInt(code->SourcePosition(code->instruction_start() +
    400                       script->eval_from_instructions_offset()->value()));
    401 }
    402 
    403 
    404 const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
    405   ScriptGetEvalFromScriptPosition,
    406   IllegalSetter,
    407   0
    408 };
    409 
    410 
    411 //
    412 // Accessors::ScriptGetEvalFromFunctionName
    413 //
    414 
    415 
    416 MaybeObject* Accessors::ScriptGetEvalFromFunctionName(Object* object, void*) {
    417   Object* script = JSValue::cast(object)->value();
    418   Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
    419       Script::cast(script)->eval_from_shared()));
    420 
    421 
    422   // Find the name of the function calling eval.
    423   if (!shared->name()->IsUndefined()) {
    424     return shared->name();
    425   } else {
    426     return shared->inferred_name();
    427   }
    428 }
    429 
    430 
    431 const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
    432   ScriptGetEvalFromFunctionName,
    433   IllegalSetter,
    434   0
    435 };
    436 
    437 
    438 //
    439 // Accessors::FunctionPrototype
    440 //
    441 
    442 
    443 Handle<Object> Accessors::FunctionGetPrototype(Handle<Object> object) {
    444   Isolate* isolate = Isolate::Current();
    445   CALL_HEAP_FUNCTION(
    446       isolate, Accessors::FunctionGetPrototype(*object, 0), Object);
    447 }
    448 
    449 
    450 MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) {
    451   Isolate* isolate = Isolate::Current();
    452   JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
    453   if (function_raw == NULL) return isolate->heap()->undefined_value();
    454   while (!function_raw->should_have_prototype()) {
    455     function_raw = FindInstanceOf<JSFunction>(isolate,
    456                                               function_raw->GetPrototype());
    457     // There has to be one because we hit the getter.
    458     ASSERT(function_raw != NULL);
    459   }
    460 
    461   if (!function_raw->has_prototype()) {
    462     HandleScope scope(isolate);
    463     Handle<JSFunction> function(function_raw);
    464     Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
    465     JSFunction::SetPrototype(function, proto);
    466     function_raw = *function;
    467   }
    468   return function_raw->prototype();
    469 }
    470 
    471 
    472 MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
    473                                              Object* value_raw,
    474                                              void*) {
    475   Isolate* isolate = object->GetIsolate();
    476   Heap* heap = isolate->heap();
    477   JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
    478   if (function_raw == NULL) return heap->undefined_value();
    479   if (!function_raw->should_have_prototype()) {
    480     // Since we hit this accessor, object will have no prototype property.
    481     return object->SetLocalPropertyIgnoreAttributes(heap->prototype_string(),
    482                                                     value_raw,
    483                                                     NONE);
    484   }
    485 
    486   HandleScope scope(isolate);
    487   Handle<JSFunction> function(function_raw, isolate);
    488   Handle<Object> value(value_raw, isolate);
    489 
    490   Handle<Object> old_value;
    491   bool is_observed =
    492       FLAG_harmony_observation &&
    493       *function == object &&
    494       function->map()->is_observed();
    495   if (is_observed) {
    496     if (function->has_prototype())
    497       old_value = handle(function->prototype(), isolate);
    498     else
    499       old_value = isolate->factory()->NewFunctionPrototype(function);
    500   }
    501 
    502   JSFunction::SetPrototype(function, value);
    503   ASSERT(function->prototype() == *value);
    504 
    505   if (is_observed && !old_value->SameValue(*value)) {
    506     JSObject::EnqueueChangeRecord(
    507         function, "updated", isolate->factory()->prototype_string(), old_value);
    508   }
    509 
    510   return *function;
    511 }
    512 
    513 
    514 const AccessorDescriptor Accessors::FunctionPrototype = {
    515   FunctionGetPrototype,
    516   FunctionSetPrototype,
    517   0
    518 };
    519 
    520 
    521 //
    522 // Accessors::FunctionLength
    523 //
    524 
    525 
    526 MaybeObject* Accessors::FunctionGetLength(Object* object, void*) {
    527   Isolate* isolate = Isolate::Current();
    528   JSFunction* function = FindInstanceOf<JSFunction>(isolate, object);
    529   if (function == NULL) return Smi::FromInt(0);
    530   // Check if already compiled.
    531   if (function->shared()->is_compiled()) {
    532     return Smi::FromInt(function->shared()->length());
    533   }
    534   // If the function isn't compiled yet, the length is not computed correctly
    535   // yet. Compile it now and return the right length.
    536   HandleScope scope(isolate);
    537   Handle<JSFunction> handle(function);
    538   if (JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) {
    539     return Smi::FromInt(handle->shared()->length());
    540   }
    541   return Failure::Exception();
    542 }
    543 
    544 
    545 const AccessorDescriptor Accessors::FunctionLength = {
    546   FunctionGetLength,
    547   ReadOnlySetAccessor,
    548   0
    549 };
    550 
    551 
    552 //
    553 // Accessors::FunctionName
    554 //
    555 
    556 
    557 MaybeObject* Accessors::FunctionGetName(Object* object, void*) {
    558   Isolate* isolate = Isolate::Current();
    559   JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
    560   return holder == NULL
    561       ? isolate->heap()->undefined_value()
    562       : holder->shared()->name();
    563 }
    564 
    565 
    566 const AccessorDescriptor Accessors::FunctionName = {
    567   FunctionGetName,
    568   ReadOnlySetAccessor,
    569   0
    570 };
    571 
    572 
    573 //
    574 // Accessors::FunctionArguments
    575 //
    576 
    577 
    578 Handle<Object> Accessors::FunctionGetArguments(Handle<Object> object) {
    579   Isolate* isolate = Isolate::Current();
    580   CALL_HEAP_FUNCTION(
    581       isolate, Accessors::FunctionGetArguments(*object, 0), Object);
    582 }
    583 
    584 
    585 static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
    586     JavaScriptFrame* frame,
    587     Handle<JSFunction> inlined_function,
    588     int inlined_frame_index) {
    589   Isolate* isolate = inlined_function->GetIsolate();
    590   Factory* factory = isolate->factory();
    591   Vector<SlotRef> args_slots =
    592       SlotRef::ComputeSlotMappingForArguments(
    593           frame,
    594           inlined_frame_index,
    595           inlined_function->shared()->formal_parameter_count());
    596   int args_count = args_slots.length();
    597   Handle<JSObject> arguments =
    598       factory->NewArgumentsObject(inlined_function, args_count);
    599   Handle<FixedArray> array = factory->NewFixedArray(args_count);
    600   for (int i = 0; i < args_count; ++i) {
    601     Handle<Object> value = args_slots[i].GetValue(isolate);
    602     array->set(i, *value);
    603   }
    604   arguments->set_elements(*array);
    605   args_slots.Dispose();
    606 
    607   // Return the freshly allocated arguments object.
    608   return *arguments;
    609 }
    610 
    611 
    612 MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
    613   Isolate* isolate = Isolate::Current();
    614   HandleScope scope(isolate);
    615   JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
    616   if (holder == NULL) return isolate->heap()->undefined_value();
    617   Handle<JSFunction> function(holder, isolate);
    618 
    619   if (function->shared()->native()) return isolate->heap()->null_value();
    620   // Find the top invocation of the function by traversing frames.
    621   List<JSFunction*> functions(2);
    622   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
    623     JavaScriptFrame* frame = it.frame();
    624     frame->GetFunctions(&functions);
    625     for (int i = functions.length() - 1; i >= 0; i--) {
    626       // Skip all frames that aren't invocations of the given function.
    627       if (functions[i] != *function) continue;
    628 
    629       if (i > 0) {
    630         // The function in question was inlined.  Inlined functions have the
    631         // correct number of arguments and no allocated arguments object, so
    632         // we can construct a fresh one by interpreting the function's
    633         // deoptimization input data.
    634         return ConstructArgumentsObjectForInlinedFunction(frame, function, i);
    635       }
    636 
    637       if (!frame->is_optimized()) {
    638         // If there is an arguments variable in the stack, we return that.
    639         Handle<ScopeInfo> scope_info(function->shared()->scope_info());
    640         int index = scope_info->StackSlotIndex(
    641             isolate->heap()->arguments_string());
    642         if (index >= 0) {
    643           Handle<Object> arguments(frame->GetExpression(index), isolate);
    644           if (!arguments->IsArgumentsMarker()) return *arguments;
    645         }
    646       }
    647 
    648       // If there is no arguments variable in the stack or we have an
    649       // optimized frame, we find the frame that holds the actual arguments
    650       // passed to the function.
    651       it.AdvanceToArgumentsFrame();
    652       frame = it.frame();
    653 
    654       // Get the number of arguments and construct an arguments object
    655       // mirror for the right frame.
    656       const int length = frame->ComputeParametersCount();
    657       Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
    658           function, length);
    659       Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
    660 
    661       // Copy the parameters to the arguments object.
    662       ASSERT(array->length() == length);
    663       for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
    664       arguments->set_elements(*array);
    665 
    666       // Return the freshly allocated arguments object.
    667       return *arguments;
    668     }
    669     functions.Rewind(0);
    670   }
    671 
    672   // No frame corresponding to the given function found. Return null.
    673   return isolate->heap()->null_value();
    674 }
    675 
    676 
    677 const AccessorDescriptor Accessors::FunctionArguments = {
    678   FunctionGetArguments,
    679   ReadOnlySetAccessor,
    680   0
    681 };
    682 
    683 
    684 //
    685 // Accessors::FunctionCaller
    686 //
    687 
    688 
    689 class FrameFunctionIterator {
    690  public:
    691   FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
    692       : frame_iterator_(isolate),
    693         functions_(2),
    694         index_(0) {
    695     GetFunctions();
    696   }
    697   JSFunction* next() {
    698     if (functions_.length() == 0) return NULL;
    699     JSFunction* next_function = functions_[index_];
    700     index_--;
    701     if (index_ < 0) {
    702       GetFunctions();
    703     }
    704     return next_function;
    705   }
    706 
    707   // Iterate through functions until the first occurence of 'function'.
    708   // Returns true if 'function' is found, and false if the iterator ends
    709   // without finding it.
    710   bool Find(JSFunction* function) {
    711     JSFunction* next_function;
    712     do {
    713       next_function = next();
    714       if (next_function == function) return true;
    715     } while (next_function != NULL);
    716     return false;
    717   }
    718 
    719  private:
    720   void GetFunctions() {
    721     functions_.Rewind(0);
    722     if (frame_iterator_.done()) return;
    723     JavaScriptFrame* frame = frame_iterator_.frame();
    724     frame->GetFunctions(&functions_);
    725     ASSERT(functions_.length() > 0);
    726     frame_iterator_.Advance();
    727     index_ = functions_.length() - 1;
    728   }
    729   JavaScriptFrameIterator frame_iterator_;
    730   List<JSFunction*> functions_;
    731   int index_;
    732 };
    733 
    734 
    735 MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
    736   Isolate* isolate = Isolate::Current();
    737   HandleScope scope(isolate);
    738   DisallowHeapAllocation no_allocation;
    739   JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
    740   if (holder == NULL) return isolate->heap()->undefined_value();
    741   if (holder->shared()->native()) return isolate->heap()->null_value();
    742   Handle<JSFunction> function(holder, isolate);
    743 
    744   FrameFunctionIterator it(isolate, no_allocation);
    745 
    746   // Find the function from the frames.
    747   if (!it.Find(*function)) {
    748     // No frame corresponding to the given function found. Return null.
    749     return isolate->heap()->null_value();
    750   }
    751 
    752   // Find previously called non-toplevel function.
    753   JSFunction* caller;
    754   do {
    755     caller = it.next();
    756     if (caller == NULL) return isolate->heap()->null_value();
    757   } while (caller->shared()->is_toplevel());
    758 
    759   // If caller is a built-in function and caller's caller is also built-in,
    760   // use that instead.
    761   JSFunction* potential_caller = caller;
    762   while (potential_caller != NULL && potential_caller->IsBuiltin()) {
    763     caller = potential_caller;
    764     potential_caller = it.next();
    765   }
    766   if (!caller->shared()->native() && potential_caller != NULL) {
    767     caller = potential_caller;
    768   }
    769   // If caller is bound, return null. This is compatible with JSC, and
    770   // allows us to make bound functions use the strict function map
    771   // and its associated throwing caller and arguments.
    772   if (caller->shared()->bound()) {
    773     return isolate->heap()->null_value();
    774   }
    775   // Censor if the caller is not a classic mode function.
    776   // Change from ES5, which used to throw, see:
    777   // https://bugs.ecmascript.org/show_bug.cgi?id=310
    778   if (!caller->shared()->is_classic_mode()) {
    779     return isolate->heap()->null_value();
    780   }
    781 
    782   return caller;
    783 }
    784 
    785 
    786 const AccessorDescriptor Accessors::FunctionCaller = {
    787   FunctionGetCaller,
    788   ReadOnlySetAccessor,
    789   0
    790 };
    791 
    792 
    793 //
    794 // Accessors::MakeModuleExport
    795 //
    796 
    797 static void ModuleGetExport(
    798     v8::Local<v8::String> property,
    799     const v8::PropertyCallbackInfo<v8::Value>& info) {
    800   JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
    801   Context* context = Context::cast(instance->context());
    802   ASSERT(context->IsModuleContext());
    803   int slot = info.Data()->Int32Value();
    804   Object* value = context->get(slot);
    805   Isolate* isolate = instance->GetIsolate();
    806   if (value->IsTheHole()) {
    807     Handle<String> name = v8::Utils::OpenHandle(*property);
    808     isolate->ScheduleThrow(
    809         *isolate->factory()->NewReferenceError("not_defined",
    810                                                HandleVector(&name, 1)));
    811     return;
    812   }
    813   info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
    814 }
    815 
    816 
    817 static void ModuleSetExport(
    818     v8::Local<v8::String> property,
    819     v8::Local<v8::Value> value,
    820     const v8::PropertyCallbackInfo<v8::Value>& info) {
    821   JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
    822   Context* context = Context::cast(instance->context());
    823   ASSERT(context->IsModuleContext());
    824   int slot = info.Data()->Int32Value();
    825   Object* old_value = context->get(slot);
    826   if (old_value->IsTheHole()) {
    827     Handle<String> name = v8::Utils::OpenHandle(*property);
    828     Isolate* isolate = instance->GetIsolate();
    829     isolate->ScheduleThrow(
    830         *isolate->factory()->NewReferenceError("not_defined",
    831                                                HandleVector(&name, 1)));
    832     return;
    833   }
    834   context->set(slot, *v8::Utils::OpenHandle(*value));
    835 }
    836 
    837 
    838 Handle<AccessorInfo> Accessors::MakeModuleExport(
    839     Handle<String> name,
    840     int index,
    841     PropertyAttributes attributes) {
    842   Factory* factory = name->GetIsolate()->factory();
    843   Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
    844   info->set_property_attributes(attributes);
    845   info->set_all_can_read(true);
    846   info->set_all_can_write(true);
    847   info->set_name(*name);
    848   info->set_data(Smi::FromInt(index));
    849   Handle<Object> getter = v8::FromCData(&ModuleGetExport);
    850   Handle<Object> setter = v8::FromCData(&ModuleSetExport);
    851   info->set_getter(*getter);
    852   if (!(attributes & ReadOnly)) info->set_setter(*setter);
    853   return info;
    854 }
    855 
    856 
    857 } }  // namespace v8::internal
    858