| Differences between
and this patch
- JSTests/ChangeLog +9 lines
Lines 1-3 JSTests/ChangeLog_sec1
1
2020-04-08  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 NOBODY (OOPS!).
7
8
        * test262/expectations.yaml: Mark 14 test cases as passing.
9
1
2020-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
10
2020-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
2
11
3
        [JSC] MultiDeleteByOffset should tell correct result AbstractValue in AI
12
        [JSC] MultiDeleteByOffset should tell correct result AbstractValue in AI
- JSTests/test262/expectations.yaml -21 lines
Lines 672-680 test/built-ins/Array/prototype/splice/S1 JSTests/test262/expectations.yaml_sec1
672
test/built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js:
672
test/built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js:
673
  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
673
  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
674
  strict mode: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
674
  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.'
678
test/built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js:
675
test/built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js:
679
  default: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
676
  default: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
680
  strict mode: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
677
  strict mode: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
Lines 1255-1269 test/built-ins/Proxy/create-target-is-re JSTests/test262/expectations.yaml_sec2
1255
test/built-ins/Proxy/defineProperty/trap-is-undefined-target-is-proxy.js:
1252
test/built-ins/Proxy/defineProperty/trap-is-undefined-target-is-proxy.js:
1256
  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
1253
  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
1257
  strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
1254
  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')"
1267
test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:
1255
test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:
1268
  default: 'Test262Error: Expected [length, foo, 0, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. '
1256
  default: 'Test262Error: Expected [length, foo, 0, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. '
1269
  strict mode: 'Test262Error: Expected [length, foo, 0, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. '
1257
  strict mode: 'Test262Error: Expected [length, foo, 0, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. '
Lines 1273-1287 test/built-ins/Proxy/set/trap-is-missing JSTests/test262/expectations.yaml_sec3
1273
test/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls.js:
1261
test/built-ins/Proxy/set/trap-is-missing-receiver-multiple-calls.js:
1274
  default: 'Test262Error: Expected [foo] and [foo, foo, foo] to have the same contents. getOwnPropertyDescriptor: key present on [[ProxyTarget]]'
1262
  default: 'Test262Error: Expected [foo] and [foo, foo, foo] to have the same contents. getOwnPropertyDescriptor: key present on [[ProxyTarget]]'
1275
  strict mode: 'TypeError: Attempted to assign to readonly property.'
1263
  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'
1285
test/built-ins/Reflect/ownKeys/order-after-define-property.js:
1264
test/built-ins/Reflect/ownKeys/order-after-define-property.js:
1286
  default: 'Test262Error: Expected [Symbol(b), Symbol(a)] and [Symbol(a), Symbol(b)] to have the same contents. '
1265
  default: 'Test262Error: Expected [Symbol(b), Symbol(a)] and [Symbol(a), Symbol(b)] to have the same contents. '
1287
  strict mode: 'Test262Error: Expected [Symbol(b), Symbol(a)] and [Symbol(a), Symbol(b)] to have the same contents. '
1266
  strict mode: 'Test262Error: Expected [Symbol(b), Symbol(a)] and [Symbol(a), Symbol(b)] to have the same contents. '
- Source/JavaScriptCore/ChangeLog +24 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2020-04-08  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 NOBODY (OOPS!).
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
1
2020-04-07  Saam Barati  <sbarati@apple.com>
25
2020-04-07  Saam Barati  <sbarati@apple.com>
2
26
3
        Delete ICs can't cache dictionaries
27
        Delete ICs can't cache dictionaries
- Source/JavaScriptCore/runtime/JSObject.cpp -25 / +5 lines
Lines 3479-3522 bool JSObject::getOwnPropertyDescriptor( Source/JavaScriptCore/runtime/JSObject.cpp_sec1
3479
{
3479
{
3480
    VM& vm = globalObject->vm();
3480
    VM& vm = globalObject->vm();
3481
    auto scope = DECLARE_THROW_SCOPE(vm);
3481
    auto scope = DECLARE_THROW_SCOPE(vm);
3482
    JSC::PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
3482
    PropertySlot slot(this, PropertySlot::InternalMethodType::GetOwnProperty);
3483
3483
3484
    bool result = methodTable(vm)->getOwnPropertySlot(this, globalObject, propertyName, slot);
3484
    bool result = methodTable(vm)->getOwnPropertySlot(this, globalObject, propertyName, slot);
3485
    EXCEPTION_ASSERT(!scope.exception() || !result);
3485
    EXCEPTION_ASSERT(!scope.exception() || !result);
3486
    if (!result)
3486
    if (!result)
3487
        return false;
3487
        return false;
3488
3488
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
3507
    if (slot.isAccessor())
3489
    if (slot.isAccessor())
3508
        descriptor.setAccessorDescriptor(slot.getterSetter(), slot.attributes());
3490
        descriptor.setAccessorDescriptor(slot.getterSetter(), slot.attributes());
3509
    else if (slot.attributes() & PropertyAttribute::CustomAccessor) {
3491
    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
3516
        CustomGetterSetter* getterSetter;
3492
        CustomGetterSetter* getterSetter;
3517
        if (slot.isCustomAccessor())
3493
        if (slot.isCustomAccessor())
3518
            getterSetter = slot.customGetterSetter();
3494
            getterSetter = slot.customGetterSetter();
3519
        else {
3495
        else {
3496
            ASSERT(slot.slotBase());
3497
            JSObject* thisObject = slot.slotBase();
3498
3520
            JSValue maybeGetterSetter = thisObject->getDirect(vm, propertyName);
3499
            JSValue maybeGetterSetter = thisObject->getDirect(vm, propertyName);
3521
            if (!maybeGetterSetter) {
3500
            if (!maybeGetterSetter) {
3522
                thisObject->reifyAllStaticProperties(globalObject);
3501
                thisObject->reifyAllStaticProperties(globalObject);
Lines 3530-3535 bool JSObject::getOwnPropertyDescriptor( Source/JavaScriptCore/runtime/JSObject.cpp_sec2
3530
        if (!getterSetter)
3509
        if (!getterSetter)
3531
            return false;
3510
            return false;
3532
3511
3512
        descriptor.setCustomDescriptor(slot.attributes());
3533
        if (getterSetter->getter())
3513
        if (getterSetter->getter())
3534
            descriptor.setGetter(getCustomGetterSetterFunctionForGetterSetter(globalObject, propertyName, getterSetter, JSCustomGetterSetterFunction::Type::Getter));
3514
            descriptor.setGetter(getCustomGetterSetterFunctionForGetterSetter(globalObject, propertyName, getterSetter, JSCustomGetterSetterFunction::Type::Getter));
3535
        if (getterSetter->setter())
3515
        if (getterSetter->setter())
- LayoutTests/ChangeLog +10 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2020-04-08  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 NOBODY (OOPS!).
7
8
        * js/getOwnPropertyDescriptor-host-object-proxy-expected.txt: Added.
9
        * js/getOwnPropertyDescriptor-host-object-proxy.html: Added.
10
1
2020-04-07  Jacob Uphoff  <jacob_uphoff@apple.com>
11
2020-04-07  Jacob Uphoff  <jacob_uphoff@apple.com>
2
12
3
        [ iOS wk2 ] http/wpt/cache-storage/cache-put-keys.https.any.html is flaky failing.
13
        [ iOS wk2 ] http/wpt/cache-storage/cache-put-keys.https.any.html is flaky failing.
- LayoutTests/js/getOwnPropertyDescriptor-host-object-proxy-expected.txt +9 lines
Line 0 LayoutTests/js/getOwnPropertyDescriptor-host-object-proxy-expected.txt_sec1
1
2
PASS Window target, no trap, "name" attribute 
3
PASS Window target, forwarding trap, [Unforgeable] "document" attribute 
4
PASS Window proxy target, custom trap, "onclick" event handler attribute 
5
PASS Document target, forwarding trap, [Unforgeable] "location" attribute 
6
PASS Document proxy target, custom trap, non-existent value attribute 
7
PASS Location target, no trap, [Unforgeable] "hash" attribute 
8
PASS Location proxy target, forwarding trap, [Unforgeable] "reload" method 
9
- LayoutTests/js/getOwnPropertyDescriptor-host-object-proxy.html +92 lines
Line 0 LayoutTests/js/getOwnPropertyDescriptor-host-object-proxy.html_sec1
1
<!DOCTYPE html>
2
<html>
3
<head>
4
  <title>getOwnPropertyDescriptor() is correct for Proxy with host object target</title>
5
  <script src="../resources/testharness.js"></script>
6
  <script src="../resources/testharnessreport.js"></script>
7
</head>
8
<body>
9
<script>
10
'use strict';
11
12
test(() => {
13
  let windowProxy = new Proxy(window, {});
14
  name = 'old_name';
15
  let descriptor = Object.getOwnPropertyDescriptor(windowProxy, 'name');
16
17
  assert_equals(descriptor.get.call(window), 'old_name');
18
  descriptor.set.call(window, 'new_name');
19
  assert_equals(name, 'new_name');
20
  assert_true(descriptor.enumerable);
21
  assert_true(descriptor.configurable);
22
}, 'Window target, no trap, "name" attribute');
23
24
test(() => {
25
  let windowProxy = new Proxy(window, {});
26
27
  assert_object_equals(
28
    Object.getOwnPropertyDescriptor(windowProxy, 'document'),
29
    Object.getOwnPropertyDescriptor(window, 'document')
30
  );
31
}, 'Window target, forwarding trap, [Unforgeable] "document" attribute');
32
33
test(() => {
34
  let trapResult = {get() {}, set(_val) {}, enumerable: false, configurable: true};
35
  let windowProxy = new Proxy(new Proxy(window, {}), {
36
    getOwnPropertyDescriptor: () => trapResult,
37
  });
38
39
  assert_object_equals(
40
    Object.getOwnPropertyDescriptor(windowProxy, 'onclick'),
41
    trapResult
42
  );
43
}, 'Window proxy target, custom trap, "onclick" event handler attribute');
44
45
test(() => {
46
  let documentProxy = new Proxy(document, {
47
    getOwnPropertyDescriptor: Reflect.getOwnPropertyDescriptor,
48
  });
49
50
  assert_object_equals(
51
    Object.getOwnPropertyDescriptor(documentProxy, 'location'),
52
    Object.getOwnPropertyDescriptor(document, 'location')
53
  );
54
}, 'Document target, forwarding trap, [Unforgeable] "location" attribute');
55
56
test(() => {
57
  let trapResult = {value: 4, writable: false, enumerable: true, configurable: true};
58
  let documentProxy = new Proxy(new Proxy(document, {}), {
59
    getOwnPropertyDescriptor: () => trapResult,
60
  });
61
62
  assert_object_equals(
63
    Object.getOwnPropertyDescriptor(documentProxy, 'foo'),
64
    trapResult
65
  );
66
}, 'Document proxy target, custom trap, non-existent value attribute');
67
68
test(() => {
69
  let locationProxy = new Proxy(location, {});
70
  location.hash = '#old';
71
  let descriptor = Object.getOwnPropertyDescriptor(locationProxy, 'hash');
72
73
  assert_equals(descriptor.get.call(location), '#old');
74
  descriptor.set.call(location, '#new');
75
  assert_equals(location.hash, '#new');
76
  assert_true(descriptor.enumerable);
77
  assert_false(descriptor.configurable);
78
}, 'Location target, no trap, [Unforgeable] "hash" attribute');
79
80
test(() => {
81
  let locationProxy = new Proxy(new Proxy(location, {}), {
82
    getOwnPropertyDescriptor: Reflect.getOwnPropertyDescriptor,
83
  });
84
85
  assert_object_equals(
86
    Object.getOwnPropertyDescriptor(locationProxy, 'reload'),
87
    Object.getOwnPropertyDescriptor(location, 'reload')
88
  );
89
}, 'Location proxy target, forwarding trap, [Unforgeable] "reload" method');
90
</script>
91
</body>
92
</html>

Return to Bug 200560