⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 259800 in webkit


Ignore:
Timestamp:
Apr 9, 2020, 8:13:07 AM (6 years ago)
Author:
Alexey Shvayka
Message:

getOwnPropertyDescriptor() is incorrect with Proxy of exotic object
https://bugs.webkit.org/show_bug.cgi?id=200560

Reviewed by Yusuke Suzuki.

JSTests:

  • test262/expectations.yaml: Mark 14 test cases as passing.

Source/JavaScriptCore:

PropertyAttribute::CustomValue path in JSObject::getOwnPropertyDescriptor() needs to perform
getDirect() on correct target. A correct target may be different since getOwnPropertySlot()
may return not *own* property.

This change removes a hack that was covering only JSProxy case and invokes getDirect() on
slotBase(), ensuring ProxyObject instances with exotic targets return correct descriptors
and aligning JSC with V8 and SpiderMonkey.

getDirect() can be safely called on slotBase(): if getOwnPropertySlot() result is returned
from JS code of ProxyObject's trap, it will never be a PropertyAttribute::CustomValue.

This patch also moves setCustomDescriptor() down below to avoid mutating a descriptor when
returning false.

  • runtime/JSObject.cpp:

(JSC::JSObject::getOwnPropertyDescriptor):

LayoutTests:

  • js/getOwnPropertyDescriptor-host-object-proxy-expected.txt: Added.
  • js/getOwnPropertyDescriptor-host-object-proxy.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r259742 r259800  
     12020-04-09  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        getOwnPropertyDescriptor() is incorrect with Proxy of exotic object
     4        https://bugs.webkit.org/show_bug.cgi?id=200560
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * test262/expectations.yaml: Mark 14 test cases as passing.
     9
    1102020-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
    211
  • trunk/JSTests/test262/expectations.yaml

    r259668 r259800  
    673673  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
    674674  strict mode: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
    675 test/built-ins/Array/prototype/splice/create-proxy.js:
    676   default: 'TypeError: Attempted to assign to readonly property.'
    677   strict mode: 'TypeError: Attempted to assign to readonly property.'
    678675test/built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js:
    679676  default: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
     
    12561253  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
    12571254  strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
    1258 test/built-ins/Proxy/getOwnPropertyDescriptor/trap-is-missing-target-is-proxy.js:
    1259   default: "TypeError: undefined is not an object (evaluating 'originalDesc.enumerable')"
    1260   strict mode: "TypeError: undefined is not an object (evaluating 'originalDesc.enumerable')"
    1261 test/built-ins/Proxy/getOwnPropertyDescriptor/trap-is-null-target-is-proxy.js:
    1262   default: "TypeError: undefined is not an object (evaluating 'originalDesc.value')"
    1263   strict mode: "TypeError: undefined is not an object (evaluating 'originalDesc.value')"
    1264 test/built-ins/Proxy/getOwnPropertyDescriptor/trap-is-undefined-target-is-proxy.js:
    1265   default: "TypeError: undefined is not an object (evaluating 'originalDesc.value')"
    1266   strict mode: "TypeError: undefined is not an object (evaluating 'originalDesc.value')"
    12671255test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:
    12681256  default: 'Test262Error: Expected [length, foo, 0, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. '
     
    12741262  default: 'Test262Error: Expected [foo] and [foo, foo, foo] to have the same contents. getOwnPropertyDescriptor: key present on [[ProxyTarget]]'
    12751263  strict mode: 'TypeError: Attempted to assign to readonly property.'
    1276 test/built-ins/Proxy/set/trap-is-missing-target-is-proxy.js:
    1277   default: 'Test262Error: Expected SameValue(«0», «1») to be true'
    1278   strict mode: 'TypeError: Attempting to change configurable attribute of unconfigurable property.'
    1279 test/built-ins/Proxy/set/trap-is-null-target-is-proxy.js:
    1280   default: 'Test262Error: Expected [1, 2, 3] and [] to have the same contents. '
    1281   strict mode: 'TypeError: Attempting to change configurable attribute of unconfigurable property.'
    1282 test/built-ins/Proxy/set/trap-is-undefined-target-is-proxy.js:
    1283   default: 'Test262Error: Expected true but got false'
    1284   strict mode: 'Test262Error: Expected true but got false'
    12851264test/built-ins/Reflect/ownKeys/order-after-define-property.js:
    12861265  default: 'Test262Error: Expected [Symbol(b), Symbol(a)] and [Symbol(a), Symbol(b)] to have the same contents. '
  • trunk/LayoutTests/ChangeLog

    r259797 r259800  
     12020-04-09  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        getOwnPropertyDescriptor() is incorrect with Proxy of exotic object
     4        https://bugs.webkit.org/show_bug.cgi?id=200560
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * js/getOwnPropertyDescriptor-host-object-proxy-expected.txt: Added.
     9        * js/getOwnPropertyDescriptor-host-object-proxy.html: Added.
     10
    1112020-04-09  Diego Pino Garcia  <dpino@igalia.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r259792 r259800  
     12020-04-09  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        getOwnPropertyDescriptor() is incorrect with Proxy of exotic object
     4        https://bugs.webkit.org/show_bug.cgi?id=200560
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        PropertyAttribute::CustomValue path in JSObject::getOwnPropertyDescriptor() needs to perform
     9        getDirect() on correct target. A correct target may be different since getOwnPropertySlot()
     10        may return not *own* property.
     11
     12        This change removes a hack that was covering only JSProxy case and invokes getDirect() on
     13        slotBase(), ensuring ProxyObject instances with exotic targets return correct descriptors
     14        and aligning JSC with V8 and SpiderMonkey.
     15
     16        getDirect() can be safely called on slotBase(): if getOwnPropertySlot() result is returned
     17        from JS code of ProxyObject's trap, it will never be a PropertyAttribute::CustomValue.
     18
     19        This patch also moves setCustomDescriptor() down below to avoid mutating a descriptor when
     20        returning `false`.
     21
     22        * runtime/JSObject.cpp:
     23        (JSC::JSObject::getOwnPropertyDescriptor):
     24
    1252020-04-09  Angelos Oikonomopoulos  <angelos@igalia.com>
    226
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r259676 r259800  
    34803480    VM& vm = globalObject->vm();
    34813481    auto scope = DECLARE_THROW_SCOPE(vm);
    3482     JSC::PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
     3482    PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
    34833483
    34843484    bool result = methodTable(vm)->getOwnPropertySlot(this, globalObject, propertyName, slot);
     
    34873487        return false;
    34883488
    3489 
    3490     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=200560
    3491     // This breaks the assumption that getOwnPropertySlot should return "own" property.
    3492     // We should fix DebuggerScope, ProxyObject etc. to remove this.
    3493     //
    3494     // DebuggerScope::getOwnPropertySlot() (and possibly others) may return attributes from the prototype chain
    3495     // but getOwnPropertyDescriptor() should only work for 'own' properties so we exit early if we detect that
    3496     // the property is not an own property.
    3497     if (slot.slotBase() != this && slot.slotBase()) {
    3498         JSProxy* jsProxy = jsDynamicCast<JSProxy*>(vm, this);
    3499         if (!jsProxy || jsProxy->target() != slot.slotBase()) {
    3500             // Try ProxyObject.
    3501             ProxyObject* proxyObject = jsDynamicCast<ProxyObject*>(vm, this);
    3502             if (!proxyObject || proxyObject->target() != slot.slotBase())
    3503                 return false;
    3504         }
    3505     }
    3506 
    35073489    if (slot.isAccessor())
    35083490        descriptor.setAccessorDescriptor(slot.getterSetter(), slot.attributes());
    35093491    else if (slot.attributes() & PropertyAttribute::CustomAccessor) {
    3510         descriptor.setCustomDescriptor(slot.attributes());
    3511 
    3512         JSObject* thisObject = this;
    3513         if (auto* proxy = jsDynamicCast<JSProxy*>(vm, this))
    3514             thisObject = proxy->target();
    3515 
    35163492        CustomGetterSetter* getterSetter;
    35173493        if (slot.isCustomAccessor())
    35183494            getterSetter = slot.customGetterSetter();
    35193495        else {
     3496            ASSERT(slot.slotBase());
     3497            JSObject* thisObject = slot.slotBase();
     3498
    35203499            JSValue maybeGetterSetter = thisObject->getDirect(vm, propertyName);
    35213500            if (!maybeGetterSetter) {
     
    35313510            return false;
    35323511
     3512        descriptor.setCustomDescriptor(slot.attributes());
    35333513        if (getterSetter->getter())
    35343514            descriptor.setGetter(getCustomGetterSetterFunctionForGetterSetter(globalObject, propertyName, getterSetter, JSCustomGetterSetterFunction::Type::Getter));
Note: See TracChangeset for help on using the changeset viewer.