summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/xdr
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/xdr')
-rw-r--r--js/src/jit-test/tests/xdr/asm.js18
-rw-r--r--js/src/jit-test/tests/xdr/async-lazy.js24
-rw-r--r--js/src/jit-test/tests/xdr/async.js32
-rw-r--r--js/src/jit-test/tests/xdr/bug1108603.js9
-rw-r--r--js/src/jit-test/tests/xdr/bug1186973.js15
-rw-r--r--js/src/jit-test/tests/xdr/classes.js7
-rw-r--r--js/src/jit-test/tests/xdr/debug-lazy.js19
-rw-r--r--js/src/jit-test/tests/xdr/function-flags.js40
-rw-r--r--js/src/jit-test/tests/xdr/lazy.js164
-rw-r--r--js/src/jit-test/tests/xdr/scope.js19
-rw-r--r--js/src/jit-test/tests/xdr/tagged-template-literals-2.js4
-rw-r--r--js/src/jit-test/tests/xdr/tagged-template-literals.js4
-rw-r--r--js/src/jit-test/tests/xdr/trivial.js42
13 files changed, 397 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/xdr/asm.js b/js/src/jit-test/tests/xdr/asm.js
new file mode 100644
index 000000000..f584ea20e
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/asm.js
@@ -0,0 +1,18 @@
+load(libdir + 'bytecode-cache.js');
+
+var test = (function () {
+ function f() {
+ var x = function inner() {
+ "use asm";
+ function g() {}
+ return g;
+ };
+ };
+ return f.toSource();
+})();
+
+try {
+ evalWithCache(test, {});
+} catch (x) {
+ assertEq(x.message.includes("Asm.js is not supported by XDR"), true);
+}
diff --git a/js/src/jit-test/tests/xdr/async-lazy.js b/js/src/jit-test/tests/xdr/async-lazy.js
new file mode 100644
index 000000000..8f8c5accc
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/async-lazy.js
@@ -0,0 +1,24 @@
+async function f1(a, b) {
+ let x = await 10;
+ return x;
+};
+var toStringResult = f1.toString();
+
+async function f2(a, b) {
+ // arguments.callee gets wrapped function from unwrapped function.
+ return arguments.callee;
+};
+
+relazifyFunctions();
+
+// toString gets unwrapped function from wrapped function.
+assertEq(f1.toString(), toStringResult);
+
+var ans = 0;
+f1().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, 10);
+
+f2().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, f2);
diff --git a/js/src/jit-test/tests/xdr/async.js b/js/src/jit-test/tests/xdr/async.js
new file mode 100644
index 000000000..5be39237b
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/async.js
@@ -0,0 +1,32 @@
+load(libdir + 'bytecode-cache.js');
+
+async function f1(a, b) {
+ let x = await 10;
+ return x;
+};
+var toStringResult = f1.toString();
+
+var test = `
+async function f1(a, b) {
+ let x = await 10;
+ return x;
+};
+// toString gets unwrapped function from wrapped function.
+assertEq(f1.toString(), \`${toStringResult}\`);
+
+var ans = 0;
+f1().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, 10);
+
+async function f2(a, b) {
+ // arguments.callee gets wrapped function from unwrapped function.
+ return arguments.callee;
+};
+
+f2().then(x => { ans = x; });
+drainJobQueue();
+assertEq(ans, f2);
+`;
+
+evalWithCache(test, { assertEqBytecode: true, checkFrozen: true});
diff --git a/js/src/jit-test/tests/xdr/bug1108603.js b/js/src/jit-test/tests/xdr/bug1108603.js
new file mode 100644
index 000000000..54ba21e79
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/bug1108603.js
@@ -0,0 +1,9 @@
+var caught = false;
+try {
+ evaluate(cacheEntry(""), {saveBytecode: {value: true}, global: this});
+ [[0]];
+} catch (err) {
+ caught = true;
+ assertEq(err.message, "compartment cannot save singleton anymore.");
+}
+assertEq(caught, true); \ No newline at end of file
diff --git a/js/src/jit-test/tests/xdr/bug1186973.js b/js/src/jit-test/tests/xdr/bug1186973.js
new file mode 100644
index 000000000..780ef55dc
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/bug1186973.js
@@ -0,0 +1,15 @@
+// |jit-test| error: cache does not have the same size
+load(libdir + 'bytecode-cache.js');
+
+var test = (function () {
+ function f(x) {
+ function ifTrue() {};
+ function ifFalse() {};
+
+ if (generation % 2 == 0)
+ return ifTrue();
+ return ifFalse();
+ }
+ return f.toSource() + "; f()";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
diff --git a/js/src/jit-test/tests/xdr/classes.js b/js/src/jit-test/tests/xdr/classes.js
new file mode 100644
index 000000000..a5dc527f1
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/classes.js
@@ -0,0 +1,7 @@
+load(libdir + 'bytecode-cache.js');
+
+var test = "new class extends class { } { constructor() { super(); } }()";
+evalWithCache(test, { assertEqBytecode : true });
+
+var test = "new class { method() { super.toString(); } }().method()";
+evalWithCache(test, { assertEqBytecode : true });
diff --git a/js/src/jit-test/tests/xdr/debug-lazy.js b/js/src/jit-test/tests/xdr/debug-lazy.js
new file mode 100644
index 000000000..c6dec561b
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/debug-lazy.js
@@ -0,0 +1,19 @@
+load(libdir + 'bytecode-cache.js');
+
+// Ensure that if a function is encoded when non-lazy but relazifiable, then
+// decoded, the resulting LazyScript is marked as being non-lazy so that when
+// the debugger tries to delazify things it doesn't get all confused. We just
+// use findScripts() to trigger debugger delazification; we don't really care
+// about the scripts themselves.
+function checkAfter(ctx) {
+ var dbg = new Debugger(ctx.global);
+ var allScripts = dbg.findScripts();
+ assertEq(allScripts.length == 0, false);
+}
+
+test = `
+ function f() { return true; };
+ f();
+ `
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true,
+ checkAfter: checkAfter });
diff --git a/js/src/jit-test/tests/xdr/function-flags.js b/js/src/jit-test/tests/xdr/function-flags.js
new file mode 100644
index 000000000..62c69752b
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/function-flags.js
@@ -0,0 +1,40 @@
+load(libdir + 'bytecode-cache.js');
+
+var test;
+
+// Ensure that if a function is encoded we don't encode its "name
+// resolved" flag.
+test = `
+ function f() { delete f.name; return f.hasOwnProperty('name'); }
+ f();
+ `
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
+test = `
+ function f() { return f.hasOwnProperty('name'); }
+ f();
+ `
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
+// Ensure that if a function is encoded we don't encode its "length
+// resolved" flag.
+test = `
+ function f() { delete f.length; return f.hasOwnProperty('length'); }
+ f();
+ `
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
+test = `
+ function f() { return f.hasOwnProperty('length'); }
+ f();
+ `
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
+// And make sure our bytecode is actually not reflecting the flags,
+// not that we ignore them on decode.
+test = `
+ function f() { return f.hasOwnProperty('length') || f.hasOwnProperty('name'); }
+ f();
+ `
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
diff --git a/js/src/jit-test/tests/xdr/lazy.js b/js/src/jit-test/tests/xdr/lazy.js
new file mode 100644
index 000000000..da9d745fc
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/lazy.js
@@ -0,0 +1,164 @@
+load(libdir + 'bytecode-cache.js');
+var test = "";
+var checkAfter;
+
+// code a function which has both used and unused inner functions.
+test = (function () {
+ function f(x) {
+ function ifTrue() {
+ return true;
+ };
+ function ifFalse() {
+ return false;
+ };
+
+ if (x) return ifTrue();
+ else return ifFalse();
+ }
+
+ return f.toSource() + "; f(true)";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a function which uses different inner functions based on the generation.
+test = (function () {
+ function f(x) {
+ function ifTrue() {
+ return true;
+ };
+ function ifFalse() {
+ return false;
+ };
+
+ if (x) return ifTrue();
+ else return ifFalse();
+ }
+
+ return f.toSource() + "; f((generation % 2) == 0)";
+})();
+evalWithCache(test, { });
+
+// Code a function which has an enclosing scope.
+test = (function () {
+ function f() {
+ var upvar = "";
+ function g() { upvar += ""; return upvar; }
+ return g;
+ }
+
+ return f.toSource() + "; f()();";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// Code a lazy function which has an enclosing scope.
+test = (function () {
+ function f() {
+ var upvar = "";
+ function g() { upvar += ""; return upvar; }
+ return g;
+ }
+
+ return f.toSource() + "; f();";
+})();
+evalWithCache(test, { assertEqBytecode: true });
+
+// (basic/bug535930) Code an enclosing scope which is a Call object.
+test = (function () {
+ return "(" + (function () {
+ p = function () {
+ Set()
+ };
+ var Set = function () {};
+ for (var x = 0; x < 5; x++) {
+ Set = function (z) {
+ return function () {
+ [z]
+ }
+ } (x)
+ }
+ }).toSource() + ")()";
+})();
+evalWithCache(test, { assertEqBytecode: true });
+
+// Code an arrow function, and execute it.
+test = (function () {
+ function f() {
+ var g = (a) => a + a;
+ return g;
+ }
+
+ return f.toSource() + "; f()(1);";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// Code an arrow function, and do not execute it.
+test = (function () {
+ function f() {
+ var g = (a) => a + a;
+ return g;
+ }
+
+ return f.toSource() + "; f();";
+})();
+evalWithCache(test, { assertEqBytecode: true });
+
+// Extra zeal GCs can cause isRelazifiableFunction() to become true after we
+// record its value by throwing away JIT code for the function.
+gczeal(0);
+
+// Ensure that decoded functions can be relazified.
+test = "function f() { }; f();"
+ + "assertEq(isLazyFunction(f), false);"
+ + "var expect = isRelazifiableFunction(f);";
+checkAfter = function (ctx) {
+ gc(ctx.global.f, "shrinking"); // relazify f, if possible.
+ evaluate("assertEq(isLazyFunction(f), expect);", ctx);
+};
+evalWithCache(test, {
+ assertEqBytecode: true, // Check that we re-encode the same thing.
+ assertEqResult: true, // The function should remain relazifiable, if it was
+ // during the first run.
+ checkAfter: checkAfter // Check that relazifying the restored function works
+ // if the original was relazifiable.
+});
+
+// Ensure that decoded functions can be relazified, even if they have free
+// variables.
+test = "function f() { return isRelazifiableFunction(f) }; var expect = f();"
+ + "assertEq(isLazyFunction(f), false);"
+ + "expect";
+checkAfter = function (ctx) {
+ gc(ctx.global.f, "shrinking"); // relazify f, if possible.
+ evaluate("assertEq(isLazyFunction(f), expect);", ctx);
+};
+evalWithCache(test, {
+ assertEqBytecode: true, // Check that we re-encode the same thing.
+ assertEqResult: true, // The function should remain relazifiable, if it was
+ // during the first run.
+ checkAfter: checkAfter // Check that relazifying the restored function works
+ // if the original was relazifiable.
+});
+
+// Ensure that if a function is encoded when non-lazy but relazifiable, then
+// decoded, relazified, and then delazified, the result actually works.
+test = `
+ function f() { return true; };
+ var canBeLazy = isRelazifiableFunction(f) || isLazyFunction(f);
+ relazifyFunctions();
+ assertEq(isLazyFunction(f), canBeLazy);
+ f()`
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
+// And more of the same, in a slightly different way
+var g1 = newGlobal({ cloneSingletons: true });
+var g2 = newGlobal();
+var res = "function f(){}";
+var code = cacheEntry(res + "; f();");
+evaluate(code, {global:g1, compileAndGo: true, saveBytecode: {value: true}});
+evaluate(code, {global:g2, loadBytecode: true});
+gc();
+assertEq(g2.f.toString(), res);
+
+// Another relazification case.
+var src = "function f() { return 3; }; f(); relazifyFunctions(); 4";
+evalWithCache(src, {assertEqBytecode: true, assertEqResult: true});
diff --git a/js/src/jit-test/tests/xdr/scope.js b/js/src/jit-test/tests/xdr/scope.js
new file mode 100644
index 000000000..417a402d2
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/scope.js
@@ -0,0 +1,19 @@
+load(libdir + 'bytecode-cache.js');
+var test = "";
+
+// code a function which has both used and unused inner functions.
+test = (function () {
+ function f() {
+ var x = 3;
+ (function() {
+ with(obj) {
+ (function() {
+ assertEq(x, 2);
+ })();
+ }
+ })();
+ };
+
+ return "var obj = { x : 2 };" + f.toSource() + "; f()";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
diff --git a/js/src/jit-test/tests/xdr/tagged-template-literals-2.js b/js/src/jit-test/tests/xdr/tagged-template-literals-2.js
new file mode 100644
index 000000000..10326eece
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/tagged-template-literals-2.js
@@ -0,0 +1,4 @@
+var code = cacheEntry("(x => x.toSource())`bar`;");
+var g = newGlobal({ cloneSingletons: true });
+assertEq("[\"bar\"]", evaluate(code, { global: g, saveBytecode: true }));
+assertEq("[\"bar\"]", evaluate(code, { global: g, loadBytecode: true }));
diff --git a/js/src/jit-test/tests/xdr/tagged-template-literals.js b/js/src/jit-test/tests/xdr/tagged-template-literals.js
new file mode 100644
index 000000000..27a8c40ed
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/tagged-template-literals.js
@@ -0,0 +1,4 @@
+var code = cacheEntry("assertEq('bar', String.raw`bar`);");
+var g = newGlobal({ cloneSingletons: true });
+evaluate(code, { global: g, saveBytecode: true });
+evaluate(code, { global: g, loadBytecode: true })
diff --git a/js/src/jit-test/tests/xdr/trivial.js b/js/src/jit-test/tests/xdr/trivial.js
new file mode 100644
index 000000000..8cb54bea5
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/trivial.js
@@ -0,0 +1,42 @@
+load(libdir + 'bytecode-cache.js');
+var test = "";
+
+// code a constant.
+test = "1;";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a string constant.
+test = "'string';";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a global variable access.
+test = "generation;";
+evalWithCache(test, { assertEqBytecode: true });
+
+// code an object constant.
+test = "var obj = { a: 1, b: 2 };";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code object literal with mutations.
+test = "var obj = { a: 1, b: 2 }; obj.a++; assertEq(obj.a, 2);";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code object literals with mutations.
+test = "var obj = { a: 1, b: { c: 3, d: 4 } }; obj.b.c++; assertEq(obj.b.c, 4);";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a function which is used.
+test = "function f() { return 1; }; f();";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a function which is not used.
+test = "function f() { return 1; }; 1;";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a function which has an object literal.
+test = "function f() { return { x: 2 }; }; f();";
+evalWithCache(test, { assertEqBytecode: true });
+
+// code call site object
+test = "function f(a) { return a; }; f`a${4}b`;";
+evalWithCache(test, { assertEqBytecode: true, checkFrozen: true});