diff options
Diffstat (limited to '')
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); |