Ignore:
Timestamp:
Feb 19, 2016, 2:56:31 PM (10 years ago)
Author:
[email protected]
Message:

[ES6] Implement Proxy.Call
https://bugs.webkit.org/show_bug.cgi?id=154425

Reviewed by Mark Lam.

This patch is a straight forward implementation of
Proxy.Call with respect to section 9.5.12
of the ECMAScript spec.
https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist

  • runtime/ProxyObject.cpp:

(JSC::ProxyObject::finishCreation):
(JSC::performProxyGet):
(JSC::ProxyObject::performInternalMethodGetOwnProperty):
(JSC::ProxyObject::performHasProperty):
(JSC::ProxyObject::getOwnPropertySlotByIndex):
(JSC::performProxyCall):
(JSC::ProxyObject::getCallData):
(JSC::ProxyObject::visitChildren):

  • runtime/ProxyObject.h:

(JSC::ProxyObject::create):

  • tests/es6.yaml:
  • tests/stress/proxy-call.js: Added.

(assert):
(throw.new.Error.let.target):
(throw.new.Error.let.handler.apply):
(throw.new.Error):
(assert.let.target):
(assert.let.handler.get apply):
(let.target):
(let.handler.apply):
(i.catch):
(assert.let.handler.apply):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp

    r196789 r196836  
    6666    }
    6767
    68     m_target.set(vm, this, jsCast<JSObject*>(target));
     68    CallData ignored;
     69    JSObject* targetAsObject = jsCast<JSObject*>(target);
     70    m_isCallable = targetAsObject->methodTable(vm)->getCallData(targetAsObject, ignored) != CallTypeNone;
     71
     72    m_target.set(vm, this, targetAsObject);
    6973    m_handler.set(vm, this, handler);
    7074}
     
    106110    arguments.append(target);
    107111    arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid())));
    108     if (exec->hadException())
    109         return JSValue::encode(jsUndefined());
    110112    arguments.append(thisObject);
    111113    JSValue trapResult = call(exec, getHandler, callType, callData, handler, arguments);
     
    153155    arguments.append(target);
    154156    arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid())));
    155     if (exec->hadException())
    156         return false;
    157157    JSValue trapResult = call(exec, getOwnPropertyDescriptorMethod, callType, callData, handler, arguments);
    158158    if (exec->hadException())
     
    235235    arguments.append(target);
    236236    arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid())));
    237     if (exec->hadException())
    238         return false;
    239237    JSValue trapResult = call(exec, hasMethod, callType, callData, handler, arguments);
    240238    if (exec->hadException())
     
    299297}
    300298
     299static EncodedJSValue JSC_HOST_CALL performProxyCall(ExecState* exec)
     300{
     301    VM& vm = exec->vm();
     302    ProxyObject* proxy = jsCast<ProxyObject*>(exec->callee());
     303    JSValue handlerValue = proxy->handler();
     304    if (handlerValue.isNull())
     305        return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object."));
     306
     307    JSObject* handler = jsCast<JSObject*>(handlerValue);
     308    CallData callData;
     309    CallType callType;
     310    JSValue applyMethod = handler->getMethod(exec, callData, callType, makeIdentifier(vm, "apply"), ASCIILiteral("'apply' property of a Proxy's handler should be callable."));
     311    if (exec->hadException())
     312        return JSValue::encode(jsUndefined());
     313    JSObject* target = proxy->target();
     314    if (applyMethod.isUndefined()) {
     315        CallData callData;
     316        CallType callType = target->methodTable(vm)->getCallData(target, callData);
     317        RELEASE_ASSERT(callType != CallTypeNone);
     318        return JSValue::encode(call(exec, target, callType, callData, exec->thisValue(), ArgList(exec)));
     319    }
     320
     321    JSArray* argArray = constructArray(exec, static_cast<ArrayAllocationProfile*>(nullptr), ArgList(exec));
     322    if (exec->hadException())
     323        return JSValue::encode(jsUndefined());
     324    MarkedArgumentBuffer arguments;
     325    arguments.append(target);
     326    arguments.append(exec->thisValue());
     327    arguments.append(argArray);
     328    return JSValue::encode(call(exec, applyMethod, callType, callData, handler, arguments));
     329}
     330
     331CallType ProxyObject::getCallData(JSCell* cell, CallData& callData)
     332{
     333    ProxyObject* proxy = jsCast<ProxyObject*>(cell);
     334    if (!proxy->m_isCallable) {
     335        callData.js.functionExecutable = nullptr;
     336        callData.js.scope = nullptr;
     337        return CallTypeNone;
     338    }
     339
     340    callData.native.function = performProxyCall;
     341    return CallTypeHost;
     342}
     343
    301344void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
    302345{
Note: See TracChangeset for help on using the changeset viewer.