diff options
Diffstat (limited to 'devtools/client/debugger/src/workers/parser/tests/mapExpression.spec.js')
-rw-r--r-- | devtools/client/debugger/src/workers/parser/tests/mapExpression.spec.js | 796 |
1 files changed, 796 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/workers/parser/tests/mapExpression.spec.js b/devtools/client/debugger/src/workers/parser/tests/mapExpression.spec.js new file mode 100644 index 0000000000..6c89231012 --- /dev/null +++ b/devtools/client/debugger/src/workers/parser/tests/mapExpression.spec.js @@ -0,0 +1,796 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ + +import mapExpression from "../mapExpression"; +import { format } from "prettier"; +import cases from "jest-in-case"; + +function test({ + expression, + newExpression, + bindings, + mappings, + shouldMapBindings, + expectedMapped, + parseExpression = true, +}) { + const res = mapExpression(expression, mappings, bindings, shouldMapBindings); + + if (parseExpression) { + expect( + format(res.expression, { + parser: "babel", + }) + ).toEqual(format(newExpression, { parser: "babel" })); + } else { + expect(res.expression).toEqual(newExpression); + } + + expect(res.mapped).toEqual(expectedMapped); +} + +function formatAwait(body) { + return `(async () => { ${body} })();`; +} + +describe("mapExpression", () => { + cases("mapExpressions", test, [ + { + name: "await", + expression: "await a()", + newExpression: formatAwait("return a()"), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (multiple statements)", + expression: "const x = await a(); x + x", + newExpression: formatAwait("self.x = await a(); return x + x;"), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (inner)", + expression: "async () => await a();", + newExpression: "async () => await a();", + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (multiple awaits)", + expression: "const x = await a(); await b(x)", + newExpression: formatAwait("self.x = await a(); return b(x);"), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (assignment)", + expression: "let x = await sleep(100, 2)", + newExpression: formatAwait("return (self.x = await sleep(100, 2))"), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (destructuring)", + expression: "const { a, c: y } = await b()", + newExpression: formatAwait( + "return ({ a: self.a, c: self.y } = await b())" + ), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (array destructuring)", + expression: "const [a, y] = await b();", + newExpression: formatAwait("return ([self.a, self.y] = await b())"), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (mixed destructuring)", + expression: "const [{ a }] = await b();", + newExpression: formatAwait("return ([{ a: self.a }] = await b())"), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (destructuring, multiple statements)", + expression: "const { a, c: y } = await b(), { x } = await y()", + newExpression: formatAwait(` + ({ a: self.a, c: self.y } = await b()) + return ({ x: self.x } = await y()); + `), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (destructuring, bindings)", + expression: "const { a, c: y } = await b();", + newExpression: formatAwait("return ({ a, c: y } = await b())"), + bindings: ["a", "y"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (array destructuring, bindings)", + expression: "const [a, y] = await b();", + newExpression: formatAwait("return ([a, y] = await b())"), + bindings: ["a", "y"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (mixed destructuring, bindings)", + expression: "const [{ a }] = await b();", + newExpression: formatAwait("return ([{ a }] = await b())"), + bindings: ["a"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (destructuring with defaults, bindings)", + expression: "const { c, a = 5 } = await b();", + newExpression: formatAwait("return ({ c: self.c, a = 5 } = await b())"), + bindings: ["a", "y"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (array destructuring with defaults, bindings)", + expression: "const [a, y = 10] = await b();", + newExpression: formatAwait("return ([a, y = 10] = await b())"), + bindings: ["a", "y"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (mixed destructuring with defaults, bindings)", + expression: "const [{ c = 5 }, a = 5] = await b();", + newExpression: formatAwait( + "return ([ { c: self.c = 5 }, a = 5] = await b())" + ), + bindings: ["a"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (nested destructuring, bindings)", + expression: "const { a, c: { y } } = await b();", + newExpression: formatAwait(` + return ({ + a, + c: { y } + } = await b()); + `), + bindings: ["a", "y"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (nested destructuring with defaults)", + expression: "const { a, c: { y = 5 } = {} } = await b();", + newExpression: formatAwait(`return ({ + a: self.a, + c: { y: self.y = 5 } = {}, + } = await b()); + `), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (very nested destructuring with defaults)", + expression: + "const { a, c: { y: { z = 10, b } = { b: 5 } } } = await b();", + newExpression: formatAwait(` + return ({ + a: self.a, + c: { + y: { z: self.z = 10, b: self.b } = { + b: 5 + } + } + } = await b()); + `), + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: true, + originalExpression: false, + }, + }, + { + name: "await (with SyntaxError)", + expression: "await new Promise())", + newExpression: formatAwait("await new Promise())"), + parseExpression: false, + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, let assignment)", + expression: "let a = await 123;", + newExpression: `let a; + (async () => { + return a = await 123; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, var assignment)", + expression: "var a = await 123;", + newExpression: `var a; + (async () => { + return a = await 123; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, const assignment)", + expression: "const a = await 123;", + newExpression: `let a; + (async () => { + return a = await 123; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, multiple assignments)", + expression: "let a = 1, b, c = 3; b = await 123; a + b + c", + newExpression: `let a, b, c; + (async () => { + a = 1; + c = 3; + b = await 123; + return a + b + c; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, object destructuring)", + expression: "let {a, b, c} = await x;", + newExpression: `let a, b, c; + (async () => { + return ({a, b, c} = await x); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, object destructuring with rest)", + expression: "let {a, ...rest} = await x;", + newExpression: `let a, rest; + (async () => { + return ({a, ...rest} = await x); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, object destructuring with renaming and default)", + expression: "let {a: hello, b, c: world, d: $ = 4} = await x;", + newExpression: `let hello, b, world, $; + (async () => { + return ({a: hello, b, c: world, d: $ = 4} = await x); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, nested object destructuring + renaming + default)", + expression: `let { + a: hello, c: { y: { z = 10, b: bill, d: [e, f = 20] }} + } = await x; z;`, + newExpression: `let hello, z, bill, e, f; + (async () => { + ({ a: hello, c: { y: { z = 10, b: bill, d: [e, f = 20] }}} = await x); + return z; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, array destructuring)", + expression: "let [a, b, c] = await x; c;", + newExpression: `let a, b, c; + (async () => { + [a, b, c] = await x; + return c; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, array destructuring with default)", + expression: "let [a, b = 1, c = 2] = await x; c;", + newExpression: `let a, b, c; + (async () => { + [a, b = 1, c = 2] = await x; + return c; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, array destructuring with default and rest)", + expression: "let [a, b = 1, c = 2, ...rest] = await x; rest;", + newExpression: `let a, b, c, rest; + (async () => { + [a, b = 1, c = 2, ...rest] = await x; + return rest; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, nested array destructuring with default)", + expression: "let [a, b = 1, [c = 2, [d = 3, e = 4]]] = await x; c;", + newExpression: `let a, b, c, d, e; + (async () => { + [a, b = 1, [c = 2, [d = 3, e = 4]]] = await x; + return c; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (no bindings, dynamic import)", + expression: ` + var {rainbowLog} = await import("./cool-module.js"); + rainbowLog("dynamic");`, + newExpression: `var rainbowLog; + (async () => { + ({rainbowLog} = await import("./cool-module.js")); + return rainbowLog("dynamic"); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (nullish coalesce operator)", + expression: "await x; true ?? false", + newExpression: `(async () => { + await x; + return true ?? false; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (optional chaining operator)", + expression: "await x; x?.y?.z", + newExpression: `(async () => { + await x; + return x?.y?.z; + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (async function declaration with nullish coalesce operator)", + expression: "async function coalesce(x) { await x; return x ?? false; }", + newExpression: + "async function coalesce(x) { await x; return x ?? false; }", + shouldMapBindings: false, + expectedMapped: { + await: false, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (async function declaration with optional chaining operator)", + expression: "async function chain(x) { await x; return x?.y?.z; }", + newExpression: "async function chain(x) { await x; return x?.y?.z; }", + shouldMapBindings: false, + expectedMapped: { + await: false, + bindings: false, + originalExpression: false, + }, + }, + { + // check that variable declaration in for loop is not put outside of the async iife + name: "await (for loop)", + expression: "for (let i=0;i<2;i++) {}; var b = await 1;", + newExpression: `var b; + (async () => { + for (let i=0;i<2;i++) {} + return (b = await 1); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + // check that variable declaration in for-in loop is not put outside of the async iife + name: "await (for..in loop)", + expression: "for (let i in {}) {}; var b = await 1;", + newExpression: `var b; + (async () => { + for (let i in {}) {} + return (b = await 1); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + // check that variable declaration in for-of loop is not put outside of the async iife + name: "await (for..of loop)", + expression: "for (let i of []) {}; var b = await 1;", + newExpression: `var b; + (async () => { + for (let i of []) {} + return (b = await 1); + })()`, + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (if condition)", + expression: "if (await true) console.log(1);", + newExpression: formatAwait("if (await true) console.log(1);"), + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "await (non-expression final statement: bug 1851759)", + expression: `j = { "foo": 1, "bar": 2 }; await 42; for (var k in j) { console.log(k); }`, + newExpression: formatAwait(` + j = { + foo: 1, + bar: 2, + }; + await 42; + for (var k in j) { + console.log(k); + }`), + shouldMapBindings: false, + expectedMapped: { + await: true, + bindings: false, + originalExpression: false, + }, + }, + { + name: "simple", + expression: "a", + newExpression: "a", + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: false, + originalExpression: false, + }, + }, + { + name: "mappings", + expression: "a", + newExpression: "_a", + bindings: [], + mappings: { + a: "_a", + }, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: false, + originalExpression: true, + }, + }, + { + name: "declaration", + expression: "var a = 3;", + newExpression: "self.a = 3", + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "declaration + destructuring", + expression: "var { a } = { a: 3 };", + newExpression: "({ a: self.a } = {\n a: 3 \n})", + bindings: [], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings", + expression: "var a = 3;", + newExpression: "a = 3", + bindings: ["a"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings + destructuring", + expression: "var { a } = { a: 3 };", + newExpression: "({ a } = { \n a: 3 \n })", + bindings: ["a"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings + destructuring + rest", + expression: "var { a, ...foo } = {}", + newExpression: "({ a, ...self.foo } = {})", + bindings: ["a"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings + array destructuring + rest", + expression: "var [a, ...foo] = []", + newExpression: "([a, ...self.foo] = [])", + bindings: ["a"], + mappings: {}, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings + mappings", + expression: "a = 3;", + newExpression: "self.a = 3", + bindings: ["_a"], + mappings: { a: "_a" }, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings + mappings + destructuring", + expression: "var { a } = { a: 4 }", + newExpression: "({ a: self.a } = {\n a: 4 \n})", + bindings: ["_a"], + mappings: { a: "_a" }, + shouldMapBindings: true, + expectedMapped: { + await: false, + bindings: true, + originalExpression: false, + }, + }, + { + name: "bindings without mappings", + expression: "a = 3;", + newExpression: "a = 3", + bindings: [], + mappings: { a: "_a" }, + shouldMapBindings: false, + expectedMapped: { + await: false, + bindings: false, + originalExpression: false, + }, + }, + { + name: "object destructuring + bindings without mappings", + expression: "({ a } = {});", + newExpression: "({ a: _a } = {})", + bindings: [], + mappings: { a: "_a" }, + shouldMapBindings: false, + expectedMapped: { + await: false, + bindings: false, + originalExpression: true, + }, + }, + ]); +}); |