summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/realms
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/jit-test/tests/realms/array-ctor.js35
-rw-r--r--js/src/jit-test/tests/realms/array-species-create.js35
-rw-r--r--js/src/jit-test/tests/realms/basic.js114
-rw-r--r--js/src/jit-test/tests/realms/bug1385890-c50.js20
-rw-r--r--js/src/jit-test/tests/realms/bug1479430.js6
-rw-r--r--js/src/jit-test/tests/realms/bug1487238.js3
-rw-r--r--js/src/jit-test/tests/realms/bug1496892.js4
-rw-r--r--js/src/jit-test/tests/realms/bug1513665.js24
-rw-r--r--js/src/jit-test/tests/realms/bug1514263.js16
-rw-r--r--js/src/jit-test/tests/realms/bug1518753.js13
-rw-r--r--js/src/jit-test/tests/realms/bug1518821.js11
-rw-r--r--js/src/jit-test/tests/realms/bug1519857.js4
-rw-r--r--js/src/jit-test/tests/realms/bug1548611.js5
-rw-r--r--js/src/jit-test/tests/realms/bug1610189.js15
-rw-r--r--js/src/jit-test/tests/realms/ccw-errors.js28
-rw-r--r--js/src/jit-test/tests/realms/first-global.js5
-rw-r--r--js/src/jit-test/tests/realms/nuking.js49
-rw-r--r--js/src/jit-test/tests/realms/promise-job-global.js31
-rw-r--r--js/src/jit-test/tests/realms/promise-then.js32
-rw-r--r--js/src/jit-test/tests/realms/proxy-realm.js14
-rw-r--r--js/src/jit-test/tests/realms/scripted-caller-global.js5
-rw-r--r--js/src/jit-test/tests/realms/switch-realms-native.js60
-rw-r--r--js/src/jit-test/tests/realms/switch-realms-scripted.js113
23 files changed, 642 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/realms/array-ctor.js b/js/src/jit-test/tests/realms/array-ctor.js
new file mode 100644
index 0000000000..b2e0497ae5
--- /dev/null
+++ b/js/src/jit-test/tests/realms/array-ctor.js
@@ -0,0 +1,35 @@
+function testArrayRealm() {
+ var g = newGlobal();
+ var A = g.Array;
+ for (var i = 0; i < 100; i++) {
+ var a;
+ a = new A();
+ assertEq(isSameCompartment(a, g), true);
+ assertEq(Object.getPrototypeOf(a), A.prototype);
+
+ a = new A(i);
+ assertEq(isSameCompartment(a, g), true);
+ assertEq(Object.getPrototypeOf(a), A.prototype);
+ }
+}
+testArrayRealm();
+
+function testErrorRealm() {
+ var g = newGlobal();
+ var A = g.Array;
+ for (var i = 50; i > -50; i--) {
+ var a = null;
+ var ex = null;
+ try {
+ a = new A(i);
+ } catch (e) {
+ ex = e;
+ }
+ if (i >= 0) {
+ assertEq(Object.getPrototypeOf(a), A.prototype);
+ } else {
+ assertEq(ex instanceof g.RangeError, true);
+ }
+ }
+}
+testErrorRealm();
diff --git a/js/src/jit-test/tests/realms/array-species-create.js b/js/src/jit-test/tests/realms/array-species-create.js
new file mode 100644
index 0000000000..e6bfd61c97
--- /dev/null
+++ b/js/src/jit-test/tests/realms/array-species-create.js
@@ -0,0 +1,35 @@
+function testSelfHosted() {
+ var g = newGlobal({sameCompartmentAs: this});
+ var arr = g.evaluate("[1, 2]");
+ for (var i = 0; i < 20; i++) {
+ var mapped = Array.prototype.map.call(arr, x => x + 1);
+ assertEq(mapped.constructor, Array);
+ }
+}
+testSelfHosted();
+
+function testNative() {
+ var g = newGlobal({sameCompartmentAs: this});
+ var arr = g.evaluate("[1, 2, 3, 4]");
+ for (var i = 0; i < 20; i++) {
+ var slice = Array.prototype.slice.call(arr, 0, 3);
+ assertEq(slice.constructor, Array);
+ }
+}
+testNative();
+
+function testIntrinsic() {
+ var g1 = newGlobal({sameCompartmentAs: this});
+ var g2 = newGlobal();
+ var IsCrossRealmArrayConstructor = getSelfHostedValue("IsCrossRealmArrayConstructor");
+ for (var i = 0; i < 20; i++) {
+ assertEq(IsCrossRealmArrayConstructor(Array), false);
+ assertEq(IsCrossRealmArrayConstructor(Math), false);
+ assertEq(IsCrossRealmArrayConstructor(() => 1), false);
+ assertEq(IsCrossRealmArrayConstructor(g1.Array), true);
+ assertEq(IsCrossRealmArrayConstructor(g2.Array), true);
+ assertEq(IsCrossRealmArrayConstructor(g1.assertEq), false);
+ assertEq(IsCrossRealmArrayConstructor(g2.assertEq), false);
+ }
+}
+testIntrinsic();
diff --git a/js/src/jit-test/tests/realms/basic.js b/js/src/jit-test/tests/realms/basic.js
new file mode 100644
index 0000000000..3c9bbd4d6d
--- /dev/null
+++ b/js/src/jit-test/tests/realms/basic.js
@@ -0,0 +1,114 @@
+var g1 = newGlobal({sameCompartmentAs: this});
+var g2 = newGlobal({sameCompartmentAs: g1});
+g2.x = g1;
+gc();
+assertEq(objectGlobal(Math), this);
+assertEq(objectGlobal(g1.print), g1);
+assertEq(objectGlobal(g2.x), g1);
+
+assertEq(isSameCompartment(g1, g2), true);
+assertEq(isSameCompartment(g1, Math), true);
+
+// Different-compartment realms have wrappers.
+assertEq(objectGlobal(newGlobal({newCompartment: true}).Math), null);
+
+function testCrossRealmProto() {
+ var g = newGlobal({sameCompartmentAs:this});
+
+ for (var i = 0; i < 20; i++) {
+ var o = Object.create(g.Math);
+ assertEq(objectGlobal(o), this);
+ assertEq(o.__proto__, g.Math);
+
+ var a = Reflect.construct(Array, [], g.Object);
+ assertEq(Array.isArray(a), true);
+ assertEq(objectGlobal(a), this);
+ assertEq(a.__proto__, g.Object.prototype);
+ }
+}
+testCrossRealmProto();
+
+function testSystemNonSystemRealms() {
+ var systemRealm = newGlobal({newCompartment: true, systemPrincipal: true});
+ var ex;
+ try {
+ var nonSystemRealm = newGlobal({sameCompartmentAs: systemRealm, principal: 10});
+ } catch(e) {
+ ex = e;
+ }
+ assertEq(ex.toString().includes("non-system realms"), true);
+ ex = null;
+ try {
+ systemRealm = newGlobal({systemPrincipal: true, sameCompartmentAs: this});
+ } catch(e) {
+ ex = e;
+ }
+ assertEq(ex.toString().includes("non-system realms"), true);
+}
+testSystemNonSystemRealms();
+
+function testNewObjectCache() {
+ // NewObjectCache lookup based on the proto should not return a cross-realm
+ // object.
+ var g = newGlobal({sameCompartmentAs: this});
+ var o1 = g.evaluate("Object.create(Math)");
+ var o2 = Object.create(g.Math);
+ assertEq(objectGlobal(o1), g);
+ assertEq(objectGlobal(o2), this);
+}
+testNewObjectCache();
+
+function testCCWs() {
+ // CCWs are allocated in the first realm.
+ var g1 = newGlobal({newCompartment: true});
+ var g2 = newGlobal({sameCompartmentAs: g1});
+ g1.o1 = {x: 1};
+ g2.o2 = {x: 2};
+ g1 = null;
+ gc();
+ g2.o3 = {x: 3};
+ assertEq(g2.o2.x, 2);
+ assertEq(g2.o3.x, 3);
+}
+testCCWs();
+
+function testTypedArrayLazyBuffer(global) {
+ var arr1 = new global.Int32Array(1);
+ var arr2 = new Int32Array(arr1);
+ assertEq(objectGlobal(arr2.buffer), this);
+ global.buf = arr1.buffer;
+ global.eval("assertEq(objectGlobal(buf), this);");
+}
+testTypedArrayLazyBuffer(newGlobal());
+testTypedArrayLazyBuffer(newGlobal({sameCompartmentAs: this}));
+
+function testEvalcx() {
+ var g = newGlobal();
+ evalcx("this.x = 7", g);
+ assertEq(g.x, 7);
+
+ g = newGlobal({newCompartment: true, invisibleToDebugger: true});
+ var ex, sb;
+ try {
+ sb = g.eval("evalcx('')");
+ } catch(e) {
+ ex = e;
+ }
+ // Check for either an exception or CCW (with --more-compartments).
+ assertEq((sb && objectGlobal(sb) === null) ||
+ ex.toString().includes("visibility"), true);
+
+ // Bug 1524707.
+ var lazysb = evalcx("lazy");
+ Object.setPrototypeOf(lazysb, Math);
+ assertEq(lazysb.__proto__, Math);
+}
+testEvalcx();
+
+function testSetProto() {
+ var o = {};
+ o.__proto__ = newGlobal();
+ o.__proto__ = newGlobal();
+ assertEq(objectGlobal(o), this);
+}
+testSetProto();
diff --git a/js/src/jit-test/tests/realms/bug1385890-c50.js b/js/src/jit-test/tests/realms/bug1385890-c50.js
new file mode 100644
index 0000000000..34dc346c93
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1385890-c50.js
@@ -0,0 +1,20 @@
+// |jit-test| skip-if: !this.hasOwnProperty("ReadableStream")
+// See <https://bugzilla.mozilla.org/show_bug.cgi?id=1385890#c50>.
+
+let otherGlobal = newGlobal();
+function getFreshInstances(type, otherType = type) {
+ stream = new ReadableStream({
+ start(c) {
+ controller = c;
+ },
+ type
+ });
+}
+getFreshInstances();
+let [branch1, branch2] = otherGlobal.ReadableStream.prototype.tee.call(stream);
+cancelPromise1 = ReadableStream.prototype.cancel.call(branch1, {
+ name: "cancel 1"
+});
+cancelPromise2 = ReadableStream.prototype.cancel.call(branch2, {
+ name: "cancel 2"
+});
diff --git a/js/src/jit-test/tests/realms/bug1479430.js b/js/src/jit-test/tests/realms/bug1479430.js
new file mode 100644
index 0000000000..a7bd9cc075
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1479430.js
@@ -0,0 +1,6 @@
+function f(a) {
+ return a.toString();
+}
+var g = newGlobal({sameCompartmentAs: this});
+g.evaluate("function Obj() {}");
+f(f(new g.Obj()));
diff --git a/js/src/jit-test/tests/realms/bug1487238.js b/js/src/jit-test/tests/realms/bug1487238.js
new file mode 100644
index 0000000000..dc0f9710a9
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1487238.js
@@ -0,0 +1,3 @@
+// |jit-test| error: TypeError
+var x = newGlobal({sameCompartmentAs: this});
+x instanceof x.Map.prototype.set;
diff --git a/js/src/jit-test/tests/realms/bug1496892.js b/js/src/jit-test/tests/realms/bug1496892.js
new file mode 100644
index 0000000000..8a38ddfaef
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1496892.js
@@ -0,0 +1,4 @@
+(function(a) {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.Object.defineProperty(arguments, "0", {value: g});
+})(0);
diff --git a/js/src/jit-test/tests/realms/bug1513665.js b/js/src/jit-test/tests/realms/bug1513665.js
new file mode 100644
index 0000000000..6fd803b486
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1513665.js
@@ -0,0 +1,24 @@
+load(libdir + "asserts.js");
+
+var g = newGlobal();
+
+function testArrayOf() {
+ var a = Array.of.call(g.Array);
+ assertEq(a instanceof g.Array, true);
+}
+testArrayOf();
+
+function testPromiseThen() {
+ var p = Promise.resolve(0);
+ p.constructor = g.Promise;
+ var r = p.then(() => {});
+ assertEq(r instanceof g.Promise, true);
+}
+testPromiseThen();
+
+function testPromiseCatch() {
+ Boolean.prototype.then = g.Promise.prototype.then;
+ assertThrowsInstanceOf(() => Promise.prototype.catch.call(false),
+ g.TypeError);
+}
+testPromiseCatch();
diff --git a/js/src/jit-test/tests/realms/bug1514263.js b/js/src/jit-test/tests/realms/bug1514263.js
new file mode 100644
index 0000000000..066663c434
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1514263.js
@@ -0,0 +1,16 @@
+function O(x) {
+ this.x = x;
+}
+
+var arr = [];
+for (var i = 0; i < 100; i++) {
+ arr.push(new O(i));
+}
+
+var g = newGlobal({sameCompartmentAs: this});
+g.trigger = function(arr) {
+ var obj = arr[90];
+ this.Object.create(obj);
+ assertEq(objectGlobal(obj), objectGlobal(arr));
+};
+g.trigger(arr);
diff --git a/js/src/jit-test/tests/realms/bug1518753.js b/js/src/jit-test/tests/realms/bug1518753.js
new file mode 100644
index 0000000000..61743d3111
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1518753.js
@@ -0,0 +1,13 @@
+var g = newGlobal({sameCompartmentAs: this});
+
+var o1 = Array(1, 2);
+var o2 = g.Array(1, 2);
+Array.prototype.x = 10;
+
+function test(o, v) {
+ for (var i = 0; i < 15; i++) {
+ assertEq(o.x, v);
+ }
+}
+test(o1, 10);
+test(o2, undefined);
diff --git a/js/src/jit-test/tests/realms/bug1518821.js b/js/src/jit-test/tests/realms/bug1518821.js
new file mode 100644
index 0000000000..03a217be81
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1518821.js
@@ -0,0 +1,11 @@
+load(libdir + "asserts.js");
+
+var g = newGlobal({newCompartment: true});
+var f = g.Function("fn", "fn()");
+f(function() {
+ nukeAllCCWs();
+ assertErrorMessage(() => { arguments.callee.caller = null; }, TypeError,
+ "can't access dead object");
+ assertErrorMessage(() => arguments.callee.caller, TypeError,
+ "can't access dead object");
+});
diff --git a/js/src/jit-test/tests/realms/bug1519857.js b/js/src/jit-test/tests/realms/bug1519857.js
new file mode 100644
index 0000000000..4b7d9511df
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1519857.js
@@ -0,0 +1,4 @@
+// |jit-test| skip-if: !("dis" in this)
+const g = newGlobal({sameCompartmentAs: this});
+g.eval(`function f() { y(); }`);
+dis(g.f);
diff --git a/js/src/jit-test/tests/realms/bug1548611.js b/js/src/jit-test/tests/realms/bug1548611.js
new file mode 100644
index 0000000000..70603e25e3
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1548611.js
@@ -0,0 +1,5 @@
+const otherGlobal = newGlobal();
+for (var i=0; i<60; i++) {
+ new otherGlobal.Array();
+ bailout();
+}
diff --git a/js/src/jit-test/tests/realms/bug1610189.js b/js/src/jit-test/tests/realms/bug1610189.js
new file mode 100644
index 0000000000..c65f8120f8
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1610189.js
@@ -0,0 +1,15 @@
+var g = newGlobal({sameCompartmentAs: this});
+var newTarget = g.Function();
+newTarget.prototype = undefined;
+
+// Reflect.construct returns an object in the current realm
+// but its prototype is g's Array.prototype.
+var arr1 = Reflect.construct(Array, [], newTarget);
+assertEq(objectGlobal(arr1), this);
+assertEq(arr1.__proto__, g.Array.prototype);
+
+// Calling cross-realm slice creates an object in that realm.
+for (var i = 0; i < 10; i++) {
+ var arr2 = arr1.slice();
+ assertEq(objectGlobal(arr2), g);
+}
diff --git a/js/src/jit-test/tests/realms/ccw-errors.js b/js/src/jit-test/tests/realms/ccw-errors.js
new file mode 100644
index 0000000000..380c81d17c
--- /dev/null
+++ b/js/src/jit-test/tests/realms/ccw-errors.js
@@ -0,0 +1,28 @@
+function test() {
+ "use strict";
+
+ const g = newGlobal({newCompartment: true});
+ Error.prototype.whence = "main global";
+ g.eval("Error.prototype.whence = 'other global'");
+
+ const obj = g.eval("[]");
+ Object.freeze(obj);
+ try {
+ obj.foo = 7;
+ assertEq("reached", "no", "This line should not be reached; the previous line should have thrown");
+ } catch(e) {
+ assertEq("" + e, `TypeError: can't define property "foo": Array is not extensible`);
+ assertEq(e.whence, "main global"); // setting operation happens in this global
+ }
+
+ const obj2 = g.eval(`obj2 = { get x() { throw new Error("go away"); } };`);
+ try {
+ obj2.x;
+ assertEq("reached", "no", "This line should not be reached; the previous line should have thrown");
+ } catch(e) {
+ assertEq("" + e, `Error: go away`);
+ assertEq(e.whence, "other global"); // Error created in other global
+ }
+}
+
+test();
diff --git a/js/src/jit-test/tests/realms/first-global.js b/js/src/jit-test/tests/realms/first-global.js
new file mode 100644
index 0000000000..d2a4bbade0
--- /dev/null
+++ b/js/src/jit-test/tests/realms/first-global.js
@@ -0,0 +1,5 @@
+var g1 = newGlobal({sameCompartmentAs: this});
+var g2 = newGlobal({newCompartment: true});
+assertEq(firstGlobalInCompartment(this), this);
+assertEq(firstGlobalInCompartment(g1), this);
+assertEq(firstGlobalInCompartment(g2), g2);
diff --git a/js/src/jit-test/tests/realms/nuking.js b/js/src/jit-test/tests/realms/nuking.js
new file mode 100644
index 0000000000..1d0656a716
--- /dev/null
+++ b/js/src/jit-test/tests/realms/nuking.js
@@ -0,0 +1,49 @@
+// Ensure nuking happens on a single target realm instead of compartment.
+
+var g1 = newGlobal({newCompartment: true});
+var g2 = newGlobal({sameCompartmentAs: g1});
+g2.other = g1;
+
+var o1 = g1.Math;
+var o2 = g2.Math;
+
+g1.nukeAllCCWs();
+
+// o1 is now dead.
+ex = null;
+try {
+ assertEq(o1.abs(1), 1);
+} catch (e) {
+ ex = e;
+}
+assertEq(ex.toString().includes("dead object"), true);
+
+// o2 still works.
+assertEq(o2.abs(1), 1);
+
+// g2 can still access g1 because they're same-compartment.
+assertEq(g2.evaluate("other.Math.abs(-2)"), 2);
+
+// Attempting to create a new wrapper targeting nuked realm g1 should return a
+// dead wrapper now. Note that we can't use g1 directly because that's now a
+// dead object, so we try to get to g1 via g2.
+ex = null;
+try {
+ g2.other.toString();
+} catch (e) {
+ ex = e;
+}
+assertEq(ex.toString().includes("dead object"), true);
+
+// Nuke g2 too. We have nuked all realms in its compartment so we should now
+// throw if we try to create a new outgoing wrapper.
+g2.evaluate("(" + function() {
+ nukeAllCCWs();
+ var ex = null;
+ try {
+ newGlobal({newCompartment: true}).Array();
+ } catch (e) {
+ ex = e;
+ }
+ assertEq(ex.toString().includes('dead object'), true);
+} + ")()");
diff --git a/js/src/jit-test/tests/realms/promise-job-global.js b/js/src/jit-test/tests/realms/promise-job-global.js
new file mode 100644
index 0000000000..246ce171a2
--- /dev/null
+++ b/js/src/jit-test/tests/realms/promise-job-global.js
@@ -0,0 +1,31 @@
+// Test that jobs added to the promise job queue have a global that's consistent
+// with and without same-compartment realms.
+
+var g1 = newGlobal();
+var g2 = newGlobal({sameCompartmentAs: this});
+
+// EnqueuePromiseReactionJob, handler is a primitive.
+// Job's global is the reaction's global.
+function test1(g) {
+ var resolve;
+ var p = new Promise(res => { resolve = res; });
+ g.Promise.prototype.then.call(p, 1);
+ resolve();
+ assertEq(globalOfFirstJobInQueue(), g);
+ drainJobQueue();
+}
+test1(g1);
+test1(g2);
+
+// EnqueuePromiseReactionJob, handler is an object.
+// Job's global is the handler's global.
+function test2(g) {
+ var resolve;
+ var p = new Promise(res => { resolve = res; });
+ p.then(new g.Function());
+ resolve();
+ assertEq(globalOfFirstJobInQueue(), g);
+ drainJobQueue();
+}
+test2(g1);
+test2(g2);
diff --git a/js/src/jit-test/tests/realms/promise-then.js b/js/src/jit-test/tests/realms/promise-then.js
new file mode 100644
index 0000000000..a12c2c6d82
--- /dev/null
+++ b/js/src/jit-test/tests/realms/promise-then.js
@@ -0,0 +1,32 @@
+load(libdir + "asserts.js");
+
+ignoreUnhandledRejections();
+
+const g = newGlobal({sameCompartmentAs: this});
+
+let resolve, reject;
+let promise = new Promise((resolveFn, rejectFn) => {
+ resolve = resolveFn;
+ reject = rejectFn;
+});
+
+// Set to a built-in Promise.prototype.then function, but from a different realm.
+promise.then = g.Promise.prototype.then;
+
+// Make SpeciesConstructor throw a TypeError exception.
+promise.constructor = {
+ [Symbol.species]: "not a constructor"
+};
+
+async function f(p) {
+ await p;
+}
+
+let error;
+f(promise).catch(e => { error = e; });
+
+resolve(promise);
+
+drainJobQueue();
+
+assertEq(error.constructor === g.TypeError, true);
diff --git a/js/src/jit-test/tests/realms/proxy-realm.js b/js/src/jit-test/tests/realms/proxy-realm.js
new file mode 100644
index 0000000000..00d984dd40
--- /dev/null
+++ b/js/src/jit-test/tests/realms/proxy-realm.js
@@ -0,0 +1,14 @@
+// Based on a test written by André Bargull (bug 1297179).
+
+load(libdir + "asserts.js");
+
+var g = newGlobal({sameCompartmentAs: this});
+var {proxy, revoke} = g.eval(`Proxy.revocable(function(){}, {})`);
+
+revoke();
+
+assertEq(objectGlobal(proxy), g);
+assertThrowsInstanceOf(() => proxy(), TypeError);
+assertThrowsInstanceOf(() => new proxy(), TypeError);
+assertThrowsInstanceOf(() => proxy.foo, TypeError);
+assertThrowsInstanceOf(() => proxy.foo = 1, TypeError);
diff --git a/js/src/jit-test/tests/realms/scripted-caller-global.js b/js/src/jit-test/tests/realms/scripted-caller-global.js
new file mode 100644
index 0000000000..15290e90b5
--- /dev/null
+++ b/js/src/jit-test/tests/realms/scripted-caller-global.js
@@ -0,0 +1,5 @@
+assertEq(scriptedCallerGlobal(), this);
+
+var g = newGlobal();
+assertEq(g.evaluate("scriptedCallerGlobal()"), g);
+assertEq(g.scriptedCallerGlobal(), this);
diff --git a/js/src/jit-test/tests/realms/switch-realms-native.js b/js/src/jit-test/tests/realms/switch-realms-native.js
new file mode 100644
index 0000000000..e4ae74cffc
--- /dev/null
+++ b/js/src/jit-test/tests/realms/switch-realms-native.js
@@ -0,0 +1,60 @@
+function testCall() {
+ var g = newGlobal({sameCompartmentAs: this});
+ for (var i = 0; i < 20; i++) {
+ assertEq(objectGlobal(g.Array(1, 2, 3)), g);
+ assertEq(objectGlobal(new g.Array(1, 2, 3)), g);
+ }
+ for (var i = 0; i < 20; i++) {
+ g.Error();
+ g.assertCorrectRealm();
+ if (i > 15)
+ g.gc();
+ }
+}
+testCall();
+
+function testAccessor() {
+ var g = newGlobal({sameCompartmentAs: this});
+ var o = {};
+ Object.defineProperty(o, "foo", {get: g.assertCorrectRealm,
+ set: g.assertCorrectRealm});
+ for (var i = 0; i < 20; i++)
+ o.foo;
+ for (var i = 0; i < 20; i++)
+ o.foo = 1;
+ Object.defineProperty(o, "arr", {get: g.Array});
+ for (var i = 0; i < 20; i++) {
+ var arr = o.arr;
+ assertEq(objectGlobal(arr), g);
+ assertEq(arr.__proto__, g.Array.prototype);
+ }
+}
+testAccessor();
+
+function testException1() {
+ var g = newGlobal({sameCompartmentAs: this});
+ for (var i = 0; i < 20; i++) {
+ var ex;
+ try {
+ g.throwOutOfMemory();
+ } catch(e) {
+ ex = e;
+ }
+ assertCorrectRealm();
+ assertEq(typeof ex, "string");
+ }
+}
+testException1();
+
+function testDOMCalls() {
+ var g = newGlobal({sameCompartmentAs: this});
+ var obj = g.evaluate("new FakeDOMObject()");
+ for (var i = 0; i < 2000; i++) {
+ assertCorrectRealm();
+ assertEq(obj.doFoo(1), 1);
+ assertEq(typeof obj.x, "number");
+ assertEq(obj.global, g);
+ obj.global = g; // Throws if not setter's global.
+ }
+}
+testDOMCalls();
diff --git a/js/src/jit-test/tests/realms/switch-realms-scripted.js b/js/src/jit-test/tests/realms/switch-realms-scripted.js
new file mode 100644
index 0000000000..24746fd4d1
--- /dev/null
+++ b/js/src/jit-test/tests/realms/switch-realms-scripted.js
@@ -0,0 +1,113 @@
+function testBasic() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function foo() { return scriptedCallerGlobal(); }");
+ for (var i = 0; i < 20; i++)
+ assertEq(g.foo(), g);
+
+ g.evaluate("function Obj() {}");
+ for (var i = 0; i < 30; i++)
+ assertEq(objectGlobal(new g.Obj()), g);
+}
+testBasic();
+
+function testFunCall() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function foo() { return scriptedCallerGlobal(); }");
+ for (var i = 0; i < 20; i++)
+ assertEq(g.foo.call(1, 2), g);
+}
+testFunCall();
+
+function testFunApplyArgs() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function foo() { return scriptedCallerGlobal(); }");
+ for (var i = 0; i < 2000; i++)
+ assertEq(g.foo.apply(null, arguments), g);
+}
+testFunApplyArgs(1, 2);
+
+function testFunApplyArray() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function foo() { return scriptedCallerGlobal(); }");
+ var arr = [1, 2];
+ for (var i = 0; i < 2000; i++)
+ assertEq(g.foo.apply(null, arr), g);
+}
+testFunApplyArray();
+
+function testAccessor() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function foo() { return scriptedCallerGlobal(); }");
+ var o = {};
+ Object.defineProperty(o, "foo", {get: g.foo, set: g.foo});
+ for (var i = 0; i < 20; i++) {
+ assertEq(o.foo, g);
+ o.foo = 1;
+ }
+}
+testAccessor();
+
+function testGenerator() {
+ var thisGlobalGen = function*() {};
+ var thisGlobalGenObj = thisGlobalGen();
+
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function* gen() { for (var i = 0; i < 2; i++) yield new Array(1, 2); }");
+ for (var i = 0; i < 20; i++) {
+ var o = g.gen();
+ for (var j = 0; j < 2; j++) {
+ var res = thisGlobalGenObj.next.call(o);
+ assertEq(objectGlobal(res), g);
+ assertEq(Array.isArray(res.value), true);
+ assertEq(objectGlobal(res.value), g);
+ }
+ }
+}
+testGenerator();
+
+function testException1() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function throwEx() { throw this; }");
+ for (var i = 0; i < 20; i++) {
+ var ex;
+ try {
+ g.throwEx();
+ } catch(e) {
+ ex = e;
+ }
+ assertCorrectRealm();
+ assertEq(ex, g);
+ }
+}
+testException1();
+
+function testException2() {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.evaluate("function f1(x) { if (x > 100) throw x; }");
+ g.f2 = function(x) { return g.f1(x); }
+ g.f3 = function(x) { return g.f2(x); }
+ g.evaluate("function f4(x) { try { return f3(x); } finally { assertCorrectRealm(); } }");
+ var ex;
+ try {
+ for (var i = 0; i < 110; i++) {
+ g.f4(i);
+ }
+ } catch (e) {
+ ex = e;
+ }
+ assertCorrectRealm();
+ assertEq(ex, 101);
+}
+testException2();
+testException2();
+
+function testException3(x) {
+ var g = newGlobal({sameCompartmentAs: this});
+ g.f1 = function(x) { if (x === max + 2) throw 1; }
+ g.evaluate("function f2(x) { try { return f1(x); } catch(e) {} }");
+ var max = 15;
+ for (var i = 0; i < max; i++)
+ g.f2(x * max + i);
+}
+testException3(0);
+testException3(1);