From 1654619602f21ef2c9a64e4a76db73de2f3a1bbc Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Tue, 19 Aug 2014 22:10:20 -0700 Subject: [PATCH] Bug 1054426 - Make Object.assign skip null/undefined source arguments if any are passed, to match not-yet-drafted semantics agreed upon in TC39 meeting minutes. Also fixes Facebook bustage. r=mjrosenb over IRC a=nigelb,facebookbustage --- js/src/builtin/Object.js | 11 ++++++++--- js/src/tests/ecma_6/Object/assign.js | 19 +++++++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/js/src/builtin/Object.js b/js/src/builtin/Object.js index adafe0bf5358..d3ecc3dbb11d 100644 --- a/js/src/builtin/Object.js +++ b/js/src/builtin/Object.js @@ -14,8 +14,14 @@ function ObjectStaticAssign(target, firstSource) { // Step 4. var i = 1; do { - // Step 5.a-b. + // Step 5.a-b, plus an unspecified flourish to skip null/undefined, so + // any site depending on agreed-upon (but not-yet-drafted) semantics + // from TC39 meeting minutes will work. (Yes, implausibly, such a site + // exists. See bug 1054426.) var nextSource = arguments[i]; + if (nextSource === null || nextSource === undefined) + continue; + var from = ToObject(nextSource); // Step 5.c-d. @@ -58,8 +64,7 @@ function ObjectStaticAssign(target, firstSource) { // Step 5.k. if (pendingException !== MISSING) throw pendingException; - i++; - } while (i < arguments.length); + } while (++i < arguments.length); // Step 6. return to; diff --git a/js/src/tests/ecma_6/Object/assign.js b/js/src/tests/ecma_6/Object/assign.js index 3cbbcf0c35cf..b39a48591fef 100644 --- a/js/src/tests/ecma_6/Object/assign.js +++ b/js/src/tests/ecma_6/Object/assign.js @@ -38,12 +38,27 @@ function basicSymbols() { } basicSymbols(); -// Calls ToObject() for target and source +// Calls ToObject() for target, skips null/undefined sources, uses +// ToObject(source) otherwise. function testToObject() { assertThrowsInstanceOf(() => Object.assign(null, null), TypeError); assertThrowsInstanceOf(() => Object.assign(), TypeError); assertThrowsInstanceOf(() => Object.assign(null, {}), TypeError); - assertThrowsInstanceOf(() => Object.assign({}, null), TypeError); + assertEq(Object.assign({}, null) instanceof Object, true); + assertEq(Object.assign({}, undefined) instanceof Object, true); + + // Technically an embedding could have this as extension acting differently + // from ours, so a feature-test is inadequate. We can move this subtest + // into extensions/ if that ever matters. + if (typeof objectEmulatingUndefined === "function") { + var falsyObject = objectEmulatingUndefined(); + falsyObject.foo = 7; + + var obj = Object.assign({}, falsyObject); + assertEq(obj instanceof Object, true); + assertEq(obj.foo, 7); + } + assertEq(Object.assign(true, {}) instanceof Boolean, true); assertEq(Object.assign(1, {}) instanceof Number, true); assertEq(Object.assign("string", {}) instanceof String, true);