Title: [198052] trunk/Source/_javascript_Core
Revision
198052
Author
[email protected]
Date
2016-03-11 15:48:46 -0800 (Fri, 11 Mar 2016)

Log Message

[ES6] Make Object.assign spec compliant
https://bugs.webkit.org/show_bug.cgi?id=155375

Reviewed by Michael Saboff.

This is a straight forward implementation of Object.assign
in the spec.
https://tc39.github.io/ecma262/#sec-object.assign
Before, weren't performing all of the specified operations.
Now, we are.

* builtins/ObjectConstructor.js:
(assign):
* runtime/CommonIdentifiers.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* tests/es6.yaml:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (198051 => 198052)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-11 23:24:00 UTC (rev 198051)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-11 23:48:46 UTC (rev 198052)
@@ -1,3 +1,23 @@
+2016-03-11  Saam barati  <[email protected]>
+
+        [ES6] Make Object.assign spec compliant
+        https://bugs.webkit.org/show_bug.cgi?id=155375
+
+        Reviewed by Michael Saboff.
+
+        This is a straight forward implementation of Object.assign
+        in the spec.
+        https://tc39.github.io/ecma262/#sec-object.assign
+        Before, weren't performing all of the specified operations.
+        Now, we are.
+
+        * builtins/ObjectConstructor.js:
+        (assign):
+        * runtime/CommonIdentifiers.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * tests/es6.yaml:
+
 2016-03-11  Mark Lam  <[email protected]>
 
         Implement Function.name and Function#toString for ES6 class.

Modified: trunk/Source/_javascript_Core/builtins/ObjectConstructor.js (198051 => 198052)


--- trunk/Source/_javascript_Core/builtins/ObjectConstructor.js	2016-03-11 23:24:00 UTC (rev 198051)
+++ trunk/Source/_javascript_Core/builtins/ObjectConstructor.js	2016-03-11 23:48:46 UTC (rev 198052)
@@ -30,15 +30,17 @@
     if (target == null)
         throw new @TypeError("can't convert " + target + " to object");
 
-    var objTarget = @Object(target);
-    for (var s = 1, argumentsLength = arguments.length; s < argumentsLength; ++s) {
-        var nextSource = arguments[s];
+    let objTarget = @Object(target);
+    for (let s = 1, argumentsLength = arguments.length; s < argumentsLength; ++s) {
+        let nextSource = arguments[s];
         if (nextSource != null) {
-            var from = @Object(nextSource);
-            var keys = @ownEnumerablePropertyKeys(from);
-            for (var i = 0, keysLength = keys.length; i < keysLength; ++i) {
-                var nextKey = keys[i];
-                objTarget[nextKey] = from[nextKey];
+            let from = @Object(nextSource);
+            let keys = @Reflect.ownKeys(from);
+            for (let i = 0, keysLength = keys.length; i < keysLength; ++i) {
+                let nextKey = keys[i];
+                let descriptor = @Reflect.getOwnPropertyDescriptor(from, nextKey);
+                if (descriptor !== @undefined && descriptor.enumerable)
+                    objTarget[nextKey] = from[nextKey];
             }
         }
     }

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (198051 => 198052)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2016-03-11 23:24:00 UTC (rev 198051)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2016-03-11 23:48:46 UTC (rev 198052)
@@ -311,6 +311,7 @@
     macro(RegExp) \
     macro(Map) \
     macro(Promise) \
+    macro(Reflect) \
     macro(InternalPromise) \
     macro(abs) \
     macro(floor) \

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (198051 => 198052)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-03-11 23:24:00 UTC (rev 198051)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-03-11 23:48:46 UTC (rev 198052)
@@ -486,7 +486,8 @@
 #endif // ENABLE(INTL)
     putDirectWithoutTransition(vm, vm.propertyNames->JSON, JSONObject::create(vm, JSONObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum);
     putDirectWithoutTransition(vm, vm.propertyNames->Math, MathObject::create(vm, this, MathObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Reflect, ReflectObject::create(vm, this, ReflectObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum);
+    ReflectObject* reflectObject = ReflectObject::create(vm, this, ReflectObject::createStructure(vm, this, m_objectPrototype.get()));
+    putDirectWithoutTransition(vm, vm.propertyNames->Reflect, reflectObject, DontEnum);
 
     JSTypedArrayViewConstructor* typedArraySuperConstructor = JSTypedArrayViewConstructor::create(vm, this, JSTypedArrayViewConstructor::createStructure(vm, this, m_functionPrototype.get()), typedArrayProto, speciesGetterSetter);
     typedArrayProto->putDirectWithoutTransition(vm, vm.propertyNames->constructor, typedArraySuperConstructor, DontEnum);
@@ -566,6 +567,7 @@
         GlobalPropertyInfo(vm.propertyNames->isFinitePrivateName, privateFuncIsFinite, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->isNaNPrivateName, privateFuncIsNaN, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->PromisePrivateName, promiseConstructor, DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->ReflectPrivateName, reflectObject, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->InternalPromisePrivateName, internalPromiseConstructor, DontEnum | DontDelete | ReadOnly),
 
         GlobalPropertyInfo(vm.propertyNames->isSetPrivateName, JSFunction::create(vm, this, 1, String(), privateFuncIsSet), DontEnum | DontDelete | ReadOnly),

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (198051 => 198052)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-11 23:24:00 UTC (rev 198051)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-11 23:48:46 UTC (rev 198052)
@@ -1025,7 +1025,7 @@
 - path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Function.prototype.bind.js
   cmd: runES6 :normal
 - path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.assign.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.prototype.hasOwnProperty.js
   cmd: runES6 :normal
 - path: es6/Proxy_internal_ownKeys_calls_SerializeJSONObject.js

Added: trunk/Source/_javascript_Core/tests/stress/object-assign-correctness.js (0 => 198052)


--- trunk/Source/_javascript_Core/tests/stress/object-assign-correctness.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/object-assign-correctness.js	2016-03-11 23:48:46 UTC (rev 198052)
@@ -0,0 +1,168 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad assertion.");
+}
+function test(f) {
+    for (let i = 0; i < 500; i++)
+        f();
+}
+
+test(function() {
+    let ownKeysCalled = false;
+    let getOwnPropertyDescriptorProps = [];
+    let getProps = [];
+    let enumerableCalled = false;
+    let handler = {
+        getOwnPropertyDescriptor: function(target, key) { 
+            getOwnPropertyDescriptorProps.push(key);
+            switch(key) {
+            case "foo":
+                return {
+                    enumerable: true,
+                    configurable: true,
+                    value: 45
+                };
+            case "bar":
+                return  {
+                    enumerable: true,
+                    get enumerable() {
+                        enumerableCalled = true;
+                        return true;
+                    },
+                    configurable: true,
+                    value: 50
+                }
+            case "baz":
+                return  {
+                    enumerable: false,
+                    configurable: true,
+                    value: 50
+                }
+            default:
+                assert(false, "should not be reached.");
+                break;
+            }
+        },
+        ownKeys: function(target) {
+            ownKeysCalled = true;
+            return ["foo", "bar", "baz"];
+        },
+        get: function(target, key) {
+            getProps.push(key);
+            switch(key) {
+            case "foo":
+                return 20;
+            case "bar":
+                return "bar";
+            default:
+                assert(false, "should not be reached.");
+                break;
+            }
+        }
+    };
+
+    let proxy = new Proxy({}, handler);
+    let foo = {};
+    Object.assign(foo, proxy);
+
+    assert(enumerableCalled);
+
+    assert(Reflect.ownKeys(foo).length === 2);
+    assert(Reflect.ownKeys(foo)[0] === "foo");
+    assert(Reflect.ownKeys(foo)[1] === "bar");
+    assert(foo.foo === 20);
+    assert(foo.bar === "bar");
+
+    assert(ownKeysCalled);
+    assert(getOwnPropertyDescriptorProps.length === 3);
+    assert(getOwnPropertyDescriptorProps[0] === "foo");
+    assert(getOwnPropertyDescriptorProps[1] === "bar");
+    assert(getOwnPropertyDescriptorProps[2] === "baz");
+
+    assert(getProps.length === 2);
+    assert(getProps[0] === "foo");
+    assert(getProps[1] === "bar");
+});
+
+
+let oldReflect = Reflect;
+Reflect = null;
+assert(Reflect === null); // Make sure Object.assign's use of Reflect is safe.
+
+test(function() {
+    let ownKeysCalled = false;
+    let getOwnPropertyDescriptorProps = [];
+    let getProps = [];
+    let enumerableCalled = false;
+    let handler = {
+        getOwnPropertyDescriptor: function(target, key) { 
+            getOwnPropertyDescriptorProps.push(key);
+            switch(key) {
+            case "foo":
+                return {
+                    enumerable: true,
+                    configurable: true,
+                    value: 45
+                };
+            case "bar":
+                return  {
+                    get enumerable() {
+                        enumerableCalled = true;
+                        return true;
+                    },
+                    configurable: true,
+                    value: 50
+                }
+            case "baz":
+                return  {
+                    enumerable: false,
+                    configurable: true,
+                    value: 50
+                }
+            default:
+                assert(false, "should not be reached.");
+                break;
+            }
+        },
+        ownKeys: function(target) {
+            ownKeysCalled = true;
+            return ["foo", "bar", "baz"];
+        },
+        get: function(target, key) {
+            getProps.push(key);
+            switch(key) {
+            case "foo":
+                return 20;
+            case "bar":
+                return "bar";
+            default:
+                assert(false, "should not be reached.");
+                break;
+            }
+        }
+    };
+
+    let proxy = new Proxy({}, handler);
+    let foo = {};
+    Object.assign(foo, proxy);
+
+    assert(enumerableCalled);
+
+    assert(oldReflect.ownKeys(foo).length === 2);
+    assert(oldReflect.ownKeys(foo)[0] === "foo");
+    assert(oldReflect.ownKeys(foo)[1] === "bar");
+    assert(foo.foo === 20);
+    assert(foo.bar === "bar");
+
+    assert(ownKeysCalled);
+    assert(getOwnPropertyDescriptorProps.length === 3);
+    assert(getOwnPropertyDescriptorProps[0] === "foo");
+    assert(getOwnPropertyDescriptorProps[1] === "bar");
+    assert(getOwnPropertyDescriptorProps[2] === "baz");
+
+    assert(getProps.length === 2);
+    assert(getProps[0] === "foo");
+    assert(getProps[1] === "bar");
+
+});
+
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to