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");
+
+});
+