diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/jit-test/tests/basic/bug1403679.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/basic/bug1403679.js')
-rw-r--r-- | js/src/jit-test/tests/basic/bug1403679.js | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/basic/bug1403679.js b/js/src/jit-test/tests/basic/bug1403679.js new file mode 100644 index 0000000000..72bb046203 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1403679.js @@ -0,0 +1,195 @@ +load(libdir + "asserts.js"); + +const thisGlobal = this; +const otherGlobalSameCompartment = newGlobal({sameCompartmentAs: thisGlobal}); +const otherGlobalNewCompartment = newGlobal({newCompartment: true}); + +const globals = [thisGlobal, otherGlobalSameCompartment, otherGlobalNewCompartment]; + +function testWithOptions(fn, variants = [undefined]) { + for (let variant of variants) { + for (let global of globals) { + for (let options of [ + {}, + {proxy: true}, + {object: new FakeDOMObject()}, + ]) { + fn(options, global, variant); + } + } + } +} + +function testWithGlobals(fn) { + for (let global of globals) { + fn(global); + } +} + +function testBasic(options, global) { + let {object: source, transplant} = transplantableObject(options); + + // Validate that |source| is an object and |transplant| is a function. + assertEq(typeof source, "object"); + assertEq(typeof transplant, "function"); + + // |source| is created in the current global. + assertEq(objectGlobal(source), this); + + // |source|'s prototype is %ObjectPrototype%, unless it's a FakeDOMObject. + let oldPrototype; + if (options.object) { + oldPrototype = FakeDOMObject.prototype; + } else { + oldPrototype = Object.prototype; + } + assertEq(Object.getPrototypeOf(source), oldPrototype); + + // Properties can be created on |source|. + assertEq(source.foo, undefined); + source.foo = 1; + assertEq(source.foo, 1); + + // Calling |transplant| transplants the object and then returns undefined. + assertEq(transplant(global), undefined); + + // |source| was moved into the new global. If the new global is in a + // different compartment, |source| is a now a CCW. + if (global !== otherGlobalNewCompartment) { + assertEq(objectGlobal(source), global); + } else { + assertEq(objectGlobal(source), null); + assertEq(isProxy(source), true); + } + + // The properties are copied over to the swapped object. + assertEq(source.foo, 1); + + // The prototype was changed to %ObjectPrototype% of |global| or the + // FakeDOMObject.prototype. + let newPrototype; + if (options.object) { + newPrototype = global.FakeDOMObject.prototype; + } else { + newPrototype = global.Object.prototype; + } + assertEq(Object.getPrototypeOf(source), newPrototype); +} +testWithOptions(testBasic); + +// Objects can be transplanted multiple times between globals. +function testTransplantMulti(options, global1, global2) { + let {object: source, transplant} = transplantableObject(options); + + transplant(global1); + transplant(global2); +} +testWithOptions(testTransplantMulti, globals); + +// Test the case when the source object already has a wrapper in the target global. +function testHasWrapperInTarget(options, global) { + let {object: source, transplant} = transplantableObject(options); + + // Create a wrapper for |source| in the other global. + global.p = source; + assertEq(global.eval("p"), source); + + if (options.proxy) { + // It's a proxy object either way. + assertEq(global.eval("isProxy(p)"), true); + } else { + if (global === otherGlobalNewCompartment) { + // |isProxy| returns true because |p| is a CCW. + assertEq(global.eval("isProxy(p)"), true); + } else { + // |isProxy| returns false because |p| is not a CCW. + assertEq(global.eval("isProxy(p)"), false); + } + } + + // And now transplant it into that global. + transplant(global); + + assertEq(global.eval("p"), source); + + if (options.proxy) { + // It's a proxy object either way. + assertEq(global.eval("isProxy(p)"), true); + } else { + // The previous CCW was replaced with a same-compartment object. + assertEq(global.eval("isProxy(p)"), false); + } +} +testWithOptions(testHasWrapperInTarget); + +// Test the case when the source object has a wrapper, but in a different compartment. +function testHasWrapperOtherCompartment(options, global) { + let thirdGlobal = newGlobal({newCompartment: true}); + let {object: source, transplant} = transplantableObject(options); + + // Create a wrapper for |source| in the new global. + thirdGlobal.p = source; + assertEq(thirdGlobal.eval("p"), source); + + // And now transplant the object. + transplant(global); + + assertEq(thirdGlobal.eval("p"), source); +} +testWithOptions(testHasWrapperOtherCompartment); + +// Ensure a transplanted object is correctly handled by (weak) collections. +function testCollections(options, global, AnySet) { + let {object, transplant} = transplantableObject(options); + + let set = new AnySet(); + + assertEq(set.has(object), false); + set.add(object); + assertEq(set.has(object), true); + + transplant(global); + + assertEq(set.has(object), true); +} +testWithOptions(testCollections, [Set, WeakSet]); + +// Ensure DOM object slot is correctly transplanted. +function testDOMObjectSlot(global) { + let domObject = new FakeDOMObject(); + let expectedValue = domObject.x; + assertEq(typeof expectedValue, "number"); + + let {object, transplant} = transplantableObject({object: domObject}); + assertEq(object, domObject); + + transplant(global); + + assertEq(object, domObject); + assertEq(domObject.x, expectedValue); +} +testWithGlobals(testDOMObjectSlot); + +function testArgumentValidation() { + // Throws an error if too many arguments are present. + assertThrowsInstanceOf(() => transplantableObject(thisGlobal, {}), Error); + + let {object, transplant} = transplantableObject(); + + // Throws an error if called with no arguments. + assertThrowsInstanceOf(() => transplant(), Error); + + // Throws an error if called with too many arguments. + assertThrowsInstanceOf(() => transplant(thisGlobal, {}), Error); + + // Throws an error if the first argument isn't an object + assertThrowsInstanceOf(() => transplant(null), Error); + + // Throws an error if the argument isn't a global object. + assertThrowsInstanceOf(() => transplant({}), Error); + + // Throws an error if the 'object' option isn't a FakeDOMObject. + assertThrowsInstanceOf(() => transplant({object: null}), Error); + assertThrowsInstanceOf(() => transplant({object: {}}), Error); +} +testArgumentValidation(); |