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