summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/object/defineProperty-setup.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/object/defineProperty-setup.js')
-rw-r--r--js/src/tests/non262/object/defineProperty-setup.js1071
1 files changed, 1071 insertions, 0 deletions
diff --git a/js/src/tests/non262/object/defineProperty-setup.js b/js/src/tests/non262/object/defineProperty-setup.js
new file mode 100644
index 0000000000..da6fe8f496
--- /dev/null
+++ b/js/src/tests/non262/object/defineProperty-setup.js
@@ -0,0 +1,1071 @@
+// |reftest| skip -- not a test.
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+assertEq("defineProperty" in Object, true);
+assertEq(Object.defineProperty.length, 3);
+
+/*
+ * Disable an assertion that is pathologically slow given the exhaustiveness of
+ * these tests.
+ */
+if (typeof enableStackWalkingAssertion === "function")
+ enableStackWalkingAssertion(false);
+
+if (!Object.prototype.toSource)
+{
+ Object.defineProperty(Object.prototype, "toSource",
+ {
+ value: function toSource()
+ {
+ if (this instanceof RegExp)
+ {
+ var v = "new RegExp(" + uneval(this.source);
+ var f = (this.multiline ? "m" : "") +
+ (this.global ? "g" : "") +
+ (this.ignoreCase ? "i" : "");
+ return v + (f ? ", '" + f + "'" : "") + ")";
+ }
+ return JSON.stringify(this);
+ },
+ enumerable: false,
+ configurable: true,
+ writable: true
+ });
+}
+if (!("uneval" in this))
+{
+ Object.defineProperty(this, "uneval",
+ {
+ value: function uneval(v)
+ {
+ if (v === null)
+ return "null";
+ if (typeof v === "object")
+ return v.toSource();
+ if (typeof v === "string")
+ {
+ v = JSON.stringify({v:v});
+ return v.substring(5, v.length - 1);
+ }
+ return "" + v;
+ },
+ enumerable: false,
+ configurable: true,
+ writable: true
+ });
+}
+
+// reimplemented for the benefit of engines which don't have this helper
+function assertEq(v1, v2, m)
+{
+ if (!SameValue(v1, v2))
+ {
+ throw "assertion failed: " +
+ "got " + uneval(v1) + ", expected " + uneval(v2) +
+ (m ? ": " + m : "");
+ }
+}
+
+function SameValue(v1, v2)
+{
+ if (v1 === 0 && v2 === 0)
+ return 1 / v1 === 1 / v2;
+ if (v1 !== v1 && v2 !== v2)
+ return true;
+ return v1 === v2;
+}
+
+function PropertyDescriptor(pd)
+{
+ if (pd)
+ this.update(pd);
+}
+PropertyDescriptor.prototype.update = function update(pd)
+{
+ if ("get" in pd)
+ this.get = pd.get;
+ if ("set" in pd)
+ this.set = pd.set;
+ if ("configurable" in pd)
+ this.configurable = pd.configurable;
+ if ("writable" in pd)
+ this.writable = pd.writable;
+ if ("enumerable" in pd)
+ this.enumerable = pd.enumerable;
+ if ("value" in pd)
+ this.value = pd.value;
+};
+PropertyDescriptor.prototype.convertToDataDescriptor = function convertToDataDescriptor()
+{
+ delete this.get;
+ delete this.set;
+ this.writable = false;
+ this.value = undefined;
+};
+PropertyDescriptor.prototype.convertToAccessorDescriptor = function convertToAccessorDescriptor()
+{
+ delete this.writable;
+ delete this.value;
+ this.get = undefined;
+ this.set = undefined;
+};
+
+function compareDescriptors(d1, d2)
+{
+ if (d1 === undefined)
+ {
+ assertEq(d2, undefined, "non-descriptors");
+ return;
+ }
+ if (d2 === undefined)
+ {
+ assertEq(true, false, "descriptor-equality mismatch: " + uneval(d1) + ", " + uneval(d2));
+ return;
+ }
+
+ var props = ["value", "get", "set", "enumerable", "configurable", "writable"];
+ for (var i = 0, sz = props.length; i < sz; i++)
+ {
+ var p = props[i];
+ assertEq(p in d1, p in d2, p + " different in d1/d2");
+ if (p in d1)
+ assertEq(d1[p], d2[p], p);
+ }
+}
+
+function examine(desc, field, allowDefault)
+{
+ if (field in desc)
+ return desc[field];
+ assertEq(allowDefault, true, "reimplementation error");
+ switch (field)
+ {
+ case "value":
+ case "get":
+ case "set":
+ return undefined;
+ case "writable":
+ case "enumerable":
+ case "configurable":
+ return false;
+ default:
+ assertEq(true, false, "bad field name: " + field);
+ }
+}
+
+function IsAccessorDescriptor(desc)
+{
+ if (!desc)
+ return false;
+ if (!("get" in desc) && !("set" in desc))
+ return false;
+ return true;
+}
+
+function IsDataDescriptor(desc)
+{
+ if (!desc)
+ return false;
+ if (!("value" in desc) && !("writable" in desc))
+ return false;
+ return true;
+}
+
+function IsGenericDescriptor(desc)
+{
+ if (!desc)
+ return false;
+ if (!IsAccessorDescriptor(desc) && !IsDataDescriptor(desc))
+ return true;
+ return false;
+}
+
+
+
+function CustomObject()
+{
+ this.properties = {};
+ this.extensible = true;
+}
+CustomObject.prototype =
+{
+ _reject: function _reject(throwing, msg)
+ {
+ if (throwing)
+ throw new TypeError(msg + "; rejected!");
+ return false;
+ },
+ defineOwnProperty: function defineOwnProperty(propname, desc, throwing)
+ {
+ assertEq(typeof propname, "string", "non-string propname");
+
+ // Step 1.
+ var current = this.properties[propname];
+
+ // Step 2.
+ var extensible = this.extensible;
+
+ // Step 3.
+ if (current === undefined && !extensible)
+ return this._reject(throwing, "object not extensible");
+
+ // Step 4.
+ if (current === undefined && extensible)
+ {
+ var p;
+ // Step 4(a).
+ if (IsGenericDescriptor(desc) || IsDataDescriptor(desc))
+ {
+ p = new PropertyDescriptor();
+ p.value = examine(desc, "value", true);
+ p.writable = examine(desc, "writable", true);
+ p.enumerable = examine(desc, "enumerable", true);
+ p.configurable = examine(desc, "configurable", true);
+ }
+ // Step 4(b).
+ else
+ {
+ p = new PropertyDescriptor();
+ p.get = examine(desc, "get", true);
+ p.set = examine(desc, "set", true);
+ p.enumerable = examine(desc, "enumerable", true);
+ p.configurable = examine(desc, "configurable", true);
+ }
+
+ this.properties[propname] = p;
+
+ // Step 4(c).
+ return true;
+ }
+
+ // Step 5.
+ if (!("value" in desc) && !("get" in desc) && !("set" in desc) &&
+ !("writable" in desc) && !("enumerable" in desc) &&
+ !("configurable" in desc))
+ {
+ return;
+ }
+
+ // Step 6.
+ do
+ {
+ if ("value" in desc)
+ {
+ if (!("value" in current) || !SameValue(desc.value, current.value))
+ break;
+ }
+ if ("get" in desc)
+ {
+ if (!("get" in current) || !SameValue(desc.get, current.get))
+ break;
+ }
+ if ("set" in desc)
+ {
+ if (!("set" in current) || !SameValue(desc.set, current.set))
+ break;
+ }
+ if ("writable" in desc)
+ {
+ if (!("writable" in current) ||
+ !SameValue(desc.writable, current.writable))
+ {
+ break;
+ }
+ }
+ if ("enumerable" in desc)
+ {
+ if (!("enumerable" in current) ||
+ !SameValue(desc.enumerable, current.enumerable))
+ {
+ break;
+ }
+ }
+ if ("configurable" in desc)
+ {
+ if (!("configurable" in current) ||
+ !SameValue(desc.configurable, current.configurable))
+ {
+ break;
+ }
+ }
+
+ // all fields in desc also in current, with the same values
+ return true;
+ }
+ while (false);
+
+ // Step 7.
+ if (!examine(current, "configurable"))
+ {
+ if ("configurable" in desc && examine(desc, "configurable"))
+ return this._reject(throwing, "can't make configurable again");
+ if ("enumerable" in desc &&
+ examine(current, "enumerable") !== examine(desc, "enumerable"))
+ {
+ return this._reject(throwing, "can't change enumerability");
+ }
+ }
+
+ // Step 8.
+ if (IsGenericDescriptor(desc))
+ {
+ // do nothing
+ }
+ // Step 9.
+ else if (IsDataDescriptor(current) !== IsDataDescriptor(desc))
+ {
+ // Step 9(a).
+ if (!examine(current, "configurable"))
+ return this._reject(throwing, "can't change unconfigurable descriptor's type");
+ // Step 9(b).
+ if (IsDataDescriptor(current))
+ current.convertToAccessorDescriptor();
+ // Step 9(c).
+ else
+ current.convertToDataDescriptor();
+ }
+ // Step 10.
+ else if (IsDataDescriptor(current) && IsDataDescriptor(desc))
+ {
+ // Step 10(a)
+ if (!examine(current, "configurable"))
+ {
+ // Step 10(a).i.
+ if (!examine(current, "writable") &&
+ "writable" in desc && examine(desc, "writable"))
+ {
+ return this._reject(throwing, "can't make data property writable again");
+ }
+ // Step 10(a).ii.
+ if (!examine(current, "writable"))
+ {
+ if ("value" in desc &&
+ !SameValue(examine(desc, "value"), examine(current, "value")))
+ {
+ return this._reject(throwing, "can't change value if not writable");
+ }
+ }
+ }
+ // Step 10(b).
+ else
+ {
+ assertEq(examine(current, "configurable"), true,
+ "spec bug step 10(b)");
+ }
+ }
+ // Step 11.
+ else
+ {
+ assertEq(IsAccessorDescriptor(current) && IsAccessorDescriptor(desc),
+ true,
+ "spec bug");
+
+ // Step 11(a).
+ if (!examine(current, "configurable"))
+ {
+ // Step 11(a).i.
+ if ("set" in desc &&
+ !SameValue(examine(desc, "set"), examine(current, "set")))
+ {
+ return this._reject(throwing, "can't change setter if not configurable");
+ }
+ // Step 11(a).ii.
+ if ("get" in desc &&
+ !SameValue(examine(desc, "get"), examine(current, "get")))
+ {
+ return this._reject(throwing, "can't change getter if not configurable");
+ }
+ }
+ }
+
+ // Step 12.
+ current.update(desc);
+
+ // Step 13.
+ return true;
+ }
+};
+
+function IsCallable(v)
+{
+ return typeof v === "undefined" || typeof v === "function";
+}
+
+var NativeTest =
+ {
+ newObject: function newObject()
+ {
+ return {};
+ },
+ defineProperty: function defineProperty(obj, propname, propdesc)
+ {
+ Object.defineProperty(obj, propname, propdesc);
+ },
+ getDescriptor: function getDescriptor(obj, propname)
+ {
+ return Object.getOwnPropertyDescriptor(obj, propname);
+ }
+ };
+
+var ReimplTest =
+ {
+ newObject: function newObject()
+ {
+ return new CustomObject();
+ },
+ defineProperty: function defineProperty(obj, propname, propdesc)
+ {
+ assertEq(obj instanceof CustomObject, true, "obj not instanceof CustomObject");
+ if ("get" in propdesc || "set" in propdesc)
+ {
+ if ("value" in propdesc || "writable" in propdesc)
+ throw new TypeError("get/set and value/writable");
+ if (!IsCallable(propdesc.get))
+ throw new TypeError("get defined, uncallable");
+ if (!IsCallable(propdesc.set))
+ throw new TypeError("set defined, uncallable");
+ }
+ return obj.defineOwnProperty(propname, propdesc, true);
+ },
+ getDescriptor: function getDescriptor(obj, propname)
+ {
+ if (!(propname in obj.properties))
+ return undefined;
+
+ return new PropertyDescriptor(obj.properties[propname]);
+ }
+ };
+
+var JSVAL_INT_MAX = Math.pow(2, 30) - 1;
+var JSVAL_INT_MIN = -Math.pow(2, 30);
+
+
+function isValidDescriptor(propdesc)
+{
+ if ("get" in propdesc || "set" in propdesc)
+ {
+ if ("value" in propdesc || "writable" in propdesc)
+ return false;
+
+ // We permit null here simply because this test's author believes the
+ // implementation may sometime be susceptible to making mistakes in this
+ // regard and would prefer to be cautious.
+ if (propdesc.get !== null && propdesc.get !== undefined && !IsCallable(propdesc.get))
+ return false;
+ if (propdesc.set !== null && propdesc.set !== undefined && !IsCallable(propdesc.set))
+ return false;
+ }
+
+ return true;
+}
+
+
+var OMIT = {};
+var VALUES =
+ [-Infinity, JSVAL_INT_MIN, -0, +0, 1.5, JSVAL_INT_MAX, Infinity,
+ NaN, "foo", "bar", null, undefined, true, false, {}, /a/, OMIT];
+var GETS =
+ [undefined, function get1() { return 1; }, function get2() { return 2; },
+ null, 5, OMIT];
+var SETS =
+ [undefined, function set1() { return 1; }, function set2() { return 2; },
+ null, 5, OMIT];
+var ENUMERABLES = [true, false, OMIT];
+var CONFIGURABLES = [true, false, OMIT];
+var WRITABLES = [true, false, OMIT];
+
+function mapTestDescriptors(filter)
+{
+ var descs = [];
+ var desc = {};
+
+ function put(field, value)
+ {
+ if (value !== OMIT)
+ desc[field] = value;
+ }
+
+ VALUES.forEach(function(value)
+ {
+ GETS.forEach(function(get)
+ {
+ SETS.forEach(function(set)
+ {
+ ENUMERABLES.forEach(function(enumerable)
+ {
+ CONFIGURABLES.forEach(function(configurable)
+ {
+ WRITABLES.forEach(function(writable)
+ {
+ desc = {};
+ put("value", value);
+ put("get", get);
+ put("set", set);
+ put("enumerable", enumerable);
+ put("configurable", configurable);
+ put("writable", writable);
+ if (filter(desc))
+ descs.push(desc);
+ });
+ });
+ });
+ });
+ });
+ });
+
+ return descs;
+}
+
+var ALL_DESCRIPTORS = mapTestDescriptors(function(d) { return true; });
+var VALID_DESCRIPTORS = mapTestDescriptors(isValidDescriptor);
+
+function TestRunner()
+{
+ this._logLines = [];
+}
+TestRunner.prototype =
+ {
+ // MAIN METHODS
+
+ runFunctionLengthTests: function runFunctionLengthTests()
+ {
+ var self = this;
+ function functionLengthTests()
+ {
+ self._fullFunctionLengthTests(() => Function("one", "/* body */"), 1);
+ self._fullFunctionLengthTests(() => function(one, two, three=null) { }, 2);
+ self._fullFunctionLengthTests(() => (one, two, ...etc) => 0, 2);
+ self._fullFunctionLengthTests(() => ({method(){}}.method), 0);
+ self._fullFunctionLengthTests(() => Object.getOwnPropertyDescriptor({set x(v){}}, "x").set, 1);
+ }
+
+ this._runTestSet(functionLengthTests, "Function length tests completed!");
+ },
+
+ runNotPresentTests: function runNotPresentTests()
+ {
+ var self = this;
+ function notPresentTests()
+ {
+ print("Running not-present tests now...");
+
+ for (var i = 0, sz = ALL_DESCRIPTORS.length; i < sz; i++)
+ self._runSingleNotPresentTest(ALL_DESCRIPTORS[i]);
+ };
+
+ this._runTestSet(notPresentTests, "Not-present length tests completed!");
+ },
+
+ runPropertyPresentTestsFraction:
+ function runPropertyPresentTestsFraction(part, parts)
+ {
+ var self = this;
+ function propertyPresentTests()
+ {
+ print("Running already-present tests now...");
+
+ var total = VALID_DESCRIPTORS.length;
+ var start = Math.floor((part - 1) / parts * total);
+ var end = Math.floor(part / parts * total);
+
+ for (var i = start; i < end; i++)
+ {
+ var old = VALID_DESCRIPTORS[i];
+ print("Starting test with old descriptor " + old.toSource() + "...");
+
+ for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
+ self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []);
+ }
+ }
+
+ this._runTestSet(propertyPresentTests,
+ "Property-present fraction " + part + " of " + parts +
+ " completed!");
+ },
+
+ runNonTerminalPropertyPresentTestsFraction:
+ function runNonTerminalPropertyPresentTestsFraction(part, parts)
+ {
+ var self = this;
+
+ /*
+ * A plain old property to define on the object before redefining the
+ * originally-added property, to test redefinition of a property that's
+ * not also lastProperty. NB: we could loop over every possible
+ * descriptor here if we wanted, even try adding more than one, but we'd
+ * hit cubic complexity and worse, and SpiderMonkey only distinguishes by
+ * the mere presence of the middle property, not its precise details.
+ */
+ var middleDefines =
+ [{
+ property: "middle",
+ descriptor:
+ { value: 17, writable: true, configurable: true, enumerable: true }
+ }];
+
+ function nonTerminalPropertyPresentTests()
+ {
+ print("Running non-terminal already-present tests now...");
+
+ var total = VALID_DESCRIPTORS.length;
+ var start = Math.floor((part - 1) / parts * total);
+ var end = Math.floor(part / parts * total);
+
+ for (var i = start; i < end; i++)
+ {
+ var old = VALID_DESCRIPTORS[i];
+ print("Starting test with old descriptor " + old.toSource() + "...");
+
+ for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
+ {
+ self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j],
+ middleDefines);
+ }
+ }
+ }
+
+ this._runTestSet(nonTerminalPropertyPresentTests,
+ "Non-terminal property-present fraction " +
+ part + " of " + parts + " completed!");
+ },
+
+ runDictionaryPropertyPresentTestsFraction:
+ function runDictionaryPropertyPresentTestsFraction(part, parts)
+ {
+ var self = this;
+
+ /*
+ * Add and readd properties such that the scope for the object is in
+ * dictionary mode.
+ */
+ var middleDefines =
+ [
+ {
+ property: "mid1",
+ descriptor:
+ { value: 17, writable: true, configurable: true, enumerable: true }
+ },
+ {
+ property: "mid2",
+ descriptor:
+ { value: 17, writable: true, configurable: true, enumerable: true }
+ },
+ {
+ property: "mid1",
+ descriptor:
+ { get: function g() { }, set: function s(v){}, configurable: false,
+ enumerable: true }
+ },
+ ];
+
+ function dictionaryPropertyPresentTests()
+ {
+ print("Running dictionary already-present tests now...");
+
+ var total = VALID_DESCRIPTORS.length;
+ var start = Math.floor((part - 1) / parts * total);
+ var end = Math.floor(part / parts * total);
+
+ for (var i = start; i < end; i++)
+ {
+ var old = VALID_DESCRIPTORS[i];
+ print("Starting test with old descriptor " + old.toSource() + "...");
+
+ for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
+ {
+ self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j],
+ middleDefines);
+ }
+ }
+ }
+
+ this._runTestSet(dictionaryPropertyPresentTests,
+ "Dictionary property-present fraction " +
+ part + " of " + parts + " completed!");
+ },
+
+
+ // HELPERS
+
+ runPropertyPresentTests: function runPropertyPresentTests()
+ {
+ print("Running already-present tests now...");
+
+ for (var i = 0, sz = VALID_DESCRIPTORS.length; i < sz; i++)
+ {
+ var old = VALID_DESCRIPTORS[i];
+ print("Starting test with old descriptor " + old.toSource() + "...");
+
+ for (var j = 0, sz2 = VALID_DESCRIPTORS.length; j < sz2; j++)
+ this._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []);
+ }
+ },
+ _runTestSet: function _runTestSet(fun, completeMessage)
+ {
+ try
+ {
+ fun();
+
+ print(completeMessage);
+ }
+ catch (e)
+ {
+ print("ERROR, EXITING (line " + (e.lineNumber || -1) + "): " + e);
+ throw e;
+ }
+ finally
+ {
+ this._reportAllErrors();
+ }
+ },
+ _reportAllErrors: function _reportAllErrors()
+ {
+ var errorCount = this._logLines.length;
+ print("Full accumulated number of errors: " + errorCount);
+ if (errorCount > 0)
+ throw errorCount + " errors detected, FAIL";
+ },
+ _fullFunctionLengthTests: function _fullFunctionLengthTests(funFactory, len)
+ {
+ print("Running Function.length (" + funFactory + ") tests now...");
+
+ for (var i = 0, sz = VALID_DESCRIPTORS.length; i < sz; i++)
+ {
+ var desc = VALID_DESCRIPTORS[i];
+ this._runSingleFunctionLengthTest(funFactory(), len, desc);
+ }
+ },
+ _log: function _log(v)
+ {
+ var m = "" + v;
+ print(m);
+ this._logLines.push(m);
+ },
+ _runSingleNotPresentTest: function _runSingleNotPresentTest(desc)
+ {
+ var nativeObj = NativeTest.newObject();
+ var reimplObj = ReimplTest.newObject();
+
+ try
+ {
+ NativeTest.defineProperty(nativeObj, "foo", desc);
+ }
+ catch (e)
+ {
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "foo", desc);
+ }
+ catch (e2)
+ {
+ if (e.constructor !== e2.constructor)
+ {
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior for new descriptor " + desc.toSource() +
+ ", native threw " + e + ", reimpl threw " + e2);
+ }
+ return;
+ }
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior for new descriptor " + desc.toSource() +
+ ", error " + e);
+ return;
+ }
+
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "foo", desc);
+ }
+ catch (e)
+ {
+ this._log("Reimpl threw defining new descriptor " + desc.toSource() +
+ ", error: " + e);
+ return;
+ }
+
+ var nativeDesc = NativeTest.getDescriptor(nativeObj, "foo");
+ var reimplDesc = ReimplTest.getDescriptor(reimplObj, "foo");
+ try
+ {
+ compareDescriptors(nativeDesc, reimplDesc);
+ }
+ catch (e)
+ {
+ this._log("Difference comparing returned descriptors for new " +
+ "property defined with descriptor " + desc.toSource() +
+ "; error: " + e);
+ return;
+ }
+ },
+ _runSinglePropertyPresentTest:
+ function _runSinglePropertyPresentTest(old, add, middleDefines)
+ {
+ var nativeObj = NativeTest.newObject();
+ var reimplObj = ReimplTest.newObject();
+
+ try
+ {
+ NativeTest.defineProperty(nativeObj, "foo", old);
+ }
+ catch (e)
+ {
+ if (!SameValue(NativeTest.getDescriptor(nativeObj, "foo"), undefined))
+ {
+ this._log("defining bad property descriptor: " + old.toSource());
+ return;
+ }
+
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "foo", old);
+ }
+ catch (e2)
+ {
+ if (!SameValue(ReimplTest.getDescriptor(reimplObj, "foo"),
+ undefined))
+ {
+ this._log("defining bad property descriptor: " + old.toSource() +
+ "; reimplObj: " + uneval(reimplObj));
+ }
+
+ if (e.constructor !== e2.constructor)
+ {
+ this._log("Different errors defining bad property descriptor: " +
+ old.toSource() + "; native threw " + e + ", reimpl " +
+ "threw " + e2);
+ }
+
+ return;
+ }
+
+ this._log("Difference defining a property with descriptor " +
+ old.toSource() + ", error " + e);
+ return;
+ }
+
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "foo", old);
+ }
+ catch (e)
+ {
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior when adding descriptor " + add.toSource() +
+ ", error: " + e);
+ return;
+ }
+
+ // Now add (or even readd) however many properties were specified between
+ // the original property to add and the new one, to test redefining
+ // non-last-properties and properties in scopes in dictionary mode.
+ for (var i = 0, sz = middleDefines.length; i < sz; i++)
+ {
+ var middle = middleDefines[i];
+ var prop = middle.property;
+ var desc = middle.descriptor;
+
+ try
+ {
+ NativeTest.defineProperty(nativeObj, prop, desc);
+ ReimplTest.defineProperty(reimplObj, prop, desc);
+ }
+ catch (e)
+ {
+ this._log("failure defining middle descriptor: " + desc.toSource() +
+ ", error " + e);
+ return;
+ }
+
+ // Sanity check
+ var nativeDesc = NativeTest.getDescriptor(nativeObj, prop);
+ var reimplDesc = ReimplTest.getDescriptor(reimplObj, prop);
+
+ compareDescriptors(nativeDesc, reimplDesc);
+ compareDescriptors(nativeDesc, desc);
+ }
+
+ try
+ {
+ NativeTest.defineProperty(nativeObj, "foo", add);
+ }
+ catch (e)
+ {
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "foo", add);
+ }
+ catch (e2)
+ {
+ if (e.constructor !== e2.constructor)
+ {
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior for descriptor " + add.toSource() +
+ " overwriting descriptor " + old.toSource() + "; " +
+ "native threw " + e + ", reimpl threw " + e2);
+ }
+ return;
+ }
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior for added descriptor " + add.toSource() + ", " +
+ "initial was " + old.toSource() + "; error: " + e);
+ return;
+ }
+
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "foo", add);
+ }
+ catch (e)
+ {
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior for readded descriptor " + add.toSource() + ", " +
+ "initial was " + old.toSource() + "; native readd didn't " +
+ "throw, reimpl add did, error: " + e);
+ return;
+ }
+
+ var nativeDesc = NativeTest.getDescriptor(nativeObj, "foo");
+ var reimplDesc = ReimplTest.getDescriptor(reimplObj, "foo");
+ try
+ {
+ compareDescriptors(nativeDesc, reimplDesc);
+ }
+ catch (e)
+ {
+ this._log("Difference comparing returned descriptors for readded " +
+ "property defined with descriptor " + add.toSource() + "; " +
+ "initial was " + old.toSource() + "; error: " + e);
+ return;
+ }
+ },
+ _runSingleFunctionLengthTest: function _runSingleFunctionLengthTest(fun, len, desc)
+ {
+ var nativeObj = fun;
+ var reimplObj = ReimplTest.newObject();
+ ReimplTest.defineProperty(reimplObj, "length",
+ {
+ value: len,
+ enumerable: false,
+ configurable: true,
+ writable: false
+ });
+
+ try
+ {
+ NativeTest.defineProperty(nativeObj, "length", desc);
+ }
+ catch (e)
+ {
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "length", desc);
+ }
+ catch (e2)
+ {
+ if (e.constructor !== e2.constructor)
+ {
+ this._log("Difference when comparing native/reimplementation " +
+ "behavior defining fun.length with " + desc.toSource() +
+ "; native threw " + e + ", reimpl threw " + e2);
+ }
+ return;
+ }
+ this._log("Difference when comparing Function.length native/reimpl " +
+ "behavior for descriptor " + desc.toSource() +
+ ", native impl threw error " + e);
+ return;
+ }
+
+ try
+ {
+ ReimplTest.defineProperty(reimplObj, "length", desc);
+ }
+ catch (e)
+ {
+ this._log("Difference defining new Function.length descriptor: impl " +
+ "succeeded, reimpl threw for descriptor " +
+ desc.toSource() + ", error: " + e);
+ return;
+ }
+
+ var nativeDesc = NativeTest.getDescriptor(nativeObj, "length");
+ var reimplDesc = ReimplTest.getDescriptor(reimplObj, "length");
+ try
+ {
+ compareDescriptors(nativeDesc, reimplDesc);
+ }
+ catch (e)
+ {
+ this._log("Difference comparing returned descriptors for " +
+ "Function.length with descriptor " + desc.toSource() +
+ "; error: " + e);
+ return;
+ }
+ }
+ };
+
+function runDictionaryPropertyPresentTestsFraction(PART, PARTS)
+{
+ var testfile =
+ '15.2.3.6-dictionary-redefinition-' + PART + '-of-' + PARTS + '.js';
+ var BUGNUMBER = 560566;
+ var summary =
+ 'ES5 Object.defineProperty(O, P, Attributes): dictionary redefinition ' +
+ PART + ' of ' + PARTS;
+
+ print(BUGNUMBER + ": " + summary);
+
+ try
+ {
+ new TestRunner().runDictionaryPropertyPresentTestsFraction(PART, PARTS);
+ }
+ catch (e)
+ {
+ throw "Error thrown during testing: " + e +
+ " at line " + e.lineNumber + "\n" +
+ (e.stack
+ ? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n"
+ : "");
+ }
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+ print("Tests complete!");
+}
+
+function runNonTerminalPropertyPresentTestsFraction(PART, PARTS)
+{
+ var BUGNUMBER = 560566;
+ var summary =
+ 'ES5 Object.defineProperty(O, P, Attributes): middle redefinition ' +
+ PART + ' of ' + PARTS;
+
+ print(BUGNUMBER + ": " + summary);
+
+
+ /**************
+ * BEGIN TEST *
+ **************/
+
+ try
+ {
+ new TestRunner().runNonTerminalPropertyPresentTestsFraction(PART, PARTS);
+ }
+ catch (e)
+ {
+ throw "Error thrown during testing: " + e +
+ " at line " + e.lineNumber + "\n" +
+ (e.stack
+ ? "Stack: " + e.stack.split("\n").slice(2).join("\n") + "\n"
+ : "");
+ }
+
+ /******************************************************************************/
+
+ if (typeof reportCompare === "function")
+ reportCompare(true, true);
+
+ print("Tests complete!");
+}