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