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