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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial