js/src/tests/ecma_5/Object/defineProperty-setup.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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)
  1001           if (e.constructor !== e2.constructor)
  1003             this._log("Difference when comparing native/reimplementation " +
  1004                       "behavior defining fun.length with " + desc.toSource() +
  1005                       "; native threw " + e + ", reimpl threw " + e2);
  1007           return;
  1009         this._log("Difference when comparing Function.length native/reimpl " +
  1010                   "behavior for descriptor " + desc.toSource() +
  1011                   ", native impl threw error " + e);
  1012         return;
  1015       try
  1017         ReimplTest.defineProperty(reimplObj, "length", desc);
  1019       catch (e)
  1021         this._log("Difference defining new Function.length descriptor: impl " +
  1022                   "succeeded, reimpl threw for descriptor " +
  1023                   desc.toSource() + ", error: " + e);
  1024         return;
  1027       var nativeDesc = NativeTest.getDescriptor(nativeObj, "length");
  1028       var reimplDesc = ReimplTest.getDescriptor(reimplObj, "length");
  1029       try
  1031         compareDescriptors(nativeDesc, reimplDesc);
  1033       catch (e)
  1035         this._log("Difference comparing returned descriptors for " +
  1036                   "Function.length with descriptor " + desc.toSource() +
  1037                   "; error: " + e);
  1038         return;
  1041   };
  1043 function runDictionaryPropertyPresentTestsFraction(PART, PARTS)
  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
  1056     new TestRunner().runDictionaryPropertyPresentTestsFraction(PART, PARTS);
  1058   catch (e)
  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             : "");
  1067   if (typeof reportCompare === "function")
  1068     reportCompare(true, true);
  1070   print("Tests complete!");
  1073 function runNonTerminalPropertyPresentTestsFraction(PART, PARTS)
  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
  1089     new TestRunner().runNonTerminalPropertyPresentTestsFraction(PART, PARTS);
  1091   catch (e)
  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             : "");
  1100   /******************************************************************************/
  1102   if (typeof reportCompare === "function")
  1103     reportCompare(true, true);
  1105   print("Tests complete!");

mercurial