Attachment #8462804: assign_test_edited_plus_mult_test.patch for bug #937855

View | Details | Raw Unified | Return to bug 937855
Collapse All | Expand All

(-)a/js/src/tests/ecma_6/Object/assign.js (+372 lines)
Line     Link Here 
Line 0    Link Here 
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
function ToObject(o) {
6
    if (o == null) throw new TypeError();
7
    return Object(o);
8
}
9
10
/* 19.1.2.1  Object.assign ( target, ...sources ) */
11
assertBuiltinFunction(Object.assign, "assign", 2);
12
// Basic functionality works with multiple sources
13
{
14
    var a = {};
15
    var b = { bProp : 7 };
16
    var c = { cProp : 8 };
17
    Object.assign(a, b, c);
18
    assertSame(7, a.bProp);
19
    assertSame(8, a.cProp);
20
}
21
22
// Calls ToObject() for target and source
23
{
24
    assertThrows(() => Object.assign(null, null), TypeError);
25
    assertThrows(() => Object.assign(null, {}), TypeError);
26
    assertThrows(() => Object.assign({}, null), TypeError);
27
    assertInstanceOf(Boolean, Object.assign(true, {}));
28
    assertInstanceOf(Number, Object.assign(1, {}));
29
    assertInstanceOf(String, Object.assign("string", {}));
30
    let o = {};
31
    assertSame(o, Object.assign(o, {}));
32
}
33
34
// Invokes [[OwnPropertyKeys]] on ToObject(source)
35
{
36
    assertThrows(() => Object.assign(null, new Proxy({}, {
37
        getOwnPropertyNames: () => fail("ToObject(target) succeeded")
38
    })), TypeError);
39
40
    let ownKeysCalled = false;
41
    Object.assign({}, new Proxy({}, {
42
        ownKeys: function() {
43
            ownKeysCalled = true;
44
            return [];
45
        }
46
    }));
47
    var thing = new Proxy({}, {
48
        ownKeys: function(target) {
49
            ownKeysCalled = true;
50
            return [];
51
        }
52
    });
53
    assertTrue(ownKeysCalled);
54
}
55
56
// Ensure correct property traversal
57
{
58
    let log = "";
59
    let source = new Proxy({a: 1, b: 2}, {
60
        ownKeys: () => ["b", "c", "a"],
61
        getOwnPropertyDescriptor: function(t, pk) {
62
            log += "#" + pk;
63
            return Object.getOwnPropertyDescriptor(t, pk);
64
        },
65
        get: function(t, pk, r) {
66
            log += "-" + pk;
67
            return t[pk];
68
        },
69
    });
70
    Object.assign({}, source);
71
    assertSame("#b-b#c#a-a", log);
72
}
73
74
// Only [[Enumerable]] properties are assigned to target
75
{
76
    let source = Object.defineProperties({}, {
77
        a: {value: 1, enumerable: true},
78
        b: {value: 2, enumerable: false},
79
    });
80
    let target = Object.assign({}, source);
81
    assertTrue("a" in target);
82
    assertFalse("b" in target);
83
}
84
85
86
// Enumerability is decided on-time, not before main loop (1)
87
{
88
    let getterCalled = false;
89
    // FIXME: sourceTarget should not be necessary, Proxy bug in SpiderMonkey
90
    let sourceTarget;
91
    let source = new Proxy(sourceTarget = {
92
        get a() { getterCalled = true },
93
        get b() { Object.defineProperty(sourceTarget /* this */, "a", {enumerable: false}) },
94
    }, {
95
        ownKeys: () => ["b", "a"]
96
    });
97
    Object.assign({}, source);
98
    assertFalse(getterCalled);
99
}
100
101
// Enumerability is decided on-time, not before main loop (2)
102
{
103
    let getterCalled = false;
104
    // FIXME: sourceTarget should not be necessary, Proxy bug in SpiderMonkey
105
    let sourceTarget;
106
    let source = new Proxy(sourceTarget = {
107
        get a() { getterCalled = true },
108
        get b() { Object.defineProperty(sourceTarget /* this */, "a", {enumerable: true}) },
109
    }, {
110
        ownKeys: () => ["b", "a"]
111
    });
112
    Object.defineProperty(sourceTarget /* source */, "a", {enumerable: false});
113
    Object.assign({}, source);
114
    assertTrue(getterCalled);
115
}
116
117
// Properties are retrieved through Get()
118
{
119
    let getterCalled = false;
120
    Object.assign({}, {get a() { getterCalled = true }});
121
    assertTrue(getterCalled);
122
}
123
124
// Properties are retrieved through Get()
125
// Properties are assigned through Put()
126
{
127
    let setterCalled = false;
128
    Object.assign({set a(v) { setterCalled = v }}, {a: true});
129
    assertTrue(setterCalled);
130
}
131
132
// Properties are retrieved through Get()
133
// Properties are assigned through Put(): Existing property attributes are not altered
134
{
135
    let source = {a: 1, b: 2, c: 3};
136
    let target = {a: 0, b: 0, c: 0};
137
    Object.defineProperty(target, "a", {enumerable: false});
138
    Object.defineProperty(target, "b", {configurable: false});
139
    Object.defineProperty(target, "c", {enumerable: false, configurable: false});
140
    Object.assign(target, source);
141
    assertDataProperty(target, "a", {value: 1, writable: true, enumerable: false, configurable: true});
142
    assertDataProperty(target, "b", {value: 2, writable: true, enumerable: true, configurable: false});
143
    assertDataProperty(target, "c", {value: 3, writable: true, enumerable: false, configurable: false});
144
}
145
146
// Properties are retrieved through Get()
147
// Properties are assigned through Put(): Throws TypeError if non-writable
148
{
149
    let source = {a: 1};
150
    let target = {a: 0};
151
    Object.defineProperty(target, "a", {writable: false});
152
    assertThrows(() => Object.assign(target, source), TypeError);
153
    assertDataProperty(target, "a", {value: 0, writable: false, enumerable: true, configurable: true});
154
}
155
156
// Properties are retrieved through Get()
157
// Put() creates standard properties; Property attributes from source are ignored
158
{
159
    let source = {a: 1, b: 2, c: 3, get d() { return 4 }};
160
    Object.defineProperty(source, "b", {writable: false});
161
    Object.defineProperty(source, "c", {configurable: false});
162
    let target = Object.assign({}, source);
163
    assertDataProperty(target, "a", {value: 1, writable: true, enumerable: true, configurable: true});
164
    assertDataProperty(target, "b", {value: 2, writable: true, enumerable: true, configurable: true});
165
    assertDataProperty(target, "c", {value: 3, writable: true, enumerable: true, configurable: true});
166
    assertDataProperty(target, "d", {value: 4, writable: true, enumerable: true, configurable: true});
167
}
168
169
// Properties created during traversal are not copied
170
{
171
    let source = {get a() { this.b = 2 }};
172
    let target = Object.assign({}, source);
173
    assertTrue("a" in target);
174
    assertFalse("b" in target);
175
}
176
177
// Properties created during traversal are copied - Proxy edition
178
// FIXME: requires [[OwnKeys]] to be an Iterable
179
if (false) {
180
    let hasB = false;
181
    let source = new Proxy({
182
        get a() { hasB = "b" in this },
183
    }, {
184
        getOwnPropertyNames: () => function*() {
185
            yield "a";
186
            source.b = 2;
187
            yield "b";
188
        }()
189
    });
190
    let target = Object.assign({}, source);
191
    assertTrue("a" in target);
192
    assertTrue("b" in target);
193
    assertFalse(hasB);
194
}
195
196
// Properties deleted during traversal are not copied
197
{
198
    let source = new Proxy({
199
        get a() { delete this.b },
200
        b: 2,
201
    }, {
202
        getOwnPropertyNames: () => ["a", "b"]
203
    });
204
    let target = Object.assign({}, source);
205
    assertTrue("a" in target);
206
    assertFalse("b" in target);
207
}
208
209
// Properties first deleted and then recreated during traversal are copied (1)
210
{
211
    let source = new Proxy({
212
        get a() { delete this.c },
213
        get b() { this.c = 4 },
214
        c: 3,
215
    }, {
216
        getOwnPropertyNames: () => ["a", "b", "c"]
217
    });
218
    let target = Object.assign({}, source);
219
    assertTrue("a" in target);
220
    assertTrue("b" in target);
221
    assertTrue("c" in target);
222
    assertDataProperty(target, "c", {value: 4, writable: true, enumerable: true, configurable: true});
223
}
224
225
// Properties first deleted and then recreated during traversal are copied (2)
226
{
227
    let source = new Proxy({
228
        get a() { delete this.c },
229
        get b() { this.c = 4 },
230
        c: 3,
231
    }, {
232
        ownKeys: () => ["a", "c", "b"]
233
    });
234
    let target = Object.assign({}, source);
235
    assertTrue("a" in target);
236
    assertTrue("b" in target);
237
    assertFalse("c" in target);
238
}
239
240
// String and Symbol valued properties are copied
241
{
242
    let keyA = "str-prop";
243
    let source = {"str-prop": 1};
244
    let target = Object.assign({}, source);
245
    assertDataProperty(target, keyA, {value: 1, writable: true, enumerable: true, configurable: true});
246
}
247
248
// Intermediate exceptions do not stop property traversal, first exception is reported (1)
249
{
250
    let ErrorA = function ErrorA() {};
251
    let ErrorB = function ErrorB() {};
252
    let log = "";
253
    let source = new Proxy({}, {
254
        getOwnPropertyDescriptor: function(t, pk) {
255
            log += pk;
256
            throw new (pk === "a" ? ErrorA : ErrorB);
257
        },
258
        ownKeys: () => ["b", "a"]
259
    });
260
    assertThrows(() => Object.assign({}, source), ErrorB);
261
    assertSame("ba", log);
262
}
263
264
// Properties are retrieved through Get()
265
// Intermediate exceptions do not stop property traversal, first exception is reported (2)
266
{
267
    let ErrorA = function ErrorA() {};
268
    let ErrorB = function ErrorB() {};
269
    let log = "";
270
    let source = new Proxy({
271
        get a() { log += "a"; throw new ErrorA },
272
        get b() { log += "b"; throw new ErrorB },
273
    }, {
274
        ownKeys: () => ["b", "a"]
275
    });
276
    assertThrows(() => Object.assign({}, source), ErrorB);
277
    assertSame("ba", log);
278
}
279
280
// Intermediate exceptions do not stop property traversal, first exception is reported (3)
281
{
282
    let ErrorA = function ErrorA() {};
283
    let ErrorB = function ErrorB() {};
284
    let log = "";
285
    let source = new Proxy({a: 1, b: 2}, {
286
        ownKeys: () => ["b", "a"]
287
    });
288
    let target = {
289
        set a(v) { log += "a"; throw new ErrorA },
290
        set b(v) { log += "b"; throw new ErrorB },
291
    };
292
    assertThrows(() => Object.assign(target, source), ErrorB);
293
    assertSame("ba", log);
294
}
295
296
// Intermediate exceptions do not stop property traversal, first exception is reported (4)
297
{
298
    let ErrorGetOwnProperty = function ErrorGetOwnProperty() {};
299
    let ErrorGet = function ErrorGet() {};
300
    let ErrorSet = function ErrorSet() {};
301
    let source = new Proxy({
302
        get a() { throw new ErrorGet }
303
    }, {
304
        getOwnPropertyDescriptor: function(t, pk) {
305
            throw new ErrorGetOwnProperty;
306
        }
307
    });
308
    let target = {
309
        set a(v) { throw new ErrorSet }
310
    };
311
    assertThrows(() => Object.assign({}, source), ErrorGetOwnProperty);
312
}
313
314
// Exceptions in Iterator directly stop property traversal (1)
315
// FIXME: requires [[OwnKeys]] to be an Iterable
316
if (false) {
317
    let ErrorNext = function ErrorNext() {};
318
    let getterCalled = false;
319
    let source = new Proxy({
320
        get a() { getterCalled = true }
321
    }, {
322
        getOwnPropertyNames: () => ({next: function() { throw new ErrorNext }})
323
    });
324
    assertThrows(() => Object.assign({}, source), ErrorNext);
325
    assertFalse(getterCalled);
326
}
327
328
// Exceptions in Iterator directly stop property traversal (2)
329
// FIXME: requires [[OwnKeys]] to be an Iterable
330
if (false) {
331
    let ErrorDone = function ErrorDone() {};
332
    let ErrorValue = function ErrorValue() {};
333
    let getterCalled = false;
334
    let source = new Proxy({
335
        get a() { getterCalled = true }
336
    }, {
337
        getOwnPropertyNames: () => ({
338
            next: function() {
339
                return {
340
                    get done() { throw new ErrorDone },
341
                    get value() { throw new ErrorValue },
342
                };
343
            }
344
        })
345
    });
346
    assertThrows(() => Object.assign({}, source), ErrorDone);
347
    assertFalse(getterCalled);
348
}
349
350
// Exceptions in Iterator directly stop property traversal (3)
351
// FIXME: requires [[OwnKeys]] to be an Iterable
352
if (false) {
353
    let ErrorValue = function ErrorValue() {};
354
    let getterCalled = false;
355
    let source = new Proxy({
356
        get a() { getterCalled = true }
357
    }, {
358
        getOwnPropertyNames: () => ({
359
            next: function() {
360
                return {
361
                    get done() { return false },
362
                    get value() { throw new ErrorValue },
363
                };
364
            }
365
        })
366
    });
367
    assertThrows(() => Object.assign({}, source), ErrorValue);
368
    assertFalse(getterCalled);
369
}
370
371
if (typeof reportCompare == "function")
372
    reportCompare(true, true);
(-)a/js/src/tests/ecma_6/Object/shell.js (+85 lines)
Line     Link Here 
Line 0    Link Here 
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
if (typeof version != 'undefined')
6
{
7
  version(185);
8
}
9
10
var assertThrows = assertThrowsInstanceOf;
11
12
function fail(message) {
13
    throw new Error(message);
14
}
15
16
function IsCallable(o) {
17
    return typeof o === "function";
18
}
19
20
function IsConstructor(o) {
21
    try {
22
        new (new Proxy(o, {construct: () => ({})}));
23
        return true;
24
    } catch(e) {
25
        return false;
26
    }
27
}
28
29
function assertSame(expected, actual) {
30
    return assertEq(actual, expected);
31
}
32
33
function assertTrue(value) {
34
    return assertSame(true, value);
35
}
36
37
function assertFalse(value) {
38
    return assertSame(false, value);
39
}
40
41
function assertNotUndefined(value) {
42
    return assertTrue(value !== undefined);
43
}
44
45
function assertInstanceOf(constructor, value) {
46
    return assertTrue(value instanceof constructor);
47
}
48
49
function assertCallable(o) {
50
    return assertTrue(IsCallable(o));
51
}
52
53
function assertNotConstructor(o) {
54
    return assertFalse(IsConstructor(o));
55
}
56
57
function assertDataProperty(object, propertyKey, {value:value, writable:writable, enumerable:enumerable, configurable:configurable}) {
58
    var desc = Object.getOwnPropertyDescriptor(object, propertyKey);
59
    assertNotUndefined(desc);
60
    assertTrue('value' in desc);
61
    assertSame(value, desc.value);
62
    assertSame(writable, desc.writable);
63
    assertSame(enumerable, desc.enumerable);
64
    assertSame(configurable, desc.configurable);
65
}
66
67
function assertAccessorProperty(object, propertyKey, {get:get, set:set, enumerable:enumerable, configurable:configurable}) {
68
    var desc = Object.getOwnPropertyDescriptor(object, propertyKey);
69
    assertNotUndefined(desc);
70
    assertFalse('value' in desc);
71
    assertSame(get, desc.get);
72
    assertSame(set, desc.set);
73
    assertSame(enumerable, desc.enumerable);
74
    assertSame(configurable, desc.configurable);
75
}
76
77
function assertBuiltinFunction(fun, name, arity) {
78
    assertSame("function", typeof fun);
79
    assertCallable(fun);
80
    // FIXME: Proxy should only have [[Construct]] if target has [[Construct]] (bug 929467)
81
    // assertNotConstructor(fun);
82
    assertSame(Function.prototype, Object.getPrototypeOf(fun));
83
    assertDataProperty(fun, "length", {value: arity, writable: false, enumerable: false, configurable: false});
84
    assertDataProperty(fun, "name", {value: name, writable: false, enumerable: false, configurable: false});
85
}

Return to bug 937855