1 <!-- Any copyright is dedicated to the Public Domain.
2 - http://creativecommons.org/publicdomain/zero/1.0/ -->
6 <title>Test Observable Array Type
</title>
7 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
8 <link rel=
"stylesheet" type=
"text/css" href=
"/tests/SimpleTest/test.css" />
12 /* global TestInterfaceObservableArray */
14 add_task(async
function init() {
15 await SpecialPowers
.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]});
18 add_task(function testObservableArrayExoticObjects_defineProperty() {
19 let setCallbackCount
= 0;
20 let deleteCallbackCount
= 0;
21 let setCallbackTests
= null;
22 let deleteCallbackTests
= null;
24 let m
= new TestInterfaceObservableArray({
25 setBooleanCallback(value
, index
) {
27 if (typeof setCallbackTests
=== 'function') {
28 setCallbackTests(value
, index
);
31 deleteBooleanCallback(value
, index
) {
32 deleteCallbackCount
++;
33 if (typeof deleteCallbackTests
=== 'function') {
34 deleteCallbackTests(value
, index
);
38 m
.observableArrayBoolean
= [true, true, true];
40 let b
= m
.observableArrayBoolean
;
41 ok(Array
.isArray(b
), "observable array should be an array type");
42 is(b
.length
, 3, "length of observable array should be 0");
46 // [descriptor, shouldThrow, expectedResult]
48 [{configurable
: true, value
: 0}, false, false],
49 [{enumerable
: true, value
: 0}, false, false],
50 [{writable
: false, value
: 0}, false, false],
51 [{get: ()=>{}}, false, false],
52 [{set: ()=>{}}, false, false],
53 [{get: ()=>{}, set: ()=>{}}, false, false],
54 [{get: ()=>{}, value
: 0}, true],
55 // Invalid length value
57 [{value
: "invalid"}, true],
59 // length value should not greater than current length
60 [{value
: b
.length
+ 1}, false, false],
61 // descriptor without value
62 [{configurable
: false, enumerable
: false, writable
: true}, false, true],
64 [{value
: b
.length
}, false, true],
65 [{value
: b
.length
- 1}, false, true],
66 [{value
: 0}, false, true],
67 ].forEach(function([descriptor
, shouldThrow
, expectedResult
]) {
69 let oldLen
= b
.length
;
70 let oldValues
= b
.slice();
71 let deleteCallbackIndex
= oldLen
- 1;
72 let success
= expectedResult
&& "value" in descriptor
;
74 deleteCallbackCount
= 0;
75 setCallbackTests
= null;
76 deleteCallbackTests = function(_value
, _index
) {
77 is(_value
, oldValues
[deleteCallbackIndex
], "deleteCallbackTests: test value argument");
78 is(_index
, deleteCallbackIndex
, "deleteCallbackTests: test index argument");
79 deleteCallbackIndex
--;
83 info(`defining "length" property with ${JSON.stringify(descriptor)}`);
85 is(Reflect
.defineProperty(b
, "length", descriptor
), expectedResult
,
86 `Reflect.defineProperty should return ${expectedResult}`);
87 ok(!shouldThrow
, "Reflect.defineProperty should not throw");
89 ok(shouldThrow
, `Reflect.defineProperty throws ${e}`);
91 is(setCallbackCount
, 0, "setCallback count");
92 is(deleteCallbackCount
, success
? oldLen
- descriptor
.value
: 0, "deleteCallback count");
93 isDeeply(b
, success
? oldValues
.slice(0, descriptor
.value
) : oldValues
, "property values");
94 is(b
.length
, success
? descriptor
.value
: oldLen
, "length of observable array");
99 // [index, descriptor, shouldThrow, expectedResult]
100 // Invalid descriptor
101 [0, {configurable
: false, value
: true}, false, false],
102 [0, {enumerable
: false, value
: true}, false, false],
103 [0, {writable
: false, value
: true}, false, false],
104 [0, {get: ()=>{}}, false, false],
105 [0, {set: ()=>{}}, false, false],
106 [0, {get: ()=>{}, set: ()=>{}}, false, false],
107 [0, {get: ()=>{}, value
: true}, true],
108 // Index could not greater than last index + 1.
109 [b
.length
+ 1, {configurable
: true, enumerable
: true, value
: true}, false, false],
110 // descriptor without value
111 [b
.length
, {configurable
: true, enumerable
: true}, false, true],
113 [b
.length
, {configurable
: true, enumerable
: true, value
: true}, false, true],
114 [b
.length
+ 1, {configurable
: true, enumerable
: true, value
: true}, false, true],
115 ].forEach(function([index
, descriptor
, shouldThrow
, expectedResult
]) {
117 let oldLen
= b
.length
;
118 let oldValue
= b
[index
];
119 let success
= expectedResult
&& "value" in descriptor
;
120 setCallbackCount
= 0;
121 deleteCallbackCount
= 0;
122 setCallbackTests = function(_value
, _index
) {
123 is(_value
, descriptor
.value
, "setCallbackTests: test value argument");
124 is(_index
, index
, "setCallbackTests: test index argument");
126 deleteCallbackTests = function(_value
, _index
) {
127 is(_value
, oldValue
, "deleteCallbackTests: test value argument");
128 is(_index
, index
, "deleteCallbackTests: test index argument");
132 info(`defining ${index} property with ${JSON.stringify(descriptor)}`);
134 is(Reflect
.defineProperty(b
, index
, descriptor
), expectedResult
,
135 `Reflect.defineProperty should return ${expectedResult}`);
136 ok(!shouldThrow
, "Reflect.defineProperty should not throw");
138 ok(shouldThrow
, `Reflect.defineProperty throws ${e}`);
140 is(setCallbackCount
, success
? 1 : 0, "setCallback count");
141 is(deleteCallbackCount
, (oldLen
> index
) ? 1 : 0, "deleteCallback count");
142 is(b
[index
], success
? descriptor
.value
: oldValue
, "property value");
143 is(b
.length
, success
? Math
.max(index
+ 1, oldLen
) : oldLen
, "length of observable array");
146 // Test other property
148 // [property, descriptor, shouldThrow, expectedResult]
149 ["prop1", {configurable
: false, value
: "value1"}, false, true],
150 ["prop1", {configurable
: true, value
: "value2"}, false, false],
151 ["prop2", {enumerable
: false, value
: 5}, false, true],
152 ["prop3", {enumerable
: false, value
: []}, false, true],
153 ["prop4", {enumerable
: false, value
: {}}, false, true],
154 ["prop5", {get: ()=>{}, value
: true}, true, false],
155 ["prop6", {get: ()=>{}, set: ()=>{}}, false, true],
156 ].forEach(function([property
, descriptor
, shouldThrow
, expectedResult
]) {
158 let oldValue
= b
[property
];
159 let oldLen
= b
.length
;
160 setCallbackCount
= 0;
161 deleteCallbackCount
= 0;
162 setCallbackTests
= null;
163 deleteCallbackTests
= null;
166 info(`defining ${property} property with ${JSON.stringify(descriptor)}`);
168 is(Reflect
.defineProperty(b
, property
, descriptor
), expectedResult
,
169 `Reflect.defineProperty should return ${expectedResult}`);
170 ok(!shouldThrow
, "Reflect.defineProperty should not throw");
172 ok(shouldThrow
, `Reflect.defineProperty throws ${e}`);
174 is(setCallbackCount
, 0, "setCallback count");
175 is(deleteCallbackCount
, 0, "deleteCallback count");
176 is(b
[property
], expectedResult
? descriptor
.value
: oldValue
, "property value");
177 is(b
.length
, oldLen
, "length of observable array");
181 add_task(function testObservableArrayExoticObjects_defineProperty_callback_throw() {
182 let setCallbackCount
= 0;
183 let deleteCallbackCount
= 0;
186 let m
= new TestInterfaceObservableArray({
187 setBooleanCallback(value
) {
190 throw new Error("setBooleanCallback");
193 deleteBooleanCallback(value
, index
) {
194 deleteCallbackCount
++;
195 if (index
< minLen
) {
196 throw new Error("deleteBooleanCallback");
200 m
.observableArrayBoolean
= [false, false, false, false, false];
202 let b
= m
.observableArrayBoolean
;
203 ok(Array
.isArray(b
), "observable array should be an array type");
204 is(b
.length
, 5, "length of observable array should be 3");
208 // [length, shouldThrow]
210 [b
.length
- 1, false],
212 ].forEach(function([length
, shouldThrow
]) {
214 let oldValues
= b
.slice();
215 let oldLen
= b
.length
;
216 let descriptor
= {value
: length
};
217 setCallbackCount
= 0;
218 deleteCallbackCount
= 0;
221 info(`defining "length" property with ${JSON.stringify(descriptor)}`);
223 ok(Reflect
.defineProperty(b
, "length", descriptor
),
224 "Reflect.defineProperty should return true");
225 ok(!shouldThrow
, "Reflect.defineProperty should not throw");
227 ok(shouldThrow
, `Reflect.defineProperty throws ${e}`);
229 is(setCallbackCount
, 0, "setCallback count");
230 is(deleteCallbackCount
, oldLen
- (shouldThrow
? minLen
- 1 : length
), "deleteCallback count");
231 isDeeply(b
, oldValues
.slice(0, shouldThrow
? minLen
: length
), "property values");
232 is(b
.length
, shouldThrow
? minLen
: length
, "length of observable array");
235 // Test indexed value
237 // [index, value, shouldThrow]
238 [b
.length
, true, true],
239 [b
.length
, false, false],
240 [b
.length
+ 1, false, false],
241 [b
.length
+ 1, true, true],
244 ].forEach(function([index
, value
, shouldThrow
]) {
246 let oldValue
= b
[index
];
247 let oldLen
= b
.length
;
248 let descriptor
= {configurable
: true, enumerable
: true, value
};
249 setCallbackCount
= 0;
250 deleteCallbackCount
= 0;
253 info(`defining ${index} property with ${JSON.stringify(descriptor)}`);
255 ok(Reflect
.defineProperty(b
, index
, descriptor
), "Reflect.defineProperty should return true");
256 ok(!shouldThrow
, "Reflect.defineProperty should not throw");
258 ok(shouldThrow
, `Reflect.defineProperty throws ${e}`);
260 is(setCallbackCount
, (index
< minLen
) ? 0 : 1, "setCallback count");
261 is(deleteCallbackCount
, (oldLen
> index
) ? 1 : 0, "deleteCallback count");
262 is(b
[index
], shouldThrow
? oldValue
: value
, "property value");
263 is(b
.length
, shouldThrow
? oldLen
: Math
.max(oldLen
, index
+ 1), "length of observable array");
266 // Test other property
268 // [property, descriptor, expectedResult]
269 ["prop1", {configurable
: false, value
: "value1"}, true],
270 ["prop1", {configurable
: true, value
: "value2"}, false],
271 ["prop2", {enumerable
: false, value
: 5}, true],
272 ["prop3", {enumerable
: false, value
: []}, true],
273 ["prop4", {enumerable
: false, value
: {}}, true],
274 ].forEach(function([property
, descriptor
, expectedResult
]) {
276 let oldValue
= b
[property
];
277 let oldLen
= b
.length
;
278 setCallbackCount
= 0;
279 deleteCallbackCount
= 0;
282 info(`defining ${property} property with ${JSON.stringify(descriptor)}`);
284 is(Reflect
.defineProperty(b
, property
, descriptor
), expectedResult
,
285 `Reflect.defineProperty should return ${expectedResult}`);
286 ok(true, "Reflect.defineProperty should not throw");
288 ok(false, `Reflect.defineProperty throws ${e}`);
290 is(setCallbackCount
, 0, "setCallback count");
291 is(deleteCallbackCount
, 0, "deleteCallback count");
292 is(b
[property
], expectedResult
? descriptor
.value
: oldValue
, "property value");
293 is(b
.length
, oldLen
, "length of observable array");
297 add_task(function testObservableArrayExoticObjects_deleteProperty() {
298 let setCallbackCount
= 0;
299 let deleteCallbackCount
= 0;
300 let deleteCallbackTests
= null;
302 let m
= new TestInterfaceObservableArray({
303 setBooleanCallback() {
306 deleteBooleanCallback(value
, index
) {
307 deleteCallbackCount
++;
308 if (typeof deleteCallbackTests
=== 'function') {
309 deleteCallbackTests(value
, index
);
313 m
.observableArrayBoolean
= [true, true];
315 let b
= m
.observableArrayBoolean
;
316 ok(Array
.isArray(b
), "observable array should be an array type");
317 is(b
.length
, 2, "length of observable array should be 2");
320 setCallbackCount
= 0;
321 deleteCallbackCount
= 0;
322 info("deleting length property");
323 ok(!Reflect
.deleteProperty(b
, "length"), "test result of deleting length property");
324 is(setCallbackCount
, 0, "setCallback should not be called");
325 is(deleteCallbackCount
, 0, "deleteCallback should not be called");
326 is(b
.length
, 2, "length should still be 2");
328 // Test indexed value
330 // [index, expectedResult]
334 ].forEach(function([index
, expectedResult
]) {
336 let oldLen
= b
.length
;
337 let oldValue
= b
[index
];
338 setCallbackCount
= 0;
339 deleteCallbackCount
= 0;
340 deleteCallbackTests = function(_value
, _index
) {
341 is(_value
, oldValue
, "deleteCallbackTests: test value argument");
342 is(_index
, index
, "deleteCallbackTests: test index argument");
346 info(`deleting ${index} property`);
347 is(Reflect
.deleteProperty(b
, index
), expectedResult
,
348 `Reflect.deleteProperty should return ${expectedResult}`);
349 is(setCallbackCount
, 0, "setCallback count");
350 is(deleteCallbackCount
, expectedResult
? 1 : 0, "deleteCallback count");
351 is(b
[index
], expectedResult
? undefined : oldValue
, "property value");
352 is(b
.length
, expectedResult
? oldLen
- 1 : oldLen
,
353 "length of observable array");
356 // Test other property
363 ].forEach(function([property
, value
]) {
366 let oldLen
= b
.length
;
367 setCallbackCount
= 0;
368 deleteCallbackCount
= 0;
369 deleteCallbackTests
= null;
372 info(`deleting ${property} property`);
373 is(b
[property
], value
, `property value should be ${value} before deleting`);
374 ok(Reflect
.deleteProperty(b
, property
), "Reflect.deleteProperty should return true");
375 is(setCallbackCount
, 0, "setCallback count");
376 is(deleteCallbackCount
, 0, "deleteCallback count");
377 is(b
[property
], undefined, "property value should be undefined after deleting");
378 is(b
.length
, oldLen
, "length of observable array");
382 add_task(function testObservableArrayExoticObjects_deleteProperty_callback_throw() {
383 let setCallbackCount
= 0;
384 let deleteCallbackCount
= 0;
386 let m
= new TestInterfaceObservableArray({
387 setBooleanCallback() {
390 deleteBooleanCallback(value
) {
391 deleteCallbackCount
++;
393 throw new Error("deleteBooleanCallback");
397 m
.observableArrayBoolean
= [true, false];
399 let b
= m
.observableArrayBoolean
;
400 ok(Array
.isArray(b
), "observable array should be an array type");
401 is(b
.length
, 2, "length of observable array should be 2");
403 // Test indexed value
404 let index
= b
.length
;
407 let oldValue
= b
[index
];
408 let oldLen
= b
.length
;
409 setCallbackCount
= 0;
410 deleteCallbackCount
= 0;
413 info(`deleting index ${index}`);
415 ok(Reflect
.deleteProperty(b
, index
), "Reflect.deleteProperty should return true");
416 ok(!oldValue
, "Reflect.deleteProperty should not throw");
418 ok(oldValue
, `Reflect.deleteProperty throws ${e}`);
420 is(setCallbackCount
, 0, "setCallback count");
421 is(deleteCallbackCount
, 1, "deleteCallback count");
422 is(b
[index
], oldValue
? oldValue
: undefined, "property value");
423 is(b
.length
, oldValue
? oldLen
: oldLen
- 1, "length of observable array");
426 // Test other property
434 ].forEach(function([property
, value
]) {
437 let oldLen
= b
.length
;
438 setCallbackCount
= 0;
439 deleteCallbackCount
= 0;
442 info(`deleting ${property} property`);
443 is(b
[property
], value
, `property value should be ${JSON.stringify(value)} before deleting`);
445 ok(Reflect
.deleteProperty(b
, property
), `Reflect.deleteProperty should return true`);
446 ok(true, "Reflect.deleteProperty should not throw");
448 ok(false, `Reflect.deleteProperty throws ${e}`);
450 is(setCallbackCount
, 0, "setCallback count");
451 is(deleteCallbackCount
, 0, "deleteCallback count");
452 is(b
[property
], undefined, `property value should be undefined after deleting`);
453 is(b
.length
, oldLen
, "length of observable array");
457 add_task(function testObservableArrayExoticObjects_get() {
458 let m
= new TestInterfaceObservableArray();
459 m
.observableArrayBoolean
= [true, false];
461 let b
= m
.observableArrayBoolean
;
462 ok(Array
.isArray(b
), "observable array should be an array type");
463 is(b
.length
, 2, "length of observable array should be 2");
466 is(Reflect
.get(b
, "length"), 2, "test result of getting length property");
468 // Test indexed value
469 is(Reflect
.get(b
, 0), true, "test result of getting index 0");
470 is(Reflect
.get(b
, 1), false, "test result of getting index 1");
471 is(Reflect
.get(b
, 2), undefined, "test result of getting index 2");
473 // Test other property
480 ].forEach(function([property
, value
]) {
481 is(Reflect
.get(b
, property
), undefined, `test ${property} property before setting property value`);
483 is(Reflect
.get(b
, property
), value
, `test ${property} property after setting property value`);
487 add_task(function testObservableArrayExoticObjects_getOwnPropertyDescriptor() {
488 function TestDescriptor(object
, property
, exist
, configurable
, enumerable
,
490 let descriptor
= Reflect
.getOwnPropertyDescriptor(object
, property
);
492 is(descriptor
, undefined, `descriptor of ${property} property should be undefined`);
496 is(descriptor
.configurable
, configurable
, `test descriptor of ${property} property (configurable)`);
497 is(descriptor
.enumerable
, enumerable
, `test descriptor of ${property} property (enumerable)`);
498 is(descriptor
.writable
, writable
, `test descriptor of ${property} property (writable)`);
499 is(descriptor
.value
, value
, `test descriptor of ${property} property (value)`);
502 let m
= new TestInterfaceObservableArray();
503 m
.observableArrayBoolean
= [true, false];
505 let b
= m
.observableArrayBoolean
;
506 ok(Array
.isArray(b
), "observable array should be an array type");
507 is(b
.length
, 2, "length of observable array should be 2");
510 TestDescriptor(b
, "length", true, false /* configurable */,
511 false /* enumerable */, true /* writable */ , 2 /* value */);
513 // Test indexed value
514 TestDescriptor(b
, 0, true, true /* configurable */, true /* enumerable */,
515 true /* writable */ , true /* value */);
516 TestDescriptor(b
, 1, true, true /* configurable */, true /* enumerable */,
517 true /* writable */ , false /* value */);
518 TestDescriptor(b
, 2, false);
520 // Test other property
522 // [property, value, configurable, enumerable, writable]
523 ["prop1", "value1", true, true, true],
524 ["prop2", 5, true, true, false],
525 ["prop3", [], true, false, false],
526 ["prop4", {}, false, false, false],
527 ].forEach(function([property
, value
, configurable
, enumerable
, writable
]) {
528 Object
.defineProperty(b
, property
, {
534 TestDescriptor(b
, property
, true, configurable
, enumerable
, writable
, value
);
538 add_task(function testObservableArrayExoticObjects_has() {
539 let m
= new TestInterfaceObservableArray();
540 m
.observableArrayBoolean
= [true, false];
542 let b
= m
.observableArrayBoolean
;
543 ok(Array
.isArray(b
), "observable array should be an array type");
544 is(b
.length
, 2, "length of observable array should be 2");
547 ok(Reflect
.has(b
, "length"), `test length property`);
549 // Test indexed value
550 ok(Reflect
.has(b
, 0), `test 0 property`);
551 ok(Reflect
.has(b
, 1), `test 1 property`);
552 ok(!Reflect
.has(b
, 2), `test 2 property`);
554 // Test other property
561 ].forEach(function([property
, value
]) {
562 ok(!Reflect
.has(b
, property
), `test ${property} property before setting property value`);
564 ok(Reflect
.has(b
, property
), `test ${property} property after setting property value`);
568 add_task(function testObservableArrayExoticObjects_ownKeys() {
569 let m
= new TestInterfaceObservableArray();
570 m
.observableArrayBoolean
= [true, false];
572 let b
= m
.observableArrayBoolean
;
573 ok(Array
.isArray(b
), "observable array should be an array type");
574 is(b
.length
, 2, "length of observable array should be 2");
576 // Add other properties
582 let keys
= Reflect
.ownKeys(b
);
583 SimpleTest
.isDeeply(keys
, ["0", "1", "length", "prop1", "prop2", "prop3", "prop4"], `test property keys`);
586 add_task(function testObservableArrayExoticObjects_preventExtensions() {
587 let m
= new TestInterfaceObservableArray();
588 let b
= m
.observableArrayBoolean
;
589 ok(Array
.isArray(b
), "observable array should be an array type");
590 is(b
.length
, 0, "length of observable array should be 0");
592 // Test preventExtensions
593 ok(Reflect
.isExtensible(b
), "test isExtensible before preventExtensions");
594 ok(!Reflect
.preventExtensions(b
), "test preventExtensions");
595 ok(Reflect
.isExtensible(b
), "test isExtensible after preventExtensions");
598 add_task(function testObservableArrayExoticObjects_set() {
599 let setCallbackCount
= 0;
600 let deleteCallbackCount
= 0;
601 let setCallbackTests
= null;
602 let deleteCallbackTests
= null;
604 let m
= new TestInterfaceObservableArray({
605 setBooleanCallback(value
, index
) {
607 if (typeof setCallbackTests
=== 'function') {
608 setCallbackTests(value
, index
);
611 deleteBooleanCallback(value
, index
) {
612 deleteCallbackCount
++;
613 if (typeof deleteCallbackTests
=== 'function') {
614 deleteCallbackTests(value
, index
);
618 m
.observableArrayBoolean
= [true, true, true];
620 let b
= m
.observableArrayBoolean
;
621 ok(Array
.isArray(b
), "observable array should be an array type");
622 is(b
.length
, 3, "length of observable array should be 3");
626 // [length, shouldThrow, expectedResult]
627 // Invalid length value
631 // length value should not greater than current length
632 [b
.length
+ 1, false, false],
634 [b
.length
, false, true],
635 [b
.length
- 1, false, true],
637 ].forEach(function([length
, shouldThrow
, expectedResult
]) {
639 let oldLen
= b
.length
;
640 let oldValues
= b
.slice();
641 setCallbackCount
= 0;
642 deleteCallbackCount
= 0;
643 setCallbackTests
= null;
644 let deleteCallbackIndex
= oldLen
- 1;
645 deleteCallbackTests = function(_value
, _index
) {
646 is(_value
, oldValues
[deleteCallbackIndex
], "deleteCallbackTests: test value argument");
647 is(_index
, deleteCallbackIndex
, "deleteCallbackTests: test index argument");
648 deleteCallbackIndex
--;
652 info(`setting "length" property value to ${length}`);
654 is(Reflect
.set(b
, "length", length
), expectedResult
, `Reflect.set should return ${expectedResult}`);
655 ok(!shouldThrow
, "Reflect.set should not throw");
657 ok(shouldThrow
, `Reflect.set throws ${e}`);
659 is(setCallbackCount
, 0, "setCallback count");
660 is(deleteCallbackCount
, expectedResult
? oldLen
- length
: 0, "deleteCallback count");
661 isDeeply(b
, expectedResult
? oldValues
.slice(0, length
) : oldValues
, "property values");
662 is(b
.length
, expectedResult
? length
: oldLen
, "length of observable array");
665 // Test indexed value
667 // [index, value, shouldThrow, expectedResult]
668 // Index could not greater than last index.
669 [b
.length
+ 1, true, false, false],
671 [b
.length
, true, false, true],
672 [b
.length
+ 1, true, false, true],
673 ].forEach(function([index
, value
, shouldThrow
, expectedResult
]) {
675 let oldLen
= b
.length
;
676 let oldValue
= b
[index
];
677 setCallbackCount
= 0;
678 deleteCallbackCount
= 0;
679 setCallbackTests = function(_value
, _index
) {
680 is(_value
, value
, "setCallbackTests: test value argument");
681 is(_index
, index
, "setCallbackTests: test index argument");
683 deleteCallbackTests = function(_value
, _index
) {
684 is(_value
, oldValue
, "deleteCallbackTests: test value argument");
685 is(_index
, index
, "deleteCallbackTests: test index argument");
689 info(`setting ${index} property to ${value}`);
691 is(Reflect
.set(b
, index
, value
), expectedResult
, `Reflect.set should return ${expectedResult}`);
692 ok(!shouldThrow
, "Reflect.set should not throw");
694 ok(shouldThrow
, `Reflect.set throws ${e}`);
696 is(setCallbackCount
, expectedResult
? 1 : 0, "setCallback count");
697 is(deleteCallbackCount
, (oldLen
> index
) ? 1 : 0, "deleteCallback count");
698 is(b
[index
], expectedResult
? value
: oldValue
, "property value");
699 is(b
.length
, expectedResult
? Math
.max(index
+ 1, oldLen
) : oldLen
, "length of observable array");
702 // Test other property
710 ].forEach(function([property
, value
]) {
712 let oldLen
= b
.length
;
713 setCallbackCount
= 0;
714 deleteCallbackCount
= 0;
715 setCallbackTests
= null;
716 deleteCallbackTests
= null;
719 info(`setting ${property} property to ${value}`);
720 ok(Reflect
.set(b
, property
, value
), "Reflect.defineProperty should return true");
721 is(setCallbackCount
, 0, "setCallback count");
722 is(deleteCallbackCount
, 0, "deleteCallback count");
723 is(b
[property
], value
, "property value");
724 is(b
.length
, oldLen
, "length of observable array");
728 add_task(function testObservableArrayExoticObjects_set_callback_throw() {
729 let setCallbackCount
= 0;
730 let deleteCallbackCount
= 0;
733 let m
= new TestInterfaceObservableArray({
734 setBooleanCallback(value
) {
737 throw new Error("setBooleanCallback");
740 deleteBooleanCallback(value
, index
) {
741 deleteCallbackCount
++;
742 if (index
< minLen
) {
743 throw new Error("deleteBooleanCallback");
747 m
.observableArrayBoolean
= [false, false, false, false, false];
749 let b
= m
.observableArrayBoolean
;
750 ok(Array
.isArray(b
), "observable array should be an array type");
751 is(b
.length
, 5, "length of observable array should be 3");
755 // [value, shouldThrow]
757 [b
.length
- 1, false],
759 ].forEach(function([length
, shouldThrow
]) {
761 let oldValues
= b
.slice();
762 let oldLen
= b
.length
;
763 setCallbackCount
= 0;
764 deleteCallbackCount
= 0;
767 info(`setting "length" property to ${length}`);
769 ok(Reflect
.set(b
, "length", length
), "Reflect.set should return true");
770 ok(!shouldThrow
, `Reflect.set should not throw`);
772 ok(shouldThrow
, `Reflect.set throws ${e}`);
774 is(setCallbackCount
, 0, "setCallback should not be called");
775 is(deleteCallbackCount
, oldLen
- (shouldThrow
? minLen
- 1 : length
), "deleteCallback count");
776 isDeeply(b
, oldValues
.slice(0, shouldThrow
? minLen
: length
), "property values");
777 is(b
.length
, shouldThrow
? minLen
: length
, "length of observable array");
780 // Test indexed value
782 // [index, value, shouldThrow]
783 [b
.length
, true, true],
784 [b
.length
, false, false],
785 [b
.length
+ 1, false, false],
786 [b
.length
+ 1, true, true],
789 ].forEach(function([index
, value
, shouldThrow
]) {
791 let oldValue
= b
[index
];
792 let oldLen
= b
.length
;
793 setCallbackCount
= 0;
794 deleteCallbackCount
= 0;
797 info(`setting ${index} property to ${value}`);
799 ok(Reflect
.set(b
, index
, value
), "Reflect.set should return true");
800 ok(!shouldThrow
, `Reflect.set should not throw`);
802 ok(shouldThrow
, `Reflect.set throws ${e}`);
804 is(setCallbackCount
, (index
< minLen
) ? 0 : 1, "setCallback count");
805 is(deleteCallbackCount
, (oldLen
> index
) ? 1 : 0, "deleteCallback count");
806 is(b
[index
], shouldThrow
? oldValue
: value
, "property value");
807 is(b
.length
, shouldThrow
? oldLen
: Math
.max(oldLen
, index
+ 1), "length of observable array");
810 // Test other property
817 ].forEach(function([property
, value
]) {
819 let oldLen
= b
.length
;
820 setCallbackCount
= 0;
821 deleteCallbackCount
= 0;
824 info(`setting ${property} property to ${JSON.stringify(value)}`);
826 ok(Reflect
.set(b
, property
, value
), "Reflect.set should return true");
827 ok(true, `Reflect.set should not throw`);
829 ok(false, `Reflect.set throws ${e}`);
831 is(setCallbackCount
, 0, "setCallback should not be called");
832 is(deleteCallbackCount
, 0, "deleteCallback should be called");
833 is(b
[property
], value
, "property value");
834 is(b
.length
, oldLen
, "length of observable array");
838 add_task(function testObservableArrayExoticObjects_invalidtype() {
839 let m
= new TestInterfaceObservableArray();
840 let i
= m
.observableArrayInterface
;
841 ok(Array
.isArray(i
), "Observable array should be an array type");
842 is(i
.length
, 0, "length should be 0");
844 [true, "invalid"].forEach(function(value
) {
845 SimpleTest
.doesThrow(() => {
846 let descriptor
= {configurable
: true, enumerable
: true, writable
: true, value
};
847 Reflect
.defineProperty(i
, i
.length
, descriptor
);
848 }, `defining ${i.length} property with ${JSON.stringify(value)} should throw`);
850 SimpleTest
.doesThrow(() => {
851 Reflect
.set(i
, i
.length
, value
);
852 }, `setting ${i.length} property to ${JSON.stringify(value)} should throw`);
855 is(i
.length
, 0, "length should still be 0");