diff --git a/test/built-ins/Object/assign/target-Array.js b/test/built-ins/Object/assign/target-Array.js new file mode 100644 index 0000000000..01af654d09 --- /dev/null +++ b/test/built-ins/Object/assign/target-Array.js @@ -0,0 +1,105 @@ +// Copyright 2015 Microsoft Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-object.assign +description: > + Object.assign with an Array Exotic Object target employs the corresponding + internal methods. +info: | + Object.assign ( _target_, ..._sources_ ) + 3.a.iii.2.b. Perform ? Set(_to_, _nextKey_, _propValue_, *true*). + + Set ( _O_, _P_, _V_, _Throw_ ) + 1. Let _success_ be ? _O_.[[Set]](_P_, _V_, _O_). + + OrdinarySet ( _O_, _P_, _V_, _Receiver_ ) + 1. Let _ownDesc_ be ? _O_.[[GetOwnProperty]](_P_). + 2. Return ? OrdinarySetWithOwnDescriptor(_O_, _P_, _V_, _Receiver_, _ownDesc_). + + OrdinarySetWithOwnDescriptor ( _O_, _P_, _V_, _Receiver_, _ownDesc_ ) + 1. If _ownDesc_ is *undefined*, then + a. Let _parent_ be ? O.[[GetPrototypeOf]](). + b. If _parent_ is not *null*, then + i. Return ? _parent_.[[Set]](_P_, _V_, _Receiver_). + c. Else, + i. Set _ownDesc_ to the PropertyDescriptor { [[Value]]: *undefined*, [[Writable]]: *true*, [[Enumerable]]: *true*, [[Configurable]]: *true* }. + 2. If IsDataDescriptor(_ownDesc_) is *true*, then + ... + c. Let _existingDescriptor_ be ? _Receiver_.[[GetOwnProperty]](_P_). + d. If _existingDescriptor_ is not *undefined*, then + ... + iii. Let _valueDesc_ be the PropertyDescriptor { [[Value]]: _V_ }. + iv. Return ? _Receiver_.[[DefineOwnProperty]](_P_, _valueDesc_). + e. Else, + i. Assert: _Receiver_ does not currently have a property _P_. + ii. Return ? CreateDataProperty(_Receiver_, _P_, _V_). + + CreateDataProperty ( _O_, _P_, _V_ ) + 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _V_, [[Writable]]: *true*, [[Enumerable]]: *true*, [[Configurable]]: *true* }. + 2. Return ? _O_.[[DefineOwnProperty]](_P_, _newDesc_). + + Array exotic object [[DefineOwnProperty]] ( _P_, _Desc_ ) + 1. If _P_ is *"length"*, then + a. Return ? ArraySetLength(_A_, _Desc_). + 2. Else if _P_ is an array index, then + ... + k. If _index_ ≥ _length_, then + i. Set _lengthDesc_.[[Value]] to _index_ + *1*𝔽. + ii. Set _succeeded_ to ! OrdinaryDefineOwnProperty(_A_, *"length"*, _lengthDesc_). + 3. Return ? OrdinaryDefineOwnProperty(_A_, _P_, _Desc_). + + The Object Type + An **integer index** is a property name _n_ such that CanonicalNumericIndexString(_n_) returns an + integral Number in the inclusive interval from *+0*𝔽 to 𝔽(2**53 - 1). An **array index** is an + integer index _n_ such that CanonicalNumericIndexString(_n_) returns an integral Number in the + inclusive interval from *+0*𝔽 to 𝔽(2**32 - 2). +---*/ + +var target = [7, 8, 9]; +var result = Object.assign(target, [1]); +assert.sameValue(result, target); +assert.compareArray(result, [1, 8, 9], + "elements must be assigned from an array source onto an array target"); + +var sparseArraySource = []; +sparseArraySource[2] = 3; +result = Object.assign(target, sparseArraySource); +assert.sameValue(result, target); +assert.compareArray(result, [1, 8, 3], "holes in a sparse array source must not be copied"); + +var shortObjectSource = { 1: 2, length: 2 }; +shortObjectSource["-0"] = -1; +shortObjectSource["1.5"] = -2; +shortObjectSource["4294967295"] = -3; // 2**32 - 1 +result = Object.assign(target, shortObjectSource); +assert.sameValue(result, target); +assert.compareArray(result, [1, 2], + "array index properties must be copied from a non-array source"); +assert.sameValue(result["-0"], -1, + "a property with name -0 must be assigned onto an array target"); +assert.sameValue(result["1.5"], -2, + "a property with name 1.5 must be assigned onto an array target"); +assert.sameValue(result["4294967295"], -3, + "a property with name 4294967295 (2**32 - 1) must be assigned onto an array target"); + +result = Object.assign(target, { length: 1 }); +assert.sameValue(result, target); +assert.compareArray(result, [1], "assigning a short length must shrink an array target"); + +result = Object.assign(target, { 2: 0 }); +assert.sameValue(result, target); +assert.compareArray(result, [1, undefined, 0], + "assigning a high array index must grow an array target"); + +if (typeof Proxy !== 'undefined') { + var accordionSource = new Proxy({ length: 0, 1: 9 }, { + ownKeys: function() { + return ["length", "1"]; + } + }); + result = Object.assign(target, accordionSource); + assert.sameValue(result, target); + assert.compareArray(result, [undefined, 9], + "assigning a short length before a high array index must shrink and then grow an array target"); +}