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