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