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