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/messages.h"
15 : #include "src/property-details.h"
16 : #include "src/prototype.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 105969 : Handle<AccessorInfo> Accessors::MakeAccessor(
22 : Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
23 : AccessorNameBooleanSetterCallback setter, PropertyAttributes attributes) {
24 : Factory* factory = isolate->factory();
25 105969 : Handle<AccessorInfo> info = factory->NewAccessorInfo();
26 105969 : info->set_property_attributes(attributes);
27 105969 : info->set_all_can_read(false);
28 105969 : info->set_all_can_write(false);
29 105969 : info->set_is_special_data_property(true);
30 105969 : info->set_is_sloppy(false);
31 105969 : info->set_replace_on_access(false);
32 105969 : name = factory->InternalizeName(name);
33 105969 : info->set_name(*name);
34 105969 : Handle<Object> get = v8::FromCData(isolate, getter);
35 105969 : if (setter == nullptr) setter = &ReconfigureToDataProperty;
36 105969 : Handle<Object> set = v8::FromCData(isolate, setter);
37 105969 : info->set_getter(*get);
38 105969 : info->set_setter(*set);
39 105969 : Address redirected = info->redirected_getter();
40 105969 : if (redirected != nullptr) {
41 104793 : Handle<Object> js_get = v8::FromCData(isolate, redirected);
42 104793 : info->set_js_getter(*js_get);
43 : }
44 105969 : return info;
45 : }
46 :
47 :
48 : static V8_INLINE bool CheckForName(Handle<Name> name,
49 : Handle<String> property_name,
50 : int offset,
51 : int* object_offset) {
52 105545 : if (Name::Equals(name, property_name)) {
53 96946 : *object_offset = offset;
54 : return true;
55 : }
56 : return false;
57 : }
58 :
59 :
60 : // Returns true for properties that are accessors to object fields.
61 : // If true, *object_offset contains offset of object field.
62 284933 : bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
63 : int* object_offset) {
64 : Isolate* isolate = name->GetIsolate();
65 :
66 284933 : switch (map->instance_type()) {
67 : case JS_ARRAY_TYPE:
68 : return
69 : CheckForName(name, isolate->factory()->length_string(),
70 101255 : JSArray::kLengthOffset, object_offset);
71 : default:
72 183678 : if (map->instance_type() < FIRST_NONSTRING_TYPE) {
73 : return CheckForName(name, isolate->factory()->length_string(),
74 4290 : String::kLengthOffset, object_offset);
75 : }
76 :
77 : return false;
78 : }
79 : }
80 :
81 :
82 : namespace {
83 :
84 12729 : MUST_USE_RESULT MaybeHandle<Object> ReplaceAccessorWithDataProperty(
85 : Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder,
86 : Handle<Name> name, Handle<Object> value) {
87 : LookupIterator it(receiver, name, holder,
88 12729 : LookupIterator::OWN_SKIP_INTERCEPTOR);
89 : // Skip any access checks we might hit. This accessor should never hit in a
90 : // situation where the caller does not have access.
91 12729 : if (it.state() == LookupIterator::ACCESS_CHECK) {
92 0 : CHECK(it.HasAccess());
93 0 : it.Next();
94 : }
95 : DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
96 12729 : CHECK_EQ(LookupIterator::ACCESSOR, it.state());
97 12729 : it.ReconfigureDataProperty(value, it.property_attributes());
98 12729 : return value;
99 : }
100 :
101 : } // namespace
102 :
103 1564 : void Accessors::ReconfigureToDataProperty(
104 : v8::Local<v8::Name> key, v8::Local<v8::Value> val,
105 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
106 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
107 : RuntimeCallTimerScope stats_scope(
108 1564 : isolate, &RuntimeCallStats::ReconfigureToDataProperty);
109 : HandleScope scope(isolate);
110 : Handle<Object> receiver = Utils::OpenHandle(*info.This());
111 : Handle<JSObject> holder =
112 1564 : Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
113 1564 : Handle<Name> name = Utils::OpenHandle(*key);
114 1564 : Handle<Object> value = Utils::OpenHandle(*val);
115 : MaybeHandle<Object> result =
116 1564 : ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value);
117 1564 : if (result.is_null()) {
118 0 : isolate->OptionalRescheduleException(false);
119 : } else {
120 : info.GetReturnValue().Set(true);
121 : }
122 1564 : }
123 :
124 : //
125 : // Accessors::ArgumentsIterator
126 : //
127 :
128 :
129 5943 : void Accessors::ArgumentsIteratorGetter(
130 : v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
131 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
132 : DisallowHeapAllocation no_allocation;
133 : HandleScope scope(isolate);
134 11886 : Object* result = isolate->native_context()->array_values_iterator();
135 : info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
136 5943 : }
137 :
138 :
139 61 : Handle<AccessorInfo> Accessors::ArgumentsIteratorInfo(
140 : Isolate* isolate, PropertyAttributes attributes) {
141 : Handle<Name> name = isolate->factory()->iterator_symbol();
142 : return MakeAccessor(isolate, name, &ArgumentsIteratorGetter, nullptr,
143 61 : attributes);
144 : }
145 :
146 :
147 : //
148 : // Accessors::ArrayLength
149 : //
150 :
151 :
152 195736 : void Accessors::ArrayLengthGetter(
153 : v8::Local<v8::Name> name,
154 : const v8::PropertyCallbackInfo<v8::Value>& info) {
155 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
156 195736 : RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::ArrayLengthGetter);
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 195736 : }
163 :
164 526792 : 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 526792 : RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::ArrayLengthSetter);
169 : HandleScope scope(isolate);
170 :
171 : DCHECK(Utils::OpenHandle(*name)->SameValue(isolate->heap()->length_string()));
172 :
173 : Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
174 : Handle<JSArray> array = Handle<JSArray>::cast(object);
175 526792 : Handle<Object> length_obj = Utils::OpenHandle(*val);
176 :
177 526792 : bool was_readonly = JSArray::HasReadOnlyLength(array);
178 :
179 526792 : uint32_t length = 0;
180 526792 : if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
181 256 : isolate->OptionalRescheduleException(false);
182 256 : return;
183 : }
184 :
185 526556 : if (!was_readonly && V8_UNLIKELY(JSArray::HasReadOnlyLength(array)) &&
186 20 : length != array->length()->Number()) {
187 : // AnythingToArrayLength() may have called setter re-entrantly and modified
188 : // its property descriptor. Don't perform this check if "length" was
189 : // previously readonly, as this may have been called during
190 : // DefineOwnPropertyIgnoreAttributes().
191 20 : if (info.ShouldThrowOnError()) {
192 : Factory* factory = isolate->factory();
193 : isolate->Throw(*factory->NewTypeError(
194 : MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
195 30 : i::Object::TypeOf(isolate, object), object));
196 10 : isolate->OptionalRescheduleException(false);
197 : } else {
198 : info.GetReturnValue().Set(false);
199 : }
200 : return;
201 : }
202 :
203 526516 : JSArray::SetLength(array, length);
204 :
205 526516 : uint32_t actual_new_len = 0;
206 526516 : CHECK(array->length()->ToArrayLength(&actual_new_len));
207 : // Fail if there were non-deletable elements.
208 526516 : if (actual_new_len != length) {
209 68 : if (info.ShouldThrowOnError()) {
210 : Factory* factory = isolate->factory();
211 : isolate->Throw(*factory->NewTypeError(
212 : MessageTemplate::kStrictDeleteProperty,
213 60 : factory->NewNumberFromUint(actual_new_len - 1), array));
214 30 : isolate->OptionalRescheduleException(false);
215 : } else {
216 : info.GetReturnValue().Set(false);
217 : }
218 : } else {
219 : info.GetReturnValue().Set(true);
220 : }
221 : }
222 :
223 :
224 183 : Handle<AccessorInfo> Accessors::ArrayLengthInfo(
225 : Isolate* isolate, PropertyAttributes attributes) {
226 : return MakeAccessor(isolate,
227 : isolate->factory()->length_string(),
228 : &ArrayLengthGetter,
229 : &ArrayLengthSetter,
230 183 : attributes);
231 : }
232 :
233 : //
234 : // Accessors::ModuleNamespaceEntry
235 : //
236 :
237 30320 : void Accessors::ModuleNamespaceEntryGetter(
238 : v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
239 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
240 : HandleScope scope(isolate);
241 : JSModuleNamespace* holder =
242 : JSModuleNamespace::cast(*Utils::OpenHandle(*info.Holder()));
243 : Handle<Object> result;
244 30320 : if (!holder->GetExport(Handle<String>::cast(Utils::OpenHandle(*name)))
245 60640 : .ToHandle(&result)) {
246 70 : isolate->OptionalRescheduleException(false);
247 : } else {
248 : info.GetReturnValue().Set(Utils::ToLocal(result));
249 : }
250 30320 : }
251 :
252 20 : void Accessors::ModuleNamespaceEntrySetter(
253 : v8::Local<v8::Name> name, v8::Local<v8::Value> val,
254 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
255 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
256 : HandleScope scope(isolate);
257 : Factory* factory = isolate->factory();
258 : Handle<JSModuleNamespace> holder =
259 : Handle<JSModuleNamespace>::cast(Utils::OpenHandle(*info.Holder()));
260 :
261 20 : if (info.ShouldThrowOnError()) {
262 : isolate->Throw(*factory->NewTypeError(
263 : MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
264 0 : i::Object::TypeOf(isolate, holder), holder));
265 0 : isolate->OptionalRescheduleException(false);
266 : } else {
267 : info.GetReturnValue().Set(false);
268 : }
269 20 : }
270 :
271 30140 : Handle<AccessorInfo> Accessors::ModuleNamespaceEntryInfo(
272 : Isolate* isolate, Handle<String> name, PropertyAttributes attributes) {
273 : return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter,
274 30140 : &ModuleNamespaceEntrySetter, attributes);
275 : }
276 :
277 :
278 : //
279 : // Accessors::StringLength
280 : //
281 :
282 30159 : void Accessors::StringLengthGetter(
283 : v8::Local<v8::Name> name,
284 : const v8::PropertyCallbackInfo<v8::Value>& info) {
285 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
286 30159 : RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::StringLengthGetter);
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 30159 : 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 30159 : }
304 :
305 :
306 61 : Handle<AccessorInfo> Accessors::StringLengthInfo(
307 : Isolate* isolate, PropertyAttributes attributes) {
308 : return MakeAccessor(isolate, isolate->factory()->length_string(),
309 61 : &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 61 : Handle<AccessorInfo> Accessors::ScriptColumnOffsetInfo(
332 : Isolate* isolate, PropertyAttributes attributes) {
333 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
334 61 : STATIC_CHAR_VECTOR("column_offset")));
335 : return MakeAccessor(isolate, name, &ScriptColumnOffsetGetter, nullptr,
336 61 : attributes);
337 : }
338 :
339 :
340 : //
341 : // Accessors::ScriptId
342 : //
343 :
344 :
345 3070 : 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 3070 : }
355 :
356 :
357 61 : Handle<AccessorInfo> Accessors::ScriptIdInfo(
358 : Isolate* isolate, PropertyAttributes attributes) {
359 : Handle<String> name(
360 61 : isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("id")));
361 61 : return MakeAccessor(isolate, name, &ScriptIdGetter, nullptr, attributes);
362 : }
363 :
364 :
365 : //
366 : // Accessors::ScriptName
367 : //
368 :
369 :
370 2104 : 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 2104 : }
380 :
381 :
382 61 : Handle<AccessorInfo> Accessors::ScriptNameInfo(
383 : Isolate* isolate, PropertyAttributes attributes) {
384 : return MakeAccessor(isolate, isolate->factory()->name_string(),
385 61 : &ScriptNameGetter, nullptr, attributes);
386 : }
387 :
388 :
389 : //
390 : // Accessors::ScriptSource
391 : //
392 :
393 :
394 2513 : 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 2513 : }
404 :
405 :
406 61 : Handle<AccessorInfo> Accessors::ScriptSourceInfo(
407 : Isolate* isolate, PropertyAttributes attributes) {
408 : return MakeAccessor(isolate, isolate->factory()->source_string(),
409 61 : &ScriptSourceGetter, nullptr, attributes);
410 : }
411 :
412 :
413 : //
414 : // Accessors::ScriptLineOffset
415 : //
416 :
417 :
418 4840 : 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 4840 : }
429 :
430 :
431 61 : Handle<AccessorInfo> Accessors::ScriptLineOffsetInfo(
432 : Isolate* isolate, PropertyAttributes attributes) {
433 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
434 61 : STATIC_CHAR_VECTOR("line_offset")));
435 : return MakeAccessor(isolate, name, &ScriptLineOffsetGetter, nullptr,
436 61 : attributes);
437 : }
438 :
439 :
440 : //
441 : // Accessors::ScriptType
442 : //
443 :
444 :
445 210 : 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 210 : }
456 :
457 :
458 61 : Handle<AccessorInfo> Accessors::ScriptTypeInfo(
459 : Isolate* isolate, PropertyAttributes attributes) {
460 : Handle<String> name(
461 61 : isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("type")));
462 61 : 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 61 : Handle<AccessorInfo> Accessors::ScriptCompilationTypeInfo(
485 : Isolate* isolate, PropertyAttributes attributes) {
486 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
487 61 : STATIC_CHAR_VECTOR("compilation_type")));
488 : return MakeAccessor(isolate, name, &ScriptCompilationTypeGetter, nullptr,
489 61 : attributes);
490 : }
491 :
492 :
493 : //
494 : // Accessors::ScriptSourceUrl
495 : //
496 :
497 :
498 2480 : 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 2480 : }
508 :
509 :
510 61 : Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
511 : Isolate* isolate, PropertyAttributes attributes) {
512 : return MakeAccessor(isolate, isolate->factory()->source_url_string(),
513 61 : &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 61 : Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
536 : Isolate* isolate, PropertyAttributes attributes) {
537 : return MakeAccessor(isolate, isolate->factory()->source_mapping_url_string(),
538 61 : &ScriptSourceMappingUrlGetter, nullptr, attributes);
539 : }
540 :
541 :
542 : //
543 : // Accessors::ScriptGetContextData
544 : //
545 :
546 :
547 3572 : 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 3572 : }
557 :
558 :
559 61 : Handle<AccessorInfo> Accessors::ScriptContextDataInfo(
560 : Isolate* isolate, PropertyAttributes attributes) {
561 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
562 61 : STATIC_CHAR_VECTOR("context_data")));
563 : return MakeAccessor(isolate, name, &ScriptContextDataGetter, nullptr,
564 61 : 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 61 : Handle<AccessorInfo> Accessors::ScriptEvalFromScriptInfo(
596 : Isolate* isolate, PropertyAttributes attributes) {
597 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
598 61 : STATIC_CHAR_VECTOR("eval_from_script")));
599 : return MakeAccessor(isolate, name, &ScriptEvalFromScriptGetter, nullptr,
600 61 : 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 61 : Handle<AccessorInfo> Accessors::ScriptEvalFromScriptPositionInfo(
626 : Isolate* isolate, PropertyAttributes attributes) {
627 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
628 61 : STATIC_CHAR_VECTOR("eval_from_script_position")));
629 : return MakeAccessor(isolate, name, &ScriptEvalFromScriptPositionGetter,
630 61 : 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 : result = Handle<Object>(shared->name(), isolate);
653 : }
654 : info.GetReturnValue().Set(Utils::ToLocal(result));
655 0 : }
656 :
657 :
658 61 : Handle<AccessorInfo> Accessors::ScriptEvalFromFunctionNameInfo(
659 : Isolate* isolate, PropertyAttributes attributes) {
660 : Handle<String> name(isolate->factory()->InternalizeOneByteString(
661 61 : STATIC_CHAR_VECTOR("eval_from_function_name")));
662 : return MakeAccessor(isolate, name, &ScriptEvalFromFunctionNameGetter, nullptr,
663 61 : attributes);
664 : }
665 :
666 :
667 : //
668 : // Accessors::FunctionPrototype
669 : //
670 :
671 251883 : static Handle<Object> GetFunctionPrototype(Isolate* isolate,
672 : Handle<JSFunction> function) {
673 251883 : if (!function->has_prototype()) {
674 86847 : Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
675 86847 : JSFunction::SetPrototype(function, proto);
676 : }
677 503766 : return Handle<Object>(function->prototype(), isolate);
678 : }
679 :
680 251883 : void Accessors::FunctionPrototypeGetter(
681 : v8::Local<v8::Name> name,
682 : const v8::PropertyCallbackInfo<v8::Value>& info) {
683 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
684 : RuntimeCallTimerScope timer(isolate,
685 251883 : &RuntimeCallStats::FunctionPrototypeGetter);
686 : HandleScope scope(isolate);
687 : Handle<JSFunction> function =
688 251883 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
689 251883 : Handle<Object> result = GetFunctionPrototype(isolate, function);
690 : info.GetReturnValue().Set(Utils::ToLocal(result));
691 251883 : }
692 :
693 332928 : void Accessors::FunctionPrototypeSetter(
694 : v8::Local<v8::Name> name, v8::Local<v8::Value> val,
695 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
696 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
697 : RuntimeCallTimerScope timer(isolate,
698 332928 : &RuntimeCallStats::FunctionPrototypeSetter);
699 : HandleScope scope(isolate);
700 332928 : Handle<Object> value = Utils::OpenHandle(*val);
701 : Handle<JSFunction> object =
702 332928 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
703 332928 : JSFunction::SetPrototype(object, value);
704 : info.GetReturnValue().Set(true);
705 332928 : }
706 :
707 :
708 549 : Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
709 : Isolate* isolate, PropertyAttributes attributes) {
710 : return MakeAccessor(isolate,
711 : isolate->factory()->prototype_string(),
712 : &FunctionPrototypeGetter,
713 : &FunctionPrototypeSetter,
714 549 : attributes);
715 : }
716 :
717 :
718 : //
719 : // Accessors::FunctionLength
720 : //
721 :
722 :
723 17234 : void Accessors::FunctionLengthGetter(
724 : v8::Local<v8::Name> name,
725 : const v8::PropertyCallbackInfo<v8::Value>& info) {
726 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
727 : HandleScope scope(isolate);
728 : Handle<JSFunction> function =
729 17234 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
730 : int length = 0;
731 34468 : if (!JSFunction::GetLength(isolate, function).To(&length)) {
732 285 : isolate->OptionalRescheduleException(false);
733 : }
734 : Handle<Object> result(Smi::FromInt(length), isolate);
735 : info.GetReturnValue().Set(Utils::ToLocal(result));
736 17234 : }
737 :
738 915 : Handle<AccessorInfo> Accessors::FunctionLengthInfo(
739 : Isolate* isolate, PropertyAttributes attributes) {
740 : return MakeAccessor(isolate, isolate->factory()->length_string(),
741 : &FunctionLengthGetter, &ReconfigureToDataProperty,
742 915 : attributes);
743 : }
744 :
745 :
746 : //
747 : // Accessors::FunctionName
748 : //
749 :
750 :
751 69088 : void Accessors::FunctionNameGetter(
752 : v8::Local<v8::Name> name,
753 : const v8::PropertyCallbackInfo<v8::Value>& info) {
754 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
755 : HandleScope scope(isolate);
756 : Handle<JSFunction> function =
757 69088 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
758 69088 : Handle<Object> result = JSFunction::GetName(isolate, function);
759 : info.GetReturnValue().Set(Utils::ToLocal(result));
760 69088 : }
761 :
762 70563 : Handle<AccessorInfo> Accessors::FunctionNameInfo(
763 : Isolate* isolate, PropertyAttributes attributes) {
764 : return MakeAccessor(isolate, isolate->factory()->name_string(),
765 : &FunctionNameGetter, &ReconfigureToDataProperty,
766 70563 : attributes);
767 : }
768 :
769 :
770 : //
771 : // Accessors::FunctionArguments
772 : //
773 :
774 :
775 2517 : static Handle<Object> ArgumentsForInlinedFunction(
776 : JavaScriptFrame* frame,
777 : Handle<JSFunction> inlined_function,
778 : int inlined_frame_index) {
779 : Isolate* isolate = inlined_function->GetIsolate();
780 : Factory* factory = isolate->factory();
781 :
782 2517 : TranslatedState translated_values(frame);
783 2517 : translated_values.Prepare(frame->fp());
784 :
785 2517 : int argument_count = 0;
786 : TranslatedFrame* translated_frame =
787 : translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
788 2517 : &argument_count);
789 : TranslatedFrame::iterator iter = translated_frame->begin();
790 :
791 : // Skip the function.
792 : iter++;
793 :
794 : // Skip the receiver.
795 : iter++;
796 2517 : argument_count--;
797 :
798 : Handle<JSObject> arguments =
799 2517 : factory->NewArgumentsObject(inlined_function, argument_count);
800 2517 : Handle<FixedArray> array = factory->NewFixedArray(argument_count);
801 : bool should_deoptimize = false;
802 9667 : for (int i = 0; i < argument_count; ++i) {
803 : // If we materialize any object, we should deoptimize the frame because we
804 : // might alias an object that was eliminated by escape analysis.
805 14286 : should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
806 7150 : Handle<Object> value = iter->GetValue();
807 7150 : array->set(i, *value);
808 : iter++;
809 : }
810 2517 : arguments->set_elements(*array);
811 :
812 2517 : if (should_deoptimize) {
813 146 : translated_values.StoreMaterializedValuesAndDeopt(frame);
814 : }
815 :
816 : // Return the freshly allocated arguments object.
817 5034 : return arguments;
818 : }
819 :
820 :
821 202427 : static int FindFunctionInFrame(JavaScriptFrame* frame,
822 : Handle<JSFunction> function) {
823 : std::vector<FrameSummary> frames;
824 202427 : frame->Summarize(&frames);
825 757103 : for (size_t i = frames.size(); i != 0; i--) {
826 426080 : if (*frames[i - 1].AsJavaScript().function() == *function) {
827 63218 : return static_cast<int>(i) - 1;
828 : }
829 : }
830 202427 : return -1;
831 : }
832 :
833 :
834 : namespace {
835 :
836 64244 : Handle<Object> GetFunctionArguments(Isolate* isolate,
837 : Handle<JSFunction> function) {
838 : // Find the top invocation of the function by traversing frames.
839 406906 : for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
840 : JavaScriptFrame* frame = it.frame();
841 202427 : int function_index = FindFunctionInFrame(frame, function);
842 341636 : if (function_index < 0) continue;
843 :
844 63218 : if (function_index > 0) {
845 : // The function in question was inlined. Inlined functions have the
846 : // correct number of arguments and no allocated arguments object, so
847 : // we can construct a fresh one by interpreting the function's
848 : // deoptimization input data.
849 65735 : return ArgumentsForInlinedFunction(frame, function, function_index);
850 : }
851 :
852 : // Find the frame that holds the actual arguments passed to the function.
853 60701 : if (it.frame()->has_adapted_arguments()) {
854 : it.AdvanceOneFrame();
855 : DCHECK(it.frame()->is_arguments_adaptor());
856 : }
857 : frame = it.frame();
858 :
859 : // Get the number of arguments and construct an arguments object
860 : // mirror for the right frame.
861 60701 : const int length = frame->ComputeParametersCount();
862 : Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject(
863 60701 : function, length);
864 60701 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
865 :
866 : // Copy the parameters to the arguments object.
867 : DCHECK(array->length() == length);
868 195889 : for (int i = 0; i < length; i++) {
869 135188 : Object* value = frame->GetParameter(i);
870 135188 : if (value->IsTheHole(isolate)) {
871 : // Generators currently use holes as dummy arguments when resuming. We
872 : // must not leak those.
873 : DCHECK(IsResumableFunction(function->shared()->kind()));
874 88 : value = isolate->heap()->undefined_value();
875 : }
876 135188 : array->set(i, value);
877 : }
878 60701 : arguments->set_elements(*array);
879 :
880 : // Return the freshly allocated arguments object.
881 60701 : return arguments;
882 : }
883 :
884 : // No frame corresponding to the given function found. Return null.
885 1026 : return isolate->factory()->null_value();
886 : }
887 :
888 : } // namespace
889 :
890 :
891 10114 : Handle<JSObject> Accessors::FunctionGetArguments(Handle<JSFunction> function) {
892 : Handle<Object> arguments =
893 10114 : GetFunctionArguments(function->GetIsolate(), function);
894 10114 : CHECK(arguments->IsJSObject());
895 10114 : return Handle<JSObject>::cast(arguments);
896 : }
897 :
898 :
899 54130 : void Accessors::FunctionArgumentsGetter(
900 : v8::Local<v8::Name> name,
901 : const v8::PropertyCallbackInfo<v8::Value>& info) {
902 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
903 : HandleScope scope(isolate);
904 : Handle<JSFunction> function =
905 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
906 : Handle<Object> result =
907 : function->shared()->native()
908 : ? Handle<Object>::cast(isolate->factory()->null_value())
909 108260 : : GetFunctionArguments(isolate, function);
910 : info.GetReturnValue().Set(Utils::ToLocal(result));
911 54130 : }
912 :
913 :
914 305 : Handle<AccessorInfo> Accessors::FunctionArgumentsInfo(
915 : Isolate* isolate, PropertyAttributes attributes) {
916 : return MakeAccessor(isolate, isolate->factory()->arguments_string(),
917 305 : &FunctionArgumentsGetter, nullptr, attributes);
918 : }
919 :
920 :
921 : //
922 : // Accessors::FunctionCaller
923 : //
924 :
925 :
926 : static inline bool AllowAccessToFunction(Context* current_context,
927 : JSFunction* function) {
928 17879 : return current_context->HasSameSecurityTokenAs(function->context());
929 : }
930 :
931 :
932 3787 : class FrameFunctionIterator {
933 : public:
934 3787 : explicit FrameFunctionIterator(Isolate* isolate)
935 11361 : : isolate_(isolate), frame_iterator_(isolate), inlined_frame_index_(-1) {
936 : GetFrames();
937 3787 : }
938 :
939 : // Iterate through functions until the first occurrence of 'function'.
940 : // Returns true if one is found, and false if the iterator ends before.
941 3787 : bool Find(Handle<JSFunction> function) {
942 10662 : do {
943 23432 : if (!next().ToHandle(&function_)) return false;
944 : } while (!function_.is_identical_to(function));
945 : return true;
946 : }
947 :
948 : // Iterate through functions until the next non-toplevel one is found.
949 : // Returns true if one is found, and false if the iterator ends before.
950 2733 : bool FindNextNonTopLevel() {
951 4811 : do {
952 9778 : if (!next().ToHandle(&function_)) return false;
953 : } while (function_->shared()->is_toplevel());
954 : return true;
955 : }
956 :
957 : // Iterate through function until the first native or user-provided function
958 : // is found. Functions not defined in user-provided scripts are not visible
959 : // unless directly exposed, in which case the native flag is set on them.
960 : // Returns true if one is found, and false if the iterator ends before.
961 2655 : bool FindFirstNativeOrUserJavaScript() {
962 7926 : while (!function_->shared()->native() &&
963 2586 : !function_->shared()->IsUserJavaScript()) {
964 60 : if (!next().ToHandle(&function_)) return false;
965 : }
966 : return true;
967 : }
968 :
969 : // In case of inlined frames the function could have been materialized from
970 : // deoptimization information. If that is the case we need to make sure that
971 : // subsequent call will see the same function, since we are about to hand out
972 : // the value to JavaScript. Make sure to store the materialized value and
973 : // trigger a deoptimization of the underlying frame.
974 2655 : Handle<JSFunction> MaterializeFunction() {
975 2655 : if (inlined_frame_index_ == 0) return function_;
976 :
977 : JavaScriptFrame* frame = frame_iterator_.frame();
978 36 : TranslatedState translated_values(frame);
979 36 : translated_values.Prepare(frame->fp());
980 :
981 : TranslatedFrame* translated_frame =
982 36 : translated_values.GetFrameFromJSFrameIndex(inlined_frame_index_);
983 : TranslatedFrame::iterator iter = translated_frame->begin();
984 :
985 : // First value is the function.
986 36 : bool should_deoptimize = iter->IsMaterializedObject();
987 36 : Handle<Object> value = iter->GetValue();
988 36 : if (should_deoptimize) {
989 21 : translated_values.StoreMaterializedValuesAndDeopt(frame);
990 : }
991 :
992 : return Handle<JSFunction>::cast(value);
993 : }
994 :
995 : private:
996 16635 : MaybeHandle<JSFunction> next() {
997 : while (true) {
998 16665 : inlined_frame_index_--;
999 16665 : if (inlined_frame_index_ == -1) {
1000 9889 : if (!frame_iterator_.done()) {
1001 9889 : frame_iterator_.Advance();
1002 15533 : frames_.clear();
1003 : GetFrames();
1004 : }
1005 9889 : if (inlined_frame_index_ == -1) return MaybeHandle<JSFunction>();
1006 8757 : inlined_frame_index_--;
1007 : }
1008 : Handle<JSFunction> next_function =
1009 15533 : frames_[inlined_frame_index_].AsJavaScript().function();
1010 : // Skip functions from other origins.
1011 31066 : if (!AllowAccessToFunction(isolate_->context(), *next_function)) continue;
1012 15503 : return next_function;
1013 : }
1014 : }
1015 : void GetFrames() {
1016 : DCHECK_EQ(-1, inlined_frame_index_);
1017 13676 : if (frame_iterator_.done()) return;
1018 : JavaScriptFrame* frame = frame_iterator_.frame();
1019 12544 : frame->Summarize(&frames_);
1020 12544 : inlined_frame_index_ = static_cast<int>(frames_.size());
1021 : DCHECK_LT(0, inlined_frame_index_);
1022 : }
1023 : Isolate* isolate_;
1024 : Handle<JSFunction> function_;
1025 : JavaScriptFrameIterator frame_iterator_;
1026 : std::vector<FrameSummary> frames_;
1027 : int inlined_frame_index_;
1028 : };
1029 :
1030 :
1031 6133 : MaybeHandle<JSFunction> FindCaller(Isolate* isolate,
1032 : Handle<JSFunction> function) {
1033 3787 : FrameFunctionIterator it(isolate);
1034 3787 : if (function->shared()->native()) {
1035 0 : return MaybeHandle<JSFunction>();
1036 : }
1037 : // Find the function from the frames. Return null in case no frame
1038 : // corresponding to the given function was found.
1039 3787 : if (!it.Find(function)) {
1040 1054 : return MaybeHandle<JSFunction>();
1041 : }
1042 : // Find previously called non-toplevel function.
1043 2733 : if (!it.FindNextNonTopLevel()) {
1044 78 : return MaybeHandle<JSFunction>();
1045 : }
1046 : // Find the first user-land JavaScript function (or the entry point into
1047 : // native JavaScript builtins in case such a builtin was the caller).
1048 2655 : if (!it.FindFirstNativeOrUserJavaScript()) {
1049 0 : return MaybeHandle<JSFunction>();
1050 : }
1051 :
1052 : // Materialize the function that the iterator is currently sitting on. Note
1053 : // that this might trigger deoptimization in case the function was actually
1054 : // materialized. Identity of the function must be preserved because we are
1055 : // going to return it to JavaScript after this point.
1056 2655 : Handle<JSFunction> caller = it.MaterializeFunction();
1057 :
1058 : // Censor if the caller is not a sloppy mode function.
1059 : // Change from ES5, which used to throw, see:
1060 : // https://bugs.ecmascript.org/show_bug.cgi?id=310
1061 2655 : if (is_strict(caller->shared()->language_mode())) {
1062 309 : return MaybeHandle<JSFunction>();
1063 : }
1064 : // Don't return caller from another security context.
1065 2346 : if (!AllowAccessToFunction(isolate->context(), *caller)) {
1066 0 : return MaybeHandle<JSFunction>();
1067 : }
1068 2346 : return caller;
1069 : }
1070 :
1071 :
1072 3787 : void Accessors::FunctionCallerGetter(
1073 : v8::Local<v8::Name> name,
1074 : const v8::PropertyCallbackInfo<v8::Value>& info) {
1075 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1076 : HandleScope scope(isolate);
1077 : Handle<JSFunction> function =
1078 3787 : Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
1079 : Handle<Object> result;
1080 : MaybeHandle<JSFunction> maybe_caller;
1081 3787 : maybe_caller = FindCaller(isolate, function);
1082 : Handle<JSFunction> caller;
1083 3787 : if (maybe_caller.ToHandle(&caller)) {
1084 : result = caller;
1085 : } else {
1086 : result = isolate->factory()->null_value();
1087 : }
1088 : info.GetReturnValue().Set(Utils::ToLocal(result));
1089 3787 : }
1090 :
1091 :
1092 305 : Handle<AccessorInfo> Accessors::FunctionCallerInfo(
1093 : Isolate* isolate, PropertyAttributes attributes) {
1094 : return MakeAccessor(isolate, isolate->factory()->caller_string(),
1095 305 : &FunctionCallerGetter, nullptr, attributes);
1096 : }
1097 :
1098 :
1099 : //
1100 : // Accessors::BoundFunctionLength
1101 : //
1102 :
1103 342 : void Accessors::BoundFunctionLengthGetter(
1104 : v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1105 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1106 : RuntimeCallTimerScope timer(isolate,
1107 342 : &RuntimeCallStats::BoundFunctionLengthGetter);
1108 : HandleScope scope(isolate);
1109 : Handle<JSBoundFunction> function =
1110 342 : Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1111 :
1112 : int length = 0;
1113 684 : if (!JSBoundFunction::GetLength(isolate, function).To(&length)) {
1114 0 : isolate->OptionalRescheduleException(false);
1115 342 : return;
1116 : }
1117 : Handle<Object> result(Smi::FromInt(length), isolate);
1118 : info.GetReturnValue().Set(Utils::ToLocal(result));
1119 : }
1120 :
1121 61 : Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo(
1122 : Isolate* isolate, PropertyAttributes attributes) {
1123 : return MakeAccessor(isolate, isolate->factory()->length_string(),
1124 : &BoundFunctionLengthGetter, &ReconfigureToDataProperty,
1125 61 : attributes);
1126 : }
1127 :
1128 : //
1129 : // Accessors::BoundFunctionName
1130 : //
1131 :
1132 82 : void Accessors::BoundFunctionNameGetter(
1133 : v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1134 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1135 : RuntimeCallTimerScope timer(isolate,
1136 82 : &RuntimeCallStats::BoundFunctionNameGetter);
1137 : HandleScope scope(isolate);
1138 : Handle<JSBoundFunction> function =
1139 82 : Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
1140 : Handle<Object> result;
1141 164 : if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
1142 0 : isolate->OptionalRescheduleException(false);
1143 82 : return;
1144 : }
1145 : info.GetReturnValue().Set(Utils::ToLocal(result));
1146 : }
1147 :
1148 61 : Handle<AccessorInfo> Accessors::BoundFunctionNameInfo(
1149 : Isolate* isolate, PropertyAttributes attributes) {
1150 : return MakeAccessor(isolate, isolate->factory()->name_string(),
1151 : &BoundFunctionNameGetter, &ReconfigureToDataProperty,
1152 61 : attributes);
1153 : }
1154 :
1155 : //
1156 : // Accessors::ErrorStack
1157 : //
1158 :
1159 : namespace {
1160 :
1161 12119 : MaybeHandle<JSReceiver> ClearInternalStackTrace(Isolate* isolate,
1162 : Handle<JSObject> error) {
1163 24238 : RETURN_ON_EXCEPTION(
1164 : isolate,
1165 : JSReceiver::SetProperty(error, isolate->factory()->stack_trace_symbol(),
1166 : isolate->factory()->undefined_value(),
1167 : LanguageMode::kStrict),
1168 : JSReceiver);
1169 12119 : return error;
1170 : }
1171 :
1172 12041 : bool IsAccessor(Handle<Object> receiver, Handle<Name> name,
1173 : Handle<JSObject> holder) {
1174 : LookupIterator it(receiver, name, holder,
1175 12041 : LookupIterator::OWN_SKIP_INTERCEPTOR);
1176 : // Skip any access checks we might hit. This accessor should never hit in a
1177 : // situation where the caller does not have access.
1178 12041 : if (it.state() == LookupIterator::ACCESS_CHECK) {
1179 0 : CHECK(it.HasAccess());
1180 0 : it.Next();
1181 : }
1182 12041 : return (it.state() == LookupIterator::ACCESSOR);
1183 : }
1184 :
1185 : } // namespace
1186 :
1187 12245 : void Accessors::ErrorStackGetter(
1188 : v8::Local<v8::Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
1189 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1190 : HandleScope scope(isolate);
1191 : Handle<JSObject> holder =
1192 : Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
1193 :
1194 : // Retrieve the structured stack trace.
1195 :
1196 : Handle<Object> stack_trace;
1197 : Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
1198 : MaybeHandle<Object> maybe_stack_trace =
1199 12245 : JSObject::GetProperty(holder, stack_trace_symbol);
1200 24490 : if (!maybe_stack_trace.ToHandle(&stack_trace) ||
1201 : stack_trace->IsUndefined(isolate)) {
1202 : Handle<Object> result = isolate->factory()->undefined_value();
1203 : info.GetReturnValue().Set(Utils::ToLocal(result));
1204 : return;
1205 : }
1206 :
1207 : // Format it, clear the internal structured trace and reconfigure as a data
1208 : // property.
1209 :
1210 : Handle<Object> formatted_stack_trace;
1211 12157 : if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace)
1212 24314 : .ToHandle(&formatted_stack_trace)) {
1213 116 : isolate->OptionalRescheduleException(false);
1214 116 : return;
1215 : }
1216 :
1217 12041 : MaybeHandle<Object> result = ClearInternalStackTrace(isolate, holder);
1218 12041 : if (result.is_null()) {
1219 0 : isolate->OptionalRescheduleException(false);
1220 0 : return;
1221 : }
1222 :
1223 : // If stack is still an accessor (this could have changed in the meantime
1224 : // since FormatStackTrace can execute arbitrary JS), replace it with a data
1225 : // property.
1226 : Handle<Object> receiver =
1227 12041 : Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
1228 12041 : Handle<Name> name = Utils::OpenHandle(*key);
1229 12041 : if (IsAccessor(receiver, name, holder)) {
1230 : result = ReplaceAccessorWithDataProperty(isolate, receiver, holder, name,
1231 11165 : formatted_stack_trace);
1232 11165 : if (result.is_null()) {
1233 0 : isolate->OptionalRescheduleException(false);
1234 0 : return;
1235 : }
1236 : } else {
1237 : // The stack property has been modified in the meantime.
1238 1752 : if (!JSObject::GetProperty(holder, name).ToHandle(&formatted_stack_trace)) {
1239 0 : isolate->OptionalRescheduleException(false);
1240 0 : return;
1241 : }
1242 : }
1243 :
1244 : v8::Local<v8::Value> value = Utils::ToLocal(formatted_stack_trace);
1245 : info.GetReturnValue().Set(value);
1246 : }
1247 :
1248 78 : void Accessors::ErrorStackSetter(
1249 : v8::Local<v8::Name> name, v8::Local<v8::Value> val,
1250 : const v8::PropertyCallbackInfo<v8::Boolean>& info) {
1251 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
1252 : HandleScope scope(isolate);
1253 : Handle<JSObject> obj = Handle<JSObject>::cast(
1254 : Utils::OpenHandle(*v8::Local<v8::Value>(info.This())));
1255 :
1256 : // Clear internal properties to avoid memory leaks.
1257 : Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
1258 156 : if (JSReceiver::HasOwnProperty(obj, stack_trace_symbol).FromMaybe(false)) {
1259 78 : ClearInternalStackTrace(isolate, obj);
1260 : }
1261 :
1262 78 : Accessors::ReconfigureToDataProperty(name, val, info);
1263 78 : }
1264 :
1265 790 : Handle<AccessorInfo> Accessors::ErrorStackInfo(Isolate* isolate,
1266 : PropertyAttributes attributes) {
1267 : Handle<AccessorInfo> info =
1268 : MakeAccessor(isolate, isolate->factory()->stack_string(),
1269 790 : &ErrorStackGetter, &ErrorStackSetter, attributes);
1270 790 : return info;
1271 : }
1272 :
1273 : } // namespace internal
1274 : } // namespace v8
|