The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / accessors.cc @ f230a1cf

History | View | Annotate | Download (29 KB)

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(Isolate* isolate,
55
                                      JSObject*,
56
                                      Object*,
57
                                      void*) {
58
  UNREACHABLE();
59
  return NULL;
60
}
61

    
62

    
63
Object* Accessors::IllegalGetAccessor(Isolate* isolate,
64
                                      Object* object,
65
                                      void*) {
66
  UNREACHABLE();
67
  return object;
68
}
69

    
70

    
71
MaybeObject* Accessors::ReadOnlySetAccessor(Isolate* isolate,
72
                                            JSObject*,
73
                                            Object* value,
74
                                            void*) {
75
  // According to ECMA-262, section 8.6.2.2, page 28, setting
76
  // read-only properties must be silently ignored.
77
  return value;
78
}
79

    
80

    
81
static V8_INLINE bool CheckForName(Handle<String> name,
82
                                   String* property_name,
83
                                   int offset,
84
                                   int* object_offset) {
85
  if (name->Equals(property_name)) {
86
    *object_offset = offset;
87
    return true;
88
  }
89
  return false;
90
}
91

    
92

    
93
bool Accessors::IsJSObjectFieldAccessor(
94
      Handle<Map> map, Handle<String> name,
95
      int* object_offset) {
96
  Isolate* isolate = map->GetIsolate();
97
  switch (map->instance_type()) {
98
    case JS_ARRAY_TYPE:
99
      return
100
        CheckForName(name, isolate->heap()->length_string(),
101
                     JSArray::kLengthOffset, object_offset);
102
    case JS_TYPED_ARRAY_TYPE:
103
      return
104
        CheckForName(name, isolate->heap()->length_string(),
105
                     JSTypedArray::kLengthOffset, object_offset) ||
106
        CheckForName(name, isolate->heap()->byte_length_string(),
107
                     JSTypedArray::kByteLengthOffset, object_offset) ||
108
        CheckForName(name, isolate->heap()->byte_offset_string(),
109
                     JSTypedArray::kByteOffsetOffset, object_offset) ||
110
        CheckForName(name, isolate->heap()->buffer_string(),
111
                     JSTypedArray::kBufferOffset, object_offset);
112
    case JS_ARRAY_BUFFER_TYPE:
113
      return
114
        CheckForName(name, isolate->heap()->byte_length_string(),
115
                     JSArrayBuffer::kByteLengthOffset, object_offset);
116
    case JS_DATA_VIEW_TYPE:
117
      return
118
        CheckForName(name, isolate->heap()->byte_length_string(),
119
                     JSDataView::kByteLengthOffset, object_offset) ||
120
        CheckForName(name, isolate->heap()->byte_offset_string(),
121
                     JSDataView::kByteOffsetOffset, object_offset) ||
122
        CheckForName(name, isolate->heap()->buffer_string(),
123
                     JSDataView::kBufferOffset, object_offset);
124
    default: {
125
      if (map->instance_type() < FIRST_NONSTRING_TYPE) {
126
        return
127
          CheckForName(name, isolate->heap()->length_string(),
128
                       String::kLengthOffset, object_offset);
129
      }
130
      return false;
131
    }
132
  }
133
}
134

    
135

    
136
//
137
// Accessors::ArrayLength
138
//
139

    
140

    
141
MaybeObject* Accessors::ArrayGetLength(Isolate* isolate,
142
                                       Object* object,
143
                                       void*) {
144
  // Traverse the prototype chain until we reach an array.
145
  JSArray* holder = FindInstanceOf<JSArray>(isolate, object);
146
  return holder == NULL ? Smi::FromInt(0) : holder->length();
147
}
148

    
149

    
150
// The helper function will 'flatten' Number objects.
151
Object* Accessors::FlattenNumber(Isolate* isolate, Object* value) {
152
  if (value->IsNumber() || !value->IsJSValue()) return value;
153
  JSValue* wrapper = JSValue::cast(value);
154
  ASSERT(wrapper->GetIsolate()->context()->native_context()->number_function()->
155
      has_initial_map());
156
  Map* number_map = isolate->context()->native_context()->
157
      number_function()->initial_map();
158
  if (wrapper->map() == number_map) return wrapper->value();
159
  return value;
160
}
161

    
162

    
163
MaybeObject* Accessors::ArraySetLength(Isolate* isolate,
164
                                       JSObject* object,
165
                                       Object* value,
166
                                       void*) {
167
  // This means one of the object's prototypes is a JSArray and the
168
  // object does not have a 'length' property.  Calling SetProperty
169
  // causes an infinite loop.
170
  if (!object->IsJSArray()) {
171
    return object->SetLocalPropertyIgnoreAttributesTrampoline(
172
        isolate->heap()->length_string(), value, NONE);
173
  }
174

    
175
  value = FlattenNumber(isolate, value);
176

    
177
  // Need to call methods that may trigger GC.
178
  HandleScope scope(isolate);
179

    
180
  // Protect raw pointers.
181
  Handle<JSArray> array_handle(JSArray::cast(object), isolate);
182
  Handle<Object> value_handle(value, isolate);
183

    
184
  bool has_exception;
185
  Handle<Object> uint32_v =
186
      Execution::ToUint32(isolate, value_handle, &has_exception);
187
  if (has_exception) return Failure::Exception();
188
  Handle<Object> number_v =
189
      Execution::ToNumber(isolate, value_handle, &has_exception);
190
  if (has_exception) return Failure::Exception();
191

    
192
  if (uint32_v->Number() == number_v->Number()) {
193
    return array_handle->SetElementsLength(*uint32_v);
194
  }
195
  return isolate->Throw(
196
      *isolate->factory()->NewRangeError("invalid_array_length",
197
                                         HandleVector<Object>(NULL, 0)));
198
}
199

    
200

    
201
const AccessorDescriptor Accessors::ArrayLength = {
202
  ArrayGetLength,
203
  ArraySetLength,
204
  0
205
};
206

    
207

    
208
//
209
// Accessors::StringLength
210
//
211

    
212

    
213
MaybeObject* Accessors::StringGetLength(Isolate* isolate,
214
                                        Object* object,
215
                                        void*) {
216
  Object* value = object;
217
  if (object->IsJSValue()) value = JSValue::cast(object)->value();
218
  if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
219
  // If object is not a string we return 0 to be compatible with WebKit.
220
  // Note: Firefox returns the length of ToString(object).
221
  return Smi::FromInt(0);
222
}
223

    
224

    
225
const AccessorDescriptor Accessors::StringLength = {
226
  StringGetLength,
227
  IllegalSetter,
228
  0
229
};
230

    
231

    
232
//
233
// Accessors::ScriptSource
234
//
235

    
236

    
237
MaybeObject* Accessors::ScriptGetSource(Isolate* isolate,
238
                                        Object* object,
239
                                        void*) {
240
  Object* script = JSValue::cast(object)->value();
241
  return Script::cast(script)->source();
242
}
243

    
244

    
245
const AccessorDescriptor Accessors::ScriptSource = {
246
  ScriptGetSource,
247
  IllegalSetter,
248
  0
249
};
250

    
251

    
252
//
253
// Accessors::ScriptName
254
//
255

    
256

    
257
MaybeObject* Accessors::ScriptGetName(Isolate* isolate,
258
                                      Object* object,
259
                                      void*) {
260
  Object* script = JSValue::cast(object)->value();
261
  return Script::cast(script)->name();
262
}
263

    
264

    
265
const AccessorDescriptor Accessors::ScriptName = {
266
  ScriptGetName,
267
  IllegalSetter,
268
  0
269
};
270

    
271

    
272
//
273
// Accessors::ScriptId
274
//
275

    
276

    
277
MaybeObject* Accessors::ScriptGetId(Isolate* isolate, Object* object, void*) {
278
  Object* script = JSValue::cast(object)->value();
279
  return Script::cast(script)->id();
280
}
281

    
282

    
283
const AccessorDescriptor Accessors::ScriptId = {
284
  ScriptGetId,
285
  IllegalSetter,
286
  0
287
};
288

    
289

    
290
//
291
// Accessors::ScriptLineOffset
292
//
293

    
294

    
295
MaybeObject* Accessors::ScriptGetLineOffset(Isolate* isolate,
296
                                            Object* object,
297
                                            void*) {
298
  Object* script = JSValue::cast(object)->value();
299
  return Script::cast(script)->line_offset();
300
}
301

    
302

    
303
const AccessorDescriptor Accessors::ScriptLineOffset = {
304
  ScriptGetLineOffset,
305
  IllegalSetter,
306
  0
307
};
308

    
309

    
310
//
311
// Accessors::ScriptColumnOffset
312
//
313

    
314

    
315
MaybeObject* Accessors::ScriptGetColumnOffset(Isolate* isolate,
316
                                              Object* object,
317
                                              void*) {
318
  Object* script = JSValue::cast(object)->value();
319
  return Script::cast(script)->column_offset();
320
}
321

    
322

    
323
const AccessorDescriptor Accessors::ScriptColumnOffset = {
324
  ScriptGetColumnOffset,
325
  IllegalSetter,
326
  0
327
};
328

    
329

    
330
//
331
// Accessors::ScriptData
332
//
333

    
334

    
335
MaybeObject* Accessors::ScriptGetData(Isolate* isolate,
336
                                      Object* object,
337
                                      void*) {
338
  Object* script = JSValue::cast(object)->value();
339
  return Script::cast(script)->data();
340
}
341

    
342

    
343
const AccessorDescriptor Accessors::ScriptData = {
344
  ScriptGetData,
345
  IllegalSetter,
346
  0
347
};
348

    
349

    
350
//
351
// Accessors::ScriptType
352
//
353

    
354

    
355
MaybeObject* Accessors::ScriptGetType(Isolate* isolate,
356
                                      Object* object,
357
                                      void*) {
358
  Object* script = JSValue::cast(object)->value();
359
  return Script::cast(script)->type();
360
}
361

    
362

    
363
const AccessorDescriptor Accessors::ScriptType = {
364
  ScriptGetType,
365
  IllegalSetter,
366
  0
367
};
368

    
369

    
370
//
371
// Accessors::ScriptCompilationType
372
//
373

    
374

    
375
MaybeObject* Accessors::ScriptGetCompilationType(Isolate* isolate,
376
                                                 Object* object,
377
                                                 void*) {
378
  Object* script = JSValue::cast(object)->value();
379
  return Smi::FromInt(Script::cast(script)->compilation_type());
380
}
381

    
382

    
383
const AccessorDescriptor Accessors::ScriptCompilationType = {
384
  ScriptGetCompilationType,
385
  IllegalSetter,
386
  0
387
};
388

    
389

    
390
//
391
// Accessors::ScriptGetLineEnds
392
//
393

    
394

    
395
MaybeObject* Accessors::ScriptGetLineEnds(Isolate* isolate,
396
                                          Object* object,
397
                                          void*) {
398
  JSValue* wrapper = JSValue::cast(object);
399
  HandleScope scope(isolate);
400
  Handle<Script> script(Script::cast(wrapper->value()), isolate);
401
  InitScriptLineEnds(script);
402
  ASSERT(script->line_ends()->IsFixedArray());
403
  Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
404
  // We do not want anyone to modify this array from JS.
405
  ASSERT(*line_ends == isolate->heap()->empty_fixed_array() ||
406
         line_ends->map() == isolate->heap()->fixed_cow_array_map());
407
  Handle<JSArray> js_array =
408
      isolate->factory()->NewJSArrayWithElements(line_ends);
409
  return *js_array;
410
}
411

    
412

    
413
const AccessorDescriptor Accessors::ScriptLineEnds = {
414
  ScriptGetLineEnds,
415
  IllegalSetter,
416
  0
417
};
418

    
419

    
420
//
421
// Accessors::ScriptGetContextData
422
//
423

    
424

    
425
MaybeObject* Accessors::ScriptGetContextData(Isolate* isolate,
426
                                             Object* object,
427
                                             void*) {
428
  Object* script = JSValue::cast(object)->value();
429
  return Script::cast(script)->context_data();
430
}
431

    
432

    
433
const AccessorDescriptor Accessors::ScriptContextData = {
434
  ScriptGetContextData,
435
  IllegalSetter,
436
  0
437
};
438

    
439

    
440
//
441
// Accessors::ScriptGetEvalFromScript
442
//
443

    
444

    
445
MaybeObject* Accessors::ScriptGetEvalFromScript(Isolate* isolate,
446
                                                Object* object,
447
                                                void*) {
448
  Object* script = JSValue::cast(object)->value();
449
  if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
450
    Handle<SharedFunctionInfo> eval_from_shared(
451
        SharedFunctionInfo::cast(Script::cast(script)->eval_from_shared()));
452

    
453
    if (eval_from_shared->script()->IsScript()) {
454
      Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
455
      return *GetScriptWrapper(eval_from_script);
456
    }
457
  }
458
  return isolate->heap()->undefined_value();
459
}
460

    
461

    
462
const AccessorDescriptor Accessors::ScriptEvalFromScript = {
463
  ScriptGetEvalFromScript,
464
  IllegalSetter,
465
  0
466
};
467

    
468

    
469
//
470
// Accessors::ScriptGetEvalFromScriptPosition
471
//
472

    
473

    
474
MaybeObject* Accessors::ScriptGetEvalFromScriptPosition(Isolate* isolate,
475
                                                        Object* object,
476
                                                        void*) {
477
  Script* raw_script = Script::cast(JSValue::cast(object)->value());
478
  HandleScope scope(isolate);
479
  Handle<Script> script(raw_script);
480

    
481
  // If this is not a script compiled through eval there is no eval position.
482
  if (script->compilation_type() != Script::COMPILATION_TYPE_EVAL) {
483
    return script->GetHeap()->undefined_value();
484
  }
485

    
486
  // Get the function from where eval was called and find the source position
487
  // from the instruction offset.
488
  Handle<Code> code(SharedFunctionInfo::cast(
489
      script->eval_from_shared())->code());
490
  return Smi::FromInt(code->SourcePosition(code->instruction_start() +
491
                      script->eval_from_instructions_offset()->value()));
492
}
493

    
494

    
495
const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
496
  ScriptGetEvalFromScriptPosition,
497
  IllegalSetter,
498
  0
499
};
500

    
501

    
502
//
503
// Accessors::ScriptGetEvalFromFunctionName
504
//
505

    
506

    
507
MaybeObject* Accessors::ScriptGetEvalFromFunctionName(Isolate* isolate,
508
                                                      Object* object,
509
                                                      void*) {
510
  Object* script = JSValue::cast(object)->value();
511
  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
512
      Script::cast(script)->eval_from_shared()));
513

    
514

    
515
  // Find the name of the function calling eval.
516
  if (!shared->name()->IsUndefined()) {
517
    return shared->name();
518
  } else {
519
    return shared->inferred_name();
520
  }
521
}
522

    
523

    
524
const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
525
  ScriptGetEvalFromFunctionName,
526
  IllegalSetter,
527
  0
528
};
529

    
530

    
531
//
532
// Accessors::FunctionPrototype
533
//
534

    
535

    
536
Handle<Object> Accessors::FunctionGetPrototype(Handle<JSFunction> function) {
537
  CALL_HEAP_FUNCTION(function->GetIsolate(),
538
                     Accessors::FunctionGetPrototype(function->GetIsolate(),
539
                                                     *function,
540
                                                     NULL),
541
                     Object);
542
}
543

    
544

    
545
Handle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
546
                                               Handle<Object> prototype) {
547
  ASSERT(function->should_have_prototype());
548
  CALL_HEAP_FUNCTION(function->GetIsolate(),
549
                     Accessors::FunctionSetPrototype(function->GetIsolate(),
550
                                                     *function,
551
                                                     *prototype,
552
                                                     NULL),
553
                     Object);
554
}
555

    
556

    
557
MaybeObject* Accessors::FunctionGetPrototype(Isolate* isolate,
558
                                             Object* object,
559
                                             void*) {
560
  JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
561
  if (function_raw == NULL) return isolate->heap()->undefined_value();
562
  while (!function_raw->should_have_prototype()) {
563
    function_raw = FindInstanceOf<JSFunction>(isolate,
564
                                              function_raw->GetPrototype());
565
    // There has to be one because we hit the getter.
566
    ASSERT(function_raw != NULL);
567
  }
568

    
569
  if (!function_raw->has_prototype()) {
570
    HandleScope scope(isolate);
571
    Handle<JSFunction> function(function_raw);
572
    Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
573
    JSFunction::SetPrototype(function, proto);
574
    function_raw = *function;
575
  }
576
  return function_raw->prototype();
577
}
578

    
579

    
580
MaybeObject* Accessors::FunctionSetPrototype(Isolate* isolate,
581
                                             JSObject* object,
582
                                             Object* value_raw,
583
                                             void*) {
584
  Heap* heap = isolate->heap();
585
  JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
586
  if (function_raw == NULL) return heap->undefined_value();
587
  if (!function_raw->should_have_prototype()) {
588
    // Since we hit this accessor, object will have no prototype property.
589
    return object->SetLocalPropertyIgnoreAttributesTrampoline(
590
        heap->prototype_string(), value_raw, NONE);
591
  }
592

    
593
  HandleScope scope(isolate);
594
  Handle<JSFunction> function(function_raw, isolate);
595
  Handle<Object> value(value_raw, isolate);
596

    
597
  Handle<Object> old_value;
598
  bool is_observed =
599
      FLAG_harmony_observation &&
600
      *function == object &&
601
      function->map()->is_observed();
602
  if (is_observed) {
603
    if (function->has_prototype())
604
      old_value = handle(function->prototype(), isolate);
605
    else
606
      old_value = isolate->factory()->NewFunctionPrototype(function);
607
  }
608

    
609
  JSFunction::SetPrototype(function, value);
610
  ASSERT(function->prototype() == *value);
611

    
612
  if (is_observed && !old_value->SameValue(*value)) {
613
    JSObject::EnqueueChangeRecord(
614
        function, "updated", isolate->factory()->prototype_string(), old_value);
615
  }
616

    
617
  return *function;
618
}
619

    
620

    
621
const AccessorDescriptor Accessors::FunctionPrototype = {
622
  FunctionGetPrototype,
623
  FunctionSetPrototype,
624
  0
625
};
626

    
627

    
628
//
629
// Accessors::FunctionLength
630
//
631

    
632

    
633
MaybeObject* Accessors::FunctionGetLength(Isolate* isolate,
634
                                          Object* object,
635
                                          void*) {
636
  JSFunction* function = FindInstanceOf<JSFunction>(isolate, object);
637
  if (function == NULL) return Smi::FromInt(0);
638
  // Check if already compiled.
639
  if (function->shared()->is_compiled()) {
640
    return Smi::FromInt(function->shared()->length());
641
  }
642
  // If the function isn't compiled yet, the length is not computed correctly
643
  // yet. Compile it now and return the right length.
644
  HandleScope scope(isolate);
645
  Handle<JSFunction> handle(function);
646
  if (JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) {
647
    return Smi::FromInt(handle->shared()->length());
648
  }
649
  return Failure::Exception();
650
}
651

    
652

    
653
const AccessorDescriptor Accessors::FunctionLength = {
654
  FunctionGetLength,
655
  ReadOnlySetAccessor,
656
  0
657
};
658

    
659

    
660
//
661
// Accessors::FunctionName
662
//
663

    
664

    
665
MaybeObject* Accessors::FunctionGetName(Isolate* isolate,
666
                                        Object* object,
667
                                        void*) {
668
  JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
669
  return holder == NULL
670
      ? isolate->heap()->undefined_value()
671
      : holder->shared()->name();
672
}
673

    
674

    
675
const AccessorDescriptor Accessors::FunctionName = {
676
  FunctionGetName,
677
  ReadOnlySetAccessor,
678
  0
679
};
680

    
681

    
682
//
683
// Accessors::FunctionArguments
684
//
685

    
686

    
687
Handle<Object> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
688
  CALL_HEAP_FUNCTION(function->GetIsolate(),
689
                     Accessors::FunctionGetArguments(function->GetIsolate(),
690
                                                     *function,
691
                                                     NULL),
692
                     Object);
693
}
694

    
695

    
696
static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
697
    JavaScriptFrame* frame,
698
    Handle<JSFunction> inlined_function,
699
    int inlined_frame_index) {
700
  Isolate* isolate = inlined_function->GetIsolate();
701
  Factory* factory = isolate->factory();
702
  Vector<SlotRef> args_slots =
703
      SlotRef::ComputeSlotMappingForArguments(
704
          frame,
705
          inlined_frame_index,
706
          inlined_function->shared()->formal_parameter_count());
707
  int args_count = args_slots.length();
708
  Handle<JSObject> arguments =
709
      factory->NewArgumentsObject(inlined_function, args_count);
710
  Handle<FixedArray> array = factory->NewFixedArray(args_count);
711
  for (int i = 0; i < args_count; ++i) {
712
    Handle<Object> value = args_slots[i].GetValue(isolate);
713
    array->set(i, *value);
714
  }
715
  arguments->set_elements(*array);
716
  args_slots.Dispose();
717

    
718
  // Return the freshly allocated arguments object.
719
  return *arguments;
720
}
721

    
722

    
723
MaybeObject* Accessors::FunctionGetArguments(Isolate* isolate,
724
                                             Object* object,
725
                                             void*) {
726
  HandleScope scope(isolate);
727
  JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
728
  if (holder == NULL) return isolate->heap()->undefined_value();
729
  Handle<JSFunction> function(holder, isolate);
730

    
731
  if (function->shared()->native()) return isolate->heap()->null_value();
732
  // Find the top invocation of the function by traversing frames.
733
  List<JSFunction*> functions(2);
734
  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
735
    JavaScriptFrame* frame = it.frame();
736
    frame->GetFunctions(&functions);
737
    for (int i = functions.length() - 1; i >= 0; i--) {
738
      // Skip all frames that aren't invocations of the given function.
739
      if (functions[i] != *function) continue;
740

    
741
      if (i > 0) {
742
        // The function in question was inlined.  Inlined functions have the
743
        // correct number of arguments and no allocated arguments object, so
744
        // we can construct a fresh one by interpreting the function's
745
        // deoptimization input data.
746
        return ConstructArgumentsObjectForInlinedFunction(frame, function, i);
747
      }
748

    
749
      if (!frame->is_optimized()) {
750
        // If there is an arguments variable in the stack, we return that.
751
        Handle<ScopeInfo> scope_info(function->shared()->scope_info());
752
        int index = scope_info->StackSlotIndex(
753
            isolate->heap()->arguments_string());
754
        if (index >= 0) {
755
          Handle<Object> arguments(frame->GetExpression(index), isolate);
756
          if (!arguments->IsArgumentsMarker()) return *arguments;
757
        }
758
      }
759

    
760
      // If there is no arguments variable in the stack or we have an
761
      // optimized frame, we find the frame that holds the actual arguments
762
      // passed to the function.
763
      it.AdvanceToArgumentsFrame();
764
      frame = it.frame();
765

    
766
      // Get the number of arguments and construct an arguments object
767
      // mirror for the right frame.
768
      const int length = frame->ComputeParametersCount();
769
      Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
770
          function, length);
771
      Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
772

    
773
      // Copy the parameters to the arguments object.
774
      ASSERT(array->length() == length);
775
      for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
776
      arguments->set_elements(*array);
777

    
778
      // Return the freshly allocated arguments object.
779
      return *arguments;
780
    }
781
    functions.Rewind(0);
782
  }
783

    
784
  // No frame corresponding to the given function found. Return null.
785
  return isolate->heap()->null_value();
786
}
787

    
788

    
789
const AccessorDescriptor Accessors::FunctionArguments = {
790
  FunctionGetArguments,
791
  ReadOnlySetAccessor,
792
  0
793
};
794

    
795

    
796
//
797
// Accessors::FunctionCaller
798
//
799

    
800

    
801
class FrameFunctionIterator {
802
 public:
803
  FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
804
      : frame_iterator_(isolate),
805
        functions_(2),
806
        index_(0) {
807
    GetFunctions();
808
  }
809
  JSFunction* next() {
810
    if (functions_.length() == 0) return NULL;
811
    JSFunction* next_function = functions_[index_];
812
    index_--;
813
    if (index_ < 0) {
814
      GetFunctions();
815
    }
816
    return next_function;
817
  }
818

    
819
  // Iterate through functions until the first occurence of 'function'.
820
  // Returns true if 'function' is found, and false if the iterator ends
821
  // without finding it.
822
  bool Find(JSFunction* function) {
823
    JSFunction* next_function;
824
    do {
825
      next_function = next();
826
      if (next_function == function) return true;
827
    } while (next_function != NULL);
828
    return false;
829
  }
830

    
831
 private:
832
  void GetFunctions() {
833
    functions_.Rewind(0);
834
    if (frame_iterator_.done()) return;
835
    JavaScriptFrame* frame = frame_iterator_.frame();
836
    frame->GetFunctions(&functions_);
837
    ASSERT(functions_.length() > 0);
838
    frame_iterator_.Advance();
839
    index_ = functions_.length() - 1;
840
  }
841
  JavaScriptFrameIterator frame_iterator_;
842
  List<JSFunction*> functions_;
843
  int index_;
844
};
845

    
846

    
847
MaybeObject* Accessors::FunctionGetCaller(Isolate* isolate,
848
                                          Object* object,
849
                                          void*) {
850
  HandleScope scope(isolate);
851
  DisallowHeapAllocation no_allocation;
852
  JSFunction* holder = FindInstanceOf<JSFunction>(isolate, object);
853
  if (holder == NULL) return isolate->heap()->undefined_value();
854
  if (holder->shared()->native()) return isolate->heap()->null_value();
855
  Handle<JSFunction> function(holder, isolate);
856

    
857
  FrameFunctionIterator it(isolate, no_allocation);
858

    
859
  // Find the function from the frames.
860
  if (!it.Find(*function)) {
861
    // No frame corresponding to the given function found. Return null.
862
    return isolate->heap()->null_value();
863
  }
864

    
865
  // Find previously called non-toplevel function.
866
  JSFunction* caller;
867
  do {
868
    caller = it.next();
869
    if (caller == NULL) return isolate->heap()->null_value();
870
  } while (caller->shared()->is_toplevel());
871

    
872
  // If caller is a built-in function and caller's caller is also built-in,
873
  // use that instead.
874
  JSFunction* potential_caller = caller;
875
  while (potential_caller != NULL && potential_caller->IsBuiltin()) {
876
    caller = potential_caller;
877
    potential_caller = it.next();
878
  }
879
  if (!caller->shared()->native() && potential_caller != NULL) {
880
    caller = potential_caller;
881
  }
882
  // If caller is bound, return null. This is compatible with JSC, and
883
  // allows us to make bound functions use the strict function map
884
  // and its associated throwing caller and arguments.
885
  if (caller->shared()->bound()) {
886
    return isolate->heap()->null_value();
887
  }
888
  // Censor if the caller is not a classic mode function.
889
  // Change from ES5, which used to throw, see:
890
  // https://bugs.ecmascript.org/show_bug.cgi?id=310
891
  if (!caller->shared()->is_classic_mode()) {
892
    return isolate->heap()->null_value();
893
  }
894

    
895
  return caller;
896
}
897

    
898

    
899
const AccessorDescriptor Accessors::FunctionCaller = {
900
  FunctionGetCaller,
901
  ReadOnlySetAccessor,
902
  0
903
};
904

    
905

    
906
//
907
// Accessors::MakeModuleExport
908
//
909

    
910
static void ModuleGetExport(
911
    v8::Local<v8::String> property,
912
    const v8::PropertyCallbackInfo<v8::Value>& info) {
913
  JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
914
  Context* context = Context::cast(instance->context());
915
  ASSERT(context->IsModuleContext());
916
  int slot = info.Data()->Int32Value();
917
  Object* value = context->get(slot);
918
  Isolate* isolate = instance->GetIsolate();
919
  if (value->IsTheHole()) {
920
    Handle<String> name = v8::Utils::OpenHandle(*property);
921
    isolate->ScheduleThrow(
922
        *isolate->factory()->NewReferenceError("not_defined",
923
                                               HandleVector(&name, 1)));
924
    return;
925
  }
926
  info.GetReturnValue().Set(v8::Utils::ToLocal(Handle<Object>(value, isolate)));
927
}
928

    
929

    
930
static void ModuleSetExport(
931
    v8::Local<v8::String> property,
932
    v8::Local<v8::Value> value,
933
    const v8::PropertyCallbackInfo<v8::Value>& info) {
934
  JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
935
  Context* context = Context::cast(instance->context());
936
  ASSERT(context->IsModuleContext());
937
  int slot = info.Data()->Int32Value();
938
  Object* old_value = context->get(slot);
939
  if (old_value->IsTheHole()) {
940
    Handle<String> name = v8::Utils::OpenHandle(*property);
941
    Isolate* isolate = instance->GetIsolate();
942
    isolate->ScheduleThrow(
943
        *isolate->factory()->NewReferenceError("not_defined",
944
                                               HandleVector(&name, 1)));
945
    return;
946
  }
947
  context->set(slot, *v8::Utils::OpenHandle(*value));
948
}
949

    
950

    
951
Handle<AccessorInfo> Accessors::MakeModuleExport(
952
    Handle<String> name,
953
    int index,
954
    PropertyAttributes attributes) {
955
  Isolate* isolate = name->GetIsolate();
956
  Factory* factory = isolate->factory();
957
  Handle<ExecutableAccessorInfo> info = factory->NewExecutableAccessorInfo();
958
  info->set_property_attributes(attributes);
959
  info->set_all_can_read(true);
960
  info->set_all_can_write(true);
961
  info->set_name(*name);
962
  info->set_data(Smi::FromInt(index));
963
  Handle<Object> getter = v8::FromCData(isolate, &ModuleGetExport);
964
  Handle<Object> setter = v8::FromCData(isolate, &ModuleSetExport);
965
  info->set_getter(*getter);
966
  if (!(attributes & ReadOnly)) info->set_setter(*setter);
967
  return info;
968
}
969

    
970

    
971
} }  // namespace v8::internal