From 155f8add0a243f3ca0224b6e79153a9edd179b10 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 4 May 2010 10:12:50 -0700 Subject: [PATCH 01/24] Bug 563374 - clear exceptions thrown during js_TraceOpcode (r=igor) --HG-- extra : rebase_source : 24db0cc50d368dc56aa4a44971f56ea0521b6fa9 --- js/src/jsinterp.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 6cec086ca697..b703e81b6e1a 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1559,6 +1559,8 @@ js_TraceOpcode(JSContext *cx) (n == -ndefs) ? " output:" : ",", bytes); cx->free(bytes); + } else { + JS_ClearPendingException(cx); } } fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp))); @@ -1566,10 +1568,12 @@ js_TraceOpcode(JSContext *cx) fprintf(tracefp, " stack: "); for (siter = StackBase(fp); siter < regs->sp; siter++) { str = js_ValueToString(cx, *siter); - if (!str) + if (!str) { fputs("", tracefp); - else + } else { + JS_ClearPendingException(cx); js_FileEscapedString(tracefp, str, 0); + } fputc(' ', tracefp); } fputc('\n', tracefp); @@ -1591,6 +1595,8 @@ js_TraceOpcode(JSContext *cx) (n == -nuses) ? " inputs:" : ",", bytes); cx->free(bytes); + } else { + JS_ClearPendingException(cx); } } fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp))); From ef40b312bb3c1292c0682a8d2c420acae6268ac8 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 22 Apr 2010 18:53:54 -0700 Subject: [PATCH 02/24] Bug 560566 - Add this particular failure mode to the Object.defineProperty megatests. r=jorendorff --- ...15.2.3.6-dictionary-redefinition-1-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-2-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-3-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-4-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-5-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-6-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-7-of-8.js | 5 + ...15.2.3.6-dictionary-redefinition-8-of-8.js | 5 + .../15.2.3.6-middle-redefinition-1-of-8.js | 5 + .../15.2.3.6-middle-redefinition-2-of-8.js | 5 + .../15.2.3.6-middle-redefinition-3-of-8.js | 5 + .../15.2.3.6-middle-redefinition-4-of-8.js | 5 + .../15.2.3.6-middle-redefinition-5-of-8.js | 5 + .../15.2.3.6-middle-redefinition-6-of-8.js | 5 + .../15.2.3.6-middle-redefinition-7-of-8.js | 5 + .../15.2.3.6-middle-redefinition-8-of-8.js | 5 + .../ecma_5/Object/defineProperty-setup.js | 206 +++++++++++++++++- js/src/tests/ecma_5/Object/jstests.list | 16 ++ 18 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-1-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-2-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-3-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-4-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-5-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-6-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-7-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-8-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-1-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-2-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-3-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-4-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-5-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-6-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-7-of-8.js create mode 100644 js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-8-of-8.js diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-1-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-1-of-8.js new file mode 100644 index 000000000000..ff31648b9a80 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-1-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(1, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-2-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-2-of-8.js new file mode 100644 index 000000000000..55f4b0da6441 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-2-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(2, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-3-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-3-of-8.js new file mode 100644 index 000000000000..70faf015e415 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-3-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(3, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-4-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-4-of-8.js new file mode 100644 index 000000000000..ef4ca378672b --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-4-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(4, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-5-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-5-of-8.js new file mode 100644 index 000000000000..c2be22b97e89 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-5-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(5, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-6-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-6-of-8.js new file mode 100644 index 000000000000..8b62151f3916 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-6-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(6, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-7-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-7-of-8.js new file mode 100644 index 000000000000..ab41c070e255 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-7-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(7, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-8-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-8-of-8.js new file mode 100644 index 000000000000..1d5b57672db0 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-dictionary-redefinition-8-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runDictionaryPropertyPresentTestsFraction(8, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-1-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-1-of-8.js new file mode 100644 index 000000000000..4d310ea4a1a1 --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-1-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(1, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-2-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-2-of-8.js new file mode 100644 index 000000000000..40b5c48a113b --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-2-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(2, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-3-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-3-of-8.js new file mode 100644 index 000000000000..fb75c7779fbb --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-3-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(3, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-4-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-4-of-8.js new file mode 100644 index 000000000000..73e5d412152b --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-4-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(4, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-5-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-5-of-8.js new file mode 100644 index 000000000000..d5b90167c77d --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-5-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(5, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-6-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-6-of-8.js new file mode 100644 index 000000000000..0757ba186f2b --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-6-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(6, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-7-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-7-of-8.js new file mode 100644 index 000000000000..ecdb3a8d70ab --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-7-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(7, 8); diff --git a/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-8-of-8.js b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-8-of-8.js new file mode 100644 index 000000000000..86b410398ece --- /dev/null +++ b/js/src/tests/ecma_5/Object/15.2.3.6-middle-redefinition-8-of-8.js @@ -0,0 +1,5 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +load("ecma_5/Object/defineProperty-setup.js"); +runNonTerminalPropertyPresentTestsFraction(8, 8); diff --git a/js/src/tests/ecma_5/Object/defineProperty-setup.js b/js/src/tests/ecma_5/Object/defineProperty-setup.js index d707fc2afd6a..f4240eb8edac 100644 --- a/js/src/tests/ecma_5/Object/defineProperty-setup.js +++ b/js/src/tests/ecma_5/Object/defineProperty-setup.js @@ -578,7 +578,7 @@ TestRunner.prototype = 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]); + self._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []); } } @@ -587,6 +587,107 @@ TestRunner.prototype = " 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 @@ -600,7 +701,7 @@ TestRunner.prototype = 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]); + this._runSinglePropertyPresentTest(old, VALID_DESCRIPTORS[j], []); } }, _runTestSet: function _runTestSet(fun, completeMessage) @@ -724,7 +825,8 @@ TestRunner.prototype = return; } }, - _runSinglePropertyPresentTest: function _runSinglePropertyPresentTest(old, add) + _runSinglePropertyPresentTest: + function _runSinglePropertyPresentTest(old, add, middleDefines) { var nativeObj = NativeTest.newObject(); var reimplObj = ReimplTest.newObject(); @@ -781,6 +883,35 @@ TestRunner.prototype = 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); @@ -900,3 +1031,72 @@ TestRunner.prototype = } } }; + +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 PART = 1, PARTS = 4; + + var gTestfile = + '15.2.3.6-middle-redefinition-' + PART + '-of-' + PARTS + '.js'; + 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!"); +} diff --git a/js/src/tests/ecma_5/Object/jstests.list b/js/src/tests/ecma_5/Object/jstests.list index 92e6d293c87e..07ae554be779 100644 --- a/js/src/tests/ecma_5/Object/jstests.list +++ b/js/src/tests/ecma_5/Object/jstests.list @@ -11,3 +11,19 @@ skip-if(!xulRuntime.shell) script 15.2.3.6-redefinition-3-of-4.js # uses shell l skip-if(!xulRuntime.shell) script 15.2.3.6-redefinition-4-of-4.js # uses shell load() function script 15.2.3.7-01.js script 15.2.3.14-01.js # does not use reportCompare +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-1-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-2-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-3-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-4-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-5-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-6-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-7-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-middle-redefinition-8-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-1-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-2-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-3-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-4-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-5-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-6-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-7-of-8.js # uses shell load() function +skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-8-of-8.js # uses shell load() function From 4532818401a4d0e942bf5d989cba6ed5ebaa1520 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 28 Apr 2010 15:54:28 -0700 Subject: [PATCH 03/24] Fix typo in patch for bug 562193, r=firebot --- js/src/xpconnect/idl/xpccomponents.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/xpconnect/idl/xpccomponents.idl b/js/src/xpconnect/idl/xpccomponents.idl index 29c2a812ef37..0c820c0a5caf 100644 --- a/js/src/xpconnect/idl/xpccomponents.idl +++ b/js/src/xpconnect/idl/xpccomponents.idl @@ -223,7 +223,7 @@ interface nsIXPCComponents_Utils : nsISupports * * Returns the global object with which the given object is associated. * - * @param obj The JavaScript object whose parent is to be gotten. + * @param obj The JavaScript object whose global is to be gotten. * @return the corresponding global. */ void /* JSObject */ getGlobalForObject(/* in JSObject obj */); From 23aeebc51132caf6b4c13bdca8a731f08e4002a7 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Sun, 11 Apr 2010 13:51:00 -0700 Subject: [PATCH 04/24] Bug 552560 - Remove support for __parent__. r=mrbkap --- content/xul/content/src/nsXULElement.cpp | 8 +- dom/base/nsDOMWindowUtils.cpp | 52 +++++++ dom/interfaces/base/nsIDOMWindowUtils.idl | 10 +- .../jssh/resources/content/jssh-debug.js | 15 -- js/src/jsapi.cpp | 1 - js/src/jsatom.cpp | 2 - js/src/jsatom.h | 2 - js/src/jscntxt.h | 7 +- js/src/jsemit.cpp | 26 ++-- js/src/jsobj.cpp | 99 ++++-------- js/src/jsobj.h | 2 +- js/src/jsops.cpp | 5 +- js/src/shell/js.cpp | 22 ++- js/src/tests/e4x/extensions/regress-313080.js | 3 +- .../tests/js1_5/extensions/regress-164697.js | 10 +- .../tests/js1_5/extensions/regress-220584.js | 147 ------------------ .../tests/js1_5/extensions/regress-312278.js | 4 +- .../tests/js1_5/extensions/regress-452372.js | 2 +- .../tests/js1_7/extensions/regress-355578.js | 2 +- .../tests/js1_7/extensions/regress-355583.js | 2 +- js/src/tests/js1_8/extensions/for-in.js | 6 +- js/src/trace-test/tests/basic/bug533705.js | 26 ---- .../trace-test/tests/basic/testBug532363.js | 2 - js/src/xpconnect/shell/xpcshell.cpp | 19 +++ .../xpconnect/src/XPCChromeObjectWrapper.cpp | 3 +- js/src/xpconnect/src/XPCNativeWrapper.cpp | 2 +- js/src/xpconnect/src/xpcjsruntime.cpp | 1 - js/src/xpconnect/src/xpcprivate.h | 12 +- js/src/xpconnect/tests/js/old/threads.js | 74 --------- .../mochitest/chrome_wrappers_helper.html | 8 +- .../xpconnect/tests/mochitest/test_cows.html | 3 +- testing/mochitest/tests/test_bug366645.xhtml | 8 +- .../ctypes/tests/unit/test_jsctypes.js.in | 60 +++---- .../tests/test_enchash-decrypter.xhtml | 8 +- 34 files changed, 219 insertions(+), 434 deletions(-) delete mode 100644 js/src/tests/js1_5/extensions/regress-220584.js delete mode 100644 js/src/trace-test/tests/basic/bug533705.js delete mode 100644 js/src/trace-test/tests/basic/testBug532363.js delete mode 100644 js/src/xpconnect/tests/js/old/threads.js diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index e7beaafbcd83..103c1770c64b 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -3101,10 +3101,10 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, // // Compiling it using (for example) the first document's global // object would cause JS to keep a reference via the __proto__ or - // __parent__ pointer to the first document's global. If that - // happened, our script object would reference the first document, - // and the first document would indirectly reference the prototype - // document because it keeps the prototype cache alive. Circularity! + // parent pointer to the first document's global. If that happened, + // our script object would reference the first document, and the + // first document would indirectly reference the prototype document + // because it keeps the prototype cache alive. Circularity! nsresult rv; // Use the prototype document's special context diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index d3ef96dbbc6e..df63899aaa9a 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1266,3 +1266,55 @@ nsDOMWindowUtils::GetVisitedDependentComputedStyle( return rv; } + +NS_IMETHODIMP +nsDOMWindowUtils::GetParent() +{ + // This wasn't privileged in the past, but better to expose less than more. + if (!IsUniversalXPConnectCapable()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsCOMPtr xpc = nsContentUtils::XPConnect(); + + // get the xpconnect native call context + nsAXPCNativeCallContext *cc = nsnull; + xpc->GetCurrentNativeCallContext(&cc); + if(!cc) + return NS_ERROR_FAILURE; + + // Get JSContext of current call + JSContext* cx; + nsresult rv = cc->GetJSContext(&cx); + if(NS_FAILED(rv) || !cx) + return NS_ERROR_FAILURE; + + // get place for return value + jsval *rval = nsnull; + rv = cc->GetRetValPtr(&rval); + if(NS_FAILED(rv) || !rval) + return NS_ERROR_FAILURE; + + // get argc and argv and verify arg count + PRUint32 argc; + rv = cc->GetArgc(&argc); + if(NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + if(argc != 1) + return NS_ERROR_XPC_NOT_ENOUGH_ARGS; + + jsval* argv; + rv = cc->GetArgvPtr(&argv); + if(NS_FAILED(rv) || !argv) + return NS_ERROR_FAILURE; + + // first argument must be an object + if(JSVAL_IS_PRIMITIVE(argv[0])) + return NS_ERROR_XPC_BAD_CONVERT_JS; + + *rval = OBJECT_TO_JSVAL(JS_GetParent(cx, JSVAL_TO_OBJECT(argv[0]))); + cc->SetReturnValueWasSet(PR_TRUE); + return NS_OK; +} + diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 79a838e39d10..af312b401abf 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -53,7 +53,7 @@ interface nsIDOMEvent; interface nsITransferable; interface nsIQueryContentEventResult; -[scriptable, uuid(22a62b54-bcf5-422a-a329-fed4de5e78b2)] +[scriptable, uuid(352ff0af-bb38-496a-a067-b54771168d6d)] interface nsIDOMWindowUtils : nsISupports { /** @@ -655,4 +655,12 @@ interface nsIDOMWindowUtils : nsISupports { AString getVisitedDependentComputedStyle(in nsIDOMElement aElement, in AString aPseudoElement, in AString aPropertyName); + + /** + * Returns the parent of obj. + * + * @param obj The JavaScript object whose parent is to be gotten. + * @return the parent. + */ + void getParent(/* obj */); }; diff --git a/extensions/jssh/resources/content/jssh-debug.js b/extensions/jssh/resources/content/jssh-debug.js index 448ee2c3033f..ac44be615506 100644 --- a/extensions/jssh/resources/content/jssh-debug.js +++ b/extensions/jssh/resources/content/jssh-debug.js @@ -77,21 +77,6 @@ function inspect(obj) { return; } print("* Object type: "+typeof obj+"\n"); - if (typeof obj != "xml") { - print("* Parent chain: "); - try { - var parent = obj.__parent__; - while(parent) { - try { - print(parent); - } - catch(e) { dump("(?)"); } - finally { dump(" "); } - parent = parent.__parent__; - } - } catch(e) { dump("...(?)"); } - print("\n"); - } switch(typeof obj) { case "object": print("* Prototype chain: "); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 3e57e67148e9..fa6bb8bc2288 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1345,7 +1345,6 @@ static JSStdName standard_class_names[] = { static JSStdName object_prototype_names[] = { /* Object.prototype properties (global delegates to Object.prototype). */ {js_InitObjectClass, EAGER_ATOM(proto), NULL}, - {js_InitObjectClass, EAGER_ATOM(parent), NULL}, #if JS_HAS_TOSOURCE {js_InitObjectClass, EAGER_ATOM(toSource), NULL}, #endif diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 68f1f045d435..78e79453f06e 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -147,7 +147,6 @@ const char *const js_common_atom_names[] = { js_name_str, /* nameAtom */ js_next_str, /* nextAtom */ js_noSuchMethod_str, /* noSuchMethodAtom */ - js_parent_str, /* parentAtom */ js_proto_str, /* protoAtom */ js_set_str, /* setAtom */ js_stack_str, /* stackAtom */ @@ -220,7 +219,6 @@ const char js_name_str[] = "name"; const char js_next_str[] = "next"; const char js_noSuchMethod_str[] = "__noSuchMethod__"; const char js_object_str[] = "object"; -const char js_parent_str[] = "__parent__"; const char js_proto_str[] = "__proto__"; const char js_setter_str[] = "setter"; const char js_set_str[] = "set"; diff --git a/js/src/jsatom.h b/js/src/jsatom.h index e0ffb95bd78d..ee85eac192de 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -259,7 +259,6 @@ struct JSAtomState { JSAtom *nameAtom; JSAtom *nextAtom; JSAtom *noSuchMethodAtom; - JSAtom *parentAtom; JSAtom *protoAtom; JSAtom *setAtom; JSAtom *stackAtom; @@ -388,7 +387,6 @@ extern const char js_namespace_str[]; extern const char js_next_str[]; extern const char js_noSuchMethod_str[]; extern const char js_object_str[]; -extern const char js_parent_str[]; extern const char js_proto_str[]; extern const char js_ptagc_str[]; extern const char js_qualifier_str[]; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 983f454e73bb..900a1a89a549 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -832,10 +832,9 @@ struct JSRuntime { void *gcExtraRootsData; /* - * Used to serialize cycle checks when setting __proto__ or __parent__ by - * requesting the GC handle the required cycle detection. If the GC hasn't - * been poked, it won't scan for garbage. This member is protected by - * rt->gcLock. + * Used to serialize cycle checks when setting __proto__ by requesting the + * GC handle the required cycle detection. If the GC hasn't been poked, it + * won't scan for garbage. This member is protected by rt->gcLock. */ JSSetSlotRequest *setSlotRequests; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index 16371e91ece3..0a6c7ade9ee3 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -2688,10 +2688,9 @@ static JSBool EmitSpecialPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) { /* - * Special case for obj.__proto__ and obj.__parent__ to deoptimize away - * from fast paths in the interpreter and trace recorder, which skip dense - * array instances by going up to Array.prototype before looking up the - * property name. + * Special case for obj.__proto__ to deoptimize away from fast paths in the + * interpreter and trace recorder, which skip dense array instances by + * going up to Array.prototype before looking up the property name. */ JSAtomListElement *ale = cg->atomList.add(cg->parser, pn->pn_atom); if (!ale) @@ -2713,10 +2712,9 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, JS_ASSERT(pn->pn_arity == PN_NAME); pn2 = pn->maybeExpr(); - /* Special case deoptimization on __proto__ and __parent__. */ + /* Special case deoptimization for __proto__. */ if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) && - (pn->pn_atom == cx->runtime->atomState.protoAtom || - pn->pn_atom == cx->runtime->atomState.parentAtom)) { + pn->pn_atom == cx->runtime->atomState.protoAtom) { if (pn2 && !js_EmitTree(cx, cg, pn2)) return JS_FALSE; return EmitSpecialPropOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, cg); @@ -2802,13 +2800,8 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, return JS_FALSE; } - /* - * Special case deoptimization on __proto__ and __parent__, as - * above. - */ - if (pndot->pn_arity == PN_NAME && - (pndot->pn_atom == cx->runtime->atomState.protoAtom || - pndot->pn_atom == cx->runtime->atomState.parentAtom)) { + /* Special case deoptimization on __proto__, as above. */ + if (pndot->pn_arity == PN_NAME && pndot->pn_atom == cx->runtime->atomState.protoAtom) { if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, cg)) return JS_FALSE; } else if (!EmitAtomOp(cx, pndot, PN_OP(pndot), cg)) { @@ -7409,9 +7402,8 @@ js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array) * * In such cases, naively following ECMA leads to wrongful sharing of RegExp * objects, which makes for collisions on the lastIndex property (especially - * for global regexps) and on any ad-hoc properties. Also, __proto__ and - * __parent__ refer to the pre-compilation prototype and global objects, a - * pigeon-hole problem for instanceof tests. + * for global regexps) and on any ad-hoc properties. Also, __proto__ refers to + * the pre-compilation prototype, a pigeon-hole problem for instanceof tests. */ uintN JSCGObjectList::index(JSObjectBox *objbox) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index e257cea70057..b163c5aa5f2e 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -126,59 +126,29 @@ JSClass js_ObjectClass = { #if JS_HAS_OBJ_PROTO_PROP static JSBool -obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp); +obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp); static JSBool -obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp); +obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp); static JSPropertySpec object_props[] = { - /* These two must come first; see object_props[slot].name usage below. */ - {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED, - obj_getSlot, obj_setSlot}, - {js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, - obj_getSlot, obj_setSlot}, + {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED, obj_getProto, obj_setProto}, {0,0,0,0,0} }; -/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */ -#define JSSLOT_COUNT 2 - static JSBool -ReportStrictSlot(JSContext *cx, uint32 slot) +obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - if (slot == JSSLOT_PROTO) - return JS_TRUE; - return JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING | JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_DEPRECATED_USAGE, - object_props[slot].name); -} - -static JSBool -obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsid propid; - JSAccessMode mode; - uintN attrs; - JSObject *pobj; - JSClass *clasp; - - if (id == INT_TO_JSVAL(JSSLOT_PROTO)) { - propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom); - mode = JSACC_PROTO; - } else { - propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom); - mode = JSACC_PARENT; - } + JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO)); /* Let obj->checkAccess get the slot's value, based on the access mode. */ - if (!obj->checkAccess(cx, propid, mode, vp, &attrs)) + uintN attrs; + id = ATOM_TO_JSID(cx->runtime->atomState.protoAtom); + if (!obj->checkAccess(cx, id, JSACC_PROTO, vp, &attrs)) return JS_FALSE; - pobj = JSVAL_TO_OBJECT(*vp); - if (pobj) { - clasp = pobj->getClass(); + if (JSObject *pobj = JSVAL_TO_OBJECT(*vp)) { + JSClass *clasp = pobj->getClass(); if (clasp == &js_CallClass || clasp == &js_BlockClass) { /* Censor activations and lexical scopes per ECMA-262. */ *vp = JSVAL_NULL; @@ -188,8 +158,8 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) * censor. So it cannot escape to scripts. */ JS_ASSERT(clasp != &js_DeclEnvClass); - if (pobj->map->ops->thisObject) { - pobj = pobj->map->ops->thisObject(cx, pobj); + if (JSObjectOp thisObject = pobj->map->ops->thisObject) { + pobj = thisObject(cx, pobj); if (!pobj) return JS_FALSE; *vp = OBJECT_TO_JSVAL(pobj); @@ -200,17 +170,14 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) } static JSBool -obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { - JSObject *pobj; - uint32 slot; - jsid propid; - uintN attrs; + JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO)); if (!JSVAL_IS_OBJECT(*vp)) return JS_TRUE; - pobj = JSVAL_TO_OBJECT(*vp); + JSObject *pobj = JSVAL_TO_OBJECT(*vp); if (pobj) { /* * Innerize pobj here to avoid sticking unwanted properties on the @@ -221,16 +188,13 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) if (!pobj) return JS_FALSE; } - slot = (uint32) JSVAL_TO_INT(id); - if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot)) + + uintN attrs; + id = ATOM_TO_JSID(cx->runtime->atomState.protoAtom); + if (!obj->checkAccess(cx, id, JSAccessMode(JSACC_PROTO|JSACC_WRITE), vp, &attrs)) return JS_FALSE; - /* __parent__ is readonly and permanent, only __proto__ may be set. */ - propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom); - if (!obj->checkAccess(cx, propid, (JSAccessMode)(JSACC_PROTO|JSACC_WRITE), vp, &attrs)) - return JS_FALSE; - - return js_SetProtoOrParent(cx, obj, slot, pobj, JS_TRUE); + return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, pobj, JS_TRUE); } #else /* !JS_HAS_OBJ_PROTO_PROP */ @@ -300,15 +264,8 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj, } if (ssr.cycle) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CYCLIC_VALUE, -#if JS_HAS_OBJ_PROTO_PROP - object_props[slot].name -#else - (slot == JSSLOT_PROTO) ? js_proto_str - : js_parent_str -#endif - ); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CYCLIC_VALUE, + (slot == JSSLOT_PROTO) ? js_proto_str : "parent"); return JS_FALSE; } } @@ -3839,8 +3796,8 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, AutoValueRooter tvr(cx, cval); /* - * If proto or parent are NULL, set them to Constructor.prototype and/or - * Constructor.__parent__, just like JSOP_NEW does. + * If proto is NULL, set it to Constructor.prototype, just like JSOP_NEW + * does, likewise for the new object's parent. */ ctor = JSVAL_TO_OBJECT(cval); if (!parent) @@ -5691,10 +5648,10 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, * We don't want to require all classes to supply a checkAccess hook; we * need that hook only for certain classes used when precompiling scripts * and functions ("brutal sharing"). But for general safety of built-in - * magic properties such as __proto__ and __parent__, we route all access - * checks, even for classes that stub out checkAccess, through the global - * checkObjectAccess hook. This covers precompilation-based sharing and - * (possibly unintended) runtime sharing across trust boundaries. + * magic properties like __proto__, we route all access checks, even for + * classes that stub out checkAccess, through the global checkObjectAccess + * hook. This covers precompilation-based sharing and (possibly + * unintended) runtime sharing across trust boundaries. */ clasp = pobj->getClass(); check = clasp->checkAccess; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 8bd83ac62c78..0798f214d658 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -364,7 +364,7 @@ struct JSObject { JSObject *parent = getParent(); if (parent) - JS_CALL_OBJECT_TRACER(trc, parent, "__parent__"); + JS_CALL_OBJECT_TRACER(trc, parent, "parent"); } JSObject *getGlobal(); diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index 974a36ed0ad1..d97d6f6164a7 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -3333,9 +3333,8 @@ BEGIN_CASE(JSOP_INITMETHOD) * So check first. * * On a hit, if the cached sprop has a non-default setter, it must be - * __proto__ or __parent__. If sprop->parent != scope->lastProperty(), - * there is a repeated property name. The fast path does not handle these - * two cases. + * __proto__. If sprop->parent != scope->lastProperty(), there is a + * repeated property name. The fast path does not handle these two cases. */ if (CX_OWNS_OBJECT_TITLE(cx, obj) && JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, scope, &sprop, &entry) && diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 08fb626cbdc3..12401a87eaab 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3658,6 +3658,24 @@ Elapsed(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; } +static JSBool +Parent(JSContext *cx, uintN argc, jsval *vp) +{ + if (argc != 1) { + JS_ReportError(cx, "Wrong number of arguments"); + return JS_FALSE; + } + + jsval v = JS_ARGV(cx, vp)[0]; + if (JSVAL_IS_PRIMITIVE(v)) { + JS_ReportError(cx, "Only objects have parents!"); + return JS_FALSE; + } + + *vp = OBJECT_TO_JSVAL(JS_GetParent(cx, JSVAL_TO_OBJECT(v))); + return JS_TRUE; +} + #ifdef XP_UNIX #include @@ -3911,6 +3929,7 @@ static JSFunctionSpec shell_functions[] = { JS_FN("parse", Parse, 1,0), JS_FN("timeout", Timeout, 1,0), JS_FN("elapsed", Elapsed, 0,0), + JS_FN("parent", Parent, 1,0), JS_FS_END }; @@ -4018,7 +4037,8 @@ static const char *const shell_help_messages[] = { "timeout([seconds])\n" " Get/Set the limit in seconds for the execution time for the current context.\n" " A negative value (default) means that the execution time is unlimited.", -"elapsed() Execution time elapsed for the current context.\n", +"elapsed() Execution time elapsed for the current context.", +"parent(obj) Returns the parent of obj.\n", }; /* Help messages must match shell functions. */ diff --git a/js/src/tests/e4x/extensions/regress-313080.js b/js/src/tests/e4x/extensions/regress-313080.js index bfc0d3db3e71..2db69fa084ec 100644 --- a/js/src/tests/e4x/extensions/regress-313080.js +++ b/js/src/tests/e4x/extensions/regress-313080.js @@ -37,7 +37,7 @@ gTestfile = 'regress-313080.js'; -var summary = "Regression - Do not crash calling __proto__, __parent__"; +var summary = "Regression - Do not crash calling __proto__"; var BUGNUMBER = 313080; var actual = 'No Crash'; var expect = 'No Crash'; @@ -48,7 +48,6 @@ START(summary); try { .__proto__(); - .__parent__(); .function::__proto__(); } catch(e) diff --git a/js/src/tests/js1_5/extensions/regress-164697.js b/js/src/tests/js1_5/extensions/regress-164697.js index e4259c6e310c..5bb34e3eb956 100644 --- a/js/src/tests/js1_5/extensions/regress-164697.js +++ b/js/src/tests/js1_5/extensions/regress-164697.js @@ -38,7 +38,7 @@ var gTestfile = 'regress-164697.js'; //----------------------------------------------------------------------------- var BUGNUMBER = 164697; -var summary = '(instance.__parent__ == constructor.__parent__)'; +var summary = '(parent(instance) == parent(constructor))'; var actual = ''; var expect = ''; @@ -61,13 +61,10 @@ runtest('new Function(";")', 'Function'); runtest('[]', 'Array'); runtest('new Array()', 'Array'); -runtest('""', 'String'); runtest('new String()', 'String'); -runtest('true', 'Boolean'); runtest('new Boolean()', 'Boolean'); -runtest('1', 'Number'); runtest('new Number("1")', 'Number'); runtest('new Date()', 'Date'); @@ -84,8 +81,9 @@ function runtest(myinstance, myconstructor) try { - expr = '(' + myinstance + ').__parent__ == ' + - myconstructor + '.__parent__'; + expr = + 'parent(' + myinstance + ') == ' + + 'parent(' + myconstructor + ')'; printStatus(expr); actual = eval(expr).toString(); } diff --git a/js/src/tests/js1_5/extensions/regress-220584.js b/js/src/tests/js1_5/extensions/regress-220584.js deleted file mode 100644 index 4ca34d2b884e..000000000000 --- a/js/src/tests/js1_5/extensions/regress-220584.js +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is JavaScript Engine testing utilities. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corp. - * Portions created by the Initial Developer are Copyright (C) 2003 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * igor@fastmail.fm, pschwartau@netscape.com - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * - * Date: 29 Sep 2003 - * SUMMARY: Testing __parent__ and __proto__ of Script object - * - * See http://bugzilla.mozilla.org/show_bug.cgi?id=220584 - */ -//----------------------------------------------------------------------------- -var gTestfile = 'regress-220584.js'; -var UBound = 0; -var BUGNUMBER = 220584; -var summary = 'Testing __parent__ and __proto__ of Script object'; -var status = ''; -var statusitems = []; -var actual = ''; -var actualvalues = []; -var expect= ''; -var expectedvalues = []; -var s; - - -// invoke |Script| as a function -status = inSection(1); -if (typeof Script == 'undefined') -{ - reportCompare("Script not defined, Test skipped.", - "Script not defined, Test skipped.", - summary); -} -else -{ - s = Script('1;'); - actual = s instanceof Object; - expect = true; - addThis(); - - status = inSection(2); - actual = (s.__parent__ == undefined) || (s.__parent__ == null); - expect = false; - addThis(); - - status = inSection(3); - actual = (s.__proto__ == undefined) || (s.__proto__ == null); - expect = false; - addThis(); - - status = inSection(4); - actual = (s + '').length > 0; - expect = true; - addThis(); - -} - -// invoke |Script| as a constructor -status = inSection(5); -if (typeof Script == 'undefined') -{ - print('Test skipped. Script not defined.'); -} -else -{ - s = new Script('1;'); - - actual = s instanceof Object; - expect = true; - addThis(); - - status = inSection(6); - actual = (s.__parent__ == undefined) || (s.__parent__ == null); - expect = false; - addThis(); - - status = inSection(7); - actual = (s.__proto__ == undefined) || (s.__proto__ == null); - expect = false; - addThis(); - - status = inSection(8); - actual = (s + '').length > 0; - expect = true; - addThis(); -} - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function addThis() -{ - statusitems[UBound] = status; - actualvalues[UBound] = actual; - expectedvalues[UBound] = expect; - UBound++; -} - - -function test() -{ - enterFunc('test'); - printBugNumber(BUGNUMBER); - printStatus(summary); - - for (var i=0; i= 0; i--) { - // main_thread.sleep(1); - threads[i].join(); - } - - print(" printed from main thread. foo is "+foo); -} - -var total_interval = 0; - -for(i = 0; i < LOOP_COUNT; i++) { - var start_time = new Date().getTime()/1000; - - foo = 0; - bar = new Array(THREAD_COUNT); - print("--- loop number "+i); - runThreads(); - - var end_time = new Date().getTime()/1000; - - var interval = parseInt(100*(end_time - start_time),10)/100; - print(" Interval = "+interval+ " seconds."); - // ignore first loop - if(i) { - total_interval += end_time - start_time; - var average_interval = parseInt(100*(total_interval / i),10)/100 - print("Average Interval = "+average_interval+" seconds."); - } -} - diff --git a/js/src/xpconnect/tests/mochitest/chrome_wrappers_helper.html b/js/src/xpconnect/tests/mochitest/chrome_wrappers_helper.html index a6e3423a8647..4f7170eb1cc7 100644 --- a/js/src/xpconnect/tests/mochitest/chrome_wrappers_helper.html +++ b/js/src/xpconnect/tests/mochitest/chrome_wrappers_helper.html @@ -7,10 +7,16 @@ .getInterface(Components.interfaces.nsIDOMWindowUtils); ok(utils.getClassName(wrapper) === expected, note); } + function check_parent(ok, obj, expected, note) { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + ok(utils.getParent(obj) === expected, note); + } function run_test(ok, xpcnw, sjow) { // both wrappers should point to our window: XOW check_wrapper(ok, ok, "Function", "functions are wrapped properly") - ok(ok.__parent__ == window, "ok is parented correctly"); + check_parent(ok, ok, window, "ok is parented correctly"); check_wrapper(ok, xpcnw, "XPCCrossOriginWrapper", "XPCNWs are transformed correctly"); check_wrapper(ok, sjow, "XPCCrossOriginWrapper", "SJOWs are transformed correctly"); diff --git a/js/src/xpconnect/tests/mochitest/test_cows.html b/js/src/xpconnect/tests/mochitest/test_cows.html index e42a5861db71..4b8a745c9f87 100644 --- a/js/src/xpconnect/tests/mochitest/test_cows.html +++ b/js/src/xpconnect/tests/mochitest/test_cows.html @@ -62,8 +62,7 @@ function COWTests() { var empty = {}; isProp(getCOW(empty), "foo", undefined, "empty.foo is undefined"); - const PROPS_TO_TEST = ['foo', '__parent__', '__proto__', - 'prototype', 'constructor']; + const PROPS_TO_TEST = ['foo', '__proto__', 'prototype', 'constructor']; var strict = { __exposedProps__: {} }; var strictCOW = getCOW(strict); diff --git a/testing/mochitest/tests/test_bug366645.xhtml b/testing/mochitest/tests/test_bug366645.xhtml index c035a3dc0cfd..1a4b449f968c 100644 --- a/testing/mochitest/tests/test_bug366645.xhtml +++ b/testing/mochitest/tests/test_bug366645.xhtml @@ -20,11 +20,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366645 /** Test for Bug 366645 **/ +function getParent(obj) { + return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils) + .getParent(obj); +} + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); var Cc = Components.classes; var Ci = Components.interfaces; var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance(); -var componentScope = table.wrappedJSObject.__parent__; +var componentScope = getParent(table.wrappedJSObject); ok(!!componentScope, "unable to get wrapped js object"); var PROT_EnchashDecrypter = componentScope.PROT_EnchashDecrypter; diff --git a/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in b/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in index 32bf924163f4..49800feb0ca6 100644 --- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in +++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in @@ -233,16 +233,16 @@ function run_abstract_class_tests() do_check_class(ctypes.CType, "Function"); do_check_class(ctypes.CType.prototype, "CType"); - do_check_true(ctypes.CType.__parent__ === ctypes); - do_check_true(ctypes.CType.__proto__ === ctypes.__parent__.Function.prototype); - do_check_true(ctypes.CType instanceof ctypes.__parent__.Function); + do_check_true(parent(ctypes.CType) === ctypes); + do_check_true(ctypes.CType.__proto__ === parent(ctypes).Function.prototype); + do_check_true(ctypes.CType instanceof parent(ctypes).Function); do_check_true(ctypes.CType.hasOwnProperty("prototype")); do_check_throws(function() { ctypes.CType.prototype(); }, Error); do_check_throws(function() { new ctypes.CType.prototype() }, Error); - do_check_true(ctypes.CType.prototype.__parent__ === ctypes); - do_check_true(ctypes.CType.prototype.__proto__ === ctypes.__parent__.Function.prototype); - do_check_true(ctypes.CType.prototype instanceof ctypes.__parent__.Function); + do_check_true(parent(ctypes.CType.prototype) === ctypes); + do_check_true(ctypes.CType.prototype.__proto__ === parent(ctypes).Function.prototype); + do_check_true(ctypes.CType.prototype instanceof parent(ctypes).Function); do_check_true(ctypes.CType.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.CType.prototype.constructor === ctypes.CType); @@ -270,13 +270,13 @@ function run_abstract_class_tests() do_check_class(ctypes.CData, "Function"); do_check_class(ctypes.CData.prototype, "CData"); - do_check_true(ctypes.CData.__parent__ === ctypes); + do_check_true(parent(ctypes.CData) === ctypes); do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype); do_check_true(ctypes.CData instanceof ctypes.CType); do_check_true(ctypes.CData.hasOwnProperty("prototype")); - do_check_true(ctypes.CData.prototype.__parent__ === ctypes); - do_check_true(ctypes.CData.prototype.__proto__ === ctypes.__parent__.Object.prototype); + do_check_true(parent(ctypes.CData.prototype) === ctypes); + do_check_true(ctypes.CData.prototype.__proto__ === parent(ctypes).Object.prototype); do_check_true(ctypes.CData.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.CData.prototype.constructor === ctypes.CData); @@ -303,12 +303,12 @@ function run_Int64_tests() { do_check_class(ctypes.Int64, "Function"); do_check_class(ctypes.Int64.prototype, "Int64"); - do_check_true(ctypes.Int64.__parent__ === ctypes); - do_check_true(ctypes.Int64.__proto__ === ctypes.__parent__.Function.prototype); + do_check_true(parent(ctypes.Int64) === ctypes); + do_check_true(ctypes.Int64.__proto__ === parent(ctypes).Function.prototype); do_check_true(ctypes.Int64.hasOwnProperty("prototype")); - do_check_true(ctypes.Int64.prototype.__parent__ === ctypes); - do_check_true(ctypes.Int64.prototype.__proto__ === ctypes.__parent__.Object.prototype); + do_check_true(parent(ctypes.Int64.prototype) === ctypes); + do_check_true(ctypes.Int64.prototype.__proto__ === parent(ctypes).Object.prototype); do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64); @@ -326,7 +326,7 @@ function run_Int64_tests() { do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, Error); let i = ctypes.Int64(0); - do_check_true(i.__parent__ === ctypes); + do_check_true(parent(i) === ctypes); do_check_true(i.__proto__ === ctypes.Int64.prototype); do_check_true(i instanceof ctypes.Int64); @@ -480,12 +480,12 @@ function run_UInt64_tests() { do_check_class(ctypes.UInt64, "Function"); do_check_class(ctypes.UInt64.prototype, "UInt64"); - do_check_true(ctypes.UInt64.__parent__ === ctypes); - do_check_true(ctypes.UInt64.__proto__ === ctypes.__parent__.Function.prototype); + do_check_true(parent(ctypes.UInt64) === ctypes); + do_check_true(ctypes.UInt64.__proto__ === parent(ctypes).Function.prototype); do_check_true(ctypes.UInt64.hasOwnProperty("prototype")); - do_check_true(ctypes.UInt64.prototype.__parent__ === ctypes); - do_check_true(ctypes.UInt64.prototype.__proto__ === ctypes.__parent__.Object.prototype); + do_check_true(parent(ctypes.UInt64.prototype) === ctypes); + do_check_true(ctypes.UInt64.prototype.__proto__ === parent(ctypes).Object.prototype); do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor")); do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64); @@ -503,7 +503,7 @@ function run_UInt64_tests() { do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, Error); let i = ctypes.UInt64(0); - do_check_true(i.__parent__ === ctypes); + do_check_true(parent(i) === ctypes); do_check_true(i.__proto__ === ctypes.UInt64.prototype); do_check_true(i instanceof ctypes.UInt64); @@ -720,11 +720,11 @@ function run_basic_class_tests(t) do_check_class(t, "CType"); do_check_class(t.prototype, "CData"); - do_check_true(t.__parent__ === ctypes); + do_check_true(parent(t) === ctypes); do_check_true(t.__proto__ === ctypes.CType.prototype); do_check_true(t instanceof ctypes.CType); - do_check_true(t.prototype.__parent__ === ctypes); + do_check_true(parent(t.prototype) === ctypes); do_check_true(t.prototype.__proto__ === ctypes.CData.prototype); do_check_true(t.prototype instanceof ctypes.CData); do_check_true(t.prototype.constructor === t); @@ -740,7 +740,7 @@ function run_basic_class_tests(t) // Test that an instance 'd' of 't' is a CData. let d = t(); do_check_class(d, "CData"); - do_check_true(d.__parent__ === ctypes); + do_check_true(parent(d) === ctypes); do_check_true(d.__proto__ === t.prototype); do_check_true(d instanceof t); do_check_true(d.constructor === t); @@ -1265,11 +1265,11 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance do_check_class(c, "Function"); do_check_class(c.prototype, "CType"); - do_check_true(c.__parent__ === ctypes); - do_check_true(c.__proto__ === ctypes.__parent__.Function.prototype); - do_check_true(c instanceof ctypes.__parent__.Function); + do_check_true(parent(c) === ctypes); + do_check_true(c.__proto__ === parent(ctypes).Function.prototype); + do_check_true(c instanceof parent(ctypes).Function); - do_check_true(c.prototype.__parent__ === ctypes); + do_check_true(parent(c.prototype) === ctypes); do_check_true(c.prototype.__proto__ === ctypes.CType.prototype); do_check_true(c.prototype instanceof ctypes.CType); do_check_true(c.prototype.constructor === c); @@ -1291,18 +1291,18 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance do_check_class(t, "CType"); do_check_class(t.prototype, "CData"); - do_check_true(t.__parent__ === ctypes); + do_check_true(parent(t) === ctypes); do_check_true(t.__proto__ === c.prototype); do_check_true(t instanceof c); - do_check_true(t.prototype.__parent__ === ctypes); + do_check_true(parent(t.prototype) === ctypes); do_check_class(t.prototype.__proto__, "CData"); // 't.prototype.__proto__' is the common ancestor of all types constructed // from 'c'; while not available from 'c' directly, it should be identically // equal to 't2.prototype.__proto__' where 't2' is a different CType // constructed from 'c'. do_check_true(t.prototype.__proto__ === t2.prototype.__proto__); - do_check_true(t.prototype.__proto__.__parent__ === ctypes); + do_check_true(parent(t.prototype.__proto__) === ctypes); do_check_true(t.prototype.__proto__.__proto__ === ctypes.CData.prototype); do_check_true(t.prototype instanceof ctypes.CData); do_check_true(t.prototype.constructor === t); @@ -1337,7 +1337,7 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance if (t.__proto__ != ctypes.FunctionType.prototype) { let d = t(); do_check_class(d, "CData"); - do_check_true(d.__parent__ === ctypes); + do_check_true(parent(d) === ctypes); do_check_true(d.__proto__ === t.prototype); do_check_true(d instanceof t); do_check_true(d.constructor === t); diff --git a/toolkit/components/url-classifier/tests/test_enchash-decrypter.xhtml b/toolkit/components/url-classifier/tests/test_enchash-decrypter.xhtml index dbb1dfaa355d..af1032dcadbf 100644 --- a/toolkit/components/url-classifier/tests/test_enchash-decrypter.xhtml +++ b/toolkit/components/url-classifier/tests/test_enchash-decrypter.xhtml @@ -18,11 +18,17 @@ mochitest framework.