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