OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/base/ieee754.h" | 10 #include "src/base/ieee754.h" |
(...skipping 5083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5094 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill)); | 5094 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill)); |
5095 } | 5095 } |
5096 | 5096 |
5097 | 5097 |
5098 // ----------------------------------------------------------------------------- | 5098 // ----------------------------------------------------------------------------- |
5099 // | 5099 // |
5100 | 5100 |
5101 | 5101 |
5102 namespace { | 5102 namespace { |
5103 | 5103 |
| 5104 // Returns the holder JSObject if the function can legally be called with this |
| 5105 // receiver. Returns nullptr if the call is illegal. |
| 5106 // TODO(dcarney): CallOptimization duplicates this logic, merge. |
| 5107 JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info, |
| 5108 JSObject* receiver) { |
| 5109 Object* recv_type = info->signature(); |
| 5110 // No signature, return holder. |
| 5111 if (!recv_type->IsFunctionTemplateInfo()) return receiver; |
| 5112 FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type); |
| 5113 |
| 5114 // Check the receiver. Fast path for receivers with no hidden prototypes. |
| 5115 if (signature->IsTemplateFor(receiver)) return receiver; |
| 5116 if (!receiver->map()->has_hidden_prototype()) return nullptr; |
| 5117 for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype, |
| 5118 PrototypeIterator::END_AT_NON_HIDDEN); |
| 5119 !iter.IsAtEnd(); iter.Advance()) { |
| 5120 JSObject* current = iter.GetCurrent<JSObject>(); |
| 5121 if (signature->IsTemplateFor(current)) return current; |
| 5122 } |
| 5123 return nullptr; |
| 5124 } |
| 5125 |
5104 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(Isolate* isolate, | 5126 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(Isolate* isolate, |
5105 BuiltinArguments args) { | 5127 BuiltinArguments args) { |
5106 HandleScope scope(isolate); | 5128 HandleScope scope(isolate); |
5107 Handle<HeapObject> function = args.target<HeapObject>(); | 5129 Handle<HeapObject> function = args.target<HeapObject>(); |
5108 Handle<HeapObject> new_target = args.new_target(); | 5130 Handle<HeapObject> new_target = args.new_target(); |
5109 bool is_construct = !new_target->IsUndefined(isolate); | 5131 bool is_construct = !new_target->IsUndefined(isolate); |
5110 Handle<JSReceiver> receiver; | 5132 Handle<JSObject> receiver; |
5111 | 5133 |
5112 DCHECK(function->IsFunctionTemplateInfo() || | 5134 DCHECK(function->IsFunctionTemplateInfo() || |
5113 Handle<JSFunction>::cast(function)->shared()->IsApiFunction()); | 5135 Handle<JSFunction>::cast(function)->shared()->IsApiFunction()); |
5114 | 5136 |
5115 Handle<FunctionTemplateInfo> fun_data = | 5137 Handle<FunctionTemplateInfo> fun_data = |
5116 function->IsFunctionTemplateInfo() | 5138 function->IsFunctionTemplateInfo() |
5117 ? Handle<FunctionTemplateInfo>::cast(function) | 5139 ? Handle<FunctionTemplateInfo>::cast(function) |
5118 : handle(JSFunction::cast(*function)->shared()->get_api_func_data()); | 5140 : handle(JSFunction::cast(*function)->shared()->get_api_func_data()); |
| 5141 JSObject* raw_holder; |
5119 if (is_construct) { | 5142 if (is_construct) { |
5120 DCHECK(args.receiver()->IsTheHole(isolate)); | 5143 DCHECK(args.receiver()->IsTheHole(isolate)); |
5121 if (fun_data->instance_template()->IsUndefined(isolate)) { | 5144 if (fun_data->instance_template()->IsUndefined(isolate)) { |
5122 v8::Local<ObjectTemplate> templ = | 5145 v8::Local<ObjectTemplate> templ = |
5123 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate), | 5146 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate), |
5124 ToApiHandle<v8::FunctionTemplate>(fun_data)); | 5147 ToApiHandle<v8::FunctionTemplate>(fun_data)); |
5125 fun_data->set_instance_template(*Utils::OpenHandle(*templ)); | 5148 fun_data->set_instance_template(*Utils::OpenHandle(*templ)); |
5126 } | 5149 } |
5127 Handle<ObjectTemplateInfo> instance_template( | 5150 Handle<ObjectTemplateInfo> instance_template( |
5128 ObjectTemplateInfo::cast(fun_data->instance_template()), isolate); | 5151 ObjectTemplateInfo::cast(fun_data->instance_template()), isolate); |
5129 ASSIGN_RETURN_ON_EXCEPTION( | 5152 ASSIGN_RETURN_ON_EXCEPTION( |
5130 isolate, receiver, | 5153 isolate, receiver, |
5131 ApiNatives::InstantiateObject(instance_template, | 5154 ApiNatives::InstantiateObject(instance_template, |
5132 Handle<JSReceiver>::cast(new_target)), | 5155 Handle<JSReceiver>::cast(new_target)), |
5133 Object); | 5156 Object); |
5134 args[0] = *receiver; | 5157 args[0] = *receiver; |
5135 DCHECK_EQ(*receiver, *args.receiver()); | 5158 DCHECK_EQ(*receiver, *args.receiver()); |
| 5159 |
| 5160 raw_holder = *receiver; |
5136 } else { | 5161 } else { |
5137 DCHECK(args.receiver()->IsJSReceiver()); | 5162 DCHECK(args.receiver()->IsJSReceiver()); |
5138 receiver = args.at<JSReceiver>(0); | |
5139 } | |
5140 | 5163 |
5141 if (!is_construct && !fun_data->accept_any_receiver()) { | 5164 Handle<JSReceiver> object = args.at<JSReceiver>(0); |
5142 if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) { | 5165 if (!object->IsJSObject()) { |
5143 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); | 5166 // This function cannot be called with the given receiver. Abort! |
5144 if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) { | 5167 THROW_NEW_ERROR( |
5145 isolate->ReportFailedAccessCheck(js_receiver); | 5168 isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object); |
5146 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5169 } |
5147 } | 5170 |
| 5171 receiver = Handle<JSObject>::cast(object); |
| 5172 |
| 5173 if (!fun_data->accept_any_receiver() && receiver->IsAccessCheckNeeded() && |
| 5174 !isolate->MayAccess(handle(isolate->context()), receiver)) { |
| 5175 isolate->ReportFailedAccessCheck(receiver); |
| 5176 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5177 } |
| 5178 |
| 5179 raw_holder = GetCompatibleReceiver(isolate, *fun_data, *receiver); |
| 5180 |
| 5181 if (raw_holder == nullptr) { |
| 5182 // This function cannot be called with the given receiver. Abort! |
| 5183 THROW_NEW_ERROR( |
| 5184 isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object); |
5148 } | 5185 } |
5149 } | 5186 } |
5150 | 5187 |
5151 Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, *receiver); | |
5152 | |
5153 if (raw_holder->IsNull(isolate)) { | |
5154 // This function cannot be called with the given receiver. Abort! | |
5155 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation), | |
5156 Object); | |
5157 } | |
5158 | |
5159 Object* raw_call_data = fun_data->call_code(); | 5188 Object* raw_call_data = fun_data->call_code(); |
5160 if (!raw_call_data->IsUndefined(isolate)) { | 5189 if (!raw_call_data->IsUndefined(isolate)) { |
5161 DCHECK(raw_call_data->IsCallHandlerInfo()); | 5190 DCHECK(raw_call_data->IsCallHandlerInfo()); |
5162 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); | 5191 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); |
5163 Object* callback_obj = call_data->callback(); | 5192 Object* callback_obj = call_data->callback(); |
5164 v8::FunctionCallback callback = | 5193 v8::FunctionCallback callback = |
5165 v8::ToCData<v8::FunctionCallback>(callback_obj); | 5194 v8::ToCData<v8::FunctionCallback>(callback_obj); |
5166 Object* data_obj = call_data->data(); | 5195 Object* data_obj = call_data->data(); |
5167 | 5196 |
5168 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); | 5197 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); |
5169 DCHECK(raw_holder->IsJSObject()); | |
5170 | 5198 |
5171 FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder, | 5199 FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder, |
5172 *new_target, &args[0] - 1, | 5200 *new_target, &args[0] - 1, |
5173 args.length() - 1); | 5201 args.length() - 1); |
5174 | 5202 |
5175 Handle<Object> result = custom.Call(callback); | 5203 Handle<Object> result = custom.Call(callback); |
5176 if (result.is_null()) result = isolate->factory()->undefined_value(); | 5204 if (result.is_null()) result = isolate->factory()->undefined_value(); |
5177 | 5205 |
5178 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5206 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5179 if (!is_construct || result->IsJSObject()) { | 5207 if (!is_construct || result->IsJSObject()) { |
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6065 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 6093 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
6066 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 6094 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
6067 #undef DEFINE_BUILTIN_ACCESSOR_C | 6095 #undef DEFINE_BUILTIN_ACCESSOR_C |
6068 #undef DEFINE_BUILTIN_ACCESSOR_A | 6096 #undef DEFINE_BUILTIN_ACCESSOR_A |
6069 #undef DEFINE_BUILTIN_ACCESSOR_T | 6097 #undef DEFINE_BUILTIN_ACCESSOR_T |
6070 #undef DEFINE_BUILTIN_ACCESSOR_S | 6098 #undef DEFINE_BUILTIN_ACCESSOR_S |
6071 #undef DEFINE_BUILTIN_ACCESSOR_H | 6099 #undef DEFINE_BUILTIN_ACCESSOR_H |
6072 | 6100 |
6073 } // namespace internal | 6101 } // namespace internal |
6074 } // namespace v8 | 6102 } // namespace v8 |
OLD | NEW |