Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/accessors.h"
6 :
7 : #include "src/api.h"
8 : #include "src/contexts.h"
9 : #include "src/deoptimizer.h"
10 : #include "src/execution.h"
11 : #include "src/factory.h"
12 : #include "src/frames-inl.h"
13 : #include "src/isolate-inl.h"
14 : #include "src/list-inl.h"
15 : #include "src/messages.h"
16 : #include "src/property-details.h"
17 : #include "src/prototype.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 53859 : Handle<AccessorInfo> Accessors::MakeAccessor(
23 : Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
24 : AccessorNameBooleanSetterCallback setter, PropertyAttributes attributes) {
25 : Factory* factory = isolate->factory();
26 53859 : 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 53859 : name = factory->InternalizeName(name);
34 53859 : info->set_name(*name);
35 53859 : Handle<Object> get = v8::FromCData(isolate, getter);
36 53859 : if (setter == nullptr) setter = &ReconfigureToDataProperty;
37 53859 : Handle<Object> set = v8::FromCData(isolate, setter);
38 53859 : info->set_getter(*get);
39 53859 : info->set_setter(*set);
40 53859 : Address redirected = info->redirected_getter();
41 53859 : if (redirected != nullptr) {
42 52487 : Handle<Object> js_get = v8::FromCData(isolate, redirected);
43 52487 : info->set_js_getter(*js_get);
44 : }
45 53859 : return info;
46 : }
47 :
48 :
49 : static V8_INLINE bool CheckForName(Handle<Name> name,
50 : Handle<String> property_name,
51 : int offset,
52 : int* object_offset) {
53 329851 : if (Name::Equals(name, property_name)) {
54 246773 : *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.
63 1222505 : bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
64 : int* object_offset) {
65 : Isolate* isolate = name->GetIsolate();
66 :
67 1222505 : switch (map->instance_type()) {
68 : case JS_ARRAY_TYPE:
69 : return
70 : CheckForName(name, isolate->factory()->length_string(),
71 267590 : JSArray::kLengthOffset, object_offset);
72 : default:
73 954915 : if (map->instance_type() < FIRST_NONSTRING_TYPE) {
74 : return CheckForName(name, isolate->factory()->length_string(),
75 62261 : String::kLengthOffset, object_offset);
76 : }
77 :
78 : return false;
79 : }
80 : }
81 :
82 :
83 : namespace {
84 :
85 1514402 : 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 1514402 : 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 1514404 : if (it.state() == LookupIterator::ACCESS_CHECK) {
93 0 : CHECK(it.HasAccess());
94 0 : it.Next();
95 : }
96 : DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
97 1514404 : CHECK_EQ(LookupIterator::ACCESSOR, it.state());
98 1514404 : it.ReconfigureDataProperty(value, it.property_attributes());
99 1514402 : return value;
100 : }
101 :
102 : } // namespace
103 :
104 1491626 : 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 1491626 : Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
112 1491626 : Handle<Name> name = Utils::OpenHandle(*key);
113 1491626 : Handle<Object> value = Utils::OpenHandle(*val);
114 : MaybeHandle<Object> result =
115 1491626 : ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value);
116 1491633 : if (result.is_null()) {
117 0 : isolate->OptionalRescheduleException(false);
118 : } else {
119 : info.GetReturnValue().Set(true);
120 : }
121 1491629 : }
122 :
123 : //
124 : // Accessors::ArgumentsIterator
125 : //
126 :
127 :
128 9324 : 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 18648 : Object* result = isolate->native_context()->array_values_iterator();
134 : info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
135 9324 : }
136 :
137 :
138 79 : 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 79 : attributes);
143 : }
144 :
145 :
146 : //
147 : // Accessors::ArrayLength
148 : //
149 :
150 :
151 533389 : 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 533389 : 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 533389 : }
163 :
164 1003395 : 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 1003395 : Handle<Object> length_obj = Utils::OpenHandle(*val);
175 :
176 1003395 : bool was_readonly = JSArray::HasReadOnlyLength(array);
177 :
178 1003395 : uint32_t length = 0;
179 1003395 : if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
180 386 : isolate->OptionalRescheduleException(false);
181 386 : return;
182 : }
183 :
184 1003039 : if (!was_readonly && V8_UNLIKELY(JSArray::HasReadOnlyLength(array)) &&
185 30 : 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 30 : if (info.ShouldThrowOnError()) {
191 : Factory* factory = isolate->factory();
192 : isolate->Throw(*factory->NewTypeError(
193 : MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
194 45 : i::Object::TypeOf(isolate, object), object));
195 15 : isolate->OptionalRescheduleException(false);
196 : } else {
197 : info.GetReturnValue().Set(false);
198 : }
199 : return;
200 : }
201 :
202 1002979 : JSArray::SetLength(array, length);
203 :
204 1002979 : uint32_t actual_new_len = 0;
205 1002979 : CHECK(array->length()->ToArrayLength(&actual_new_len));
206 : // Fail if there were non-deletable elements.
207 1002979 : if (actual_new_len != length) {
208 103 : if (info.ShouldThrowOnError()) {
209 : Factory* factory = isolate->factory();
210 : isolate->Throw(*factory->NewTypeError(
211 : MessageTemplate::kStrictDeleteProperty,
212 90 : factory->NewNumberFromUint(actual_new_len - 1), array));
213 45 : isolate->OptionalRescheduleException(false);
214 : } else {
215 : info.GetReturnValue().Set(false);
216 : }
217 : } else {
218 : info.GetReturnValue().Set(true);
219 : }
220 : }
221 :
222 :
223 316 : Handle<AccessorInfo> Accessors::ArrayLengthInfo(
224 : Isolate* isolate, PropertyAttributes attributes) {
225 : return MakeAccessor(isolate,
226 : isolate->factory()->length_string(),
227 : &ArrayLengthGetter,
228 : &ArrayLengthSetter,
229 316 : attributes);
230 : }
231 :
232 : //
233 : // Accessors::ModuleNamespaceEntry
234 : //
235 :
236 853 : 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 853 : if (!holder->GetExport(Handle<String>::cast(Utils::OpenHandle(*name)))
244 1706 : .ToHandle(&result)) {
245 105 : isolate->OptionalRescheduleException(false);
246 : } else {
247 : info.GetReturnValue().Set(Utils::ToLocal(result));
248 : }
249 853 : }
250 :
251 15 : 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 15 : if (info.ShouldThrowOnError()) {
261 : isolate->Throw(*factory->NewTypeError(
262 : MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
263 0 : i::Object::TypeOf(isolate, holder), holder));
264 0 : isolate->OptionalRescheduleException(false);
265 : } else {
266 : info.GetReturnValue().Set(false);
267 : }
268 15 : }
269 :
270 611 : Handle<AccessorInfo> Accessors::ModuleNamespaceEntryInfo(
271 : Isolate* isolate, Handle<String> name, PropertyAttributes attributes) {
272 : return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter,
273 611 : &ModuleNamespaceEntrySetter, attributes);
274 : }
275 :
276 :
277 : //
278 : // Accessors::StringLength
279 : //
280 :
281 47285 : 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 47285 : 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 47285 : 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 47285 : }
304 :
305 :
306 79 : Handle<AccessorInfo> Accessors::StringLengthInfo(
307 : Isolate* isolate, PropertyAttributes attributes) {
308 : return MakeAccessor(isolate, isolate->factory()->length_string(),
309 79 : &StringLengthGetter, nullptr, attributes);
310 : }
311 :
312 :
313 : //
314 : // Accessors::ScriptColumnOffset
315 : //
316 :
317 :
318 0 : 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 0 : }
329 :
330 :
331 79 : Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
332 : Isolate* isolate, PropertyAttributes attributes) {
333 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
334 79 : STATIC_CHAR_VECTOR("column_offset")));
335 : return MakeAccessor(isolate, name, &ScriptColumnOffsetGetter, nullptr,
336 79 : attributes);
337 : }
338 :
339 :
340 : //
341 : // Accessors::ScriptId
342 : //
343 :
344 :
345 717059 : 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 717059 : }
355 :
356 :
357 79 : Handle<AccessorInfo> Accessors::ScriptIdInfo(
358 : Isolate* isolate, PropertyAttributes attributes) {
359 : Handle<String> name(
360 79 : isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
361 79 : return MakeAccessor(isolate, name, &ScriptIdGetter, nullptr, attributes);
362 : }
363 :
364 :
365 : //
366 : // Accessors::ScriptName
367 : //
368 :
369 :
370 3602 : 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 3602 : }
380 :
381 :
382 79 : Handle<AccessorInfo> Accessors::ScriptNameInfo(
383 : Isolate* isolate, PropertyAttributes attributes) {
384 : return MakeAccessor(isolate, isolate->factory()->name_string(),
385 79 : &ScriptNameGetter, nullptr, attributes);
386 : }
387 :
388 :
389 : //
390 : // Accessors::ScriptSource
391 : //
392 :
393 :
394 2748 : 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 2748 : }
404 :
405 :
406 79 : Handle<AccessorInfo> Accessors::ScriptSourceInfo(
407 : Isolate* isolate, PropertyAttributes attributes) {
408 : return MakeAccessor(isolate, isolate->factory()->source_string(),
409 79 : &ScriptSourceGetter, nullptr, attributes);
410 : }
411 :
412 :
413 : //
414 : // Accessors::ScriptLineOffset
415 : //
416 :
417 :
418 7608 : 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 7608 : }
429 :
430 :
431 79 : Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
432 : Isolate* isolate, PropertyAttributes attributes) {
433 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
434 79 : STATIC_CHAR_VECTOR("line_offset")));
435 : return MakeAccessor(isolate, name, &ScriptLineOffsetGetter, nullptr,
436 79 : attributes);
437 : }
438 :
439 :
440 : //
441 : // Accessors::ScriptType
442 : //
443 :
444 :
445 321 : 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 321 : }
456 :
457 :
458 79 : Handle<AccessorInfo> Accessors::ScriptTypeInfo(
459 : Isolate* isolate, PropertyAttributes attributes) {
460 : Handle<String> name(
461 79 : isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
462 79 : return MakeAccessor(isolate, name, &ScriptTypeGetter, nullptr, attributes);
463 : }
464 :
465 :
466 : //
467 : // Accessors::ScriptCompilationType
468 : //
469 :
470 :
471 0 : 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 0 : Script::cast(JSValue::cast(object)->value())->compilation_type());
480 : info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
481 0 : }
482 :
483 :
484 79 : Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
485 : Isolate* isolate, PropertyAttributes attributes) {
486 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
487 79 : STATIC_CHAR_VECTOR("compilation_type")));
488 : return MakeAccessor(isolate, name, &ScriptCompilationTypeGetter, nullptr,
489 79 : attributes);
490 : }
491 :
492 :
493 : //
494 : // Accessors::ScriptSourceUrl
495 : //
496 :
497 :
498 4548 : 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 4548 : }
508 :
509 :
510 79 : Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
511 : Isolate* isolate, PropertyAttributes attributes) {
512 : return MakeAccessor(isolate, isolate->factory()->source_url_string(),
513 79 : &ScriptSourceUrlGetter, nullptr, attributes);
514 : }
515 :
516 :
517 : //
518 : // Accessors::ScriptSourceMappingUrl
519 : //
520 :
521 :
522 0 : 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 0 : }
533 :
534 :
535 79 : Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
536 : Isolate* isolate, PropertyAttributes attributes) {
537 : return MakeAccessor(isolate, isolate->factory()->source_mapping_url_string(),
538 79 : &ScriptSourceMappingUrlGetter, nullptr, attributes);
539 : }
540 :
541 :
542 : //
543 : // Accessors::ScriptGetContextData
544 : //
545 :
546 :
547 516638 : 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 516638 : }
557 :
558 :
559 79 : Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
560 : Isolate* isolate, PropertyAttributes attributes) {
561 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
562 79 : STATIC_CHAR_VECTOR("context_data")));
563 : return MakeAccessor(isolate, name, &ScriptContextDataGetter, nullptr,
564 79 : attributes);
565 : }
566 :
567 :
568 : //
569 : // Accessors::ScriptGetEvalFromScript
570 : //
571 :
572 :
573 0 : 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 0 : if (!script->eval_from_shared()->IsUndefined(isolate)) {
583 : Handle<SharedFunctionInfo> eval_from_shared(
584 : SharedFunctionInfo::cast(script->eval_from_shared()));
585 0 : if (eval_from_shared->script()->IsScript()) {
586 : Handle<Script> eval_from_script(Script::cast(eval_from_shared->script()));
587 0 : result = Script::GetWrapper(eval_from_script);
588 : }
589 : }
590 :
591 : info.GetReturnValue().Set(Utils::ToLocal(result));
592 0 : }
593 :
594 :
595 79 : Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
596 : Isolate* isolate, PropertyAttributes attributes) {
597 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
598 79 : STATIC_CHAR_VECTOR("eval_from_script")));
599 : return MakeAccessor(isolate, name, &ScriptEvalFromScriptGetter, nullptr,
600 79 : attributes);
601 : }
602 :
603 :
604 : //
605 : // Accessors::ScriptGetEvalFromScriptPosition
606 : //
607 :
608 :
609 0 : 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 0 : if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
619 0 : result = Handle<Object>(Smi::FromInt(script->GetEvalPosition()), isolate);
620 : }
621 : info.GetReturnValue().Set(Utils::ToLocal(result));
622 0 : }
623 :
624 :
625 79 : Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
626 : Isolate* isolate, PropertyAttributes attributes) {
627 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
628 79 : STATIC_CHAR_VECTOR("eval_from_script_position")));
629 : return MakeAccessor(isolate, name, &ScriptEvalFromScriptPositionGetter,
630 79 : nullptr, attributes);
631 : }
632 :
633 :
634 : //
635 : // Accessors::ScriptGetEvalFromFunctionName
636 : //
637 :
638 :
639 0 : 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 0 : 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 0 : if (!shared->name()->IsUndefined(isolate)) {
653 : result = Handle<Object>(shared->name(), isolate);
654 : } else {
655 0 : result = Handle<Object>(shared->inferred_name(), isolate);
656 : }
657 : }
658 : info.GetReturnValue().Set(Utils::ToLocal(result));
659 0 : }
660 :
661 :
662 79 : Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
663 : Isolate* isolate, PropertyAttributes attributes) {
664 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
665 79 : STATIC_CHAR_VECTOR("eval_from_function_name")));
666 : return MakeAccessor(isolate, name, &ScriptEvalFromFunctionNameGetter, nullptr,
667 79 : attributes);
668 : }
669 :
670 :
671 : //
672 : // Accessors::FunctionPrototype
673 : //
674 :
675 210768 : static Handle<Object> GetFunctionPrototype(Isolate* isolate,
676 : Handle<JSFunction> function) {
677 210768 : if (!function->has_prototype()) {
678 119781 : Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
679 119781 : JSFunction::SetPrototype(function, proto);
680 : }
681 421536 : return Handle<Object>(function->prototype(), isolate);
682 : }
683 :
684 210768 : void Accessors::FunctionPrototypeGetter(
685 : v8::Local<v8::Name> name,
686 : const v8::PropertyCallbackInfo<v8::Value>& info) {
687 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
688 : RuntimeCallTimerScope timer(
689 210768 : isolate, &RuntimeCallStats::AccessorNameGetterCallback_FunctionPrototype);
690 : HandleScope scope(isolate);
691 : Handle<JSFunction> function =
692 210768 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
693 210768 : Handle<Object> result = GetFunctionPrototype(isolate, function);
694 : info.GetReturnValue().Set(Utils::ToLocal(result));
695 210768 : }
696 :
697 408301 : void Accessors::FunctionPrototypeSetter(
698 : v8::Local<v8::Name> name, v8::Local<v8::Value> val,
699 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
700 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
701 : HandleScope scope(isolate);
702 408301 : Handle<Object> value = Utils::OpenHandle(*val);
703 : Handle<JSFunction> object =
704 408301 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
705 408301 : JSFunction::SetPrototype(object, value);
706 : info.GetReturnValue().Set(true);
707 408301 : }
708 :
709 :
710 407 : Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
711 : Isolate* isolate, PropertyAttributes attributes) {
712 : return MakeAccessor(isolate,
713 : isolate->factory()->prototype_string(),
714 : &FunctionPrototypeGetter,
715 : &FunctionPrototypeSetter,
716 407 : attributes);
717 : }
718 :
719 :
720 : //
721 : // Accessors::FunctionLength
722 : //
723 :
724 :
725 23870 : void Accessors::FunctionLengthGetter(
726 : v8::Local<v8::Name> name,
727 : const v8::PropertyCallbackInfo<v8::Value>& info) {
728 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
729 : HandleScope scope(isolate);
730 : Handle<JSFunction> function =
731 23870 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
732 : Handle<Object> result;
733 47740 : if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) {
734 : result = handle(Smi::kZero, isolate);
735 292 : isolate->OptionalRescheduleException(false);
736 : }
737 :
738 : info.GetReturnValue().Set(Utils::ToLocal(result));
739 23870 : }
740 :
741 644 : Handle<AccessorInfo> Accessors::FunctionLengthInfo(
742 : Isolate* isolate, PropertyAttributes attributes) {
743 : return MakeAccessor(isolate, isolate->factory()->length_string(),
744 : &FunctionLengthGetter, &ReconfigureToDataProperty,
745 644 : attributes);
746 : }
747 :
748 :
749 : //
750 : // Accessors::FunctionName
751 : //
752 :
753 :
754 117513 : void Accessors::FunctionNameGetter(
755 : v8::Local<v8::Name> name,
756 : const v8::PropertyCallbackInfo<v8::Value>& info) {
757 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
758 : HandleScope scope(isolate);
759 : Handle<JSFunction> function =
760 117513 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
761 117513 : Handle<Object> result = JSFunction::GetName(isolate, function);
762 : info.GetReturnValue().Set(Utils::ToLocal(result));
763 117513 : }
764 :
765 47713 : Handle<AccessorInfo> Accessors::FunctionNameInfo(
766 : Isolate* isolate, PropertyAttributes attributes) {
767 : return MakeAccessor(isolate, isolate->factory()->name_string(),
768 : &FunctionNameGetter, &ReconfigureToDataProperty,
769 47713 : attributes);
770 : }
771 :
772 :
773 : //
774 : // Accessors::FunctionArguments
775 : //
776 :
777 :
778 13597 : static Handle<Object> ArgumentsForInlinedFunction(
779 : JavaScriptFrame* frame,
780 : Handle<JSFunction> inlined_function,
781 : int inlined_frame_index) {
782 : Isolate* isolate = inlined_function->GetIsolate();
783 : Factory* factory = isolate->factory();
784 :
785 13597 : TranslatedState translated_values(frame);
786 13597 : translated_values.Prepare(false, frame->fp());
787 :
788 13597 : int argument_count = 0;
789 : TranslatedFrame* translated_frame =
790 : translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
791 13597 : &argument_count);
792 : TranslatedFrame::iterator iter = translated_frame->begin();
793 :
794 : // Skip the function.
795 : iter++;
796 :
797 : // Skip the receiver.
798 : iter++;
799 13597 : argument_count--;
800 :
801 : Handle<JSObject> arguments =
802 13597 : factory->NewArgumentsObject(inlined_function, argument_count);
803 13597 : Handle<FixedArray> array = factory->NewFixedArray(argument_count);
804 : bool should_deoptimize = false;
805 48862 : for (int i = 0; i < argument_count; ++i) {
806 : // If we materialize any object, we should deoptimize the frame because we
807 : // might alias an object that was eliminated by escape analysis.
808 70520 : should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
809 35265 : Handle<Object> value = iter->GetValue();
810 35265 : array->set(i, *value);
811 : iter++;
812 : }
813 13597 : arguments->set_elements(*array);
814 :
815 13597 : if (should_deoptimize) {
816 111 : translated_values.StoreMaterializedValuesAndDeopt(frame);
817 : }
818 :
819 : // Return the freshly allocated arguments object.
820 27194 : return arguments;
821 : }
822 :
823 :
824 336870 : static int FindFunctionInFrame(JavaScriptFrame* frame,
825 : Handle<JSFunction> function) {
826 : DisallowHeapAllocation no_allocation;
827 : List<FrameSummary> frames(2);
828 336870 : frame->Summarize(&frames);
829 605278 : for (int i = frames.length() - 1; i >= 0; i--) {
830 732386 : if (*frames[i].AsJavaScript().function() == *function) return i;
831 : }
832 : return -1;
833 : }
834 :
835 :
836 : namespace {
837 :
838 99738 : Handle<Object> GetFunctionArguments(Isolate* isolate,
839 : Handle<JSFunction> function) {
840 : // Find the top invocation of the function by traversing frames.
841 677646 : for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
842 : JavaScriptFrame* frame = it.frame();
843 336870 : int function_index = FindFunctionInFrame(frame, function);
844 575955 : if (function_index < 0) continue;
845 :
846 97785 : if (function_index > 0) {
847 : // The function in question was inlined. Inlined functions have the
848 : // correct number of arguments and no allocated arguments object, so
849 : // we can construct a fresh one by interpreting the function's
850 : // deoptimization input data.
851 111382 : return ArgumentsForInlinedFunction(frame, function, function_index);
852 : }
853 :
854 : // Find the frame that holds the actual arguments passed to the function.
855 84188 : it.AdvanceToArgumentsFrame();
856 : frame = it.frame();
857 :
858 : // Get the number of arguments and construct an arguments object
859 : // mirror for the right frame.
860 84188 : const int length = frame->ComputeParametersCount();
861 : Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
862 84188 : function, length);
863 84188 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
864 :
865 : // Copy the parameters to the arguments object.
866 : DCHECK(array->length() == length);
867 270112 : for (int i = 0; i < length; i++) {
868 185924 : Object* value = frame->GetParameter(i);
869 185924 : if (value->IsTheHole(isolate)) {
870 : // Generators currently use holes as dummy arguments when resuming. We
871 : // must not leak those.
872 : DCHECK(IsResumableFunction(function->shared()->kind()));
873 224 : value = isolate->heap()->undefined_value();
874 : }
875 185924 : array->set(i, value);
876 : }
877 84188 : arguments->set_elements(*array);
878 :
879 : // Return the freshly allocated arguments object.
880 84188 : return arguments;
881 : }
882 :
883 : // No frame corresponding to the given function found. Return null.
884 1953 : return isolate->factory()->null_value();
885 : }
886 :
887 : } // namespace
888 :
889 :
890 15293 : Handle<JSObject> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
891 : Handle<Object> arguments =
892 15293 : GetFunctionArguments(function->GetIsolate(), function);
893 15293 : CHECK(arguments->IsJSObject());
894 15293 : return Handle<JSObject>::cast(arguments);
895 : }
896 :
897 :
898 88398 : void Accessors::FunctionArgumentsGetter(
899 : v8::Local<v8::Name> name,
900 : const v8::PropertyCallbackInfo<v8::Value>& info) {
901 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
902 : HandleScope scope(isolate);
903 : Handle<JSFunction> function =
904 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
905 : Handle<Object> result =
906 : function->shared()->native()
907 : ? Handle<Object>::cast(isolate->factory()->null_value())
908 172843 : : GetFunctionArguments(isolate, function);
909 : info.GetReturnValue().Set(Utils::ToLocal(result));
910 88398 : }
911 :
912 :
913 328 : Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
914 : Isolate* isolate, PropertyAttributes attributes) {
915 : return MakeAccessor(isolate, isolate->factory()->arguments_string(),
916 328 : &FunctionArgumentsGetter, nullptr, attributes);
917 : }
918 :
919 :
920 : //
921 : // Accessors::FunctionCaller
922 : //
923 :
924 :
925 : static inline bool AllowAccessToFunction(Context* current_context,
926 : JSFunction* function) {
927 30613 : return current_context->HasSameSecurityTokenAs(function->context());
928 : }
929 :
930 :
931 : class FrameFunctionIterator {
932 : public:
933 9872 : FrameFunctionIterator(Isolate* isolate, const DisallowHeapAllocation& promise)
934 19744 : : isolate_(isolate), frame_iterator_(isolate), frames_(2), index_(0) {
935 9872 : GetFrames();
936 9872 : }
937 29145 : JSFunction* next() {
938 : while (true) {
939 56297 : if (frames_.length() == 0) return NULL;
940 27107 : JSFunction* next_function = *frames_[index_].AsJavaScript().function();
941 27107 : index_--;
942 27107 : if (index_ < 0) {
943 24822 : GetFrames();
944 : }
945 : // Skip functions from other origins.
946 54214 : if (!AllowAccessToFunction(isolate_->context(), next_function)) continue;
947 : return next_function;
948 : }
949 : }
950 :
951 : // Iterate through functions until the first occurence of 'function'.
952 : // Returns true if 'function' is found, and false if the iterator ends
953 : // without finding it.
954 : bool Find(JSFunction* function) {
955 : JSFunction* next_function;
956 17798 : do {
957 21766 : next_function = next();
958 21766 : if (next_function == function) return true;
959 : } while (next_function != NULL);
960 : return false;
961 : }
962 :
963 : private:
964 34694 : void GetFrames() {
965 32536 : frames_.Rewind(0);
966 69388 : if (frame_iterator_.done()) return;
967 : JavaScriptFrame* frame = frame_iterator_.frame();
968 32536 : frame->Summarize(&frames_);
969 : DCHECK(frames_.length() > 0);
970 32536 : frame_iterator_.Advance();
971 32536 : index_ = frames_.length() - 1;
972 : }
973 : Isolate* isolate_;
974 : JavaScriptFrameIterator frame_iterator_;
975 : List<FrameSummary> frames_;
976 : int index_;
977 : };
978 :
979 :
980 13378 : MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
981 : Handle<JSFunction> function) {
982 : DisallowHeapAllocation no_allocation;
983 9872 : FrameFunctionIterator it(isolate, no_allocation);
984 9872 : if (function->shared()->native()) {
985 : return MaybeHandle<JSFunction>();
986 : }
987 : // Find the function from the frames.
988 5934 : if (!it.Find(*function)) {
989 : // No frame corresponding to the given function found. Return null.
990 : return MaybeHandle<JSFunction>();
991 : }
992 : // Find previously called non-toplevel function.
993 : JSFunction* caller;
994 7086 : do {
995 7203 : caller = it.next();
996 7203 : if (caller == NULL) return MaybeHandle<JSFunction>();
997 : } while (caller->shared()->is_toplevel());
998 :
999 : // If caller is not user code and caller's caller is also not user code,
1000 : // use that instead.
1001 : JSFunction* potential_caller = caller;
1002 8054 : while (potential_caller != NULL &&
1003 4027 : !potential_caller->shared()->IsUserJavaScript()) {
1004 : caller = potential_caller;
1005 176 : potential_caller = it.next();
1006 : }
1007 3851 : if (!caller->shared()->native() && potential_caller != NULL) {
1008 : caller = potential_caller;
1009 : }
1010 : // Censor if the caller is not a sloppy mode function.
1011 : // Change from ES5, which used to throw, see:
1012 : // https://bugs.ecmascript.org/show_bug.cgi?id=310
1013 3851 : if (is_strict(caller->shared()->language_mode())) {
1014 : return MaybeHandle<JSFunction>();
1015 : }
1016 : // Don't return caller from another security context.
1017 3506 : if (!AllowAccessToFunction(isolate->context(), caller)) {
1018 : return MaybeHandle<JSFunction>();
1019 : }
1020 : return Handle<JSFunction>(caller);
1021 : }
1022 :
1023 :
1024 9872 : void Accessors::FunctionCallerGetter(
1025 : v8::Local<v8::Name> name,
1026 : const v8::PropertyCallbackInfo<v8::Value>& info) {
1027 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1028 : HandleScope scope(isolate);
1029 : Handle<JSFunction> function =
1030 9872 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1031 : Handle<Object> result;
1032 : MaybeHandle<JSFunction> maybe_caller;
1033 9872 : maybe_caller = FindCaller(isolate, function);
1034 : Handle<JSFunction> caller;
1035 9872 : if (maybe_caller.ToHandle(&caller)) {
1036 : result = caller;
1037 : } else {
1038 : result = isolate->factory()->null_value();
1039 : }
1040 : info.GetReturnValue().Set(Utils::ToLocal(result));
1041 9872 : }
1042 :
1043 :
1044 328 : Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1045 : Isolate* isolate, PropertyAttributes attributes) {
1046 : return MakeAccessor(isolate, isolate->factory()->caller_string(),
1047 328 : &FunctionCallerGetter, nullptr, attributes);
1048 : }
1049 :
1050 :
1051 : //
1052 : // Accessors::BoundFunctionLength
1053 : //
1054 :
1055 521 : void Accessors::BoundFunctionLengthGetter(
1056 : v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1057 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1058 : RuntimeCallTimerScope timer(
1059 : isolate,
1060 521 : &RuntimeCallStats::AccessorNameGetterCallback_BoundFunctionLength);
1061 : HandleScope scope(isolate);
1062 : Handle<JSBoundFunction> function =
1063 : Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1064 :
1065 : Handle<Smi> target_length;
1066 : Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
1067 : isolate);
1068 1042 : if (!JSFunction::GetLength(isolate, target).ToHandle(&target_length)) {
1069 : target_length = handle(Smi::kZero, isolate);
1070 0 : isolate->OptionalRescheduleException(false);
1071 521 : return;
1072 : }
1073 :
1074 : int bound_length = function->bound_arguments()->length();
1075 521 : int length = Max(0, target_length->value() - bound_length);
1076 :
1077 : Handle<Object> result(Smi::FromInt(length), isolate);
1078 : info.GetReturnValue().Set(Utils::ToLocal(result));
1079 : }
1080 :
1081 79 : Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo(
1082 : Isolate* isolate, PropertyAttributes attributes) {
1083 : return MakeAccessor(isolate, isolate->factory()->length_string(),
1084 : &BoundFunctionLengthGetter, &ReconfigureToDataProperty,
1085 79 : attributes);
1086 : }
1087 :
1088 : //
1089 : // Accessors::BoundFunctionName
1090 : //
1091 :
1092 341 : void Accessors::BoundFunctionNameGetter(
1093 : v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1094 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1095 : RuntimeCallTimerScope timer(
1096 341 : isolate, &RuntimeCallStats::AccessorNameGetterCallback_BoundFunctionName);
1097 : HandleScope scope(isolate);
1098 : Handle<JSBoundFunction> function =
1099 341 : Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1100 : Handle<Object> result;
1101 682 : if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
1102 0 : isolate->OptionalRescheduleException(false);
1103 341 : return;
1104 : }
1105 : info.GetReturnValue().Set(Utils::ToLocal(result));
1106 : }
1107 :
1108 79 : Handle<AccessorInfo> Accessors::BoundFunctionNameInfo(
1109 : Isolate* isolate, PropertyAttributes attributes) {
1110 : return MakeAccessor(isolate, isolate->factory()->name_string(),
1111 : &BoundFunctionNameGetter, &ReconfigureToDataProperty,
1112 79 : attributes);
1113 : }
1114 :
1115 : //
1116 : // Accessors::ErrorStack
1117 : //
1118 :
1119 : namespace {
1120 :
1121 22899 : MaybeHandle<JSReceiver> ClearInternalStackTrace(Isolate* isolate,
1122 : Handle<JSObject> error) {
1123 45798 : RETURN_ON_EXCEPTION(
1124 : isolate,
1125 : JSReceiver::SetProperty(error, isolate->factory()->stack_trace_symbol(),
1126 : isolate->factory()->undefined_value(), STRICT),
1127 : JSReceiver);
1128 : return error;
1129 : }
1130 :
1131 22801 : bool IsAccessor(Handle<Object> receiver, Handle<Name> name,
1132 : Handle<JSObject> holder) {
1133 : LookupIterator it(receiver, name, holder,
1134 22801 : LookupIterator::OWN_SKIP_INTERCEPTOR);
1135 : // Skip any access checks we might hit. This accessor should never hit in a
1136 : // situation where the caller does not have access.
1137 22801 : if (it.state() == LookupIterator::ACCESS_CHECK) {
1138 0 : CHECK(it.HasAccess());
1139 0 : it.Next();
1140 : }
1141 22801 : return (it.state() == LookupIterator::ACCESSOR);
1142 : }
1143 :
1144 : } // namespace
1145 :
1146 22946 : void Accessors::ErrorStackGetter(
1147 : v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
1148 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1149 : HandleScope scope(isolate);
1150 : Handle<JSObject> holder =
1151 : Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
1152 :
1153 : // Retrieve the structured stack trace.
1154 :
1155 : Handle<Object> stack_trace;
1156 : Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
1157 : MaybeHandle<Object> maybe_stack_trace =
1158 22946 : JSObject::GetProperty(holder, stack_trace_symbol);
1159 45892 : if (!maybe_stack_trace.ToHandle(&stack_trace) ||
1160 : stack_trace->IsUndefined(isolate)) {
1161 : Handle<Object> result = isolate->factory()->undefined_value();
1162 : info.GetReturnValue().Set(Utils::ToLocal(result));
1163 : return;
1164 : }
1165 :
1166 : // Format it, clear the internal structured trace and reconfigure as a data
1167 : // property.
1168 :
1169 : Handle<Object> formatted_stack_trace;
1170 22846 : if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace)
1171 45692 : .ToHandle(&formatted_stack_trace)) {
1172 45 : isolate->OptionalRescheduleException(false);
1173 45 : return;
1174 : }
1175 :
1176 45602 : MaybeHandle<Object> result = ClearInternalStackTrace(isolate, holder);
1177 22801 : if (result.is_null()) {
1178 0 : isolate->OptionalRescheduleException(false);
1179 0 : return;
1180 : }
1181 :
1182 : // If stack is still an accessor (this could have changed in the meantime
1183 : // since FormatStackTrace can execute arbitrary JS), replace it with a data
1184 : // property.
1185 : Handle<Object> receiver =
1186 22801 : Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
1187 22801 : Handle<Name> name = Utils::OpenHandle(*key);
1188 22801 : if (IsAccessor(receiver, name, holder)) {
1189 : result = ReplaceAccessorWithDataProperty(isolate, receiver, holder, name,
1190 22771 : formatted_stack_trace);
1191 22771 : if (result.is_null()) {
1192 0 : isolate->OptionalRescheduleException(false);
1193 0 : return;
1194 : }
1195 : } else {
1196 : // The stack property has been modified in the meantime.
1197 60 : if (!JSObject::GetProperty(holder, name).ToHandle(&formatted_stack_trace)) {
1198 0 : isolate->OptionalRescheduleException(false);
1199 0 : return;
1200 : }
1201 : }
1202 :
1203 : v8::Local<v8::Value> value = Utils::ToLocal(formatted_stack_trace);
1204 : info.GetReturnValue().Set(value);
1205 : }
1206 :
1207 98 : void Accessors::ErrorStackSetter(
1208 : v8::Local<v8::Name> name, v8::Local<v8::Value> val,
1209 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
1210 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1211 : HandleScope scope(isolate);
1212 : Handle<JSObject> obj = Handle<JSObject>::cast(
1213 : Utils::OpenHandle(*v8::Local<v8::Value>(info.This())));
1214 :
1215 : // Clear internal properties to avoid memory leaks.
1216 : Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
1217 196 : if (JSReceiver::HasOwnProperty(obj, stack_trace_symbol).FromMaybe(false)) {
1218 98 : ClearInternalStackTrace(isolate, obj);
1219 : }
1220 :
1221 98 : Accessors::ReconfigureToDataProperty(name, val, info);
1222 98 : }
1223 :
1224 790 : Handle<AccessorInfo> Accessors::ErrorStackInfo(Isolate* isolate,
1225 : PropertyAttributes attributes) {
1226 : Handle<AccessorInfo> info =
1227 : MakeAccessor(isolate, isolate->factory()->stack_string(),
1228 790 : &ErrorStackGetter, &ErrorStackSetter, attributes);
1229 790 : return info;
1230 : }
1231 :
1232 : } // namespace internal
1233 : } // namespace v8
|