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