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