5 #include "src/accessors.h" 7 #include "src/api-inl.h" 8 #include "src/contexts.h" 9 #include "src/counters.h" 10 #include "src/deoptimizer.h" 11 #include "src/execution.h" 12 #include "src/frames-inl.h" 13 #include "src/heap/factory.h" 14 #include "src/isolate-inl.h" 15 #include "src/messages.h" 16 #include "src/objects/api-callbacks.h" 17 #include "src/objects/js-array-inl.h" 18 #include "src/objects/module-inl.h" 19 #include "src/property-details.h" 20 #include "src/prototype.h" 25 Handle<AccessorInfo> Accessors::MakeAccessor(
26 Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter,
27 AccessorNameBooleanSetterCallback setter) {
28 Factory* factory = isolate->factory();
29 Handle<AccessorInfo> info = factory->NewAccessorInfo();
30 info->set_all_can_read(
false);
31 info->set_all_can_write(
false);
32 info->set_is_special_data_property(
true);
33 info->set_is_sloppy(
false);
34 info->set_replace_on_access(
false);
35 info->set_getter_side_effect_type(SideEffectType::kHasSideEffect);
36 info->set_setter_side_effect_type(SideEffectType::kHasSideEffect);
37 name = factory->InternalizeName(name);
38 info->set_name(*name);
39 Handle<Object>
get = v8::FromCData(isolate, getter);
40 if (setter ==
nullptr) setter = &ReconfigureToDataProperty;
41 Handle<Object>
set = v8::FromCData(isolate, setter);
42 info->set_getter(*
get);
43 info->set_setter(*
set);
44 Address redirected = info->redirected_getter();
45 if (redirected != kNullAddress) {
46 Handle<Object> js_get = v8::FromCData(isolate, redirected);
47 info->set_js_getter(*js_get);
52 static V8_INLINE
bool CheckForName(Isolate* isolate, Handle<Name> name,
53 Handle<String> property_name,
int offset,
54 FieldIndex::Encoding encoding,
56 if (Name::Equals(isolate, name, property_name)) {
57 *index = FieldIndex::ForInObjectOffset(offset, encoding);
66 bool Accessors::IsJSObjectFieldAccessor(Isolate* isolate, Handle<Map> map,
67 Handle<Name> name, FieldIndex* index) {
68 switch (map->instance_type()) {
70 return CheckForName(isolate, name, isolate->factory()->length_string(),
71 JSArray::kLengthOffset, FieldIndex::kTagged, index);
73 if (map->instance_type() < FIRST_NONSTRING_TYPE) {
74 return CheckForName(isolate, name, isolate->factory()->length_string(),
75 String::kLengthOffset, FieldIndex::kWord32, index);
82 V8_WARN_UNUSED_RESULT MaybeHandle<Object>
83 Accessors::ReplaceAccessorWithDataProperty(Handle<Object> receiver,
84 Handle<JSObject> holder,
86 Handle<Object> value) {
87 LookupIterator it(receiver, name, holder,
88 LookupIterator::OWN_SKIP_INTERCEPTOR);
91 if (it.state() == LookupIterator::ACCESS_CHECK) {
92 CHECK(it.HasAccess());
95 DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
96 CHECK_EQ(LookupIterator::ACCESSOR, it.state());
97 it.ReconfigureDataProperty(value, it.property_attributes());
105 void Accessors::ReconfigureToDataProperty(
109 RuntimeCallTimerScope stats_scope(
110 isolate, RuntimeCallCounterId::kReconfigureToDataProperty);
111 HandleScope scope(isolate);
112 Handle<Object> receiver = Utils::OpenHandle(*info.
This());
113 Handle<JSObject> holder =
114 Handle<JSObject>::cast(Utils::OpenHandle(*info.
Holder()));
115 Handle<Name> name = Utils::OpenHandle(*key);
116 Handle<Object> value = Utils::OpenHandle(*val);
117 MaybeHandle<Object> result =
118 Accessors::ReplaceAccessorWithDataProperty(receiver, holder, name, value);
119 if (result.is_null()) {
120 isolate->OptionalRescheduleException(
false);
132 void Accessors::ArgumentsIteratorGetter(
135 DisallowHeapAllocation no_allocation;
136 HandleScope scope(isolate);
137 Object* result = isolate->native_context()->array_values_iterator();
138 info.
GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
141 Handle<AccessorInfo> Accessors::MakeArgumentsIteratorInfo(Isolate* isolate) {
142 Handle<Name> name = isolate->factory()->iterator_symbol();
143 return MakeAccessor(isolate, name, &ArgumentsIteratorGetter,
nullptr);
152 void Accessors::ArrayLengthGetter(
156 RuntimeCallTimerScope timer(isolate,
157 RuntimeCallCounterId::kArrayLengthGetter);
158 DisallowHeapAllocation no_allocation;
159 HandleScope scope(isolate);
160 JSArray* holder = JSArray::cast(*Utils::OpenHandle(*info.
Holder()));
161 Object* result = holder->length();
162 info.
GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
165 void Accessors::ArrayLengthSetter(
169 RuntimeCallTimerScope timer(isolate,
170 RuntimeCallCounterId::kArrayLengthSetter);
171 HandleScope scope(isolate);
173 DCHECK(Utils::OpenHandle(*name)->SameValue(
174 ReadOnlyRoots(isolate).length_string()));
176 Handle<JSReceiver>
object = Utils::OpenHandle(*info.
Holder());
177 Handle<JSArray> array = Handle<JSArray>::cast(
object);
178 Handle<Object> length_obj = Utils::OpenHandle(*val);
180 bool was_readonly = JSArray::HasReadOnlyLength(array);
183 if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) {
184 isolate->OptionalRescheduleException(
false);
188 if (!was_readonly && V8_UNLIKELY(JSArray::HasReadOnlyLength(array)) &&
189 length != array->length()->Number()) {
195 Factory* factory = isolate->factory();
196 isolate->Throw(*factory->NewTypeError(
197 MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
198 i::Object::TypeOf(isolate,
object),
object));
199 isolate->OptionalRescheduleException(
false);
206 JSArray::SetLength(array, length);
209 CHECK(array->length()->ToArrayLength(&actual_new_len));
211 if (actual_new_len != length) {
213 Factory* factory = isolate->factory();
214 isolate->Throw(*factory->NewTypeError(
215 MessageTemplate::kStrictDeleteProperty,
216 factory->NewNumberFromUint(actual_new_len - 1), array));
217 isolate->OptionalRescheduleException(
false);
226 Handle<AccessorInfo> Accessors::MakeArrayLengthInfo(Isolate* isolate) {
227 return MakeAccessor(isolate, isolate->factory()->length_string(),
228 &ArrayLengthGetter, &ArrayLengthSetter);
235 void Accessors::ModuleNamespaceEntryGetter(
238 HandleScope scope(isolate);
239 JSModuleNamespace* holder =
240 JSModuleNamespace::cast(*Utils::OpenHandle(*info.
Holder()));
241 Handle<Object> result;
243 ->GetExport(isolate, Handle<String>::cast(Utils::OpenHandle(*name)))
244 .ToHandle(&result)) {
245 isolate->OptionalRescheduleException(
false);
251 void Accessors::ModuleNamespaceEntrySetter(
255 HandleScope scope(isolate);
256 Factory* factory = isolate->factory();
257 Handle<JSModuleNamespace> holder =
258 Handle<JSModuleNamespace>::cast(Utils::OpenHandle(*info.
Holder()));
261 isolate->Throw(*factory->NewTypeError(
262 MessageTemplate::kStrictReadOnlyProperty, Utils::OpenHandle(*name),
263 i::Object::TypeOf(isolate, holder), holder));
264 isolate->OptionalRescheduleException(
false);
270 Handle<AccessorInfo> Accessors::MakeModuleNamespaceEntryInfo(
271 Isolate* isolate, Handle<String> name) {
272 return MakeAccessor(isolate, name, &ModuleNamespaceEntryGetter,
273 &ModuleNamespaceEntrySetter);
281 void Accessors::StringLengthGetter(
285 RuntimeCallTimerScope timer(isolate,
286 RuntimeCallCounterId::kStringLengthGetter);
287 DisallowHeapAllocation no_allocation;
288 HandleScope scope(isolate);
296 if (!value->IsString()) {
299 value = JSValue::cast(*Utils::OpenHandle(*info.
Holder()))->value();
301 Object* result = Smi::FromInt(String::cast(value)->length());
302 info.
GetReturnValue().Set(Utils::ToLocal(Handle<Object>(result, isolate)));
305 Handle<AccessorInfo> Accessors::MakeStringLengthInfo(Isolate* isolate) {
306 return MakeAccessor(isolate, isolate->factory()->length_string(),
307 &StringLengthGetter,
nullptr);
314 static Handle<Object> GetFunctionPrototype(Isolate* isolate,
315 Handle<JSFunction>
function) {
316 if (!function->has_prototype()) {
317 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(
function);
318 JSFunction::SetPrototype(
function, proto);
320 return Handle<Object>(
function->prototype(), isolate);
323 void Accessors::FunctionPrototypeGetter(
327 RuntimeCallTimerScope timer(isolate,
328 RuntimeCallCounterId::kFunctionPrototypeGetter);
329 HandleScope scope(isolate);
330 Handle<JSFunction>
function =
331 Handle<JSFunction>::cast(Utils::OpenHandle(*info.
Holder()));
332 DCHECK(function->has_prototype_property());
333 Handle<Object> result = GetFunctionPrototype(isolate,
function);
337 void Accessors::FunctionPrototypeSetter(
341 RuntimeCallTimerScope timer(isolate,
342 RuntimeCallCounterId::kFunctionPrototypeSetter);
343 HandleScope scope(isolate);
344 Handle<Object> value = Utils::OpenHandle(*val);
345 Handle<JSFunction>
object =
346 Handle<JSFunction>::cast(Utils::OpenHandle(*info.
Holder()));
347 DCHECK(object->has_prototype_property());
348 JSFunction::SetPrototype(
object, value);
352 Handle<AccessorInfo> Accessors::MakeFunctionPrototypeInfo(Isolate* isolate) {
353 return MakeAccessor(isolate, isolate->factory()->prototype_string(),
354 &FunctionPrototypeGetter, &FunctionPrototypeSetter);
363 void Accessors::FunctionLengthGetter(
367 RuntimeCallTimerScope timer(isolate,
368 RuntimeCallCounterId::kFunctionLengthGetter);
369 HandleScope scope(isolate);
370 Handle<JSFunction>
function =
371 Handle<JSFunction>::cast(Utils::OpenHandle(*info.
Holder()));
373 if (!JSFunction::GetLength(isolate,
function).To(&length)) {
374 isolate->OptionalRescheduleException(
false);
376 Handle<Object> result(Smi::FromInt(length), isolate);
380 Handle<AccessorInfo> Accessors::MakeFunctionLengthInfo(Isolate* isolate) {
381 return MakeAccessor(isolate, isolate->factory()->length_string(),
382 &FunctionLengthGetter, &ReconfigureToDataProperty);
391 void Accessors::FunctionNameGetter(
395 HandleScope scope(isolate);
396 Handle<JSFunction>
function =
397 Handle<JSFunction>::cast(Utils::OpenHandle(*info.
Holder()));
398 Handle<Object> result = JSFunction::GetName(isolate,
function);
402 Handle<AccessorInfo> Accessors::MakeFunctionNameInfo(Isolate* isolate) {
403 return MakeAccessor(isolate, isolate->factory()->name_string(),
404 &FunctionNameGetter, &ReconfigureToDataProperty);
414 Handle<JSObject> ArgumentsForInlinedFunction(JavaScriptFrame* frame,
415 int inlined_frame_index) {
416 Isolate* isolate = frame->isolate();
417 Factory* factory = isolate->factory();
419 TranslatedState translated_values(frame);
420 translated_values.Prepare(frame->fp());
422 int argument_count = 0;
423 TranslatedFrame* translated_frame =
424 translated_values.GetArgumentsInfoFromJSFrameIndex(inlined_frame_index,
426 TranslatedFrame::iterator iter = translated_frame->begin();
429 bool should_deoptimize = iter->IsMaterializedObject();
430 Handle<JSFunction>
function = Handle<JSFunction>::cast(iter->GetValue());
437 Handle<JSObject> arguments =
438 factory->NewArgumentsObject(
function, argument_count);
439 Handle<FixedArray> array = factory->NewFixedArray(argument_count);
440 for (
int i = 0;
i < argument_count; ++
i) {
443 should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
444 Handle<Object> value = iter->GetValue();
445 array->set(
i, *value);
448 arguments->set_elements(*array);
450 if (should_deoptimize) {
451 translated_values.StoreMaterializedValuesAndDeopt(frame);
458 int FindFunctionInFrame(JavaScriptFrame* frame, Handle<JSFunction>
function) {
459 std::vector<FrameSummary> frames;
460 frame->Summarize(&frames);
461 for (
size_t i = frames.size();
i != 0;
i--) {
462 if (*frames[
i - 1].AsJavaScript().function() == *
function) {
463 return static_cast<int>(
i) - 1;
469 Handle<JSObject> GetFrameArguments(Isolate* isolate,
470 JavaScriptFrameIterator* it,
471 int function_index) {
472 JavaScriptFrame* frame = it->frame();
474 if (function_index > 0) {
479 return ArgumentsForInlinedFunction(frame, function_index);
483 if (it->frame()->has_adapted_arguments()) {
484 it->AdvanceOneFrame();
485 DCHECK(it->frame()->is_arguments_adaptor());
491 const int length = frame->ComputeParametersCount();
492 Handle<JSFunction>
function(frame->function(), isolate);
493 Handle<JSObject> arguments =
494 isolate->factory()->NewArgumentsObject(
function, length);
495 Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
498 DCHECK(array->length() == length);
499 for (
int i = 0;
i < length;
i++) {
500 Object* value = frame->GetParameter(
i);
501 if (value->IsTheHole(isolate)) {
504 DCHECK(IsResumableFunction(function->shared()->kind()));
505 value = ReadOnlyRoots(isolate).undefined_value();
507 array->set(
i, value);
509 arguments->set_elements(*array);
517 Handle<JSObject> Accessors::FunctionGetArguments(JavaScriptFrame* frame,
518 int inlined_jsframe_index) {
519 Isolate* isolate = frame->isolate();
520 Address requested_frame_fp = frame->fp();
523 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
524 if (it.frame()->fp() != requested_frame_fp)
continue;
525 return GetFrameArguments(isolate, &it, inlined_jsframe_index);
528 return Handle<JSObject>();
532 void Accessors::FunctionArgumentsGetter(
536 HandleScope scope(isolate);
537 Handle<JSFunction>
function =
538 Handle<JSFunction>::cast(Utils::OpenHandle(*info.
Holder()));
539 Handle<Object> result = isolate->factory()->null_value();
540 if (!function->shared()->native()) {
542 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
543 JavaScriptFrame* frame = it.frame();
544 int function_index = FindFunctionInFrame(frame,
function);
545 if (function_index >= 0) {
546 result = GetFrameArguments(isolate, &it, function_index);
554 Handle<AccessorInfo> Accessors::MakeFunctionArgumentsInfo(Isolate* isolate) {
555 return MakeAccessor(isolate, isolate->factory()->arguments_string(),
556 &FunctionArgumentsGetter,
nullptr);
564 static inline bool AllowAccessToFunction(Context current_context,
565 JSFunction*
function) {
566 return current_context->HasSameSecurityTokenAs(function->context());
573 : isolate_(isolate), frame_iterator_(isolate), inlined_frame_index_(-1) {
581 if (!next().ToHandle(&function_))
return false;
582 }
while (!function_.is_identical_to(
function));
588 bool FindNextNonTopLevel() {
590 if (!next().ToHandle(&function_))
return false;
591 }
while (function_->shared()->is_toplevel());
599 bool FindFirstNativeOrUserJavaScript() {
600 while (!function_->shared()->native() &&
601 !function_->shared()->IsUserJavaScript()) {
602 if (!next().ToHandle(&function_))
return false;
613 if (inlined_frame_index_ == 0)
return function_;
617 translated_values.Prepare(frame->fp());
620 translated_values.GetFrameFromJSFrameIndex(inlined_frame_index_);
624 bool should_deoptimize = iter->IsMaterializedObject();
626 if (should_deoptimize) {
627 translated_values.StoreMaterializedValuesAndDeopt(frame);
636 if (inlined_frame_index_ <= 0) {
637 if (!frame_iterator_.done()) {
638 frame_iterator_.Advance();
640 inlined_frame_index_ = -1;
646 --inlined_frame_index_;
648 frames_[inlined_frame_index_].AsJavaScript().function();
650 if (!AllowAccessToFunction(isolate_->context(), *next_function))
continue;
651 return next_function;
655 DCHECK_EQ(-1, inlined_frame_index_);
656 if (frame_iterator_.done())
return;
658 frame->Summarize(&frames_);
659 inlined_frame_index_ =
static_cast<int>(frames_.size());
660 DCHECK_LT(0, inlined_frame_index_);
665 std::vector<FrameSummary> frames_;
666 int inlined_frame_index_;
673 if (function->shared()->native()) {
678 if (!it.Find(
function)) {
679 return MaybeHandle<JSFunction>();
682 if (!it.FindNextNonTopLevel()) {
683 return MaybeHandle<JSFunction>();
687 if (!it.FindFirstNativeOrUserJavaScript()) {
688 return MaybeHandle<JSFunction>();
695 Handle<JSFunction> caller = it.MaterializeFunction();
700 if (is_strict(caller->shared()->language_mode())) {
701 return MaybeHandle<JSFunction>();
704 if (!AllowAccessToFunction(isolate->context(), *caller)) {
705 return MaybeHandle<JSFunction>();
711 void Accessors::FunctionCallerGetter(
715 HandleScope scope(isolate);
716 Handle<JSFunction>
function =
717 Handle<JSFunction>::cast(Utils::OpenHandle(*info.
Holder()));
718 Handle<Object> result;
719 MaybeHandle<JSFunction> maybe_caller;
720 maybe_caller = FindCaller(isolate,
function);
721 Handle<JSFunction> caller;
722 if (maybe_caller.ToHandle(&caller)) {
725 result = isolate->factory()->null_value();
730 Handle<AccessorInfo> Accessors::MakeFunctionCallerInfo(Isolate* isolate) {
731 return MakeAccessor(isolate, isolate->factory()->caller_string(),
732 &FunctionCallerGetter,
nullptr);
740 void Accessors::BoundFunctionLengthGetter(
743 RuntimeCallTimerScope timer(isolate,
744 RuntimeCallCounterId::kBoundFunctionLengthGetter);
745 HandleScope scope(isolate);
746 Handle<JSBoundFunction>
function =
747 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.
Holder()));
750 if (!JSBoundFunction::GetLength(isolate,
function).To(&length)) {
751 isolate->OptionalRescheduleException(
false);
754 Handle<Object> result(Smi::FromInt(length), isolate);
758 Handle<AccessorInfo> Accessors::MakeBoundFunctionLengthInfo(Isolate* isolate) {
759 return MakeAccessor(isolate, isolate->factory()->length_string(),
760 &BoundFunctionLengthGetter, &ReconfigureToDataProperty);
767 void Accessors::BoundFunctionNameGetter(
770 RuntimeCallTimerScope timer(isolate,
771 RuntimeCallCounterId::kBoundFunctionNameGetter);
772 HandleScope scope(isolate);
773 Handle<JSBoundFunction>
function =
774 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.
Holder()));
775 Handle<Object> result;
776 if (!JSBoundFunction::GetName(isolate,
function).ToHandle(&result)) {
777 isolate->OptionalRescheduleException(
false);
783 Handle<AccessorInfo> Accessors::MakeBoundFunctionNameInfo(Isolate* isolate) {
784 return MakeAccessor(isolate, isolate->factory()->name_string(),
785 &BoundFunctionNameGetter, &ReconfigureToDataProperty);
794 MaybeHandle<JSReceiver> ClearInternalStackTrace(Isolate* isolate,
795 Handle<JSObject> error) {
798 JSReceiver::SetProperty(
799 isolate, error, isolate->factory()->stack_trace_symbol(),
800 isolate->factory()->undefined_value(), LanguageMode::kStrict),
805 bool IsAccessor(Handle<Object> receiver, Handle<Name> name,
806 Handle<JSObject> holder) {
807 LookupIterator it(receiver, name, holder,
808 LookupIterator::OWN_SKIP_INTERCEPTOR);
811 if (it.state() == LookupIterator::ACCESS_CHECK) {
812 CHECK(it.HasAccess());
815 return (it.state() == LookupIterator::ACCESSOR);
820 void Accessors::ErrorStackGetter(
823 HandleScope scope(isolate);
824 Handle<JSObject> holder =
825 Handle<JSObject>::cast(Utils::OpenHandle(*info.
Holder()));
829 Handle<Object> stack_trace;
830 Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
831 MaybeHandle<Object> maybe_stack_trace =
832 JSObject::GetProperty(isolate, holder, stack_trace_symbol);
833 if (!maybe_stack_trace.ToHandle(&stack_trace) ||
834 stack_trace->IsUndefined(isolate)) {
835 Handle<Object> result = isolate->factory()->undefined_value();
843 Handle<Object> formatted_stack_trace;
844 if (!ErrorUtils::FormatStackTrace(isolate, holder, stack_trace)
845 .ToHandle(&formatted_stack_trace)) {
846 isolate->OptionalRescheduleException(
false);
850 MaybeHandle<Object> result = ClearInternalStackTrace(isolate, holder);
851 if (result.is_null()) {
852 isolate->OptionalRescheduleException(
false);
859 Handle<Object> receiver =
861 Handle<Name> name = Utils::OpenHandle(*key);
862 if (IsAccessor(receiver, name, holder)) {
863 result = Accessors::ReplaceAccessorWithDataProperty(receiver, holder, name,
864 formatted_stack_trace);
865 if (result.is_null()) {
866 isolate->OptionalRescheduleException(
false);
871 if (!JSObject::GetProperty(isolate, holder, name)
872 .ToHandle(&formatted_stack_trace)) {
873 isolate->OptionalRescheduleException(
false);
882 void Accessors::ErrorStackSetter(
886 HandleScope scope(isolate);
887 Handle<JSObject> obj = Handle<JSObject>::cast(
891 Handle<Symbol> stack_trace_symbol = isolate->factory()->stack_trace_symbol();
892 if (JSReceiver::HasOwnProperty(obj, stack_trace_symbol).FromMaybe(
false)) {
893 ClearInternalStackTrace(isolate, obj);
896 Accessors::ReconfigureToDataProperty(name, val, info);
899 Handle<AccessorInfo> Accessors::MakeErrorStackInfo(Isolate* isolate) {
900 return MakeAccessor(isolate, isolate->factory()->stack_string(),
901 &ErrorStackGetter, &ErrorStackSetter);
V8_INLINE Isolate * GetIsolate() const
V8_INLINE bool ShouldThrowOnError() const
V8_INLINE ReturnValue< T > GetReturnValue() const
V8_INLINE Local< Object > Holder() const
V8_INLINE Local< Object > This() const