cleanup check for compatible receiver of api callback
BUG= Review URL: https://codereview.chromium.org/873623002 Cr-Commit-Position: refs/heads/master@{#26242}
This commit is contained in:
parent
cd2bc96808
commit
845072e66e
@ -1022,45 +1022,6 @@ BUILTIN(GeneratorPoisonPill) {
|
||||
//
|
||||
|
||||
|
||||
// Searches the hidden prototype chain of the given object for the first
|
||||
// object that is an instance of the given type. If no such object can
|
||||
// be found then Heap::null_value() is returned.
|
||||
static inline Object* FindHidden(Heap* heap,
|
||||
Object* object,
|
||||
FunctionTemplateInfo* type) {
|
||||
for (PrototypeIterator iter(heap->isolate(), object,
|
||||
PrototypeIterator::START_AT_RECEIVER);
|
||||
!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
|
||||
if (type->IsTemplateFor(iter.GetCurrent())) {
|
||||
return iter.GetCurrent();
|
||||
}
|
||||
}
|
||||
return heap->null_value();
|
||||
}
|
||||
|
||||
|
||||
// Returns the holder JSObject if the function can legally be called
|
||||
// with this receiver. Returns Heap::null_value() if the call is
|
||||
// illegal. Any arguments that don't fit the expected type is
|
||||
// overwritten with undefined. Note that holder and the arguments are
|
||||
// implicitly rewritten with the first object in the hidden prototype
|
||||
// chain that actually has the expected type.
|
||||
static inline Object* TypeCheck(Heap* heap, Object* recv,
|
||||
FunctionTemplateInfo* info) {
|
||||
// API calls are only supported with JSObject receivers.
|
||||
if (!recv->IsJSObject()) return heap->null_value();
|
||||
Object* recv_type = info->signature();
|
||||
if (recv_type->IsUndefined()) return recv;
|
||||
// If necessary, check the receiver
|
||||
Object* holder = recv;
|
||||
if (!recv_type->IsUndefined()) {
|
||||
holder = FindHidden(heap, holder, FunctionTemplateInfo::cast(recv_type));
|
||||
if (holder == heap->null_value()) return heap->null_value();
|
||||
}
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
||||
template <bool is_construct>
|
||||
MUST_USE_RESULT static Object* HandleApiCallHelper(
|
||||
BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) {
|
||||
@ -1084,7 +1045,7 @@ MUST_USE_RESULT static Object* HandleApiCallHelper(
|
||||
DCHECK(!args[0]->IsNull());
|
||||
if (args[0]->IsUndefined()) args[0] = function->global_proxy();
|
||||
|
||||
Object* raw_holder = TypeCheck(heap, args[0], *fun_data);
|
||||
Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]);
|
||||
|
||||
if (raw_holder->IsNull()) {
|
||||
// This function cannot be called with the given receiver. Abort!
|
||||
|
@ -234,6 +234,25 @@ bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
|
||||
}
|
||||
|
||||
|
||||
// TODO(dcarney): CallOptimization duplicates this logic, merge.
|
||||
Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
|
||||
Object* receiver) {
|
||||
// API calls are only supported with JSObject receivers.
|
||||
if (!receiver->IsJSObject()) return isolate->heap()->null_value();
|
||||
Object* recv_type = this->signature();
|
||||
// No signature, return holder.
|
||||
if (recv_type->IsUndefined()) return receiver;
|
||||
FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
|
||||
// Check the receiver.
|
||||
for (PrototypeIterator iter(isolate, receiver,
|
||||
PrototypeIterator::START_AT_RECEIVER);
|
||||
!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
|
||||
if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
|
||||
}
|
||||
return isolate->heap()->null_value();
|
||||
}
|
||||
|
||||
|
||||
Handle<FixedArray> JSObject::EnsureWritableFastElements(
|
||||
Handle<JSObject> object) {
|
||||
DCHECK(object->HasFastSmiOrObjectElements());
|
||||
|
@ -10640,6 +10640,10 @@ class FunctionTemplateInfo: public TemplateInfo {
|
||||
bool IsTemplateFor(Object* object);
|
||||
bool IsTemplateFor(Map* map);
|
||||
|
||||
// Returns the holder JSObject if the function can legally be called with this
|
||||
// receiver. Returns Heap::null_value() if the call is illegal.
|
||||
Object* GetCompatibleReceiver(Isolate* isolate, Object* receiver);
|
||||
|
||||
private:
|
||||
// Bit position in the flag, from least significant bit position.
|
||||
static const int kHiddenPrototypeBit = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user