Attachment #8341713: 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 (+383 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
    let source = new Proxy({
108
        get a() { getterCalled = true },
109
        get b() { Object.defineProperty(this, "a", {enumerable: false}) },
110
    }, {
111
        getOwnPropertyNames: () => ["b", "a"]
112
    });
113
    Object.assign({}, source);
114
    assertFalse(getterCalled);
115
}
116
117
// Enumerability is decided on-time, not before main loop (2)
118
{
119
    let getterCalled = false;
120
    // FIXME: sourceTarget should not be necessary, Proxy bug in SpiderMonkey
121
    let sourceTarget;
122
    let source = new Proxy(sourceTarget = {
123
        get a() { getterCalled = true },
124
        get b() { Object.defineProperty(sourceTarget /* this */, "a", {enumerable: true}) },
125
    }, {
126
        getOwnPropertyNames: () => ["b", "a"]
127
    });
128
    Object.defineProperty(sourceTarget /* source */, "a", {enumerable: false});
129
    Object.assign({}, source);
130
    assertTrue(getterCalled);
131
}
132
133
// Properties are retrieved through Get()
134
{
135
    let getterCalled = false;
136
    Object.assign({}, {get a() { getterCalled = true }});
137
    assertTrue(getterCalled);
138
}
139
140
// Properties are assigned through Put()
141
{
142
    let setterCalled = false;
143
    Object.assign({set a(v) { setterCalled = v }}, {a: true});
144
    assertTrue(setterCalled);
145
}
146
147
// Properties are assigned through Put(): Existing property attributes are not altered
148
{
149
    let source = {a: 1, b: 2, c: 3};
150
    let target = {a: 0, b: 0, c: 0};
151
    Object.defineProperty(target, "a", {enumerable: false});
152
    Object.defineProperty(target, "b", {configurable: false});
153
    Object.defineProperty(target, "c", {enumerable: false, configurable: false});
154
    Object.assign(target, source);
155
    assertDataProperty(target, "a", {value: 1, writable: true, enumerable: false, configurable: true});
156
    assertDataProperty(target, "b", {value: 2, writable: true, enumerable: true, configurable: false});
157
    assertDataProperty(target, "c", {value: 3, writable: true, enumerable: false, configurable: false});
158
}
159
160
// Properties are assigned through Put(): Throws TypeError if non-writable
161
{
162
    let source = {a: 1};
163
    let target = {a: 0};
164
    Object.defineProperty(target, "a", {writable: false});
165
    assertThrows(() => Object.assign(target, source), TypeError);
166
    assertDataProperty(target, "a", {value: 0, writable: false, enumerable: true, configurable: true});
167
}
168
169
// Put() creates standard properties; Property attributes from source are ignored
170
{
171
    let source = {a: 1, b: 2, c: 3, get d() { return 4 }};
172
    Object.defineProperty(source, "b", {writable: false});
173
    Object.defineProperty(source, "c", {configurable: false});
174
    let target = Object.assign({}, source);
175
    assertDataProperty(target, "a", {value: 1, writable: true, enumerable: true, configurable: true});
176
    assertDataProperty(target, "b", {value: 2, writable: true, enumerable: true, configurable: true});
177
    assertDataProperty(target, "c", {value: 3, writable: true, enumerable: true, configurable: true});
178
    assertDataProperty(target, "d", {value: 4, writable: true, enumerable: true, configurable: true});
179
}
180
181
// Properties created during traversal are not copied
182
{
183
    let source = {get a() { this.b = 2 }};
184
    let target = Object.assign({}, source);
185
    assertTrue("a" in target);
186
    assertFalse("b" in target);
187
}
188
189
// Properties created during traversal are copied - Proxy edition
190
// FIXME: requires [[OwnKeys]] to be an Iterable
191
if (false) {
192
    let hasB = false;
193
    let source = new Proxy({
194
        get a() { hasB = "b" in this },
195
    }, {
196
        getOwnPropertyNames: () => function*() {
197
            yield "a";
198
            source.b = 2;
199
            yield "b";
200
        }()
201
    });
202
    let target = Object.assign({}, source);
203
    assertTrue("a" in target);
204
    assertTrue("b" in target);
205
    assertFalse(hasB);
206
}
207
208
// Properties deleted during traversal are not copied
209
{
210
    let source = new Proxy({
211
        get a() { delete this.b },
212
        b: 2,
213
    }, {
214
        getOwnPropertyNames: () => ["a", "b"]
215
    });
216
    let target = Object.assign({}, source);
217
    assertTrue("a" in target);
218
    assertFalse("b" in target);
219
}
220
221
// Properties first deleted and then recreated during traversal are copied (1)
222
{
223
    let source = new Proxy({
224
        get a() { delete this.c },
225
        get b() { this.c = 4 },
226
        c: 3,
227
    }, {
228
        getOwnPropertyNames: () => ["a", "b", "c"]
229
    });
230
    let target = Object.assign({}, source);
231
    assertTrue("a" in target);
232
    assertTrue("b" in target);
233
    assertTrue("c" in target);
234
    assertDataProperty(target, "c", {value: 4, writable: true, enumerable: true, configurable: true});
235
}
236
237
// Properties first deleted and then recreated during traversal are copied (2)
238
{
239
    let source = new Proxy({
240
        get a() { delete this.c },
241
        get b() { this.c = 4 },
242
        c: 3,
243
    }, {
244
        getOwnPropertyNames: () => ["a", "c", "b"]
245
    });
246
    let target = Object.assign({}, source);
247
    assertTrue("a" in target);
248
    assertTrue("b" in target);
249
    assertFalse("c" in target);
250
}
251
252
// String and Symbol valued properties are copied
253
{
254
    let keyA = "str-prop";
255
    let source = {"str-prop": 1};
256
    let target = Object.assign({}, source);
257
    assertDataProperty(target, keyA, {value: 1, writable: true, enumerable: true, configurable: true});
258
}
259
260
// Intermediate exceptions do not stop property traversal, first exception is reported (1)
261
{
262
    let ErrorA = function ErrorA() {};
263
    let ErrorB = function ErrorB() {};
264
    let log = "";
265
    let source = new Proxy({}, {
266
        getOwnPropertyDescriptor: function(t, pk) {
267
            log += pk;
268
            throw new (pk === "a" ? ErrorA : ErrorB);
269
        },
270
        getOwnPropertyNames: () => ["b", "a"]
271
    });
272
    assertThrows(() => Object.assign({}, source), ErrorB);
273
    assertSame("ba", log);
274
}
275
276
// Intermediate exceptions do not stop property traversal, first exception is reported (2)
277
{
278
    let ErrorA = function ErrorA() {};
279
    let ErrorB = function ErrorB() {};
280
    let log = "";
281
    let source = new Proxy({
282
        get a() { log += "a"; throw new ErrorA },
283
        get b() { log += "b"; throw new ErrorB },
284
    }, {
285
        getOwnPropertyNames: () => ["b", "a"]
286
    });
287
    assertThrows(() => Object.assign({}, source), ErrorB);
288
    assertSame("ba", log);
289
}
290
291
// Intermediate exceptions do not stop property traversal, first exception is reported (3)
292
{
293
    let ErrorA = function ErrorA() {};
294
    let ErrorB = function ErrorB() {};
295
    let log = "";
296
    let source = new Proxy({a: 1, b: 2}, {
297
        getOwnPropertyNames: () => ["b", "a"]
298
    });
299
    let target = {
300
        set a(v) { log += "a"; throw new ErrorA },
301
        set b(v) { log += "b"; throw new ErrorB },
302
    };
303
    assertThrows(() => Object.assign(target, source), ErrorB);
304
    assertSame("ba", log);
305
}
306
307
// Intermediate exceptions do not stop property traversal, first exception is reported (4)
308
{
309
    let ErrorGetOwnProperty = function ErrorGetOwnProperty() {};
310
    let ErrorGet = function ErrorGet() {};
311
    let ErrorSet = function ErrorSet() {};
312
    let source = new Proxy({
313
        get a() { throw new ErrorGet }
314
    }, {
315
        getOwnPropertyDescriptor: function(t, pk) {
316
            throw new ErrorGetOwnProperty;
317
        }
318
    });
319
    let target = {
320
        set a(v) { throw new ErrorSet }
321
    };
322
    assertThrows(() => Object.assign({}, source), ErrorGetOwnProperty);
323
}
324
325
// Exceptions in Iterator directly stop property traversal (1)
326
// FIXME: requires [[OwnKeys]] to be an Iterable
327
if (false) {
328
    let ErrorNext = function ErrorNext() {};
329
    let getterCalled = false;
330
    let source = new Proxy({
331
        get a() { getterCalled = true }
332
    }, {
333
        getOwnPropertyNames: () => ({next: function() { throw new ErrorNext }})
334
    });
335
    assertThrows(() => Object.assign({}, source), ErrorNext);
336
    assertFalse(getterCalled);
337
}
338
339
// Exceptions in Iterator directly stop property traversal (2)
340
// FIXME: requires [[OwnKeys]] to be an Iterable
341
if (false) {
342
    let ErrorDone = function ErrorDone() {};
343
    let ErrorValue = function ErrorValue() {};
344
    let getterCalled = false;
345
    let source = new Proxy({
346
        get a() { getterCalled = true }
347
    }, {
348
        getOwnPropertyNames: () => ({
349
            next: function() {
350
                return {
351
                    get done() { throw new ErrorDone },
352
                    get value() { throw new ErrorValue },
353
                };
354
            }
355
        })
356
    });
357
    assertThrows(() => Object.assign({}, source), ErrorDone);
358
    assertFalse(getterCalled);
359
}
360
361
// Exceptions in Iterator directly stop property traversal (3)
362
// FIXME: requires [[OwnKeys]] to be an Iterable
363
if (false) {
364
    let ErrorValue = function ErrorValue() {};
365
    let getterCalled = false;
366
    let source = new Proxy({
367
        get a() { getterCalled = true }
368
    }, {
369
        getOwnPropertyNames: () => ({
370
            next: function() {
371
                return {
372
                    get done() { return false },
373
                    get value() { throw new ErrorValue },
374
                };
375
            }
376
        })
377
    });
378
    assertThrows(() => Object.assign({}, source), ErrorValue);
379
    assertFalse(getterCalled);
380
}
381
382
if (typeof reportCompare == "function")
383
    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