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