Ignore:
Timestamp:
Feb 18, 2016, 5:07:37 PM (10 years ago)
Author:
[email protected]
Message:

Implement Proxy.HasProperty
https://bugs.webkit.org/show_bug.cgi?id=154313

Reviewed by Filip Pizlo.

This patch is a straight forward implementation of
Proxy.HasProperty with respect to section 9.5.7
of the ECMAScript spec.
https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p

  • runtime/ProxyObject.cpp:

(JSC::ProxyObject::performInternalMethodGetOwnProperty):
(JSC::ProxyObject::performHasProperty):
(JSC::ProxyObject::getOwnPropertySlotCommon):

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

(assert):
(let.handler.has):

  • tests/stress/proxy-has-property.js: Added.

(assert):
(throw.new.Error.let.handler.get has):
(throw.new.Error):
(assert.let.handler.has):
(let.handler.has):
(getOwnPropertyDescriptor):
(i.catch):

File:
1 edited

Legend:

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

    r196785 r196789  
    211211}
    212212
     213bool ProxyObject::performHasProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
     214{
     215    VM& vm = exec->vm();
     216    slot.setValue(this, None, jsUndefined()); // Nobody should rely on our value, but be safe and protect against any bad actors reading our value.
     217   
     218    JSValue handlerValue = this->handler();
     219    if (handlerValue.isNull()) {
     220        throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object."));
     221        return false;
     222    }
     223
     224    JSObject* handler = jsCast<JSObject*>(handlerValue);
     225    CallData callData;
     226    CallType callType;
     227    JSValue hasMethod = handler->getMethod(exec, callData, callType, vm.propertyNames->has, ASCIILiteral("'has' property of a Proxy's handler should be callable."));
     228    if (exec->hadException())
     229        return false;
     230    JSObject* target = this->target();
     231    if (hasMethod.isUndefined())
     232        return target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot);
     233
     234    MarkedArgumentBuffer arguments;
     235    arguments.append(target);
     236    arguments.append(identifierToSafePublicJSValue(vm, Identifier::fromUid(&vm, propertyName.uid())));
     237    if (exec->hadException())
     238        return false;
     239    JSValue trapResult = call(exec, hasMethod, callType, callData, handler, arguments);
     240    if (exec->hadException())
     241        return false;
     242
     243    bool trapResultAsBool = trapResult.toBoolean(exec);
     244    if (exec->hadException())
     245        return false;
     246
     247    if (!trapResultAsBool) {
     248        PropertyDescriptor descriptor;
     249        bool isPropertyDescriptorDefined = target->getOwnPropertyDescriptor(exec, propertyName, descriptor);
     250        if (exec->hadException())
     251            return false;
     252        if (isPropertyDescriptorDefined) {
     253            if (!descriptor.configurable()) {
     254                throwVMTypeError(exec, ASCIILiteral("Proxy 'has' must return 'true' for non-configurable properties."));
     255                return false;
     256            }
     257            if (!target->isExtensible()) {
     258                throwVMTypeError(exec, ASCIILiteral("Proxy 'has' must return 'true' for a non-extensible 'target' object with a configurable property."));
     259                return false;
     260            }
     261        }
     262    }
     263
     264    return trapResultAsBool;
     265}
     266
    213267bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
    214268{
     269    slot.disableCaching();
    215270    switch (slot.internalMethodType()) {
    216271    case PropertySlot::InternalMethodType::Get:
    217272        slot.setCustom(this, CustomAccessor, performProxyGet);
    218         slot.disableCaching();
    219273        return true;
    220274    case PropertySlot::InternalMethodType::GetOwnProperty:
    221275        return performInternalMethodGetOwnProperty(exec, propertyName, slot);
     276    case PropertySlot::InternalMethodType::HasProperty:
     277        return performHasProperty(exec, propertyName, slot);
    222278    default:
    223         // FIXME: Implement Proxy.[[HasProperty]].
    224         // https://bugs.webkit.org/show_bug.cgi?id=154313
    225279        return false;
    226280    }
Note: See TracChangeset for help on using the changeset viewer.