Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // |reftest| skip -- not a test.
2 // Any copyright is dedicated to the Public Domain.
3 // http://creativecommons.org/licenses/publicdomain/
5 assertEq("defineProperty" in Object, true);
6 assertEq(Object.defineProperty.length, 3);
8 /*
9 * Disable an assertion that is pathologically slow given the exhaustiveness of
10 * these tests.
11 */
12 if (typeof enableStackWalkingAssertion === "function")
13 enableStackWalkingAssertion(false);
15 if (!Object.prototype.toSource)
16 {
17 Object.defineProperty(Object.prototype, "toSource",
18 {
19 value: function toSource()
20 {
21 if (this instanceof RegExp)
22 {
23 var v = "new RegExp(" + uneval(this.source);
24 var f = (this.multiline ? "m" : "") +
25 (this.global ? "g" : "") +
26 (this.ignoreCase ? "i" : "");
27 return v + (f ? ", '" + f + "'" : "") + ")";
28 }
29 return JSON.stringify(this);
30 },
31 enumerable: false,
32 configurable: true,
33 writable: true
34 });
35 }
36 if (!("uneval" in this))
37 {
38 Object.defineProperty(this, "uneval",
39 {
40 value: function uneval(v)
41 {
42 if (v === null)
43 return "null";
44 if (typeof v === "object")
45 return v.toSource();
46 if (typeof v === "string")
47 {
48 v = JSON.stringify({v:v});
49 return v.substring(5, v.length - 1);
50 }
51 return "" + v;
52 },
53 enumerable: false,
54 configurable: true,
55 writable: true
56 });
57 }
59 // reimplemented for the benefit of engines which don't have this helper
60 function assertEq(v1, v2, m)
61 {
62 if (!SameValue(v1, v2))
63 {
64 throw "assertion failed: " +
65 "got " + uneval(v1) + ", expected " + uneval(v2) +
66 (m ? ": " + m : "");
67 }
68 }
70 function SameValue(v1, v2)
71 {
72 if (v1 === 0 && v2 === 0)
73 return 1 / v1 === 1 / v2;
74 if (v1 !== v1 && v2 !== v2)
75 return true;
76 return v1 === v2;
77 }
79 function PropertyDescriptor(pd)
80 {
81 if (pd)
82 this.update(pd);
83 }
84 PropertyDescriptor.prototype.update = function update(pd)
85 {
86 if ("get" in pd)
87 this.get = pd.get;
88 if ("set" in pd)
89 this.set = pd.set;
90 if ("configurable" in pd)
91 this.configurable = pd.configurable;
92 if ("writable" in pd)
93 this.writable = pd.writable;
94 if ("enumerable" in pd)
95 this.enumerable = pd.enumerable;
96 if ("value" in pd)
97 this.value = pd.value;
98 };
99 PropertyDescriptor.prototype.convertToDataDescriptor = function convertToDataDescriptor()
100 {
101 delete this.get;
102 delete this.set;
103 this.writable = false;
104 this.value = undefined;
105 };
106 PropertyDescriptor.prototype.convertToAccessorDescriptor = function convertToAccessorDescriptor()
107 {
108 delete this.writable;
109 delete this.value;
110 this.get = undefined;
111 this.set = undefined;
112 };
114 function compareDescriptors(d1, d2)
115 {
116 if (d1 === undefined)
117 {
118 assertEq(d2, undefined, "non-descriptors");
119 return;
120 }
121 if (d2 === undefined)
122 {
123 assertEq(true, false, "descriptor-equality mismatch: " + uneval(d1) + ", " + uneval(d2));
124 return;
125 }
127 var props = ["value", "get", "set", "enumerable", "configurable", "writable"];
128 for (var i = 0, sz = props.length; i < sz; i++)
129 {
130 var p = props[i];
131 assertEq(p in d1, p in d2, p + " different in d1/d2");
132 if (p in d1)
133 assertEq(d1[p], d2[p], p);
134 }
135 }
137 function examine(desc, field, allowDefault)
138 {
139 if (field in desc)
140 return desc[field];
141 assertEq(allowDefault, true, "reimplementation error");
142 switch (field)
143 {
144 case "value":
145 case "get":
146 case "set":
147 return undefined;
148 case "writable":
149 case "enumerable":
150 case "configurable":
151 return false;
152 default:
153 assertEq(true, false, "bad field name: " + field);
154 }
155 }
157 function IsAccessorDescriptor(desc)
158 {
159 if (!desc)
160 return false;
161 if (!("get" in desc) && !("set" in desc))
162 return false;
163 return true;
164 }
166 function IsDataDescriptor(desc)
167 {
168 if (!desc)
169 return false;
170 if (!("value" in desc) && !("writable" in desc))
171 return false;
172 return true;
173 }
175 function IsGenericDescriptor(desc)
176 {
177 if (!desc)
178 return false;
179 if (!IsAccessorDescriptor(desc) && !IsDataDescriptor(desc))
180 return true;
181 return false;
182 }
186 function CustomObject()
187 {
188 this.properties = {};
189 this.extensible = true;
190 }
191 CustomObject.prototype =
192 {
193 _reject: function _reject(throwing, msg)
194 {
195 if (throwing)
196 throw new TypeError(msg + "; rejected!");
197 return false;
198 },
199 defineOwnProperty: function defineOwnProperty(propname, desc, throwing)
200 {
201 assertEq(typeof propname, "string", "non-string propname");
203 // Step 1.
204 var current = this.properties[propname];
206 // Step 2.
207 var extensible = this.extensible;
209 // Step 3.
210 if (current === undefined && !extensible)
211 return this._reject(throwing, "object not extensible");
213 // Step 4.
214 if (current === undefined && extensible)
215 {
216 var p;
217 // Step 4(a).
218 if (IsGenericDescriptor(desc) || IsDataDescriptor(desc))
219 {
220 p = new PropertyDescriptor();
221 p.value = examine(desc, "value", true);
222 p.writable = examine(desc, "writable", true);
223 p.enumerable = examine(desc, "enumerable", true);
224 p.configurable = examine(desc, "configurable", true);
225 }
226 // Step 4(b).
227 else
228 {
229 p = new PropertyDescriptor();
230 p.get = examine(desc, "get", true);
231 p.set = examine(desc, "set", true);
232 p.enumerable = examine(desc, "enumerable", true);
233 p.configurable = examine(desc, "configurable", true);
234 }
236 this.properties[propname] = p;
238 // Step 4(c).
239 return true;
240 }
242 // Step 5.
243 if (!("value" in desc) && !("get" in desc) && !("set" in desc) &&
244 !("writable" in desc) && !("enumerable" in desc) &&
245 !("configurable" in desc))
246 {
247 return;
248 }
250 // Step 6.
251 do
252 {
253 if ("value" in desc)
254 {
255 if (!("value" in current) || !SameValue(desc.value, current.value))
256 break;
257 }
258 if ("get" in desc)
259 {
260 if (!("get" in current) || !SameValue(desc.get, current.get))
261 break;
262 }
263 if ("set" in desc)
264 {
265 if (!("set" in current) || !SameValue(desc.set, current.set))
266 break;
267 }
268 if ("writable" in desc)
269 {
270 if (!("writable" in current) ||
271 !SameValue(desc.writable, current.writable))
272 {
273 break;
274 }
275 }
276 if ("enumerable" in desc)
277 {
278 if (!("enumerable" in current) ||
279 !SameValue(desc.enumerable, current.enumerable))
280 {
281 break;
282 }
283 }
284 if ("configurable" in desc)
285 {
286 if (!("configurable" in current) ||
287 !SameValue(desc.configurable, current.configurable))
288 {
289 break;
290 }
291 }
293 // all fields in desc also in current, with the same values
294 return true;
295 }
296 while (false);
298 // Step 7.
299 if (!examine(current, "configurable"))
300 {
301 if ("configurable" in desc && examine(desc, "configurable"))
302 return this._reject(throwing, "can't make configurable again");
303 if ("enumerable" in desc &&
304 examine(current, "enumerable") !== examine(desc, "enumerable"))
305 {
306 return this._reject(throwing, "can't change enumerability");
307 }
308 }
310 // Step 8.
311 if (IsGenericDescriptor(desc))
312 {
313 // do nothing
314 }
315 // Step 9.
316 else if (IsDataDescriptor(current) !== IsDataDescriptor(desc))
317 {
318 // Step 9(a).
319 if (!examine(current, "configurable"))
320 return this._reject(throwing, "can't change unconfigurable descriptor's type");
321 // Step 9(b).
322 if (IsDataDescriptor(current))
323 current.convertToAccessorDescriptor();
324 // Step 9(c).
325 else
326 current.convertToDataDescriptor();
327 }
328 // Step 10.
329 else if (IsDataDescriptor(current) && IsDataDescriptor(desc))
330 {
331 // Step 10(a)
332 if (!examine(current, "configurable"))
333 {
334 // Step 10(a).i.
335 if (!examine(current, "writable") &&
336 "writable" in desc && examine(desc, "writable"))
337 {
338 return this._reject(throwing, "can't make data property writable again");
339 }
340 // Step 10(a).ii.
341 if (!examine(current, "writable"))
342 {
343 if ("value" in desc &&
344 !SameValue(examine(desc, "value"), examine(current, "value")))
345 {
346 return this._reject(throwing, "can't change value if not writable");
347 }
348 }
349 }
350 // Step 10(b).
351 else
352 {
353 assertEq(examine(current, "configurable"), true,
354 "spec bug step 10(b)");
355 }
356 }
357 // Step 11.
358 else
359 {
360 assertEq(IsAccessorDescriptor(current) && IsAccessorDescriptor(desc),
361 true,
362 "spec bug");
364 // Step 11(a).
365 if (!examine(current, "configurable"))
366 {
367 // Step 11(a).i.
368 if ("set" in desc &&
369 !SameValue(examine(desc, "set"), examine(current, "set")))
370 {
371 return this._reject(throwing, "can't change setter if not configurable");
372 }
373 // Step 11(a).ii.
374 if ("get" in desc &&
375 !SameValue(examine(desc, "get"), examine(current, "get")))
376 {
377 return this._reject(throwing, "can't change getter if not configurable");
378 }
379 }
380 }
382 // Step 12.
383 current.update(desc);
385 // Step 13.
386 return true;
387 }
388 };
390 function IsCallable(v)
391 {
392 return typeof v === "undefined" || typeof v === "function";
393 }
395 var NativeTest =
396 {
397 newObject: function newObject()
398 {
399 return {};
400 },
401 defineProperty: function defineProperty(obj, propname, propdesc)
402 {
403 Object.defineProperty(obj, propname, propdesc);
404 },
405 getDescriptor: function getDescriptor(obj, propname)
406 {
407 return Object.getOwnPropertyDescriptor(obj, propname);
408 }
409 };
411 var ReimplTest =
412 {
413 newObject: function newObject()
414 {
415 return new CustomObject();
416 },
417 defineProperty: function defineProperty(obj, propname, propdesc)
418 {
419 assertEq(obj instanceof CustomObject, true, "obj not instanceof CustomObject");
420 if ("get" in propdesc || "set" in propdesc)
421 {
422 if ("value" in propdesc || "writable" in propdesc)
423 throw new TypeError("get/set and value/writable");
424 if (!IsCallable(propdesc.get))
425 throw new TypeError("get defined, uncallable");
426 if (!IsCallable(propdesc.set))
427 throw new TypeError("set defined, uncallable");
428 }
429 return obj.defineOwnProperty(propname, propdesc, true);
430 },
431 getDescriptor: function getDescriptor(obj, propname)
432 {
433 if (!(propname in obj.properties))
434 return undefined;
436 return new PropertyDescriptor(obj.properties[propname]);
437 }
438 };
440 var JSVAL_INT_MAX = Math.pow(2, 30) - 1;
441 var JSVAL_INT_MIN = -Math.pow(2, 30);
444 function isValidDescriptor(propdesc)
445 {
446 if ("get" in propdesc || "set" in propdesc)
447 {
448 if ("value" in propdesc || "writable" in propdesc)
449 return false;
451 // We permit null here simply because this test's author believes the
452 // implementation may sometime be susceptible to making mistakes in this
453 // regard and would prefer to be cautious.
454 if (propdesc.get !== null && propdesc.get !== undefined && !IsCallable(propdesc.get))
455 return false;
456 if (propdesc.set !== null && propdesc.set !== undefined && !IsCallable(propdesc.set))
457 return false;
458 }
460 return true;
461 }
464 var OMIT = {};
465 var VALUES =
466 [-Infinity, JSVAL_INT_MIN, -0, +0, 1.5, JSVAL_INT_MAX, Infinity,
467 NaN, "foo", "bar", null, undefined, true, false, {}, /a/, OMIT];
468 var GETS =
469 [undefined, function get1() { return 1; }, function get2() { return 2; },
470 null, 5, OMIT];
471 var SETS =
472 [undefined, function set1() { return 1; }, function set2() { return 2; },
473 null, 5, OMIT];
474 var ENUMERABLES = [true, false, OMIT];
475 var CONFIGURABLES = [true, false, OMIT];
476 var WRITABLES = [true, false, OMIT];
478 function mapTestDescriptors(filter)
479 {
480 var descs = [];
481 var desc = {};
483 function put(field, value)
484 {
485 if (value !== OMIT)
486 desc[field] = value;
487 }
489 VALUES.forEach(function(value)
490 {
491 GETS.forEach(function(get)
492 {
493 SETS.forEach(function(set)
494 {
495 ENUMERABLES.forEach(function(enumerable)
496 {
497 CONFIGURABLES.forEach(function(configurable)
498 {
499 WRITABLES.forEach(function(writable)
500 {
501 desc = {};
502 put("value", value);
503 put("get", get);
504 put("set", set);
505 put("enumerable", enumerable);
506 put("configurable", configurable);
507 put("writable", writable);
508 if (filter(desc))
509 descs.push(desc);
510 });
511 });
512 });
513 });
514 });
515 });
517 return descs;
518 }
520 var ALL_DESCRIPTORS = mapTestDescriptors(function(d) { return true; });
521 var VALID_DESCRIPTORS = mapTestDescriptors(isValidDescriptor);
523 var SKIP_FULL_FUNCTION_LENGTH_TESTS = true;
525 function TestRunner()
526 {
527 this._logLines = [];
528 }
529 TestRunner.prototype =
530 {
531 // MAIN METHODS
533 runFunctionLengthTests: function runFunctionLengthTests()
534 {
535 var self = this;
536 function functionLengthTests()
537 {
538 if (SKIP_FULL_FUNCTION_LENGTH_TESTS)
539 {
540 print("Skipping full tests for redefining Function.length for now " +
541 "because we don't support redefinition of properties with " +
542 "native getter or setter...");
543 self._simpleFunctionLengthTests();
544 }
545 else
546 {
547 self._simpleFunctionLengthTests();
548 self._fullFunctionLengthTests(function() { }, 0);
549 self._fullFunctionLengthTests(function(one) { }, 1);
550 self._fullFunctionLengthTests(function(one, two) { }, 2);
551 }
552 }
554 this._runTestSet(functionLengthTests, "Function length tests completed!");
555 },
557 runNotPresentTests: function runNotPresentTests()
558 {
559 var self = this;
560 function notPresentTests()
561 {
562 print("Running not-present tests now...");
564 for (var i = 0, sz = ALL_DESCRIPTORS.length; i < sz; i++)
565 self._runSingleNotPresentTest(ALL_DESCRIPTORS[i]);
566 };
568 this._runTestSet(notPresentTests, "Not-present length tests completed!");
569 },
571 runPropertyPresentTestsFraction:
572 function runPropertyPresentTestsFraction(part, parts)
573 {
574 var self = this;
575 function propertyPresentTests()
576 {
577 print("Running already-present tests now...");
579 var total = VALID_DESCRIPTORS.length;
580 var start = Math.floor((part - 1) / parts * total);
581 var end = Math.floor(part / parts * total);
583 for (var i = start; i < end; i++)
584 {
585 var old = VALID_DESCRIPTORS[i];
586 print("Starting test with old descriptor " + old.toSource() + "...");
588 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
589 self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []);
590 }
591 }
593 this._runTestSet(propertyPresentTests,
594 "Property-present fraction " + part + " of " + parts +
595 " completed!");
596 },
598 runNonTerminalPropertyPresentTestsFraction:
599 function runNonTerminalPropertyPresentTestsFraction(part, parts)
600 {
601 var self = this;
603 /*
604 * A plain old property to define on the object before redefining the
605 * originally-added property, to test redefinition of a property that's
606 * not also lastProperty. NB: we could loop over every possible
607 * descriptor here if we wanted, even try adding more than one, but we'd
608 * hit cubic complexity and worse, and SpiderMonkey only distinguishes by
609 * the mere presence of the middle property, not its precise details.
610 */
611 var middleDefines =
612 [{
613 property: "middle",
614 descriptor:
615 { value: 17, writable: true, configurable: true, enumerable: true }
616 }];
618 function nonTerminalPropertyPresentTests()
619 {
620 print("Running non-terminal already-present tests now...");
622 var total = VALID_DESCRIPTORS.length;
623 var start = Math.floor((part - 1) / parts * total);
624 var end = Math.floor(part / parts * total);
626 for (var i = start; i < end; i++)
627 {
628 var old = VALID_DESCRIPTORS[i];
629 print("Starting test with old descriptor " + old.toSource() + "...");
631 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
632 {
633 self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j],
634 middleDefines);
635 }
636 }
637 }
639 this._runTestSet(nonTerminalPropertyPresentTests,
640 "Non-terminal property-present fraction " +
641 part + " of " + parts + " completed!");
642 },
644 runDictionaryPropertyPresentTestsFraction:
645 function runDictionaryPropertyPresentTestsFraction(part, parts)
646 {
647 var self = this;
649 /*
650 * Add and readd properties such that the scope for the object is in
651 * dictionary mode.
652 */
653 var middleDefines =
654 [
655 {
656 property: "mid1",
657 descriptor:
658 { value: 17, writable: true, configurable: true, enumerable: true }
659 },
660 {
661 property: "mid2",
662 descriptor:
663 { value: 17, writable: true, configurable: true, enumerable: true }
664 },
665 {
666 property: "mid1",
667 descriptor:
668 { get: function g() { }, set: function s(v){}, configurable: false,
669 enumerable: true }
670 },
671 ];
673 function dictionaryPropertyPresentTests()
674 {
675 print("Running dictionary already-present tests now...");
677 var total = VALID_DESCRIPTORS.length;
678 var start = Math.floor((part - 1) / parts * total);
679 var end = Math.floor(part / parts * total);
681 for (var i = start; i < end; i++)
682 {
683 var old = VALID_DESCRIPTORS[i];
684 print("Starting test with old descriptor " + old.toSource() + "...");
686 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
687 {
688 self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j],
689 middleDefines);
690 }
691 }
692 }
694 this._runTestSet(dictionaryPropertyPresentTests,
695 "Dictionary property-present fraction " +
696 part + " of " + parts + " completed!");
697 },
700 // HELPERS
702 runPropertyPresentTests: function runPropertyPresentTests()
703 {
704 print("Running already-present tests now...");
706 for (var i = 0, sz = VALID_DESCRIPTORS.length; i < sz; i++)
707 {
708 var old = VALID_DESCRIPTORS[i];
709 print("Starting test with old descriptor " + old.toSource() + "...");
711 for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
712 this._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []);
713 }
714 },
715 _runTestSet: function _runTestSet(fun, completeMessage)
716 {
717 try
718 {
719 fun();
721 print(completeMessage);
722 }
723 catch (e)
724 {
725 print("ERROR, EXITING (line " + (e.lineNumber || -1) + "): " + e);
726 throw e;
727 }
728 finally
729 {
730 this._reportAllErrors();
731 }
732 },
733 _reportAllErrors: function _reportAllErrors()
734 {
735 var errorCount = this._logLines.length;
736 print("Full accumulated number of errors: " + errorCount);
737 if (errorCount > 0)
738 throw errorCount + " errors detected, FAIL";
739 },
740 _simpleFunctionLengthTests: function _simpleFunctionLengthTests(fun)
741 {
742 print("Running simple Function.length tests now..");
744 function expectThrowTypeError(o, p, desc)
745 {
746 var err = "<none>", passed = false;
747 try
748 {
749 Object.defineProperty(o, p, desc);
750 }
751 catch (e)
752 {
753 err = e;
754 passed = e instanceof TypeError;
755 }
756 assertEq(passed, true, fun + " didn't throw TypeError when called: " + err);
757 }
759 expectThrowTypeError(function a() { }, "length", { value: 1 });
760 expectThrowTypeError(function a() { }, "length", { enumerable: true });
761 expectThrowTypeError(function a() { }, "length", { configurable: true });
762 expectThrowTypeError(function a() { }, "length", { writable: true });
763 },
764 _fullFunctionLengthTests: function _fullFunctionLengthTests(fun)
765 {
766 var len = fun.length;
767 print("Running Function.length (" + len + ") tests now...");
769 var desc;
770 var gen = new DescriptorState();
771 while ((desc = gen.nextDescriptor()))
772 this._runSingleFunctionLengthTest(fun, len, desc);
773 },
774 _log: function _log(v)
775 {
776 var m = "" + v;
777 print(m);
778 this._logLines.push(m);
779 },
780 _runSingleNotPresentTest: function _runSingleNotPresentTest(desc)
781 {
782 var nativeObj = NativeTest.newObject();
783 var reimplObj = ReimplTest.newObject();
785 try
786 {
787 NativeTest.defineProperty(nativeObj, "foo", desc);
788 }
789 catch (e)
790 {
791 try
792 {
793 ReimplTest.defineProperty(reimplObj, "foo", desc);
794 }
795 catch (e2)
796 {
797 if (e.constructor !== e2.constructor)
798 {
799 this._log("Difference when comparing native/reimplementation " +
800 "behavior for new descriptor " + desc.toSource() +
801 ", native threw " + e + ", reimpl threw " + e2);
802 }
803 return;
804 }
805 this._log("Difference when comparing native/reimplementation " +
806 "behavior for new descriptor " + desc.toSource() +
807 ", error " + e);
808 return;
809 }
811 try
812 {
813 ReimplTest.defineProperty(reimplObj, "foo", desc);
814 }
815 catch (e)
816 {
817 this._log("Reimpl threw defining new descriptor " + desc.toSource() +
818 ", error: " + e);
819 return;
820 }
822 var nativeDesc = NativeTest.getDescriptor(nativeObj, "foo");
823 var reimplDesc = ReimplTest.getDescriptor(reimplObj, "foo");
824 try
825 {
826 compareDescriptors(nativeDesc, reimplDesc);
827 }
828 catch (e)
829 {
830 this._log("Difference comparing returned descriptors for new " +
831 "property defined with descriptor " + desc.toSource() +
832 "; error: " + e);
833 return;
834 }
835 },
836 _runSinglePropertyPresentTest:
837 function _runSinglePropertyPresentTest(old, add, middleDefines)
838 {
839 var nativeObj = NativeTest.newObject();
840 var reimplObj = ReimplTest.newObject();
842 try
843 {
844 NativeTest.defineProperty(nativeObj, "foo", old);
845 }
846 catch (e)
847 {
848 if (!SameValue(NativeTest.getDescriptor(nativeObj, "foo"), undefined))
849 {
850 this._log("defining bad property descriptor: " + old.toSource());
851 return;
852 }
854 try
855 {
856 ReimplTest.defineProperty(reimplObj, "foo", old);
857 }
858 catch (e2)
859 {
860 if (!SameValue(ReimplTest.getDescriptor(reimplObj, "foo"),
861 undefined))
862 {
863 this._log("defining bad property descriptor: " + old.toSource() +
864 "; reimplObj: " + uneval(reimplObj));
865 }
867 if (e.constructor !== e2.constructor)
868 {
869 this._log("Different errors defining bad property descriptor: " +
870 old.toSource() + "; native threw " + e + ", reimpl " +
871 "threw " + e2);
872 }
874 return;
875 }
877 this._log("Difference defining a property with descriptor " +
878 old.toSource() + ", error " + e);
879 return;
880 }
882 try
883 {
884 ReimplTest.defineProperty(reimplObj, "foo", old);
885 }
886 catch (e)
887 {
888 this._log("Difference when comparing native/reimplementation " +
889 "behavior when adding descriptor " + add.toSource() +
890 ", error: " + e);
891 return;
892 }
894 // Now add (or even readd) however many properties were specified between
895 // the original property to add and the new one, to test redefining
896 // non-last-properties and properties in scopes in dictionary mode.
897 for (var i = 0, sz = middleDefines.length; i < sz; i++)
898 {
899 var middle = middleDefines[i];
900 var prop = middle.property;
901 var desc = middle.descriptor;
903 try
904 {
905 NativeTest.defineProperty(nativeObj, prop, desc);
906 ReimplTest.defineProperty(reimplObj, prop, desc);
907 }
908 catch (e)
909 {
910 this._log("failure defining middle descriptor: " + desc.toSource() +
911 ", error " + e);
912 return;
913 }
915 // Sanity check
916 var nativeDesc = NativeTest.getDescriptor(nativeObj, prop);
917 var reimplDesc = ReimplTest.getDescriptor(reimplObj, prop);
919 compareDescriptors(nativeDesc, reimplDesc);
920 compareDescriptors(nativeDesc, desc);
921 }
923 try
924 {
925 NativeTest.defineProperty(nativeObj, "foo", add);
926 }
927 catch (e)
928 {
929 try
930 {
931 ReimplTest.defineProperty(reimplObj, "foo", add);
932 }
933 catch (e2)
934 {
935 if (e.constructor !== e2.constructor)
936 {
937 this._log("Difference when comparing native/reimplementation " +
938 "behavior for descriptor " + add.toSource() +
939 " overwriting descriptor " + old.toSource() + "; " +
940 "native threw " + e + ", reimpl threw " + e2);
941 }
942 return;
943 }
944 this._log("Difference when comparing native/reimplementation " +
945 "behavior for added descriptor " + add.toSource() + ", " +
946 "initial was " + old.toSource() + "; error: " + e);
947 return;
948 }
950 try
951 {
952 ReimplTest.defineProperty(reimplObj, "foo", add);
953 }
954 catch (e)
955 {
956 this._log("Difference when comparing native/reimplementation " +
957 "behavior for readded descriptor " + add.toSource() + ", " +
958 "initial was " + old.toSource() + "; native readd didn't " +
959 "throw, reimpl add did, error: " + e);
960 return;
961 }
963 var nativeDesc = NativeTest.getDescriptor(nativeObj, "foo");
964 var reimplDesc = ReimplTest.getDescriptor(reimplObj, "foo");
965 try
966 {
967 compareDescriptors(nativeDesc, reimplDesc);
968 }
969 catch (e)
970 {
971 this._log("Difference comparing returned descriptors for readded " +
972 "property defined with descriptor " + add.toSource() + "; " +
973 "initial was " + old.toSource() + "; error: " + e);
974 return;
975 }
976 },
977 _runSingleFunctionLengthTest: function _runSingleFunctionLengthTest(fun, len, desc)
978 {
979 var nativeObj = fun;
980 var reimplObj = ReimplTest.newObject();
981 ReimplTest.defineProperty(reimplObj, "length",
982 {
983 value: len,
984 enumerable: false,
985 configurable: false,
986 writable: false
987 });
989 try
990 {
991 NativeTest.defineProperty(nativeObj, "length", desc);
992 }
993 catch (e)
994 {
995 try
996 {
997 ReimplTest.defineProperty(reimplObj, "length", desc);
998 }
999 catch (e2)
1000 {
1001 if (e.constructor !== e2.constructor)
1002 {
1003 this._log("Difference when comparing native/reimplementation " +
1004 "behavior defining fun.length with " + desc.toSource() +
1005 "; native threw " + e + ", reimpl threw " + e2);
1006 }
1007 return;
1008 }
1009 this._log("Difference when comparing Function.length native/reimpl " +
1010 "behavior for descriptor " + desc.toSource() +
1011 ", native impl threw error " + e);
1012 return;
1013 }
1015 try
1016 {
1017 ReimplTest.defineProperty(reimplObj, "length", desc);
1018 }
1019 catch (e)
1020 {
1021 this._log("Difference defining new Function.length descriptor: impl " +
1022 "succeeded, reimpl threw for descriptor " +
1023 desc.toSource() + ", error: " + e);
1024 return;
1025 }
1027 var nativeDesc = NativeTest.getDescriptor(nativeObj, "length");
1028 var reimplDesc = ReimplTest.getDescriptor(reimplObj, "length");
1029 try
1030 {
1031 compareDescriptors(nativeDesc, reimplDesc);
1032 }
1033 catch (e)
1034 {
1035 this._log("Difference comparing returned descriptors for " +
1036 "Function.length with descriptor " + desc.toSource() +
1037 "; error: " + e);
1038 return;
1039 }
1040 }
1041 };
1043 function runDictionaryPropertyPresentTestsFraction(PART, PARTS)
1044 {
1045 var testfile =
1046 '15.2.3.6-dictionary-redefinition-' + PART + '-of-' + PARTS + '.js';
1047 var BUGNUMBER = 560566;
1048 var summary =
1049 'ES5 Object.defineProperty(O, P, Attributes): dictionary redefinition ' +
1050 PART + ' of ' + PARTS;
1052 print(BUGNUMBER + ": " + summary);
1054 try
1055 {
1056 new TestRunner().runDictionaryPropertyPresentTestsFraction(PART, PARTS);
1057 }
1058 catch (e)
1059 {
1060 throw "Error thrown during testing: " + e +
1061 " at line " + e.lineNumber + "\n" +
1062 (e.stack
1063 ? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n"
1064 : "");
1065 }
1067 if (typeof reportCompare === "function")
1068 reportCompare(true, true);
1070 print("Tests complete!");
1071 }
1073 function runNonTerminalPropertyPresentTestsFraction(PART, PARTS)
1074 {
1075 var BUGNUMBER = 560566;
1076 var summary =
1077 'ES5 Object.defineProperty(O, P, Attributes): middle redefinition ' +
1078 PART + ' of ' + PARTS;
1080 print(BUGNUMBER + ": " + summary);
1083 /**************
1084 * BEGIN TEST *
1085 **************/
1087 try
1088 {
1089 new TestRunner().runNonTerminalPropertyPresentTestsFraction(PART, PARTS);
1090 }
1091 catch (e)
1092 {
1093 throw "Error thrown during testing: " + e +
1094 " at line " + e.lineNumber + "\n" +
1095 (e.stack
1096 ? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n"
1097 : "");
1098 }
1100 /******************************************************************************/
1102 if (typeof reportCompare === "function")
1103 reportCompare(true, true);
1105 print("Tests complete!");
1106 }