Ignore:
Timestamp:
Feb 20, 2016, 3:51:33 PM (10 years ago)
Author:
[email protected]
Message:

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

Reviewed by Oliver Hunt.

This patch is mostly an implementation of
Proxy.Construct with respect to section 9.5.13
of the ECMAScript spec.
https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget

This patch also changes op_create_this to accept new.target's
that aren't JSFunctions. This is necessary implementing Proxy.Construct
because we might construct a JSFunction with a new.target being
a Proxy. This will also be needed when we implement Reflect.construct.

  • dfg/DFGOperations.cpp:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_create_this):
(JSC::JIT::emitSlow_op_create_this):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_create_this):
(JSC::JIT::emitSlow_op_create_this):

  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/ProxyObject.cpp:

(JSC::ProxyObject::finishCreation):
(JSC::ProxyObject::visitChildren):
(JSC::performProxyConstruct):
(JSC::ProxyObject::getConstructData):

  • runtime/ProxyObject.h:
  • tests/es6.yaml:
  • tests/stress/proxy-construct.js: Added.

(assert):
(throw.new.Error.let.target):
(throw.new.Error):
(assert.let.target):
(assert.let.handler.get construct):
(let.target):
(let.handler.construct):
(i.catch):
(assert.let.handler.construct):
(assert.let.construct):
(assert.else.assert.let.target):
(assert.else.assert.let.construct):
(assert.else.assert):
(new.proxy.let.target):
(new.proxy.let.construct):
(new.proxy):

File:
1 edited

Legend:

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

    r196836 r196868  
    6666    }
    6767
    68     CallData ignored;
    6968    JSObject* targetAsObject = jsCast<JSObject*>(target);
    70     m_isCallable = targetAsObject->methodTable(vm)->getCallData(targetAsObject, ignored) != CallTypeNone;
     69
     70    CallData ignoredCallData;
     71    m_isCallable = targetAsObject->methodTable(vm)->getCallData(targetAsObject, ignoredCallData) != CallTypeNone;
     72
     73    ConstructData ignoredConstructData;
     74    m_isConstructible = jsCast<JSObject*>(target)->methodTable(vm)->getConstructData(jsCast<JSObject*>(target), ignoredConstructData) != ConstructTypeNone;
    7175
    7276    m_target.set(vm, this, targetAsObject);
     
    352356}
    353357
     358static EncodedJSValue JSC_HOST_CALL performProxyConstruct(ExecState* exec)
     359{
     360    VM& vm = exec->vm();
     361    ProxyObject* proxy = jsCast<ProxyObject*>(exec->callee());
     362    JSValue handlerValue = proxy->handler();
     363    if (handlerValue.isNull())
     364        return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object."));
     365
     366    JSObject* handler = jsCast<JSObject*>(handlerValue);
     367    CallData callData;
     368    CallType callType;
     369    JSValue constructMethod = handler->getMethod(exec, callData, callType, makeIdentifier(vm, "construct"), ASCIILiteral("'construct' property of a Proxy's handler should be constructible."));
     370    if (exec->hadException())
     371        return JSValue::encode(jsUndefined());
     372    JSObject* target = proxy->target();
     373    if (constructMethod.isUndefined()) {
     374        ConstructData constructData;
     375        ConstructType constructType = target->methodTable(vm)->getConstructData(target, constructData);
     376        RELEASE_ASSERT(constructType != ConstructTypeNone);
     377        return JSValue::encode(construct(exec, target, constructType, constructData, ArgList(exec), exec->newTarget()));
     378    }
     379
     380    JSArray* argArray = constructArray(exec, static_cast<ArrayAllocationProfile*>(nullptr), ArgList(exec));
     381    if (exec->hadException())
     382        return JSValue::encode(jsUndefined());
     383    MarkedArgumentBuffer arguments;
     384    arguments.append(target);
     385    arguments.append(argArray);
     386    arguments.append(exec->newTarget());
     387    JSValue result = call(exec, constructMethod, callType, callData, handler, arguments);
     388    if (exec->hadException())
     389        return JSValue::encode(jsUndefined());
     390    if (!result.isObject())
     391        return throwVMTypeError(exec, ASCIILiteral("Result from Proxy handler's 'construct' method should be an object."));
     392    return JSValue::encode(result);
     393}
     394
     395ConstructType ProxyObject::getConstructData(JSCell* cell, ConstructData& constructData)
     396{
     397    ProxyObject* proxy = jsCast<ProxyObject*>(cell);
     398    if (!proxy->m_isConstructible) {
     399        constructData.js.functionExecutable = nullptr;
     400        constructData.js.scope = nullptr;
     401        return ConstructTypeNone;
     402    }
     403
     404    constructData.native.function = performProxyConstruct;
     405    return ConstructTypeHost;
     406}
     407
    354408} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.