| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +42 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2016-02-17  Saam barati  <sbarati@apple.com>
2
3
        Implement Proxy.[[GetOwnProperty]]
4
        https://bugs.webkit.org/show_bug.cgi?id=154314
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        This patch implements Proxy.[[GetOwnProperty]].
9
        It's a straight forward implementation as described
10
        in section 9.5.5 of the specification:
11
        http://www.ecma-international.org/ecma-262/6.0/index.html#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p
12
13
        * runtime/FunctionPrototype.cpp:
14
        (JSC::functionProtoFuncBind):
15
        * runtime/JSObject.cpp:
16
        (JSC::validateAndApplyPropertyDescriptor):
17
        (JSC::JSObject::defineOwnNonIndexProperty):
18
        (JSC::JSObject::defineOwnProperty):
19
        (JSC::JSObject::getGenericPropertyNames):
20
        (JSC::JSObject::getMethod):
21
        * runtime/JSObject.h:
22
        (JSC::JSObject::butterflyAddress):
23
        (JSC::makeIdentifier):
24
        * runtime/ProxyObject.cpp:
25
        (JSC::performProxyGet):
26
        (JSC::ProxyObject::performInternalMethodGetOwnProperty):
27
        (JSC::ProxyObject::getOwnPropertySlotCommon):
28
        (JSC::ProxyObject::getOwnPropertySlot):
29
        (JSC::ProxyObject::getOwnPropertySlotByIndex):
30
        (JSC::ProxyObject::visitChildren):
31
        * runtime/ProxyObject.h:
32
        * tests/es6.yaml:
33
        * tests/stress/proxy-basic.js:
34
        (let.handler.get null):
35
        * tests/stress/proxy-get-own-property.js: Added.
36
        (assert):
37
        (throw.new.Error.let.handler.getOwnPropertyDescriptor):
38
        (throw.new.Error):
39
        (let.handler.getOwnPropertyDescriptor):
40
        (i.catch):
41
        (assert.let.handler.getOwnPropertyDescriptor):
42
1
2016-02-17  Benjamin Poulain  <bpoulain@apple.com>
43
2016-02-17  Benjamin Poulain  <bpoulain@apple.com>
2
44
3
        [JSC] ARM64: Support the immediate format used for bit operations in Air
45
        [JSC] ARM64: Support the immediate format used for bit operations in Air
- Source/JavaScriptCore/runtime/FunctionPrototype.cpp -5 / +10 lines
Lines 153-165 EncodedJSValue JSC_HOST_CALL functionPro Source/JavaScriptCore/runtime/FunctionPrototype.cpp_sec1
153
    // If the [[Class]] internal property of Target is "Function", then ...
153
    // If the [[Class]] internal property of Target is "Function", then ...
154
    // Else set the length own property of F to 0.
154
    // Else set the length own property of F to 0.
155
    unsigned length = 0;
155
    unsigned length = 0;
156
    if (targetObject->inherits(JSFunction::info())) {
156
    if (targetObject->hasOwnProperty(exec, exec->propertyNames().length)) {
157
        ASSERT(target.get(exec, exec->propertyNames().length).isNumber());
157
        if (exec->hadException())
158
            return JSValue::encode(jsUndefined());
159
158
        // a. Let L be the length property of Target minus the length of A.
160
        // a. Let L be the length property of Target minus the length of A.
159
        // b. Set the length own property of F to either 0 or L, whichever is larger.
161
        // b. Set the length own property of F to either 0 or L, whichever is larger.
160
        unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).asNumber();
162
        JSValue lengthValue = target.get(exec, exec->propertyNames().length);
161
        if (targetLength > numBoundArgs)
163
        if (lengthValue.isNumber()) {
162
            length = targetLength - numBoundArgs;
164
            unsigned targetLength = (unsigned)lengthValue.asNumber();
165
            if (targetLength > numBoundArgs)
166
                length = targetLength - numBoundArgs;
167
        }
163
    }
168
    }
164
169
165
    JSString* name = target.get(exec, exec->propertyNames().name).toString(exec);
170
    JSString* name = target.get(exec, exec->propertyNames().name).toString(exec);
- Source/JavaScriptCore/runtime/JSObject.cpp -25 / +80 lines
Lines 2646-2679 private: Source/JavaScriptCore/runtime/JSObject.cpp_sec1
2646
    VM& m_vm;
2646
    VM& m_vm;
2647
};
2647
};
2648
2648
2649
bool JSObject::defineOwnNonIndexProperty(ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
2649
2650
// 9.1.6.3 of the spec
2651
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-validateandapplypropertydescriptor
2652
bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, PropertyName propertyName, bool isExtensible,
2653
    const PropertyDescriptor& descriptor, bool isCurrentDefined, const PropertyDescriptor& current, bool throwException)
2650
{
2654
{
2651
    // Track on the globaldata that we're in define property.
2652
    // Currently DefineOwnProperty uses delete to remove properties when they are being replaced
2653
    // (particularly when changing attributes), however delete won't allow non-configurable (i.e.
2654
    // DontDelete) properties to be deleted. For now, we can use this flag to make this work.
2655
    DefineOwnPropertyScope scope(exec);
2656
    
2657
    // If we have a new property we can just put it on normally
2655
    // If we have a new property we can just put it on normally
2658
    PropertyDescriptor current;
2656
    // Step 2.
2659
    if (!getOwnPropertyDescriptor(exec, propertyName, current)) {
2657
    if (!isCurrentDefined) {
2660
        // unless extensions are prevented!
2658
        // unless extensions are prevented!
2661
        if (!isExtensible()) {
2659
        // Step 2.a
2660
        if (!isExtensible) {
2662
            if (throwException)
2661
            if (throwException)
2663
                exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible.")));
2662
                exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible.")));
2664
            return false;
2663
            return false;
2665
        }
2664
        }
2665
        if (!object)
2666
            return true;
2667
        // Step 2.c/d
2666
        PropertyDescriptor oldDescriptor;
2668
        PropertyDescriptor oldDescriptor;
2667
        oldDescriptor.setValue(jsUndefined());
2669
        oldDescriptor.setValue(jsUndefined());
2668
        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
2670
        // FIXME: spec says to always return true here.
2671
        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
2669
    }
2672
    }
2670
2673
    // Step 3.
2671
    if (descriptor.isEmpty())
2674
    if (descriptor.isEmpty())
2672
        return true;
2675
        return true;
2673
2676
    // Step 4.
2674
    if (current.equalTo(exec, descriptor))
2677
    if (current.equalTo(exec, descriptor))
2675
        return true;
2678
        return true;
2676
2679
2680
    // Step 5.
2677
    // Filter out invalid changes
2681
    // Filter out invalid changes
2678
    if (!current.configurable()) {
2682
    if (!current.configurable()) {
2679
        if (descriptor.configurable()) {
2683
        if (descriptor.configurable()) {
Lines 2687-2702 bool JSObject::defineOwnNonIndexProperty Source/JavaScriptCore/runtime/JSObject.cpp_sec2
2687
            return false;
2691
            return false;
2688
        }
2692
        }
2689
    }
2693
    }
2690
2694
    
2695
    // Step 6.
2691
    // A generic descriptor is simply changing the attributes of an existing property
2696
    // A generic descriptor is simply changing the attributes of an existing property
2692
    if (descriptor.isGenericDescriptor()) {
2697
    if (descriptor.isGenericDescriptor()) {
2693
        if (!current.attributesEqual(descriptor)) {
2698
        if (!current.attributesEqual(descriptor) && object) {
2694
            methodTable(exec->vm())->deleteProperty(this, exec, propertyName);
2699
            object->methodTable(exec->vm())->deleteProperty(object, exec, propertyName);
2695
            return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
2700
            return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
2696
        }
2701
        }
2697
        return true;
2702
        return true;
2698
    }
2703
    }
2699
2704
    
2705
    // Step 7.
2700
    // Changing between a normal property or an accessor property
2706
    // Changing between a normal property or an accessor property
2701
    if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
2707
    if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
2702
        if (!current.configurable()) {
2708
        if (!current.configurable()) {
Lines 2704-2713 bool JSObject::defineOwnNonIndexProperty Source/JavaScriptCore/runtime/JSObject.cpp_sec3
2704
                exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
2710
                exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
2705
            return false;
2711
            return false;
2706
        }
2712
        }
2707
        methodTable(exec->vm())->deleteProperty(this, exec, propertyName);
2713
2708
        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
2714
        if (!object)
2715
            return true;
2716
2717
        object->methodTable(exec->vm())->deleteProperty(object, exec, propertyName);
2718
        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
2709
    }
2719
    }
2710
2720
2721
    // Step 8.
2711
    // Changing the value and attributes of an existing property
2722
    // Changing the value and attributes of an existing property
2712
    if (descriptor.isDataDescriptor()) {
2723
    if (descriptor.isDataDescriptor()) {
2713
        if (!current.configurable()) {
2724
        if (!current.configurable()) {
Lines 2726-2735 bool JSObject::defineOwnNonIndexProperty Source/JavaScriptCore/runtime/JSObject.cpp_sec4
2726
        }
2737
        }
2727
        if (current.attributesEqual(descriptor) && !descriptor.value())
2738
        if (current.attributesEqual(descriptor) && !descriptor.value())
2728
            return true;
2739
            return true;
2729
        methodTable(exec->vm())->deleteProperty(this, exec, propertyName);
2740
        if (!object)
2730
        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
2741
            return true;
2742
        object->methodTable(exec->vm())->deleteProperty(object, exec, propertyName);
2743
        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
2731
    }
2744
    }
2732
2745
2746
    // Step 9.
2733
    // Changing the accessor functions of an existing accessor property
2747
    // Changing the accessor functions of an existing accessor property
2734
    ASSERT(descriptor.isAccessorDescriptor());
2748
    ASSERT(descriptor.isAccessorDescriptor());
2735
    if (!current.configurable()) {
2749
    if (!current.configurable()) {
Lines 2749-2755 bool JSObject::defineOwnNonIndexProperty Source/JavaScriptCore/runtime/JSObject.cpp_sec5
2749
            return false;
2763
            return false;
2750
        }
2764
        }
2751
    }
2765
    }
2752
    JSValue accessor = getDirect(exec->vm(), propertyName);
2766
2767
    // Step 10/11.
2768
    if (!object)
2769
        return true;
2770
    JSValue accessor = object->getDirect(exec->vm(), propertyName);
2753
    if (!accessor)
2771
    if (!accessor)
2754
        return false;
2772
        return false;
2755
    GetterSetter* getterSetter;
2773
    GetterSetter* getterSetter;
Lines 2770-2781 bool JSObject::defineOwnNonIndexProperty Source/JavaScriptCore/runtime/JSObject.cpp_sec6
2770
    }
2788
    }
2771
    if (current.attributesEqual(descriptor) && !getterSetterChanged)
2789
    if (current.attributesEqual(descriptor) && !getterSetterChanged)
2772
        return true;
2790
        return true;
2773
    methodTable(exec->vm())->deleteProperty(this, exec, propertyName);
2791
    object->methodTable(exec->vm())->deleteProperty(object, exec, propertyName);
2774
    unsigned attrs = descriptor.attributesOverridingCurrent(current);
2792
    unsigned attrs = descriptor.attributesOverridingCurrent(current);
2775
    putDirectAccessor(exec, propertyName, getterSetter, attrs | Accessor);
2793
    object->putDirectAccessor(exec, propertyName, getterSetter, attrs | Accessor);
2776
    return true;
2794
    return true;
2777
}
2795
}
2778
2796
2797
bool JSObject::defineOwnNonIndexProperty(ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
2798
{
2799
    // Track on the globaldata that we're in define property.
2800
    // Currently DefineOwnProperty uses delete to remove properties when they are being replaced
2801
    // (particularly when changing attributes), however delete won't allow non-configurable (i.e.
2802
    // DontDelete) properties to be deleted. For now, we can use this flag to make this work.
2803
    DefineOwnPropertyScope scope(exec);
2804
    PropertyDescriptor current;
2805
    bool isCurrentDefined = getOwnPropertyDescriptor(exec, propertyName, current);
2806
    return validateAndApplyPropertyDescriptor(exec, this, propertyName, isExtensible(), descriptor, isCurrentDefined, current, throwException);
2807
}
2808
2779
bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
2809
bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
2780
{
2810
{
2781
    // If it's an array index, then use the indexed property storage.
2811
    // If it's an array index, then use the indexed property storage.
Lines 2895-2898 void JSObject::getGenericPropertyNames(J Source/JavaScriptCore/runtime/JSObject.cpp_sec7
2895
    }
2925
    }
2896
}
2926
}
2897
2927
2928
// Implements GetMethod(O, P) in section 7.3.9 of the spec.
2929
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-getmethod
2930
JSValue JSObject::getMethod(ExecState* exec, CallData& callData, CallType& callType, const Identifier& ident, const String& errorMessage)
2931
{
2932
    JSValue method = get(exec, ident);
2933
    if (exec->hadException())
2934
        return jsUndefined();
2935
2936
    if (method.isUndefined() || method.isNull())
2937
        return jsUndefined();
2938
2939
    if (!method.isCell()) {
2940
        throwVMTypeError(exec, errorMessage);
2941
        return jsUndefined();
2942
    }
2943
2944
    callType = method.asCell()->methodTable()->getCallData(method.asCell(), callData);
2945
    if (callType == CallTypeNone) {
2946
        throwVMTypeError(exec, errorMessage);
2947
        return jsUndefined();
2948
    }
2949
2950
    return method;
2951
}
2952
2898
} // namespace JSC
2953
} // namespace JSC
- Source/JavaScriptCore/runtime/JSObject.h +5 lines
Lines 717-722 public: Source/JavaScriptCore/runtime/JSObject.h_sec1
717
        return &m_butterfly;
717
        return &m_butterfly;
718
    }
718
    }
719
719
720
    JSValue getMethod(ExecState* exec, CallData& callData, CallType& callType, const Identifier& ident, const String& errorMessage);
721
720
    DECLARE_EXPORT_INFO;
722
    DECLARE_EXPORT_INFO;
721
723
722
protected:
724
protected:
Lines 1471-1476 ALWAYS_INLINE Identifier makeIdentifier( Source/JavaScriptCore/runtime/JSObject.h_sec2
1471
    return name;
1473
    return name;
1472
}
1474
}
1473
1475
1476
bool validateAndApplyPropertyDescriptor(ExecState*, JSObject*, PropertyName, bool isExtensible,
1477
    const PropertyDescriptor& descriptor, bool isCurrentDefined, const PropertyDescriptor& current, bool throwException);
1478
1474
// Helper for defining native functions, if you're not using a static hash table.
1479
// Helper for defining native functions, if you're not using a static hash table.
1475
// Use this macro from within finishCreation() methods in prototypes. This assumes
1480
// Use this macro from within finishCreation() methods in prototypes. This assumes
1476
// you've defined variables called exec, globalObject, and vm, and they
1481
// you've defined variables called exec, globalObject, and vm, and they
- Source/JavaScriptCore/runtime/ProxyObject.cpp -23 / +106 lines
Lines 27-34 Source/JavaScriptCore/runtime/ProxyObject.cpp_sec1
27
#include "ProxyObject.h"
27
#include "ProxyObject.h"
28
28
29
#include "Error.h"
29
#include "Error.h"
30
#include "IdentifierInlines.h"
30
#include "JSCJSValueInlines.h"
31
#include "JSCJSValueInlines.h"
31
#include "JSCellInlines.h"
32
#include "JSCellInlines.h"
33
#include "ObjectConstructor.h"
32
#include "SlotVisitorInlines.h"
34
#include "SlotVisitorInlines.h"
33
#include "StructureInlines.h"
35
#include "StructureInlines.h"
34
36
Lines 90-114 static EncodedJSValue performProxyGet(Ex Source/JavaScriptCore/runtime/ProxyObject.cpp_sec2
90
        return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object."));
92
        return throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object."));
91
93
92
    JSObject* handler = jsCast<JSObject*>(handlerValue);
94
    JSObject* handler = jsCast<JSObject*>(handlerValue);
93
    JSObject* target = proxyObject->target();
95
    CallData callData;
94
    JSValue getHandler = handler->get(exec, vm.propertyNames->get);
96
    CallType callType;
97
    JSValue getHandler = handler->getMethod(exec, callData, callType, vm.propertyNames->get, ASCIILiteral("'get' property of a Proxy's handler object should be callable."));
95
    if (exec->hadException())
98
    if (exec->hadException())
96
        return JSValue::encode(jsUndefined());
99
        return JSValue::encode(jsUndefined());
97
100
101
    JSObject* target = proxyObject->target();
98
    if (getHandler.isUndefined())
102
    if (getHandler.isUndefined())
99
        return JSValue::encode(target->get(exec, propertyName));
103
        return JSValue::encode(target->get(exec, propertyName));
100
104
101
    if (!getHandler.isCell())
102
        return throwVMTypeError(exec, ASCIILiteral("'get' property of Proxy's handler should be callable."));
103
104
    CallData callData;
105
    CallType callType = getHandler.asCell()->methodTable()->getCallData(getHandler.asCell(), callData);
106
    if (callType == CallTypeNone)
107
        return throwVMTypeError(exec, ASCIILiteral("'get' property of Proxy's handler should be callable."));
108
109
    MarkedArgumentBuffer arguments;
105
    MarkedArgumentBuffer arguments;
110
    arguments.append(target);
106
    arguments.append(target);
111
    arguments.append(jsString(exec, propertyName.uid()));
107
    arguments.append(jsString(exec, propertyName.uid()));
108
    if (exec->hadException())
109
        return JSValue::encode(jsUndefined());
112
    arguments.append(thisObject);
110
    arguments.append(thisObject);
113
    JSValue trapResult = call(exec, getHandler, callType, callData, handler, arguments);
111
    JSValue trapResult = call(exec, getHandler, callType, callData, handler, arguments);
114
    if (exec->hadException())
112
    if (exec->hadException())
Lines 125-163 static EncodedJSValue performProxyGet(Ex Source/JavaScriptCore/runtime/ProxyObject.cpp_sec3
125
        }
123
        }
126
    }
124
    }
127
125
128
    // FIXME: when implementing Proxy.[[GetOwnProperty]] it would be a good test to
129
    // have handler be another Proxy where its handler throws on [[GetOwnProperty]]
130
    // right here.
131
    // https://bugs.webkit.org/show_bug.cgi?id=154314
132
    if (exec->hadException())
126
    if (exec->hadException())
133
        return JSValue::encode(jsUndefined());
127
        return JSValue::encode(jsUndefined());
134
128
135
    return JSValue::encode(trapResult);
129
    return JSValue::encode(trapResult);
136
}
130
}
137
131
138
bool ProxyObject::getOwnPropertySlotCommon(ExecState*, PropertySlot& slot)
132
bool ProxyObject::performInternalMethodGetOwnProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
133
{
134
    VM& vm = exec->vm();
135
    slot.setValue(this, None, jsUndefined()); // We do this to protect against any bad actors. Nobody should depend on this value.
136
    JSValue handlerValue = this->handler();
137
    if (handlerValue.isNull()) {
138
        throwVMTypeError(exec, ASCIILiteral("Proxy 'handler' is null. It should be an Object."));
139
        return false;
140
    }
141
142
    JSObject* handler = jsCast<JSObject*>(handlerValue);
143
    CallData callData;
144
    CallType callType;
145
    JSValue getOwnPropertyDescriptorMethod = handler->getMethod(exec, callData, callType, makeIdentifier(vm, "getOwnPropertyDescriptor"), ASCIILiteral("'getOwnPropertyDescriptor' property of a Proxy's handler should be callable."));
146
    JSObject* target = this->target();
147
    if (getOwnPropertyDescriptorMethod.isUndefined())
148
        return target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot);
149
150
    MarkedArgumentBuffer arguments;
151
    arguments.append(target);
152
    arguments.append(jsString(exec, propertyName.uid()));
153
    if (exec->hadException())
154
        return false;
155
    JSValue trapResult = call(exec, getOwnPropertyDescriptorMethod, callType, callData, handler, arguments);
156
    if (exec->hadException())
157
        return false;
158
159
    if (!trapResult.isUndefined() && !trapResult.isObject()) {
160
        throwVMTypeError(exec, ASCIILiteral("result of 'getOwnPropertyDescriptor' call should either be an Object or undefined."));
161
        return false;
162
    }
163
164
    PropertyDescriptor targetPropertyDescriptor;
165
    bool isTargetPropertyDescriptorDefined = target->getOwnPropertyDescriptor(exec, propertyName, targetPropertyDescriptor);
166
    if (exec->hadException())
167
        return false;
168
169
    if (trapResult.isUndefined()) {
170
        if (!isTargetPropertyDescriptorDefined)
171
            return false;
172
        if (!targetPropertyDescriptor.configurable()) {
173
            throwVMTypeError(exec, ASCIILiteral("When the result of 'getOwnPropertyDescriptor' is undefined the target must be configurable."));
174
            return false;
175
        }
176
        // FIXME: this doesn't work if 'target' is another Proxy. We don't have isExtensible implemented in a way that fits w/ Proxys.
177
        // https://bugs.webkit.org/show_bug.cgi?id=154375
178
        if (!target->isExtensible()) {
179
            // FIXME: Come up with a test for this error. I'm not sure how to because
180
            // Object.seal(o) will make all fields [[Configurable]] false.
181
            // https://bugs.webkit.org/show_bug.cgi?id=154376
182
            throwVMTypeError(exec, ASCIILiteral("When 'getOwnPropertyDescriptor' returns undefined, the 'target' of a Proxy should be extensible."));
183
            return false;
184
        }
185
186
        return false;
187
    }
188
189
    PropertyDescriptor trapResultAsDescriptor;
190
    toPropertyDescriptor(exec, trapResult, trapResultAsDescriptor);
191
    if (exec->hadException())
192
        return false;
193
    // FIXME: implement step 14. CompletePropertyDescriptor(trapResultAsDescriptor) in the spec. Maybe this is already done?
194
    bool throwException = false;
195
    bool valid = validateAndApplyPropertyDescriptor(exec, nullptr, propertyName, target->isExtensible(),
196
        trapResultAsDescriptor, isTargetPropertyDescriptorDefined, targetPropertyDescriptor, throwException);
197
    if (!valid) {
198
        throwVMTypeError(exec, ASCIILiteral("Result from 'getOwnPropertyDescriptor' fails the IsCompatiblePropertyDescriptor test."));
199
        return false;
200
    }
201
202
    if (!trapResultAsDescriptor.configurable()) {
203
        if (!isTargetPropertyDescriptorDefined || targetPropertyDescriptor.configurable()) {
204
            throwVMTypeError(exec, ASCIILiteral("Result from 'getOwnPropertyDescriptor' can't be non-configurable when the 'target' doesn't have it as an own property or if it is a configurable own property on 'target'."));
205
            return false;
206
        }
207
    }
208
209
    return true;
210
}
211
212
bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
139
{
213
{
140
    if (slot.internalMethodType() == PropertySlot::InternalMethodType::Get) {
214
    switch (slot.internalMethodType()) {
215
    case PropertySlot::InternalMethodType::Get:
141
        slot.setCustom(this, CustomAccessor, performProxyGet);
216
        slot.setCustom(this, CustomAccessor, performProxyGet);
142
        slot.disableCaching();
217
        slot.disableCaching();
143
        return true;
218
        return true;
219
    case PropertySlot::InternalMethodType::GetOwnProperty:
220
        return performInternalMethodGetOwnProperty(exec, propertyName, slot);
221
    default:
222
        // FIXME: Implement Proxy.[[HasProperty]].
223
        // https://bugs.webkit.org/show_bug.cgi?id=154313
224
        return false;
144
    }
225
    }
145
226
146
    // FIXME: Implement Proxy.[[HasProperty]] and Proxy.[[GetOwnProperty]]
227
    RELEASE_ASSERT_NOT_REACHED();
147
    // https://bugs.webkit.org/show_bug.cgi?id=154313
148
    // https://bugs.webkit.org/show_bug.cgi?id=154314
149
    return false;
228
    return false;
150
}
229
}
151
bool ProxyObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName, PropertySlot& slot)
230
231
bool ProxyObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
152
{
232
{
153
    ProxyObject* thisObject = jsCast<ProxyObject*>(object);
233
    ProxyObject* thisObject = jsCast<ProxyObject*>(object);
154
    return thisObject->getOwnPropertySlotCommon(exec, slot);
234
    return thisObject->getOwnPropertySlotCommon(exec, propertyName, slot);
155
}
235
}
156
236
157
bool ProxyObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned, PropertySlot& slot)
237
bool ProxyObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot)
158
{
238
{
159
    ProxyObject* thisObject = jsCast<ProxyObject*>(object);
239
    ProxyObject* thisObject = jsCast<ProxyObject*>(object);
160
    return thisObject->getOwnPropertySlotCommon(exec, slot);
240
    Identifier ident = Identifier::from(exec, propertyName); 
241
    if (exec->hadException())
242
        return false;
243
    return thisObject->getOwnPropertySlotCommon(exec, ident.impl(), slot);
161
}
244
}
162
245
163
void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
246
void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
- Source/JavaScriptCore/runtime/ProxyObject.h -1 / +2 lines
Lines 63-69 private: Source/JavaScriptCore/runtime/ProxyObject.h_sec1
63
    static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
63
    static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
64
    static void visitChildren(JSCell*, SlotVisitor&);
64
    static void visitChildren(JSCell*, SlotVisitor&);
65
65
66
    bool getOwnPropertySlotCommon(ExecState*, PropertySlot&);
66
    bool getOwnPropertySlotCommon(ExecState*, PropertyName, PropertySlot&);
67
    bool performInternalMethodGetOwnProperty(ExecState*, PropertyName, PropertySlot&);
67
68
68
    WriteBarrier<JSObject> m_target;
69
    WriteBarrier<JSObject> m_target;
69
    WriteBarrier<Unknown> m_handler;
70
    WriteBarrier<Unknown> m_handler;
- Source/JavaScriptCore/tests/es6.yaml -1 / +1 lines
Lines 1025-1031 Source/JavaScriptCore/tests/es6.yaml_sec1
1025
- path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.assign.js
1025
- path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.assign.js
1026
  cmd: runES6 :fail
1026
  cmd: runES6 :fail
1027
- path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.prototype.hasOwnProperty.js
1027
- path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.prototype.hasOwnProperty.js
1028
  cmd: runES6 :fail
1028
  cmd: runES6 :normal
1029
- path: es6/Proxy_internal_ownKeys_calls_SerializeJSONObject.js
1029
- path: es6/Proxy_internal_ownKeys_calls_SerializeJSONObject.js
1030
  cmd: runES6 :fail
1030
  cmd: runES6 :fail
1031
- path: es6/Proxy_internal_ownKeys_calls_SetIntegrityLevel.js
1031
- path: es6/Proxy_internal_ownKeys_calls_SetIntegrityLevel.js
- Source/JavaScriptCore/tests/stress/proxy-basic.js -3 / +27 lines
Lines 63-71 assert(Proxy.prototype === undefined); Source/JavaScriptCore/tests/stress/proxy-basic.js_sec1
63
                proxy["foo"];
63
                proxy["foo"];
64
        } catch(e) {
64
        } catch(e) {
65
            threw = true;
65
            threw = true;
66
            assert(e.toString() === "TypeError: 'get' property of Proxy's handler should be callable.");
67
        }
66
        }
68
        assert(threw);
67
        assert(!threw);
69
    }
68
    }
70
}
69
}
71
70
Lines 82-88 assert(Proxy.prototype === undefined); Source/JavaScriptCore/tests/stress/proxy-basic.js_sec2
82
                proxy["foo"];
81
                proxy["foo"];
83
        } catch(e) {
82
        } catch(e) {
84
            threw = true;
83
            threw = true;
85
            assert(e.toString() === "TypeError: 'get' property of Proxy's handler should be callable.");
84
            assert(e.toString() === "TypeError: 'get' property of a Proxy's handler object should be callable.");
86
        }
85
        }
87
        assert(threw);
86
        assert(threw);
88
    }
87
    }
Lines 185-187 assert(Proxy.prototype === undefined); Source/JavaScriptCore/tests/stress/proxy-basic.js_sec3
185
        assert(proxy.x === 40);
184
        assert(proxy.x === 40);
186
    }
185
    }
187
}
186
}
187
188
{
189
    let error = null;
190
    let theTarget = new Proxy({}, {
191
        getOwnPropertyDescriptor: function(theTarget, propName) {
192
            error = new Error("hello!")
193
            throw error;
194
        }
195
    });
196
197
    let handler = {
198
        get: function(target, propName, proxyArg) {
199
            return 30;
200
        }
201
    };
202
203
    let proxy = new Proxy(theTarget, handler);
204
    for (let i = 0; i < 500; i++) {
205
        try {
206
            proxy.x;
207
        } catch(e) {
208
            assert(e === error);
209
        }
210
    }
211
}
- Source/JavaScriptCore/tests/stress/proxy-get-own-property.js +188 lines
Line 0 Source/JavaScriptCore/tests/stress/proxy-get-own-property.js_sec1
1
function assert(b) {
2
    if (!b)
3
        throw new Error("bad assertion.");
4
}
5
6
{
7
    let target = {x: 20};
8
    let called = false;
9
    let handler = {
10
        getOwnPropertyDescriptor: function(theTarget, propName) {
11
            called = true;
12
            assert(theTarget === target);
13
            assert(propName === "x");
14
            return undefined;
15
        }
16
    };
17
    let proxy = new Proxy(target, handler);
18
    for (let i = 0; i < 500; i++) {
19
        assert(Object.getOwnPropertyDescriptor(proxy, "x") === undefined);
20
        assert(called);
21
        called = false;
22
    }
23
}
24
25
{
26
    let target = {};
27
    let handler = {
28
        getOwnPropertyDescriptor: function(theTarget, propName) {
29
            return 25;
30
        }
31
    };
32
    let proxy = new Proxy(target, handler);
33
    for (let i = 0; i < 500; i++) {
34
        let threw = false;
35
        try {
36
            Object.getOwnPropertyDescriptor(proxy, "x");
37
        } catch(e) {
38
            assert(e.toString() === "TypeError: result of 'getOwnPropertyDescriptor' call should either be an Object or undefined.");
39
            threw = true;
40
        }
41
        assert(threw);
42
    }
43
}
44
45
{
46
    let target = {};
47
    Object.defineProperty(target, "x", {
48
        enumerable: true,
49
        configurable: false
50
    });
51
    let handler = {
52
        getOwnPropertyDescriptor: function(theTarget, propName) {
53
            assert(theTarget === target);
54
            assert(propName === "x");
55
            return undefined;
56
        }
57
    };
58
    let proxy = new Proxy(target, handler);
59
    for (let i = 0; i < 500; i++) {
60
        let threw = false;
61
        try {
62
            Object.getOwnPropertyDescriptor(proxy, "x");
63
        } catch(e) {
64
            assert(e.toString() === "TypeError: When the result of 'getOwnPropertyDescriptor' is undefined the target must be configurable.");
65
            threw = true;
66
        }
67
        assert(threw);
68
    }
69
}
70
71
{
72
    let target = {};
73
    Object.defineProperty(target, "x", {
74
        enumerable: true,
75
        configurable: true
76
    });
77
    let handler = {
78
        getOwnPropertyDescriptor: function(theTarget, propName) {
79
            assert(theTarget === target);
80
            assert(propName === "x");
81
            return {configurable: false};
82
        }
83
    };
84
    let proxy = new Proxy(target, handler);
85
    for (let i = 0; i < 500; i++) {
86
        let threw = false;
87
        try {
88
            Object.getOwnPropertyDescriptor(proxy, "x");
89
        } catch(e) {
90
            assert(e.toString() === "TypeError: Result from 'getOwnPropertyDescriptor' can't be non-configurable when the 'target' doesn't have it as an own property or if it is a configurable own property on 'target'.");
91
            threw = true;
92
        }
93
        assert(threw);
94
    }
95
}
96
97
{
98
    let target = {};
99
    Object.defineProperty(target, "x", {
100
        enumerable: false,
101
        configurable: false
102
    });
103
    let handler = {
104
        getOwnPropertyDescriptor: function(theTarget, propName) {
105
            assert(theTarget === target);
106
            assert(propName === "x");
107
            return {enumerable: true};
108
        }
109
    };
110
    let proxy = new Proxy(target, handler);
111
    for (let i = 0; i < 500; i++) {
112
        let threw = false;
113
        try {
114
            Object.getOwnPropertyDescriptor(proxy, "x");
115
        } catch(e) {
116
            assert(e.toString() === "TypeError: Result from 'getOwnPropertyDescriptor' fails the IsCompatiblePropertyDescriptor test.");
117
            threw = true;
118
        }
119
        assert(threw);
120
    }
121
}
122
123
{
124
    let target = {};
125
    let handler = {
126
        getOwnPropertyDescriptor: 45
127
    };
128
    let proxy = new Proxy(target, handler);
129
    for (let i = 0; i < 500; i++) {
130
        let threw = false;
131
        try {
132
            Object.getOwnPropertyDescriptor(proxy, "x");
133
        } catch(e) {
134
            assert(e.toString() === "TypeError: 'getOwnPropertyDescriptor' property of a Proxy's handler should be callable.");
135
            threw = true;
136
        }
137
        assert(threw);
138
    }
139
}
140
141
{
142
    let target = {};
143
    let handler = {
144
        getOwnPropertyDescriptor: null
145
    };
146
    Object.defineProperty(target, "x", {
147
        enumerable: true,
148
        configurable: false
149
    });
150
    let proxy = new Proxy(target, handler);
151
    for (let i = 0; i < 500; i++) {
152
        let pDesc = Object.getOwnPropertyDescriptor(proxy, "x");
153
        assert(pDesc.configurable === false);
154
        assert(pDesc.enumerable === true);
155
    }
156
}
157
158
{
159
    let target = {};
160
    let handler = {
161
        getOwnPropertyDescriptor: undefined
162
    };
163
    Object.defineProperty(target, "x", {
164
        enumerable: true,
165
        configurable: false
166
    });
167
    let proxy = new Proxy(target, handler);
168
    for (let i = 0; i < 500; i++) {
169
        let pDesc = Object.getOwnPropertyDescriptor(proxy, "x");
170
        assert(pDesc.configurable === false);
171
        assert(pDesc.enumerable === true);
172
    }
173
}
174
175
{
176
    let target = {};
177
    let handler = { };
178
    Object.defineProperty(target, "x", {
179
        enumerable: true,
180
        configurable: false
181
    });
182
    let proxy = new Proxy(target, handler);
183
    for (let i = 0; i < 500; i++) {
184
        let pDesc = Object.getOwnPropertyDescriptor(proxy, "x");
185
        assert(pDesc.configurable === false);
186
        assert(pDesc.enumerable === true);
187
    }
188
}

Return to Bug 154314