Title: [197144] trunk/Source/_javascript_Core
Revision
197144
Author
sbar...@apple.com
Date
2016-02-25 16:15:58 -0800 (Thu, 25 Feb 2016)

Log Message

[ES6] for...in iteration doesn't comply with the specification
https://bugs.webkit.org/show_bug.cgi?id=154665

Reviewed by Michael Saboff.

If you read ForIn/OfHeadEvaluation inside the spec:
https://tc39.github.io/ecma262/#sec-runtime-semantics-forin-div-ofheadevaluation-tdznames-expr-iterationkind
It calls EnumerateObjectProperties(obj) to get a set of properties
to enumerate over (it models this "set" as en ES6 generator function).
EnumerateObjectProperties is defined in section 13.7.5.15:
https://tc39.github.io/ecma262/#sec-enumerate-object-properties
The implementation calls Reflect.getOwnPropertyDescriptor(.) on the
properties it sees. We must do the same by modeling the operation as
a [[GetOwnProperty]] instead of a [[HasProperty]] internal method call.

* jit/JITOperations.cpp:
* jit/JITOperations.h:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/JSObject.cpp:
(JSC::JSObject::hasProperty):
(JSC::JSObject::hasPropertyGeneric):
* runtime/JSObject.h:
* tests/stress/proxy-get-own-property.js:
(assert):
(let.handler.getOwnPropertyDescriptor):
(i.set assert):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (197143 => 197144)


--- trunk/Source/_javascript_Core/ChangeLog	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-02-26 00:15:58 UTC (rev 197144)
@@ -1,5 +1,35 @@
 2016-02-25  Saam barati  <sbar...@apple.com>
 
+        [ES6] for...in iteration doesn't comply with the specification
+        https://bugs.webkit.org/show_bug.cgi?id=154665
+
+        Reviewed by Michael Saboff.
+
+        If you read ForIn/OfHeadEvaluation inside the spec:
+        https://tc39.github.io/ecma262/#sec-runtime-semantics-forin-div-ofheadevaluation-tdznames-expr-iterationkind
+        It calls EnumerateObjectProperties(obj) to get a set of properties
+        to enumerate over (it models this "set" as en ES6 generator function).
+        EnumerateObjectProperties is defined in section 13.7.5.15:
+        https://tc39.github.io/ecma262/#sec-enumerate-object-properties
+        The implementation calls Reflect.getOwnPropertyDescriptor(.) on the
+        properties it sees. We must do the same by modeling the operation as
+        a [[GetOwnProperty]] instead of a [[HasProperty]] internal method call.
+
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::hasProperty):
+        (JSC::JSObject::hasPropertyGeneric):
+        * runtime/JSObject.h:
+        * tests/stress/proxy-get-own-property.js:
+        (assert):
+        (let.handler.getOwnPropertyDescriptor):
+        (i.set assert):
+
+2016-02-25  Saam barati  <sbar...@apple.com>
+
         [ES6] Implement Proxy.[[Set]]
         https://bugs.webkit.org/show_bug.cgi?id=154511
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (197143 => 197144)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-02-26 00:15:58 UTC (rev 197144)
@@ -958,13 +958,6 @@
 #endif
 }
 
-size_t JIT_OPERATION operationHasProperty(ExecState* exec, JSObject* base, JSString* property)
-{
-    int result = base->hasProperty(exec, property->toIdentifier(exec));
-    return result;
-}
-    
-
 EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
 {
     VM* vm = &exec->vm();
@@ -1705,7 +1698,7 @@
         // https://bugs.webkit.org/show_bug.cgi?id=149886
         byValInfo->arrayProfile->setOutOfBounds();
     }
-    return JSValue::encode(jsBoolean(object->hasProperty(exec, index)));
+    return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, index, PropertySlot::InternalMethodType::GetOwnProperty)));
 }
     
 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
@@ -1729,7 +1722,7 @@
         // https://bugs.webkit.org/show_bug.cgi?id=149886
         byValInfo->arrayProfile->setOutOfBounds();
     }
-    return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
+    return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
 }
     
 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
@@ -2049,7 +2042,7 @@
         return JSValue::encode(jsBoolean(false));
 
     JSObject* base = baseValue.toObject(exec);
-    return JSValue::encode(jsBoolean(base->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
+    return JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, asString(propertyName)->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
 }
 
 EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
@@ -2057,7 +2050,7 @@
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
-    return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
+    return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript, PropertySlot::InternalMethodType::GetOwnProperty)));
 }
     
 JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, JSCell* cell)

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (197143 => 197144)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2016-02-26 00:15:58 UTC (rev 197144)
@@ -297,7 +297,6 @@
 #else
 size_t JIT_OPERATION operationCompareStringEq(ExecState*, JSCell* left, JSCell* right) WTF_INTERNAL;
 #endif
-size_t JIT_OPERATION operationHasProperty(ExecState*, JSObject*, JSString*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(ExecState*, ArrayAllocationProfile*, const JSValue* values, int32_t size) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationNewArrayBufferWithProfile(ExecState*, ArrayAllocationProfile*, const JSValue* values, int32_t size) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState*, ArrayAllocationProfile*, EncodedJSValue size) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (197143 => 197144)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2016-02-26 00:15:58 UTC (rev 197144)
@@ -602,7 +602,7 @@
     JSValue property = OP(3).jsValue();
     pc[4].u.arrayProfile->observeStructure(base->structure(vm));
     ASSERT(property.isUInt32());
-    RETURN(jsBoolean(base->hasProperty(exec, property.asUInt32())));
+    RETURN(jsBoolean(base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
 }
 
 SLOW_PATH_DECL(slow_path_has_structure_property)
@@ -614,7 +614,7 @@
     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
     if (base->structure(vm)->id() == enumerator->cachedStructureID())
         RETURN(jsBoolean(true));
-    RETURN(jsBoolean(base->hasProperty(exec, asString(property.asCell())->toIdentifier(exec))));
+    RETURN(jsBoolean(base->hasPropertyGeneric(exec, asString(property.asCell())->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
 }
 
 SLOW_PATH_DECL(slow_path_has_generic_property)
@@ -624,10 +624,10 @@
     JSValue property = OP(3).jsValue();
     bool result;
     if (property.isString())
-        result = base->hasProperty(exec, asString(property.asCell())->toIdentifier(exec));
+        result = base->hasPropertyGeneric(exec, asString(property.asCell())->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty);
     else {
         ASSERT(property.isUInt32());
-        result = base->hasProperty(exec, property.asUInt32());
+        result = base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty);
     }
     RETURN(jsBoolean(result));
 }

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (197143 => 197144)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2016-02-26 00:15:58 UTC (rev 197144)
@@ -1280,16 +1280,26 @@
 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-hasproperty
 bool JSObject::hasProperty(ExecState* exec, PropertyName propertyName) const
 {
-    PropertySlot slot(this, PropertySlot::InternalMethodType::HasProperty);
-    return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+    return hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::HasProperty);
 }
 
 bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const
 {
-    PropertySlot slot(this, PropertySlot::InternalMethodType::HasProperty);
+    return hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::HasProperty);
+}
+
+bool JSObject::hasPropertyGeneric(ExecState* exec, PropertyName propertyName, PropertySlot::InternalMethodType internalMethodType) const
+{
+    PropertySlot slot(this, internalMethodType);
     return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
 }
 
+bool JSObject::hasPropertyGeneric(ExecState* exec, unsigned propertyName, PropertySlot::InternalMethodType internalMethodType) const
+{
+    PropertySlot slot(this, internalMethodType);
+    return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+}
+
 // ECMA 8.6.2.5
 bool JSObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
 {

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (197143 => 197144)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2016-02-26 00:15:58 UTC (rev 197144)
@@ -478,6 +478,8 @@
 
     JS_EXPORT_PRIVATE bool hasProperty(ExecState*, PropertyName) const;
     JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
+    bool hasPropertyGeneric(ExecState*, PropertyName, PropertySlot::InternalMethodType) const;
+    bool hasPropertyGeneric(ExecState*, unsigned propertyName, PropertySlot::InternalMethodType) const;
     bool hasOwnProperty(ExecState*, PropertyName) const;
     bool hasOwnProperty(ExecState*, unsigned) const;
 

Modified: trunk/Source/_javascript_Core/tests/stress/proxy-get-own-property.js (197143 => 197144)


--- trunk/Source/_javascript_Core/tests/stress/proxy-get-own-property.js	2016-02-25 23:59:21 UTC (rev 197143)
+++ trunk/Source/_javascript_Core/tests/stress/proxy-get-own-property.js	2016-02-26 00:15:58 UTC (rev 197144)
@@ -210,3 +210,56 @@
         assert(threw);
     }
 }
+
+
+
+Object.prototype.fooBarBaz = 20; // Make for-in go over the prototype chain to the top.
+
+{
+    let target = {};
+    let called = false;
+    let handler = {
+        getOwnPropertyDescriptor: function() {
+            called = true;
+            return undefined;
+        }
+    };
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i < 1000; i++) {
+        let set = new Set();
+        for (let p in proxy) {
+            set.add(p);
+        }
+        assert(set.has("fooBarBaz"));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {};
+    let called = false;
+    let handler = {
+        getOwnPropertyDescriptor: function() {
+            called = true;
+            return undefined;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    let proxyish = Object.create(proxy, {
+        x: {value: 20, enumerable: true},
+        y: {value: 20, enumerable: true}
+    });
+    for (let i = 0; i < 1000; i++) {
+        let set = new Set;
+        for (let p in proxyish) {
+            set.add(p);
+        }
+        assert(set.has("x"));
+        assert(set.has("y"));
+        assert(set.has("fooBarBaz"));
+        assert(called);
+        called = false;
+    }
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to