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