1425bb815Sopenharmony_ci// Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci//
3425bb815Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci// you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci// You may obtain a copy of the License at
6425bb815Sopenharmony_ci//
7425bb815Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci//
9425bb815Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci// See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci// limitations under the License.
14425bb815Sopenharmony_ci
15425bb815Sopenharmony_civar object1 = {
16425bb815Sopenharmony_ci  a: 1,
17425bb815Sopenharmony_ci  b: 2,
18425bb815Sopenharmony_ci  c: 3
19425bb815Sopenharmony_ci};
20425bb815Sopenharmony_ci
21425bb815Sopenharmony_civar object2 = Object.assign ({c: 4, d: 5}, object1);
22425bb815Sopenharmony_ci
23425bb815Sopenharmony_ciassert (JSON.stringify (object2) === '{"c":3,"d":5,"a":1,"b":2}');
24425bb815Sopenharmony_ciassert (object2.c === 3);
25425bb815Sopenharmony_ciassert (object2.d === 5);
26425bb815Sopenharmony_ci
27425bb815Sopenharmony_ci// Cloning an object
28425bb815Sopenharmony_civar obj = { a: 1 };
29425bb815Sopenharmony_civar copy = Object.assign ({}, obj);
30425bb815Sopenharmony_ciassert (JSON.stringify (copy) === '{"a":1}'); // { a: 1 }
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_ci// Warning for Deep Clone
33425bb815Sopenharmony_cifunction deepClone() {
34425bb815Sopenharmony_ci  'use strict';
35425bb815Sopenharmony_ci
36425bb815Sopenharmony_ci  var obj1 = { a: 0 , b: { c: 0}};
37425bb815Sopenharmony_ci  var obj2 = Object.assign ({}, obj1);
38425bb815Sopenharmony_ci  assert (JSON.stringify (obj2) === '{"a":0,"b":{"c":0}}');
39425bb815Sopenharmony_ci
40425bb815Sopenharmony_ci  obj1.a = 1;
41425bb815Sopenharmony_ci  assert (JSON.stringify (obj1) === '{"a":1,"b":{"c":0}}');
42425bb815Sopenharmony_ci  assert (JSON.stringify (obj2) === '{"a":0,"b":{"c":0}}');
43425bb815Sopenharmony_ci
44425bb815Sopenharmony_ci  obj2.a = 2;
45425bb815Sopenharmony_ci  assert (JSON.stringify (obj1) === '{"a":1,"b":{"c":0}}');
46425bb815Sopenharmony_ci  assert (JSON.stringify (obj2) === '{"a":2,"b":{"c":0}}');
47425bb815Sopenharmony_ci
48425bb815Sopenharmony_ci  obj2.b.c = 3;
49425bb815Sopenharmony_ci  assert (JSON.stringify (obj1) === '{"a":1,"b":{"c":3}}');
50425bb815Sopenharmony_ci  assert (JSON.stringify (obj2) === '{"a":2,"b":{"c":3}}');
51425bb815Sopenharmony_ci
52425bb815Sopenharmony_ci  // Deep Clone
53425bb815Sopenharmony_ci  obj1 = { a: 0 , b: { c: 0}};
54425bb815Sopenharmony_ci  var obj3 = JSON.parse (JSON.stringify (obj1));
55425bb815Sopenharmony_ci  obj1.a = 4;
56425bb815Sopenharmony_ci  obj1.b.c = 4;
57425bb815Sopenharmony_ci  assert (JSON.stringify (obj3) === '{"a":0,"b":{"c":0}}');
58425bb815Sopenharmony_ci}
59425bb815Sopenharmony_ci
60425bb815Sopenharmony_cideepClone();
61425bb815Sopenharmony_ci
62425bb815Sopenharmony_ci// Merging objects
63425bb815Sopenharmony_civar o1 = { a: 1 };
64425bb815Sopenharmony_civar o2 = { b: 2 };
65425bb815Sopenharmony_civar o3 = { c: 3 };
66425bb815Sopenharmony_ci
67425bb815Sopenharmony_civar obj = Object.assign (o1, o2, o3);
68425bb815Sopenharmony_ciassert (JSON.stringify (obj) === '{"a":1,"b":2,"c":3}');
69425bb815Sopenharmony_ciassert (JSON.stringify (o1) === '{"a":1,"b":2,"c":3}');  //target object itself is changed.
70425bb815Sopenharmony_ci
71425bb815Sopenharmony_ci//Merging objects with same properties
72425bb815Sopenharmony_civar o1 = { a: 1, b: 1, c: 1 };
73425bb815Sopenharmony_civar o2 = { b: 2, c: 2 };
74425bb815Sopenharmony_civar o3 = { c: 3 };
75425bb815Sopenharmony_ci
76425bb815Sopenharmony_civar obj = Object.assign ({}, o1, o2, o3);
77425bb815Sopenharmony_ciassert (JSON.stringify (obj) === '{"a":1,"b":2,"c":3}');
78425bb815Sopenharmony_ci
79425bb815Sopenharmony_ci// Properties on the prototype chain and non-enumerable properties cannot be copied
80425bb815Sopenharmony_civar obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain.
81425bb815Sopenharmony_ci  bar: {
82425bb815Sopenharmony_ci    value: 2  // bar is a non-enumerable property.
83425bb815Sopenharmony_ci  },
84425bb815Sopenharmony_ci  baz: {
85425bb815Sopenharmony_ci    value: 3,
86425bb815Sopenharmony_ci    enumerable: true  // baz is an own enumerable property.
87425bb815Sopenharmony_ci  }
88425bb815Sopenharmony_ci});
89425bb815Sopenharmony_ci
90425bb815Sopenharmony_civar copy = Object.assign ({}, obj);
91425bb815Sopenharmony_ciassert (JSON.stringify (copy) === '{"baz":3}');
92425bb815Sopenharmony_ci
93425bb815Sopenharmony_ci// Primitives will be wrapped to objects
94425bb815Sopenharmony_civar v1 = 'abc';
95425bb815Sopenharmony_civar v2 = true;
96425bb815Sopenharmony_civar v3 = 10;
97425bb815Sopenharmony_ci
98425bb815Sopenharmony_civar obj = Object.assign ({}, v1, null, v2, undefined, v3);
99425bb815Sopenharmony_ci// Primitives will be wrapped, null and undefined will be ignored.
100425bb815Sopenharmony_ci// Note, only string wrappers can have own enumerable properties.
101425bb815Sopenharmony_ciassert (JSON.stringify (obj) === '{"0":"a","1":"b","2":"c"}');
102425bb815Sopenharmony_ci
103425bb815Sopenharmony_ci//Exceptions will interrupt the ongoing copying task
104425bb815Sopenharmony_civar target = Object.defineProperty ({}, 'foo', {
105425bb815Sopenharmony_ci  value: 1,
106425bb815Sopenharmony_ci  writable: false
107425bb815Sopenharmony_ci}); // target.foo is a read-only property
108425bb815Sopenharmony_ci
109425bb815Sopenharmony_citry {
110425bb815Sopenharmony_ci  // TypeError: "foo" is read-only,the Exception is thrown when assigning target.foo
111425bb815Sopenharmony_ci  Object.assign (target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
112425bb815Sopenharmony_ci  assert (false);
113425bb815Sopenharmony_ci} catch (e) {
114425bb815Sopenharmony_ci  assert (e instanceof TypeError);
115425bb815Sopenharmony_ci}
116425bb815Sopenharmony_ci
117425bb815Sopenharmony_ciassert (target.bar === 2);  // the first source was copied successfully.
118425bb815Sopenharmony_ciassert (target.foo2 === 3); // the first property of the second source was copied successfully.
119425bb815Sopenharmony_ciassert (target.foo === 1);  // exception is thrown here.
120425bb815Sopenharmony_ciassert (target.foo3 === undefined); // assign method has finished, foo3 will not be copied.
121425bb815Sopenharmony_ciassert (target.baz === undefined);  // the third source will not be copied either.
122425bb815Sopenharmony_ci
123425bb815Sopenharmony_ci// Copying accessors
124425bb815Sopenharmony_civar obj = {
125425bb815Sopenharmony_ci  foo: 1,
126425bb815Sopenharmony_ci  get bar() {
127425bb815Sopenharmony_ci    return 2;
128425bb815Sopenharmony_ci  }
129425bb815Sopenharmony_ci};
130425bb815Sopenharmony_ci
131425bb815Sopenharmony_civar copy = Object.assign ({}, obj);
132425bb815Sopenharmony_ciassert (JSON.stringify (copy) === '{"foo":1,"bar":2}');
133425bb815Sopenharmony_ciassert (copy.bar === 2); // the value of copy.bar is obj.bar's getter's return value.
134425bb815Sopenharmony_ci
135425bb815Sopenharmony_ci// This is an assign function that copies full descriptors
136425bb815Sopenharmony_cifunction completeAssign (target, sources) {
137425bb815Sopenharmony_ci  sources.forEach (source => {
138425bb815Sopenharmony_ci    var descriptors = Object.keys (source).reduce ((descriptors, key) => {
139425bb815Sopenharmony_ci      descriptors[key] = Object.getOwnPropertyDescriptor (source, key);
140425bb815Sopenharmony_ci      return descriptors;
141425bb815Sopenharmony_ci    }, {});
142425bb815Sopenharmony_ci
143425bb815Sopenharmony_ci    Object.defineProperties (target, descriptors);
144425bb815Sopenharmony_ci  });
145425bb815Sopenharmony_ci  return target;
146425bb815Sopenharmony_ci}
147425bb815Sopenharmony_ci
148425bb815Sopenharmony_civar copy = completeAssign ({}, [obj]);
149425bb815Sopenharmony_ciassert (JSON.stringify (copy) === '{"foo":1,"bar":2}');
150425bb815Sopenharmony_ciassert (copy.bar === 2);
151425bb815Sopenharmony_ci
152425bb815Sopenharmony_ci// Test when target is not coercible to object
153425bb815Sopenharmony_citry {
154425bb815Sopenharmony_ci  Object.assign.call (undefined);
155425bb815Sopenharmony_ci  assert (false);
156425bb815Sopenharmony_ci} catch (e) {
157425bb815Sopenharmony_ci  assert (e instanceof TypeError)
158425bb815Sopenharmony_ci}
159425bb815Sopenharmony_ci
160425bb815Sopenharmony_civar asd = Symbol ("asd");
161425bb815Sopenharmony_civar foo = Symbol ("foo");
162425bb815Sopenharmony_civar bar = Symbol ("bar");
163425bb815Sopenharmony_civar obj = {1: 5, "a": 6, [foo]: 7, [asd]: 8, [bar]: 9};
164425bb815Sopenharmony_civar result = Object.assign ({}, obj);
165425bb815Sopenharmony_ciassert (result[foo] == 7);
166425bb815Sopenharmony_ciassert (result[asd] == 8);
167425bb815Sopenharmony_ciassert (result[bar] == 9);
168