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 
MakeAccessor(Isolate * isolate,Handle<Name> name,AccessorNameGetterCallback getter,AccessorNameBooleanSetterCallback setter,PropertyAttributes attributes)22 Handle<AccessorInfo> Accessors::MakeAccessor(
23     Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
24     AccessorNameBooleanSetterCallback setter, PropertyAttributes attributes) {
25   Factory* factory = isolate->factory();
26   Handle<AccessorInfo> info = factory->NewAccessorInfo();
27   info->set_property_attributes(attributes);
28   info->set_all_can_read(false);
29   info->set_all_can_write(false);
30   info->set_is_special_data_property(true);
31   info->set_is_sloppy(false);
32   info->set_replace_on_access(false);
33   name = factory->InternalizeName(name);
34   info->set_name(*name);
35   Handle<Object> get = v8::FromCData(isolate, getter);
36   if (setter == nullptr) setter = &ReconfigureToDataProperty;
37   Handle<Object> set = v8::FromCData(isolate, setter);
38   info->set_getter(*get);
39   info->set_setter(*set);
40   Address redirected = info->redirected_getter();
41   if (redirected != nullptr) {
42     Handle<Object> js_get = v8::FromCData(isolate, redirected);
43     info->set_js_getter(*js_get);
44   }
45   return info;
46 }
47 
48 
CheckForName(Handle<Name> name,Handle<String> property_name,int offset,int * object_offset)49 static V8_INLINE bool CheckForName(Handle<Name> name,
50                                    Handle<String> property_name,
51                                    int offset,
52                                    int* object_offset) {
53   if (Name::Equals(name, property_name)) {
54     *object_offset = offset;
55     return true;
56   }
57   return false;
58 }
59 
60 
61 // Returns true for properties that are accessors to object fields.
62 // If true, *object_offset contains offset of object field.
IsJSObjectFieldAccessor(Handle<Map> map,Handle<Name> name,int * object_offset)63 bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
64                                         int* object_offset) {
65   Isolate* isolate = name->GetIsolate();
66 
67   switch (map->instance_type()) {
68     case JS_ARRAY_TYPE:
69       return
70         CheckForName(name, isolate->factory()->length_string(),
71                      JSArray::kLengthOffset, object_offset);
72     default:
73       if (map->instance_type() < FIRST_NONSTRING_TYPE) {
74         return CheckForName(name, isolate->factory()->length_string(),
75                             String::kLengthOffset, object_offset);
76       }
77 
78       return false;
79   }
80 }
81 
82 
83 namespace {
84 
ReplaceAccessorWithDataProperty(Isolate * isolate,Handle<Object> receiver,Handle<JSObject> holder,Handle<Name> name,Handle<Object> value)85 MUST_USE_RESULT MaybeHandle<Object> ReplaceAccessorWithDataProperty(
86     Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder,
87     Handle<Name> name, Handle<Object> value) {
88   LookupIterator it(receiver, name, holder,
89                     LookupIterator::OWN_SKIP_INTERCEPTOR);
90   // Skip any access checks we might hit. This accessor should never hit in a
91   // situation where the caller does not have access.
92   if (it.state() == LookupIterator::ACCESS_CHECK) {
93     CHECK(it.HasAccess());
94     it.Next();
95   }
96   DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
97   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
98   it.ReconfigureDataProperty(value, it.property_attributes());
99   return value;
100 }
101 
102 }  // namespace
103 
ReconfigureToDataProperty(v8::Local<v8::Name> key,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<v8::Boolean> & info)104 void Accessors::ReconfigureToDataProperty(
105     v8::Local<v8::Name> key, v8::Local<v8::Value> val,
106     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
107   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
108   HandleScope scope(isolate);
109   Handle<Object> receiver = Utils::OpenHandle(*info.This());
110   Handle<JSObject> holder =
111       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
112   Handle<Name> name = Utils::OpenHandle(*key);
113   Handle<Object> value = Utils::OpenHandle(*val);
114   MaybeHandle<Object> result =
115       ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value);
116   if (result.is_null()) {
117     isolate->OptionalRescheduleException(false);
118   } else {
119     info.GetReturnValue().Set(true);
120   }
121 }
122 
123 //
124 // Accessors::ArgumentsIterator
125 //
126 
127 
ArgumentsIteratorGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)128 void Accessors::ArgumentsIteratorGetter(
129     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
130   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
131   DisallowHeapAllocation no_allocation;
132   HandleScope scope(isolate);
133   Object* result = isolate->native_context()->array_values_iterator();
134   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
135 }
136 
137 
ArgumentsIteratorInfo(Isolate * isolate,PropertyAttributes attributes)138 Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
139     Isolate* isolate, PropertyAttributes attributes) {
140   Handle<Name> name = isolate->factory()->iterator_symbol();
141   return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, nullptr,
142                       attributes);
143 }
144 
145 
146 //
147 // Accessors::ArrayLength
148 //
149 
150 
ArrayLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)151 void Accessors::ArrayLengthGetter(
152     v8::Local<v8::Name> name,
153     const v8::PropertyCallbackInfo<v8::Value>& info) {
154   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
155   RuntimeCallTimerScope timer(
156       isolate, &RuntimeCallStats::AccessorNameGetterCallback_ArrayLength);
157   DisallowHeapAllocation no_allocation;
158   HandleScope scope(isolate);
159   JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.Holder()));
160   Object* result = holder->length();
161   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
162 }
163 
ArrayLengthSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<v8::Boolean> & info)164 void Accessors::ArrayLengthSetter(
165     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
166     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
167   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
168   HandleScope scope(isolate);
169 
170   Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
171   Handle<JSArray> array = Handle<JSArray>::cast(object);
172   Handle<Object> length_obj = Utils::OpenHandle(*val);
173 
174   uint32_t length = 0;
175   if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
176     isolate->OptionalRescheduleException(false);
177     return;
178   }
179 
180   JSArray::SetLength(array, length);
181 
182   uint32_t actual_new_len = 0;
183   CHECK(array->length()->ToArrayLength(&actual_new_len));
184   // Fail if there were non-deletable elements.
185   if (actual_new_len != length) {
186     if (info.ShouldThrowOnError()) {
187       Factory* factory = isolate->factory();
188       isolate->Throw(*factory->NewTypeError(
189           MessageTemplate::kStrictDeleteProperty,
190           factory->NewNumberFromUint(actual_new_len - 1), array));
191       isolate->OptionalRescheduleException(false);
192     } else {
193       info.GetReturnValue().Set(false);
194     }
195   } else {
196     info.GetReturnValue().Set(true);
197   }
198 }
199 
200 
ArrayLengthInfo(Isolate * isolate,PropertyAttributes attributes)201 Handle<AccessorInfo> Accessors::ArrayLengthInfo(
202       Isolate* isolate, PropertyAttributes attributes) {
203   return MakeAccessor(isolate,
204                       isolate->factory()->length_string(),
205                       &ArrayLengthGetter,
206                       &ArrayLengthSetter,
207                       attributes);
208 }
209 
210 //
211 // Accessors::ModuleNamespaceEntry
212 //
213 
ModuleNamespaceEntryGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)214 void Accessors::ModuleNamespaceEntryGetter(
215     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
216   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
217   HandleScope scope(isolate);
218   JSModuleNamespace* holder =
219       JSModuleNamespace::cast(*Utils::OpenHandle(*info.Holder()));
220   Handle<Object> result;
221   if (!holder->GetExport(Handle<String>::cast(Utils::OpenHandle(*name)))
222            .ToHandle(&result)) {
223     isolate->OptionalRescheduleException(false);
224   } else {
225     info.GetReturnValue().Set(Utils::ToLocal(result));
226   }
227 }
228 
ModuleNamespaceEntrySetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<v8::Boolean> & info)229 void Accessors::ModuleNamespaceEntrySetter(
230     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
231     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
232   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
233   HandleScope scope(isolate);
234   Factory* factory = isolate->factory();
235   Handle<JSModuleNamespace> holder =
236       Handle<JSModuleNamespace>::cast(Utils::OpenHandle(*info.Holder()));
237 
238   if (info.ShouldThrowOnError()) {
239     isolate->Throw(*factory->NewTypeError(
240         MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
241         i::Object::TypeOf(isolate, holder), holder));
242     isolate->OptionalRescheduleException(false);
243   } else {
244     info.GetReturnValue().Set(false);
245   }
246 }
247 
ModuleNamespaceEntryInfo(Isolate * isolate,Handle<String> name,PropertyAttributes attributes)248 Handle<AccessorInfo> Accessors::ModuleNamespaceEntryInfo(
249     Isolate* isolate, Handle<String> name, PropertyAttributes attributes) {
250   return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter,
251                       &ModuleNamespaceEntrySetter, attributes);
252 }
253 
254 
255 //
256 // Accessors::StringLength
257 //
258 
StringLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)259 void Accessors::StringLengthGetter(
260     v8::Local<v8::Name> name,
261     const v8::PropertyCallbackInfo<v8::Value>& info) {
262   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
263   RuntimeCallTimerScope timer(
264       isolate, &RuntimeCallStats::AccessorNameGetterCallback_StringLength);
265   DisallowHeapAllocation no_allocation;
266   HandleScope scope(isolate);
267 
268   // We have a slight impedance mismatch between the external API and the way we
269   // use callbacks internally: Externally, callbacks can only be used with
270   // v8::Object, but internally we have callbacks on entities which are higher
271   // in the hierarchy, in this case for String values.
272 
273   Object* value = *Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
274   if (!value->IsString()) {
275     // Not a string value. That means that we either got a String wrapper or
276     // a Value with a String wrapper in its prototype chain.
277     value = JSValue::cast(*Utils::OpenHandle(*info.Holder()))->value();
278   }
279   Object* result = Smi::FromInt(String::cast(value)->length());
280   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
281 }
282 
283 
StringLengthInfo(Isolate * isolate,PropertyAttributes attributes)284 Handle<AccessorInfo> Accessors::StringLengthInfo(
285       Isolate* isolate, PropertyAttributes attributes) {
286   return MakeAccessor(isolate, isolate->factory()->length_string(),
287                       &StringLengthGetter, nullptr, attributes);
288 }
289 
290 
291 //
292 // Accessors::ScriptColumnOffset
293 //
294 
295 
ScriptColumnOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)296 void Accessors::ScriptColumnOffsetGetter(
297     v8::Local<v8::Name> name,
298     const v8::PropertyCallbackInfo<v8::Value>& info) {
299   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
300   DisallowHeapAllocation no_allocation;
301   HandleScope scope(isolate);
302   Object* object = *Utils::OpenHandle(*info.Holder());
303   Object* res = Smi::FromInt(
304       Script::cast(JSValue::cast(object)->value())->column_offset());
305   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
306 }
307 
308 
ScriptColumnOffsetInfo(Isolate * isolate,PropertyAttributes attributes)309 Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
310       Isolate* isolate, PropertyAttributes attributes) {
311   Handle<String> name(isolate->factory()->InternalizeOneByteString(
312       STATIC_CHAR_VECTOR("column_offset")));
313   return MakeAccessor(isolate, name, &ScriptColumnOffsetGetter, nullptr,
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.Holder());
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 
ScriptIdInfo(Isolate * isolate,PropertyAttributes attributes)335 Handle<AccessorInfo> Accessors::ScriptIdInfo(
336       Isolate* isolate, PropertyAttributes attributes) {
337   Handle<String> name(
338       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
339   return MakeAccessor(isolate, name, &ScriptIdGetter, nullptr, attributes);
340 }
341 
342 
343 //
344 // Accessors::ScriptName
345 //
346 
347 
ScriptNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)348 void Accessors::ScriptNameGetter(
349     v8::Local<v8::Name> name,
350     const v8::PropertyCallbackInfo<v8::Value>& info) {
351   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
352   DisallowHeapAllocation no_allocation;
353   HandleScope scope(isolate);
354   Object* object = *Utils::OpenHandle(*info.Holder());
355   Object* source = Script::cast(JSValue::cast(object)->value())->name();
356   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
357 }
358 
359 
ScriptNameInfo(Isolate * isolate,PropertyAttributes attributes)360 Handle<AccessorInfo> Accessors::ScriptNameInfo(
361       Isolate* isolate, PropertyAttributes attributes) {
362   return MakeAccessor(isolate, isolate->factory()->name_string(),
363                       &ScriptNameGetter, nullptr, attributes);
364 }
365 
366 
367 //
368 // Accessors::ScriptSource
369 //
370 
371 
ScriptSourceGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)372 void Accessors::ScriptSourceGetter(
373     v8::Local<v8::Name> name,
374     const v8::PropertyCallbackInfo<v8::Value>& info) {
375   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
376   DisallowHeapAllocation no_allocation;
377   HandleScope scope(isolate);
378   Object* object = *Utils::OpenHandle(*info.Holder());
379   Object* source = Script::cast(JSValue::cast(object)->value())->source();
380   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
381 }
382 
383 
ScriptSourceInfo(Isolate * isolate,PropertyAttributes attributes)384 Handle<AccessorInfo> Accessors::ScriptSourceInfo(
385       Isolate* isolate, PropertyAttributes attributes) {
386   return MakeAccessor(isolate, isolate->factory()->source_string(),
387                       &ScriptSourceGetter, nullptr, attributes);
388 }
389 
390 
391 //
392 // Accessors::ScriptLineOffset
393 //
394 
395 
ScriptLineOffsetGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)396 void Accessors::ScriptLineOffsetGetter(
397     v8::Local<v8::Name> name,
398     const v8::PropertyCallbackInfo<v8::Value>& info) {
399   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
400   DisallowHeapAllocation no_allocation;
401   HandleScope scope(isolate);
402   Object* object = *Utils::OpenHandle(*info.Holder());
403   Object* res =
404       Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset());
405   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
406 }
407 
408 
ScriptLineOffsetInfo(Isolate * isolate,PropertyAttributes attributes)409 Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
410       Isolate* isolate, PropertyAttributes attributes) {
411   Handle<String> name(isolate->factory()->InternalizeOneByteString(
412       STATIC_CHAR_VECTOR("line_offset")));
413   return MakeAccessor(isolate, name, &ScriptLineOffsetGetter, nullptr,
414                       attributes);
415 }
416 
417 
418 //
419 // Accessors::ScriptType
420 //
421 
422 
ScriptTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)423 void Accessors::ScriptTypeGetter(
424     v8::Local<v8::Name> name,
425     const v8::PropertyCallbackInfo<v8::Value>& info) {
426   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
427   DisallowHeapAllocation no_allocation;
428   HandleScope scope(isolate);
429   Object* object = *Utils::OpenHandle(*info.Holder());
430   Object* res =
431       Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type());
432   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
433 }
434 
435 
ScriptTypeInfo(Isolate * isolate,PropertyAttributes attributes)436 Handle<AccessorInfo> Accessors::ScriptTypeInfo(
437       Isolate* isolate, PropertyAttributes attributes) {
438   Handle<String> name(
439       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
440   return MakeAccessor(isolate, name, &ScriptTypeGetter, nullptr, attributes);
441 }
442 
443 
444 //
445 // Accessors::ScriptCompilationType
446 //
447 
448 
ScriptCompilationTypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)449 void Accessors::ScriptCompilationTypeGetter(
450     v8::Local<v8::Name> name,
451     const v8::PropertyCallbackInfo<v8::Value>& info) {
452   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
453   DisallowHeapAllocation no_allocation;
454   HandleScope scope(isolate);
455   Object* object = *Utils::OpenHandle(*info.Holder());
456   Object* res = Smi::FromInt(
457       Script::cast(JSValue::cast(object)->value())->compilation_type());
458   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
459 }
460 
461 
ScriptCompilationTypeInfo(Isolate * isolate,PropertyAttributes attributes)462 Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
463       Isolate* isolate, PropertyAttributes attributes) {
464   Handle<String> name(isolate->factory()->InternalizeOneByteString(
465       STATIC_CHAR_VECTOR("compilation_type")));
466   return MakeAccessor(isolate, name, &ScriptCompilationTypeGetter, nullptr,
467                       attributes);
468 }
469 
470 
471 //
472 // Accessors::ScriptSourceUrl
473 //
474 
475 
ScriptSourceUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)476 void Accessors::ScriptSourceUrlGetter(
477     v8::Local<v8::Name> name,
478     const v8::PropertyCallbackInfo<v8::Value>& info) {
479   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
480   DisallowHeapAllocation no_allocation;
481   HandleScope scope(isolate);
482   Object* object = *Utils::OpenHandle(*info.Holder());
483   Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
484   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
485 }
486 
487 
ScriptSourceUrlInfo(Isolate * isolate,PropertyAttributes attributes)488 Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
489       Isolate* isolate, PropertyAttributes attributes) {
490   return MakeAccessor(isolate, isolate->factory()->source_url_string(),
491                       &ScriptSourceUrlGetter, nullptr, attributes);
492 }
493 
494 
495 //
496 // Accessors::ScriptSourceMappingUrl
497 //
498 
499 
ScriptSourceMappingUrlGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)500 void Accessors::ScriptSourceMappingUrlGetter(
501     v8::Local<v8::Name> name,
502     const v8::PropertyCallbackInfo<v8::Value>& info) {
503   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
504   DisallowHeapAllocation no_allocation;
505   HandleScope scope(isolate);
506   Object* object = *Utils::OpenHandle(*info.Holder());
507   Object* url =
508       Script::cast(JSValue::cast(object)->value())->source_mapping_url();
509   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
510 }
511 
512 
ScriptSourceMappingUrlInfo(Isolate * isolate,PropertyAttributes attributes)513 Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
514       Isolate* isolate, PropertyAttributes attributes) {
515   return MakeAccessor(isolate, isolate->factory()->source_mapping_url_string(),
516                       &ScriptSourceMappingUrlGetter, nullptr, attributes);
517 }
518 
519 
520 //
521 // Accessors::ScriptIsEmbedderDebugScript
522 //
523 
524 
ScriptIsEmbedderDebugScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)525 void Accessors::ScriptIsEmbedderDebugScriptGetter(
526     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
527   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
528   DisallowHeapAllocation no_allocation;
529   HandleScope scope(isolate);
530   Object* object = *Utils::OpenHandle(*info.Holder());
531   bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value())
532                                       ->origin_options()
533                                       .IsEmbedderDebugScript();
534   Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script);
535   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
536 }
537 
538 
ScriptIsEmbedderDebugScriptInfo(Isolate * isolate,PropertyAttributes attributes)539 Handle<AccessorInfo> Accessors::ScriptIsEmbedderDebugScriptInfo(
540     Isolate* isolate, PropertyAttributes attributes) {
541   Handle<String> name(isolate->factory()->InternalizeOneByteString(
542       STATIC_CHAR_VECTOR("is_debugger_script")));
543   return MakeAccessor(isolate, name, &ScriptIsEmbedderDebugScriptGetter,
544                       nullptr, attributes);
545 }
546 
547 
548 //
549 // Accessors::ScriptGetContextData
550 //
551 
552 
ScriptContextDataGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)553 void Accessors::ScriptContextDataGetter(
554     v8::Local<v8::Name> name,
555     const v8::PropertyCallbackInfo<v8::Value>& info) {
556   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
557   DisallowHeapAllocation no_allocation;
558   HandleScope scope(isolate);
559   Object* object = *Utils::OpenHandle(*info.Holder());
560   Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
561   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
562 }
563 
564 
ScriptContextDataInfo(Isolate * isolate,PropertyAttributes attributes)565 Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
566       Isolate* isolate, PropertyAttributes attributes) {
567   Handle<String> name(isolate->factory()->InternalizeOneByteString(
568       STATIC_CHAR_VECTOR("context_data")));
569   return MakeAccessor(isolate, name, &ScriptContextDataGetter, nullptr,
570                       attributes);
571 }
572 
573 
574 //
575 // Accessors::ScriptGetEvalFromScript
576 //
577 
578 
ScriptEvalFromScriptGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)579 void Accessors::ScriptEvalFromScriptGetter(
580     v8::Local<v8::Name> name,
581     const v8::PropertyCallbackInfo<v8::Value>& info) {
582   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
583   HandleScope scope(isolate);
584   Handle<Object> object = Utils::OpenHandle(*info.Holder());
585   Handle<Script> script(
586       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
587   Handle<Object> result = isolate->factory()->undefined_value();
588   if (!script->eval_from_shared()->IsUndefined(isolate)) {
589     Handle<SharedFunctionInfo> eval_from_shared(
590         SharedFunctionInfo::cast(script->eval_from_shared()));
591     if (eval_from_shared->script()->IsScript()) {
592       Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
593       result = Script::GetWrapper(eval_from_script);
594     }
595   }
596 
597   info.GetReturnValue().Set(Utils::ToLocal(result));
598 }
599 
600 
ScriptEvalFromScriptInfo(Isolate * isolate,PropertyAttributes attributes)601 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
602       Isolate* isolate, PropertyAttributes attributes) {
603   Handle<String> name(isolate->factory()->InternalizeOneByteString(
604       STATIC_CHAR_VECTOR("eval_from_script")));
605   return MakeAccessor(isolate, name, &ScriptEvalFromScriptGetter, nullptr,
606                       attributes);
607 }
608 
609 
610 //
611 // Accessors::ScriptGetEvalFromScriptPosition
612 //
613 
614 
ScriptEvalFromScriptPositionGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)615 void Accessors::ScriptEvalFromScriptPositionGetter(
616     v8::Local<v8::Name> name,
617     const v8::PropertyCallbackInfo<v8::Value>& info) {
618   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
619   HandleScope scope(isolate);
620   Handle<Object> object = Utils::OpenHandle(*info.Holder());
621   Handle<Script> script(
622       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
623   Handle<Object> result = isolate->factory()->undefined_value();
624   if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
625     result = Handle<Object>(Smi::FromInt(script->GetEvalPosition()), isolate);
626   }
627   info.GetReturnValue().Set(Utils::ToLocal(result));
628 }
629 
630 
ScriptEvalFromScriptPositionInfo(Isolate * isolate,PropertyAttributes attributes)631 Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
632       Isolate* isolate, PropertyAttributes attributes) {
633   Handle<String> name(isolate->factory()->InternalizeOneByteString(
634       STATIC_CHAR_VECTOR("eval_from_script_position")));
635   return MakeAccessor(isolate, name, &ScriptEvalFromScriptPositionGetter,
636                       nullptr, attributes);
637 }
638 
639 
640 //
641 // Accessors::ScriptGetEvalFromFunctionName
642 //
643 
644 
ScriptEvalFromFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)645 void Accessors::ScriptEvalFromFunctionNameGetter(
646     v8::Local<v8::Name> name,
647     const v8::PropertyCallbackInfo<v8::Value>& info) {
648   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
649   HandleScope scope(isolate);
650   Handle<Object> object = Utils::OpenHandle(*info.Holder());
651   Handle<Script> script(
652       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
653   Handle<Object> result = isolate->factory()->undefined_value();
654   if (!script->eval_from_shared()->IsUndefined(isolate)) {
655     Handle<SharedFunctionInfo> shared(
656         SharedFunctionInfo::cast(script->eval_from_shared()));
657     // Find the name of the function calling eval.
658     if (!shared->name()->IsUndefined(isolate)) {
659       result = Handle<Object>(shared->name(), isolate);
660     } else {
661       result = Handle<Object>(shared->inferred_name(), isolate);
662     }
663   }
664   info.GetReturnValue().Set(Utils::ToLocal(result));
665 }
666 
667 
ScriptEvalFromFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)668 Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
669       Isolate* isolate, PropertyAttributes attributes) {
670   Handle<String> name(isolate->factory()->InternalizeOneByteString(
671       STATIC_CHAR_VECTOR("eval_from_function_name")));
672   return MakeAccessor(isolate, name, &ScriptEvalFromFunctionNameGetter, nullptr,
673                       attributes);
674 }
675 
676 
677 //
678 // Accessors::FunctionPrototype
679 //
680 
GetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function)681 static Handle<Object> GetFunctionPrototype(Isolate* isolate,
682                                            Handle<JSFunction> function) {
683   if (!function->has_prototype()) {
684     Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
685     JSFunction::SetPrototype(function, proto);
686   }
687   return Handle<Object>(function->prototype(), isolate);
688 }
689 
690 
SetFunctionPrototype(Isolate * isolate,Handle<JSFunction> function,Handle<Object> value)691 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
692     Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
693   JSFunction::SetPrototype(function, value);
694   DCHECK(function->prototype() == *value);
695   return function;
696 }
697 
698 
FunctionSetPrototype(Handle<JSFunction> function,Handle<Object> prototype)699 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function,
700                                                     Handle<Object> prototype) {
701   DCHECK(function->IsConstructor());
702   Isolate* isolate = function->GetIsolate();
703   return SetFunctionPrototype(isolate, function, prototype);
704 }
705 
706 
FunctionPrototypeGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)707 void Accessors::FunctionPrototypeGetter(
708     v8::Local<v8::Name> name,
709     const v8::PropertyCallbackInfo<v8::Value>& info) {
710   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
711   RuntimeCallTimerScope timer(
712       isolate, &RuntimeCallStats::AccessorNameGetterCallback_FunctionPrototype);
713   HandleScope scope(isolate);
714   Handle<JSFunction> function =
715       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
716   Handle<Object> result = GetFunctionPrototype(isolate, function);
717   info.GetReturnValue().Set(Utils::ToLocal(result));
718 }
719 
FunctionPrototypeSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<v8::Boolean> & info)720 void Accessors::FunctionPrototypeSetter(
721     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
722     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
723   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
724   HandleScope scope(isolate);
725   Handle<Object> value = Utils::OpenHandle(*val);
726   Handle<JSFunction> object =
727       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
728   if (SetFunctionPrototype(isolate, object, value).is_null()) {
729     isolate->OptionalRescheduleException(false);
730   } else {
731     info.GetReturnValue().Set(true);
732   }
733 }
734 
735 
FunctionPrototypeInfo(Isolate * isolate,PropertyAttributes attributes)736 Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
737       Isolate* isolate, PropertyAttributes attributes) {
738   return MakeAccessor(isolate,
739                       isolate->factory()->prototype_string(),
740                       &FunctionPrototypeGetter,
741                       &FunctionPrototypeSetter,
742                       attributes);
743 }
744 
745 
746 //
747 // Accessors::FunctionLength
748 //
749 
750 
FunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)751 void Accessors::FunctionLengthGetter(
752     v8::Local<v8::Name> name,
753     const v8::PropertyCallbackInfo<v8::Value>& info) {
754   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
755   HandleScope scope(isolate);
756   Handle<JSFunction> function =
757       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
758   Handle<Object> result;
759   if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) {
760     result = handle(Smi::kZero, isolate);
761     isolate->OptionalRescheduleException(false);
762   }
763 
764   info.GetReturnValue().Set(Utils::ToLocal(result));
765 }
766 
FunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)767 Handle<AccessorInfo> Accessors::FunctionLengthInfo(
768       Isolate* isolate, PropertyAttributes attributes) {
769   return MakeAccessor(isolate, isolate->factory()->length_string(),
770                       &FunctionLengthGetter, &ReconfigureToDataProperty,
771                       attributes);
772 }
773 
774 
775 //
776 // Accessors::FunctionName
777 //
778 
779 
FunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)780 void Accessors::FunctionNameGetter(
781     v8::Local<v8::Name> name,
782     const v8::PropertyCallbackInfo<v8::Value>& info) {
783   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
784   HandleScope scope(isolate);
785   Handle<JSFunction> function =
786       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
787   Handle<Object> result = JSFunction::GetName(isolate, function);
788   info.GetReturnValue().Set(Utils::ToLocal(result));
789 }
790 
FunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)791 Handle<AccessorInfo> Accessors::FunctionNameInfo(
792       Isolate* isolate, PropertyAttributes attributes) {
793   return MakeAccessor(isolate, isolate->factory()->name_string(),
794                       &FunctionNameGetter, &ReconfigureToDataProperty,
795                       attributes);
796 }
797 
798 
799 //
800 // Accessors::FunctionArguments
801 //
802 
803 
ArgumentsForInlinedFunction(JavaScriptFrame * frame,Handle<JSFunction> inlined_function,int inlined_frame_index)804 static Handle<Object> ArgumentsForInlinedFunction(
805     JavaScriptFrame* frame,
806     Handle<JSFunction> inlined_function,
807     int inlined_frame_index) {
808   Isolate* isolate = inlined_function->GetIsolate();
809   Factory* factory = isolate->factory();
810 
811   TranslatedState translated_values(frame);
812   translated_values.Prepare(false, frame->fp());
813 
814   int argument_count = 0;
815   TranslatedFrame* translated_frame =
816       translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
817                                                          &argument_count);
818   TranslatedFrame::iterator iter = translated_frame->begin();
819 
820   // Skip the function.
821   iter++;
822 
823   // Skip the receiver.
824   iter++;
825   argument_count--;
826 
827   Handle<JSObject> arguments =
828       factory->NewArgumentsObject(inlined_function, argument_count);
829   Handle<FixedArray> array = factory->NewFixedArray(argument_count);
830   bool should_deoptimize = false;
831   for (int i = 0; i < argument_count; ++i) {
832     // If we materialize any object, we should deopt because we might alias
833     // an object that was eliminated by escape analysis.
834     should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
835     Handle<Object> value = iter->GetValue();
836     array->set(i, *value);
837     iter++;
838   }
839   arguments->set_elements(*array);
840 
841   if (should_deoptimize) {
842     translated_values.StoreMaterializedValuesAndDeopt();
843   }
844 
845   // Return the freshly allocated arguments object.
846   return arguments;
847 }
848 
849 
FindFunctionInFrame(JavaScriptFrame * frame,Handle<JSFunction> function)850 static int FindFunctionInFrame(JavaScriptFrame* frame,
851                                Handle<JSFunction> function) {
852   DisallowHeapAllocation no_allocation;
853   List<JSFunction*> functions(2);
854   frame->GetFunctions(&functions);
855   for (int i = functions.length() - 1; i >= 0; i--) {
856     if (functions[i] == *function) return i;
857   }
858   return -1;
859 }
860 
861 
862 namespace {
863 
GetFunctionArguments(Isolate * isolate,Handle<JSFunction> function)864 Handle<Object> GetFunctionArguments(Isolate* isolate,
865                                     Handle<JSFunction> function) {
866   // Find the top invocation of the function by traversing frames.
867   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
868     JavaScriptFrame* frame = it.frame();
869     int function_index = FindFunctionInFrame(frame, function);
870     if (function_index < 0) continue;
871 
872     if (function_index > 0) {
873       // The function in question was inlined.  Inlined functions have the
874       // correct number of arguments and no allocated arguments object, so
875       // we can construct a fresh one by interpreting the function's
876       // deoptimization input data.
877       return ArgumentsForInlinedFunction(frame, function, function_index);
878     }
879 
880     // Find the frame that holds the actual arguments passed to the function.
881     it.AdvanceToArgumentsFrame();
882     frame = it.frame();
883 
884     // Get the number of arguments and construct an arguments object
885     // mirror for the right frame.
886     const int length = frame->ComputeParametersCount();
887     Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
888         function, length);
889     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
890 
891     // Copy the parameters to the arguments object.
892     DCHECK(array->length() == length);
893     for (int i = 0; i < length; i++) {
894       Object* value = frame->GetParameter(i);
895       if (value->IsTheHole(isolate)) {
896         // Generators currently use holes as dummy arguments when resuming.  We
897         // must not leak those.
898         DCHECK(IsResumableFunction(function->shared()->kind()));
899         value = isolate->heap()->undefined_value();
900       }
901       array->set(i, value);
902     }
903     arguments->set_elements(*array);
904 
905     // Return the freshly allocated arguments object.
906     return arguments;
907   }
908 
909   // No frame corresponding to the given function found. Return null.
910   return isolate->factory()->null_value();
911 }
912 
913 }  // namespace
914 
915 
FunctionGetArguments(Handle<JSFunction> function)916 Handle<JSObject> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
917   Handle<Object> arguments =
918       GetFunctionArguments(function->GetIsolate(), function);
919   CHECK(arguments->IsJSObject());
920   return Handle<JSObject>::cast(arguments);
921 }
922 
923 
FunctionArgumentsGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)924 void Accessors::FunctionArgumentsGetter(
925     v8::Local<v8::Name> name,
926     const v8::PropertyCallbackInfo<v8::Value>& info) {
927   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
928   HandleScope scope(isolate);
929   Handle<JSFunction> function =
930       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
931   Handle<Object> result =
932       function->shared()->native()
933           ? Handle<Object>::cast(isolate->factory()->null_value())
934           : GetFunctionArguments(isolate, function);
935   info.GetReturnValue().Set(Utils::ToLocal(result));
936 }
937 
938 
FunctionArgumentsInfo(Isolate * isolate,PropertyAttributes attributes)939 Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
940       Isolate* isolate, PropertyAttributes attributes) {
941   return MakeAccessor(isolate, isolate->factory()->arguments_string(),
942                       &FunctionArgumentsGetter, nullptr, attributes);
943 }
944 
945 
946 //
947 // Accessors::FunctionCaller
948 //
949 
950 
AllowAccessToFunction(Context * current_context,JSFunction * function)951 static inline bool AllowAccessToFunction(Context* current_context,
952                                          JSFunction* function) {
953   return current_context->HasSameSecurityTokenAs(function->context());
954 }
955 
956 
957 class FrameFunctionIterator {
958  public:
FrameFunctionIterator(Isolate * isolate,const DisallowHeapAllocation & promise)959   FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
960       : isolate_(isolate),
961         frame_iterator_(isolate),
962         functions_(2),
963         index_(0) {
964     GetFunctions();
965   }
next()966   JSFunction* next() {
967     while (true) {
968       if (functions_.length() == 0) return NULL;
969       JSFunction* next_function = functions_[index_];
970       index_--;
971       if (index_ < 0) {
972         GetFunctions();
973       }
974       // Skip functions from other origins.
975       if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
976       return next_function;
977     }
978   }
979 
980   // Iterate through functions until the first occurence of 'function'.
981   // Returns true if 'function' is found, and false if the iterator ends
982   // without finding it.
Find(JSFunction * function)983   bool Find(JSFunction* function) {
984     JSFunction* next_function;
985     do {
986       next_function = next();
987       if (next_function == function) return true;
988     } while (next_function != NULL);
989     return false;
990   }
991 
992  private:
GetFunctions()993   void GetFunctions() {
994     functions_.Rewind(0);
995     if (frame_iterator_.done()) return;
996     JavaScriptFrame* frame = frame_iterator_.frame();
997     frame->GetFunctions(&functions_);
998     DCHECK(functions_.length() > 0);
999     frame_iterator_.Advance();
1000     index_ = functions_.length() - 1;
1001   }
1002   Isolate* isolate_;
1003   JavaScriptFrameIterator frame_iterator_;
1004   List<JSFunction*> functions_;
1005   int index_;
1006 };
1007 
1008 
FindCaller(Isolate * isolate,Handle<JSFunction> function)1009 MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
1010                                    Handle<JSFunction> function) {
1011   DisallowHeapAllocation no_allocation;
1012   FrameFunctionIterator it(isolate, no_allocation);
1013   if (function->shared()->native()) {
1014     return MaybeHandle<JSFunction>();
1015   }
1016   // Find the function from the frames.
1017   if (!it.Find(*function)) {
1018     // No frame corresponding to the given function found. Return null.
1019     return MaybeHandle<JSFunction>();
1020   }
1021   // Find previously called non-toplevel function.
1022   JSFunction* caller;
1023   do {
1024     caller = it.next();
1025     if (caller == NULL) return MaybeHandle<JSFunction>();
1026   } while (caller->shared()->is_toplevel());
1027 
1028   // If caller is a built-in function and caller's caller is also built-in,
1029   // use that instead.
1030   JSFunction* potential_caller = caller;
1031   while (potential_caller != NULL && potential_caller->shared()->IsBuiltin()) {
1032     caller = potential_caller;
1033     potential_caller = it.next();
1034   }
1035   if (!caller->shared()->native() && potential_caller != NULL) {
1036     caller = potential_caller;
1037   }
1038   // Censor if the caller is not a sloppy mode function.
1039   // Change from ES5, which used to throw, see:
1040   // https://bugs.ecmascript.org/show_bug.cgi?id=310
1041   if (is_strict(caller->shared()->language_mode())) {
1042     return MaybeHandle<JSFunction>();
1043   }
1044   // Don't return caller from another security context.
1045   if (!AllowAccessToFunction(isolate->context(), caller)) {
1046     return MaybeHandle<JSFunction>();
1047   }
1048   return Handle<JSFunction>(caller);
1049 }
1050 
1051 
FunctionCallerGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1052 void Accessors::FunctionCallerGetter(
1053     v8::Local<v8::Name> name,
1054     const v8::PropertyCallbackInfo<v8::Value>& info) {
1055   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1056   HandleScope scope(isolate);
1057   Handle<JSFunction> function =
1058       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1059   Handle<Object> result;
1060   MaybeHandle<JSFunction> maybe_caller;
1061   maybe_caller = FindCaller(isolate, function);
1062   Handle<JSFunction> caller;
1063   if (maybe_caller.ToHandle(&caller)) {
1064     result = caller;
1065   } else {
1066     result = isolate->factory()->null_value();
1067   }
1068   info.GetReturnValue().Set(Utils::ToLocal(result));
1069 }
1070 
1071 
FunctionCallerInfo(Isolate * isolate,PropertyAttributes attributes)1072 Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1073       Isolate* isolate, PropertyAttributes attributes) {
1074   return MakeAccessor(isolate, isolate->factory()->caller_string(),
1075                       &FunctionCallerGetter, nullptr, attributes);
1076 }
1077 
1078 
1079 //
1080 // Accessors::BoundFunctionLength
1081 //
1082 
BoundFunctionLengthGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1083 void Accessors::BoundFunctionLengthGetter(
1084     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1085   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1086   RuntimeCallTimerScope timer(
1087       isolate,
1088       &RuntimeCallStats::AccessorNameGetterCallback_BoundFunctionLength);
1089   HandleScope scope(isolate);
1090   Handle<JSBoundFunction> function =
1091       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1092 
1093   Handle<Smi> target_length;
1094   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
1095                             isolate);
1096   if (!JSFunction::GetLength(isolate, target).ToHandle(&target_length)) {
1097     target_length = handle(Smi::kZero, isolate);
1098     isolate->OptionalRescheduleException(false);
1099     return;
1100   }
1101 
1102   int bound_length = function->bound_arguments()->length();
1103   int length = Max(0, target_length->value() - bound_length);
1104 
1105   Handle<Object> result(Smi::FromInt(length), isolate);
1106   info.GetReturnValue().Set(Utils::ToLocal(result));
1107 }
1108 
BoundFunctionLengthInfo(Isolate * isolate,PropertyAttributes attributes)1109 Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo(
1110     Isolate* isolate, PropertyAttributes attributes) {
1111   return MakeAccessor(isolate, isolate->factory()->length_string(),
1112                       &BoundFunctionLengthGetter, &ReconfigureToDataProperty,
1113                       attributes);
1114 }
1115 
1116 //
1117 // Accessors::BoundFunctionName
1118 //
1119 
BoundFunctionNameGetter(v8::Local<v8::Name> name,const v8::PropertyCallbackInfo<v8::Value> & info)1120 void Accessors::BoundFunctionNameGetter(
1121     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1122   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1123   RuntimeCallTimerScope timer(
1124       isolate, &RuntimeCallStats::AccessorNameGetterCallback_BoundFunctionName);
1125   HandleScope scope(isolate);
1126   Handle<JSBoundFunction> function =
1127       Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1128   Handle<Object> result;
1129   if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
1130     isolate->OptionalRescheduleException(false);
1131     return;
1132   }
1133   info.GetReturnValue().Set(Utils::ToLocal(result));
1134 }
1135 
BoundFunctionNameInfo(Isolate * isolate,PropertyAttributes attributes)1136 Handle<AccessorInfo> Accessors::BoundFunctionNameInfo(
1137     Isolate* isolate, PropertyAttributes attributes) {
1138   return MakeAccessor(isolate, isolate->factory()->name_string(),
1139                       &BoundFunctionNameGetter, &ReconfigureToDataProperty,
1140                       attributes);
1141 }
1142 
1143 //
1144 // Accessors::ErrorStack
1145 //
1146 
1147 namespace {
1148 
ClearInternalStackTrace(Isolate * isolate,Handle<JSObject> error)1149 MaybeHandle<JSReceiver> ClearInternalStackTrace(Isolate* isolate,
1150                                                 Handle<JSObject> error) {
1151   RETURN_ON_EXCEPTION(
1152       isolate,
1153       JSReceiver::SetProperty(error, isolate->factory()->stack_trace_symbol(),
1154                               isolate->factory()->undefined_value(), STRICT),
1155       JSReceiver);
1156   return error;
1157 }
1158 
IsAccessor(Handle<Object> receiver,Handle<Name> name,Handle<JSObject> holder)1159 bool IsAccessor(Handle<Object> receiver, Handle<Name> name,
1160                 Handle<JSObject> holder) {
1161   LookupIterator it(receiver, name, holder,
1162                     LookupIterator::OWN_SKIP_INTERCEPTOR);
1163   // Skip any access checks we might hit. This accessor should never hit in a
1164   // situation where the caller does not have access.
1165   if (it.state() == LookupIterator::ACCESS_CHECK) {
1166     CHECK(it.HasAccess());
1167     it.Next();
1168   }
1169   return (it.state() == LookupIterator::ACCESSOR);
1170 }
1171 
1172 }  // namespace
1173 
ErrorStackGetter(v8::Local<v8::Name> key,const v8::PropertyCallbackInfo<v8::Value> & info)1174 void Accessors::ErrorStackGetter(
1175     v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
1176   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1177   HandleScope scope(isolate);
1178   Handle<JSObject> holder =
1179       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
1180 
1181   // Retrieve the structured stack trace.
1182 
1183   Handle<Object> stack_trace;
1184   Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
1185   MaybeHandle<Object> maybe_stack_trace =
1186       JSObject::GetProperty(holder, stack_trace_symbol);
1187   if (!maybe_stack_trace.ToHandle(&stack_trace) ||
1188       stack_trace->IsUndefined(isolate)) {
1189     Handle<Object> result = isolate->factory()->undefined_value();
1190     info.GetReturnValue().Set(Utils::ToLocal(result));
1191     return;
1192   }
1193 
1194   // Format it, clear the internal structured trace and reconfigure as a data
1195   // property.
1196 
1197   Handle<Object> formatted_stack_trace;
1198   if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace)
1199            .ToHandle(&formatted_stack_trace)) {
1200     isolate->OptionalRescheduleException(false);
1201     return;
1202   }
1203 
1204   MaybeHandle<Object> result = ClearInternalStackTrace(isolate, holder);
1205   if (result.is_null()) {
1206     isolate->OptionalRescheduleException(false);
1207     return;
1208   }
1209 
1210   // If stack is still an accessor (this could have changed in the meantime
1211   // since FormatStackTrace can execute arbitrary JS), replace it with a data
1212   // property.
1213   Handle<Object> receiver = Utils::OpenHandle(*info.This());
1214   Handle<Name> name = Utils::OpenHandle(*key);
1215   if (IsAccessor(receiver, name, holder)) {
1216     result = ReplaceAccessorWithDataProperty(isolate, receiver, holder, name,
1217                                              formatted_stack_trace);
1218     if (result.is_null()) {
1219       isolate->OptionalRescheduleException(false);
1220       return;
1221     }
1222   } else {
1223     // The stack property has been modified in the meantime.
1224     if (!JSObject::GetProperty(holder, name).ToHandle(&formatted_stack_trace)) {
1225       isolate->OptionalRescheduleException(false);
1226       return;
1227     }
1228   }
1229 
1230   v8::Local<v8::Value> value = Utils::ToLocal(formatted_stack_trace);
1231   info.GetReturnValue().Set(value);
1232 }
1233 
ErrorStackSetter(v8::Local<v8::Name> name,v8::Local<v8::Value> val,const v8::PropertyCallbackInfo<v8::Boolean> & info)1234 void Accessors::ErrorStackSetter(
1235     v8::Local<v8::Name> name, v8::Local<v8::Value> val,
1236     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
1237   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1238   HandleScope scope(isolate);
1239   Handle<JSObject> obj =
1240       Handle<JSObject>::cast(Utils::OpenHandle(*info.This()));
1241 
1242   // Clear internal properties to avoid memory leaks.
1243   Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
1244   if (JSReceiver::HasOwnProperty(obj, stack_trace_symbol).FromMaybe(false)) {
1245     ClearInternalStackTrace(isolate, obj);
1246   }
1247 
1248   Accessors::ReconfigureToDataProperty(name, val, info);
1249 }
1250 
ErrorStackInfo(Isolate * isolate,PropertyAttributes attributes)1251 Handle<AccessorInfo> Accessors::ErrorStackInfo(Isolate* isolate,
1252                                                PropertyAttributes attributes) {
1253   Handle<AccessorInfo> info =
1254       MakeAccessor(isolate, isolate->factory()->stack_string(),
1255                    &ErrorStackGetter, &ErrorStackSetter, attributes);
1256   return info;
1257 }
1258 
1259 }  // namespace internal
1260 }  // namespace v8
1261