diff --git a/.eslintignore b/.eslintignore
index f0fc934fb1e2..8926159d95de 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -63,7 +63,6 @@ devtools/client/debugger/bin/
devtools/client/debugger/configs/
devtools/client/debugger/dist/
devtools/client/debugger/images/
-devtools/client/debugger/packages/
devtools/client/debugger/test/mochitest/examples/
devtools/client/debugger/index.html
devtools/client/debugger/webpack.config.js
@@ -76,6 +75,7 @@ devtools/shared/css/generated/properties-db.js
devtools/client/webconsole/test/node/fixtures/stubs/*.js
!devtools/client/webconsole/test/node/fixtures/stubs/index.js
devtools/client/shared/components/test/node/stubs/reps/*.js
+devtools/client/shared/source-map-loader/test/browser/fixtures/*.js
# Ignore devtools files testing sourcemaps / code style
devtools/client/framework/test/code_*
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.js
deleted file mode 100644
index 8e80a7db7908..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.js
+++ /dev/null
@@ -1,12 +0,0 @@
-function componentWillReceiveProps(nextProps) {
- console.log('start');
- const { selectedSource } = nextProps;
-
- if (
- nextProps.startPanelSize !== this.props.startPanelSize ||
- nextProps.endPanelSize !== this.props.endPanelSize
- ) {
- this.state.editor.codeMirror.setSize();
- }
- console.log('done');
-}
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.out.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.out.js
deleted file mode 100644
index 9f9707e956d1..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.out.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use strict';
-
-function componentWillReceiveProps(nextProps) {
- console.log('start');
- var selectedSource = nextProps.selectedSource;
-
-
- if (nextProps.startPanelSize !== this.props.startPanelSize || nextProps.endPanelSize !== this.props.endPanelSize) {
- this.state.editor.codeMirror.setSize();
- }
- console.log('done');
-}
-
-//# sourceMappingURL=if.out.js.map
\ No newline at end of file
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/intermingled-sources.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/intermingled-sources.js
deleted file mode 100644
index bd1ef86ee44a..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/intermingled-sources.js
+++ /dev/null
@@ -1,28 +0,0 @@
-"use strict";
-
-var decl = function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
- return regeneratorRuntime.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- console.log("2");
-
- case 1:
- case "end":
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- return function decl() {
- return _ref.apply(this, arguments);
- };
-}();
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-console.log("1");
-
-console.log("3");
\ No newline at end of file
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/getContentType.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/getContentType.js
deleted file mode 100644
index 03b77f032454..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/getContentType.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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 . */
-
-const { getContentType, contentMapForTesting } = require("../utils");
-
-describe("getContentType", () => {
- for (const ext in contentMapForTesting) {
- test(`extension - ${ext}`, () => {
- expect(getContentType(`whatever.${ext}`)).toEqual(
- contentMapForTesting[ext]
- );
- expect(getContentType(`whatever${ext}`)).toEqual("text/plain");
- });
- }
-
- test("bad extension", () => {
- expect(getContentType("whatever.platypus")).toEqual("text/plain");
- });
-});
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/helpers.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/helpers.js
deleted file mode 100644
index 309f1019ec09..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/helpers.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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 . */
-
-const { isOriginalId } = require("../utils");
-const { getOriginalURLs } = require("../source-map");
-
-const fs = require("fs");
-const path = require("path");
-
-function formatLocations(locs) {
- return locs.map(formatLocation).join(" -> ");
-}
-
-function formatLocation(loc) {
- const label = isOriginalId(loc.sourceId) ? "O" : "G";
- const col = loc.column === undefined ? "u" : loc.column;
- return `${label}[${loc.line}, ${col}]`;
-}
-
-function getMap(_path) {
- const mapPath = path.join(__dirname, _path);
- return fs.readFileSync(mapPath, "utf8");
-}
-
-async function setupBundleFixtureAndData(name) {
- const source = {
- id: `${name}.js`,
- sourceMapURL: `${name}.js.map`,
- sourceMapBaseURL: `http://example.com/${name}.js`,
- };
-
- require("../utils/network-request").networkRequest.mockImplementationOnce(
- () => {
- const content = getMap(`fixtures/${name}.js.map`);
- return { content };
- }
- );
-
- return getOriginalURLs(source);
-}
-async function setupBundleFixture(name) {
- const data = await setupBundleFixtureAndData(name);
-
- return data.map(item => item.url);
-}
-
-module.exports = {
- formatLocations,
- formatLocation,
- setupBundleFixture,
- setupBundleFixtureAndData,
- getMap,
-};
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/locations.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/locations.js
deleted file mode 100644
index 059464e46ded..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/locations.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/* 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 . */
-
-jest.mock("../utils/network-request");
-const {
- getOriginalLocation,
- getGeneratedLocation,
- clearSourceMaps,
-} = require("../source-map");
-
-const { setupBundleFixture } = require("./helpers");
-
-describe("getOriginalLocation", () => {
- beforeEach(() => {
- clearSourceMaps();
- });
-
- test("maps a generated location", async () => {
- await setupBundleFixture("bundle");
- const location = {
- sourceId: "bundle.js",
- line: 49,
- };
-
- const originalLocation = await getOriginalLocation(location);
- expect(originalLocation).toEqual({
- column: 0,
- line: 3,
- sourceId: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
- sourceUrl: "webpack:///entry.js",
- });
- });
-
- test("does not map an original location", async () => {
- const location = {
- column: 0,
- line: 3,
- sourceId: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
- sourceUrl: "webpack:///entry.js",
- };
- const originalLocation = await getOriginalLocation(location);
- expect(originalLocation).toEqual(originalLocation);
- });
-});
-
-describe("getGeneratedLocation", () => {
- beforeEach(() => {
- clearSourceMaps();
- });
-
- test("maps an original location", async () => {
- await setupBundleFixture("bundle");
- const location = {
- column: 0,
- line: 3,
- sourceId: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
- };
-
- const source = {
- url: "webpack:///entry.js",
- id: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
- };
-
- const generatedLocation = await getGeneratedLocation(location, source);
- expect(generatedLocation).toEqual({
- sourceId: "bundle.js",
- line: 49,
- column: 0,
- });
- });
-
- test("location mapping is symmetric", async () => {
- // we expect symmetric mappings, which means that if
- // we map a generated location to an original location,
- // and then map it back, we should get the original generated value.
- // e.g. G[8, 0] -> O[5, 4] -> G[8, 0]
-
- await setupBundleFixture("if.out");
-
- const genLoc1 = {
- sourceId: "if.out.js",
- column: 0,
- line: 8,
- };
-
- const ifSource = {
- url: "if.js",
- id: "if.out.js/originalSource-5ad3141023dae912c5f8833c7e03beeb",
- };
-
- const oLoc = await getOriginalLocation(genLoc1);
- const genLoc2 = await getGeneratedLocation(oLoc, ifSource);
-
- expect(genLoc2).toEqual({
- sourceId: "if.out.js",
- column: 0,
- line: 8,
- });
- });
-
- test("undefined column is handled like 0 column", async () => {
- // we expect that an undefined column will be handled like a
- // location w/ column 0. e.g. G[8, u] -> O[5, 4] -> G[8, 0]
-
- await setupBundleFixture("if.out");
-
- const genLoc1 = {
- sourceId: "if.out.js",
- column: undefined,
- line: 8,
- };
-
- const ifSource = {
- url: "if.js",
- id: "if.out.js/originalSource-5ad3141023dae912c5f8833c7e03beeb",
- };
-
- const oLoc = await getOriginalLocation(genLoc1);
- const genLoc2 = await getGeneratedLocation(oLoc, ifSource);
- // console.log(formatLocations([genLoc1, oLoc, genLoc2]));
-
- expect(genLoc2).toEqual({
- sourceId: "if.out.js",
- column: 0,
- line: 8,
- });
- });
-
- test("does not map an original location", async () => {
- const location = {
- column: 0,
- line: 3,
- sourceId: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
- sourceUrl: "webpack:///entry.js",
- };
-
- const source = {
- url: "webpack:///entry.js",
- id: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
- };
-
- const generatedLocation = await getGeneratedLocation(location, source);
- expect(generatedLocation).toEqual(generatedLocation);
- });
-});
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/source-map.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/source-map.js
deleted file mode 100644
index 59cfa5b196f7..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/source-map.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* 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 . */
-
-jest.mock("../utils/network-request");
-const { networkRequest } = require("../utils/network-request");
-
-const {
- getOriginalURLs,
- getOriginalLocation,
- getGeneratedRangesForOriginal,
- clearSourceMaps,
-} = require("../source-map");
-
-const { setupBundleFixture, setupBundleFixtureAndData } = require("./helpers");
-
-describe("source maps", () => {
- beforeEach(() => {
- clearSourceMaps();
- });
- describe("getOriginalURLs", () => {
- test("absolute URL", async () => {
- const urls = await setupBundleFixture("absolute");
- expect(urls).toEqual(["http://example.com/cheese/heart.js"]);
- });
-
- test("source with a url", async () => {
- const urls = await setupBundleFixture("bundle");
- expect(urls).toEqual([
- "webpack:///webpack/bootstrap%204ef8c7ec7c1df790781e",
- "webpack:///entry.js",
- "webpack:///times2.js",
- "webpack:///output.js",
- "webpack:///opts.js",
- ]);
- });
-
- test("Empty sourceRoot resolution", async () => {
- const urls = await setupBundleFixture("empty");
- expect(urls).toEqual(["http://example.com/heart.js"]);
- });
-
- test("Non-existing sourceRoot resolution", async () => {
- const urls = await setupBundleFixture("noroot");
- expect(urls).toEqual(["http://example.com/heart.js"]);
- });
-
- test("Non-existing sourceRoot resolution with relative URLs", async () => {
- const urls = await setupBundleFixture("noroot2");
- expect(urls).toEqual(["http://example.com/heart.js"]);
- });
- });
-
- describe("getGeneratedRangesForOriginal", () => {
- test("the overall generated ranges on the source", async () => {
- const data = await setupBundleFixtureAndData("intermingled-sources");
-
- const ranges = await getGeneratedRangesForOriginal(data[0].id);
-
- expect(ranges).toEqual([
- {
- start: {
- line: 4,
- column: 69,
- },
- end: {
- line: 9,
- column: Infinity,
- },
- },
- {
- start: {
- line: 11,
- column: 0,
- },
- end: {
- line: 17,
- column: 3,
- },
- },
- {
- start: {
- line: 19,
- column: 18,
- },
- end: {
- line: 19,
- column: 22,
- },
- },
- {
- start: {
- line: 26,
- column: 0,
- },
- end: {
- line: 26,
- column: Infinity,
- },
- },
- {
- start: {
- line: 28,
- column: 0,
- },
- end: {
- line: 28,
- column: Infinity,
- },
- },
- ]);
- });
-
- test("the merged generated ranges on the source", async () => {
- const data = await setupBundleFixtureAndData("intermingled-sources");
-
- const ranges = await getGeneratedRangesForOriginal(data[0].id, true);
-
- expect(ranges).toEqual([
- {
- start: {
- line: 4,
- column: 69,
- },
- end: {
- line: 28,
- column: Infinity,
- },
- },
- ]);
- });
- });
-
- describe("Error handling", () => {
- test("missing map", async () => {
- const source = {
- id: "missingmap.js",
- sourceMapURL: "missingmap.js.map",
- sourceMapBaseURL: "http:://example.com/missingmap.js",
- };
-
- networkRequest.mockImplementationOnce(() => {
- throw new Error("Not found");
- });
-
- let thrown = false;
- try {
- await getOriginalURLs(source);
- } catch (e) {
- thrown = true;
- }
- expect(thrown).toBe(true);
-
- const location = {
- sourceId: "missingmap.js",
- line: 49,
- };
-
- thrown = false;
- try {
- await getOriginalLocation(location);
- } catch (e) {
- thrown = true;
- }
- expect(thrown).toBe(false);
- });
- });
-});
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/wasm-source-map.js b/devtools/client/debugger/packages/devtools-source-map/src/tests/wasm-source-map.js
deleted file mode 100644
index f79d3420874e..000000000000
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/wasm-source-map.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/* 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 . */
-
-// Test WasmRemap
-
-const { WasmRemap } = require("../utils/wasmRemap");
-const { createConsumer } = require("../utils/createConsumer");
-
-jest.mock("../utils/network-request");
-
-describe("wasm source maps", () => {
- test("smoke test", async () => {
- const testMap1 = {
- version: 3,
- file: "min.js",
- names: [],
- sources: ["one.js", "two.js"],
- sourceRoot: "/the/root",
- mappings: "CAAC,IAAM,SACU,GAAC",
- };
- const testMap1Entries = [
- { offset: 1, line: 1, column: 1 },
- { offset: 5, line: 1, column: 7 },
- { offset: 14, line: 2, column: 17 },
- { offset: 17, line: 2, column: 18 },
- ];
-
- const map1 = await createConsumer(testMap1);
- const remap1 = new WasmRemap(map1);
-
- expect(remap1.file).toEqual("min.js");
- expect(remap1.hasContentsOfAllSources()).toEqual(false);
- expect(remap1.sources).toHaveLength(2);
- expect(remap1.sources[0]).toEqual("/the/root/one.js");
- expect(remap1.sources[1]).toEqual("/the/root/two.js");
-
- const expectedEntries = testMap1Entries.slice(0);
- remap1.eachMapping(function(entry) {
- const expected = expectedEntries.shift();
- expect(entry.generatedLine).toEqual(expected.offset);
- expect(entry.generatedColumn).toEqual(0);
- expect(entry.originalLine).toEqual(expected.line);
- expect(entry.originalColumn).toEqual(expected.column);
- expect(entry.name).toEqual(null);
- });
-
- const pos1 = remap1.originalPositionFor({ line: 5, column: 0 });
- expect(pos1.line).toEqual(1);
- expect(pos1.column).toEqual(7);
- expect(pos1.source).toEqual("/the/root/one.js");
-
- const pos2 = remap1.generatedPositionFor({
- source: "/the/root/one.js",
- line: 2,
- column: 18,
- });
- expect(pos2.line).toEqual(17);
- expect(pos2.column).toEqual(0);
- expect(pos2.lastColumn).toEqual(undefined);
-
- remap1.computeColumnSpans();
- const pos3 = remap1.allGeneratedPositionsFor({
- source: "/the/root/one.js",
- line: 2,
- column: 17,
- });
- expect(pos3).toHaveLength(1);
- expect(pos3[0].line).toEqual(14);
- expect(pos3[0].column).toEqual(0);
- expect(pos3[0].lastColumn).toEqual(0);
- });
-
- test("content presents", async () => {
- const testMap2 = {
- version: 3,
- file: "none.js",
- names: [],
- sources: ["zero.js"],
- mappings: "",
- sourcesContent: ["//test"],
- };
-
- const map2 = await createConsumer(testMap2);
- const remap2 = new WasmRemap(map2);
- expect(remap2.file).toEqual("none.js");
- expect(remap2.hasContentsOfAllSources()).toEqual(true);
- expect(remap2.sourceContentFor("zero.js")).toEqual("//test");
- });
-
- test("read and transpose wasm map", async () => {
- const source = {
- id: "min.js",
- sourceMapBaseURL: "wasm:http://example.com/whatever/:min.js",
- sourceMapURL: "http://example.com/whatever/min.js.map",
- isWasm: true,
- };
-
- require("../utils/network-request").networkRequest.mockImplementationOnce(
- () => {
- const content = JSON.stringify({
- version: 3,
- file: "min.js",
- names: [],
- sources: ["one.js"],
- mappings: "CAAC,IAAM",
- });
- return { content };
- }
- );
-
- const { getOriginalURLs, getOriginalLocation } = require("../source-map");
-
- const urls = await getOriginalURLs(source);
- expect(urls).toEqual([
- {
- id: "min.js/originalSource-2133f6ef6d6c464acad221082f398cf0",
- url: "http://example.com/whatever/one.js",
- },
- ]);
-
- const { line, column } = await getOriginalLocation({
- sourceId: source.id,
- line: 5,
- });
- expect(line).toEqual(1);
- expect(column).toEqual(7);
- });
-});
diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-sourcemap.js b/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-sourcemap.js
index 435db0d505b1..e29ed842d67b 100644
--- a/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-sourcemap.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg-pretty-print-sourcemap.js
@@ -85,6 +85,14 @@ add_task(async () => {
const source1 = findSource(dbg, "js1.min.js");
await selectSource(dbg, source1);
+ // The source may be reported as pretty printable while we are fetching the sourcemap,
+ // but once the sourcemap is reported to be failing, we no longer report to be pretty printable.
+ await waitFor(
+ () =>
+ dbg.selectors.getSourceActorsForSource(source1.id)[0].sourceMapURL === "",
+ "Wait for the selector source to clear its sourceMapURL"
+ );
+
assertPrettyPrintButton(dbg, L10N.getStr("sourceTabs.prettyPrint"), false);
info(
@@ -108,7 +116,11 @@ add_task(async () => {
});
add_task(async () => {
- const dbg = await initDebugger("doc-sourcemaps2.html", "main.min.js");
+ const dbg = await initDebugger(
+ "doc-sourcemaps2.html",
+ "main.min.js",
+ "main.js"
+ );
info(
" - Test source with sourceMappingURL, sourcemap and original files exist"
diff --git a/devtools/client/shared/source-map-loader/moz.build b/devtools/client/shared/source-map-loader/moz.build
index 86f36c57d819..c3cf26b35802 100644
--- a/devtools/client/shared/source-map-loader/moz.build
+++ b/devtools/client/shared/source-map-loader/moz.build
@@ -14,3 +14,5 @@ DevToolsModules(
"source-map.js",
"worker.js",
)
+
+BROWSER_CHROME_MANIFESTS += ["test/browser/browser.ini"]
diff --git a/devtools/client/shared/source-map-loader/test/browser/browser.ini b/devtools/client/shared/source-map-loader/test/browser/browser.ini
new file mode 100644
index 000000000000..dfe490158c72
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/browser.ini
@@ -0,0 +1,13 @@
+[DEFAULT]
+tags = devtools
+subsuite = devtools
+support-files =
+ head.js
+ fixtures/*
+ !/devtools/client/shared/test/shared-head.js
+ !/devtools/client/shared/test/telemetry-test-helpers.js
+
+[browser_getContentType.js]
+[browser_locations.js]
+[browser_source-map.js]
+[browser_wasm-source-map.js]
diff --git a/devtools/client/shared/source-map-loader/test/browser/browser_getContentType.js b/devtools/client/shared/source-map-loader/test/browser/browser_getContentType.js
new file mode 100644
index 000000000000..5ac402951cd0
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/browser_getContentType.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Cover the automatic mapping of content type based on file extension
+
+const {
+ getContentType,
+ contentMapForTesting,
+} = require("resource://devtools/client/shared/source-map-loader/utils/index.js");
+
+add_task(async () => {
+ for (const ext in contentMapForTesting) {
+ is(
+ getContentType(`whatever.${ext}`),
+ contentMapForTesting[ext],
+ `${ext} file extension is correctly mapping the expected content type`
+ );
+ }
+ is(
+ getContentType(`whateverjs`),
+ "text/plain",
+ `A valid extension in file name doesn't cause a special content type mapping`
+ );
+
+ is(
+ getContentType("whatever.platypus"),
+ "text/plain",
+ "Test unknown extension defaults to text plain"
+ );
+});
diff --git a/devtools/client/shared/source-map-loader/test/browser/browser_locations.js b/devtools/client/shared/source-map-loader/test/browser/browser_locations.js
new file mode 100644
index 000000000000..50727ebd8814
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/browser_locations.js
@@ -0,0 +1,139 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Covert getOriginalLocation and getGeneratedLocation functions.
+
+add_task(async function testGetOriginalLocation() {
+ await fetchFixtureSourceMap("bundle");
+
+ const generatedLocation = {
+ sourceId: "bundle.js",
+ line: 49,
+ };
+
+ const originalLocation = await getOriginalLocation(generatedLocation);
+ Assert.deepEqual(
+ originalLocation,
+ {
+ column: 0,
+ line: 3,
+ sourceId: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
+ sourceUrl: "webpack:///entry.js",
+ },
+ "Mapped a generated location"
+ );
+
+ const originalLocation2 = await getOriginalLocation(originalLocation);
+ Assert.deepEqual(
+ originalLocation2,
+ originalLocation,
+ "original location maps to itself"
+ );
+
+ clearSourceMaps();
+ const originalLocation3 = await getOriginalLocation(generatedLocation);
+ Assert.deepEqual(
+ originalLocation3,
+ generatedLocation,
+ "after clearing the source maps, the same generated location maps to itself"
+ );
+});
+
+add_task(async function testGetGeneratedLocation() {
+ await fetchFixtureSourceMap("bundle");
+
+ const originalLocation = {
+ column: 0,
+ line: 3,
+ sourceId: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
+ };
+
+ const source = {
+ url: "webpack:///entry.js",
+ id: "bundle.js/originalSource-fe2c41d3535b76c158e39ba4f3ff826a",
+ };
+
+ const generatedLocation = await getGeneratedLocation(
+ originalLocation,
+ source
+ );
+ Assert.deepEqual(
+ generatedLocation,
+ {
+ sourceId: "bundle.js",
+ line: 49,
+ column: 0,
+ },
+ "Map an original location"
+ );
+
+ {
+ clearSourceMaps();
+
+ const secondGeneratedLocation = await getGeneratedLocation(
+ originalLocation,
+ source
+ );
+ Assert.deepEqual(
+ secondGeneratedLocation,
+ originalLocation,
+ "after clearing source maps, the same location no longer maps to an original location"
+ );
+ }
+
+ {
+ // we expect symmetric mappings, which means that if
+ // we map a generated location to an original location,
+ // and then map it back, we should get the original generated value.
+ // e.g. G[8, 0] -> O[5, 4] -> G[8, 0]
+ await fetchFixtureSourceMap("if.out");
+
+ const genLoc1 = {
+ sourceId: "if.out.js",
+ column: 0,
+ line: 8,
+ };
+
+ const ifSource = {
+ url: "if.js",
+ id: "if.out.js/originalSource-5ad3141023dae912c5f8833c7e03beeb",
+ };
+
+ const oLoc = await getOriginalLocation(genLoc1);
+ const genLoc2 = await getGeneratedLocation(oLoc, ifSource);
+
+ Assert.deepEqual(genLoc2, genLoc1, "location mapping is symmetric");
+ }
+
+ {
+ // we expect that an undefined column will be handled like a
+ // location w/ column 0. e.g. G[8, u] -> O[5, 4] -> G[8, 0]
+ await fetchFixtureSourceMap("if.out");
+
+ const genLoc1 = {
+ sourceId: "if.out.js",
+ column: undefined,
+ line: 8,
+ };
+
+ const ifSource = {
+ url: "if.js",
+ id: "if.out.js/originalSource-5ad3141023dae912c5f8833c7e03beeb",
+ };
+
+ const oLoc = await getOriginalLocation(genLoc1);
+ const genLoc2 = await getGeneratedLocation(oLoc, ifSource);
+
+ Assert.deepEqual(
+ genLoc2,
+ {
+ sourceId: "if.out.js",
+ column: 0,
+ line: 8,
+ },
+ "undefined column is handled like 0 column"
+ );
+ }
+});
diff --git a/devtools/client/shared/source-map-loader/test/browser/browser_source-map.js b/devtools/client/shared/source-map-loader/test/browser/browser_source-map.js
new file mode 100644
index 000000000000..f5ed826b36a4
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/browser_source-map.js
@@ -0,0 +1,160 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Cover the high level API of these modules:
+// getOriginalURLs getGeneratedRangesForOriginal functions
+
+async function assertFixtureOriginalURLs(
+ fixtureName,
+ expectedUrls,
+ testMessage
+) {
+ const originalSources = await fetchFixtureSourceMap(fixtureName);
+ const urls = originalSources.map(s => s.url);
+ Assert.deepEqual(urls, expectedUrls, testMessage);
+}
+
+add_task(async function testGetOriginalURLs() {
+ await assertFixtureOriginalURLs(
+ "absolute",
+ ["https://example.com/cheese/heart.js"],
+ "Test absolute URL"
+ );
+
+ await assertFixtureOriginalURLs(
+ "bundle",
+ [
+ "webpack:///webpack/bootstrap%204ef8c7ec7c1df790781e",
+ "webpack:///entry.js",
+ "webpack:///times2.js",
+ "webpack:///output.js",
+ "webpack:///opts.js",
+ ],
+ "Test source with a url"
+ );
+
+ await assertFixtureOriginalURLs(
+ "empty",
+ [`${URL_ROOT_SSL}fixtures/heart.js`],
+ "Test empty sourceRoot resolution"
+ );
+
+ await assertFixtureOriginalURLs(
+ "noroot",
+ [`${URL_ROOT_SSL}fixtures/heart.js`],
+ "Test Non-existing sourceRoot resolution"
+ );
+
+ await assertFixtureOriginalURLs(
+ "noroot2",
+ [`${URL_ROOT_SSL}fixtures/heart.js`],
+ "Test Non-existing sourceRoot resolution with relative URLs"
+ );
+});
+
+add_task(async function testGetGeneratedRangesForOriginal() {
+ const originals = await fetchFixtureSourceMap("intermingled-sources");
+
+ const ranges = await getGeneratedRangesForOriginal(originals[0].id);
+
+ Assert.deepEqual(
+ ranges,
+ [
+ {
+ start: {
+ line: 4,
+ column: 69,
+ },
+ end: {
+ line: 9,
+ column: Infinity,
+ },
+ },
+ {
+ start: {
+ line: 11,
+ column: 0,
+ },
+ end: {
+ line: 17,
+ column: 3,
+ },
+ },
+ {
+ start: {
+ line: 19,
+ column: 18,
+ },
+ end: {
+ line: 19,
+ column: 22,
+ },
+ },
+ {
+ start: {
+ line: 26,
+ column: 0,
+ },
+ end: {
+ line: 26,
+ column: Infinity,
+ },
+ },
+ {
+ start: {
+ line: 28,
+ column: 0,
+ },
+ end: {
+ line: 28,
+ column: Infinity,
+ },
+ },
+ ],
+ "Test the overall generated ranges on the source"
+ );
+
+ {
+ // Note that we have to clear the source map in order to get the merged ranges,
+ // otherwise we are still fetching the previous unmerged ones!
+ const secondOriginals = await fetchFixtureSourceMap("intermingled-sources");
+ const mergedRanges = await getGeneratedRangesForOriginal(
+ secondOriginals[0].id,
+ true
+ );
+
+ Assert.deepEqual(
+ mergedRanges,
+ [
+ {
+ start: {
+ line: 4,
+ column: 69,
+ },
+ end: {
+ line: 28,
+ column: Infinity,
+ },
+ },
+ ],
+ "Test the merged generated ranges on the source"
+ );
+ }
+});
+
+add_task(async function testErrorHandling() {
+ const source = {
+ id: "missingmap.js",
+ sourceMapURL: "missingmap.js.map",
+ // Notice the duplicated ":" which cause the error here
+ sourceMapBaseURL: "http:://example.com/missingmap.js",
+ };
+
+ await Assert.rejects(
+ getOriginalURLs(source),
+ /http::\/\/example.com\/missingmap.js is not a valid URL/,
+ "Throws on network error"
+ );
+});
diff --git a/devtools/client/shared/source-map-loader/test/browser/browser_wasm-source-map.js b/devtools/client/shared/source-map-loader/test/browser/browser_wasm-source-map.js
new file mode 100644
index 000000000000..22662d91f60a
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/browser_wasm-source-map.js
@@ -0,0 +1,125 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test source mappings WASM sources.
+// This test is quite general and test various functions.
+
+const { WasmRemap } = browserRequire(
+ "resource://devtools/client/shared/source-map-loader/utils/wasmRemap.js"
+);
+const { createConsumer } = browserRequire(
+ "resource://devtools/client/shared/source-map-loader/utils/createConsumer.js"
+);
+const { SourceMapConsumer } = browserRequire(
+ "resource://devtools/client/shared/vendor/source-map/source-map.js"
+);
+
+SourceMapConsumer.initialize({
+ "lib/mappings.wasm":
+ "resource://devtools/client/shared/vendor/source-map/lib/mappings.wasm",
+});
+
+add_task(async function smokeTest() {
+ const testMap1 = {
+ version: 3,
+ file: "min.js",
+ names: [],
+ sources: ["one.js", "two.js"],
+ sourceRoot: "/the/root",
+ mappings: "CAAC,IAAM,SACU,GAAC",
+ };
+ const testMap1Entries = [
+ { offset: 1, line: 1, column: 1 },
+ { offset: 5, line: 1, column: 7 },
+ { offset: 14, line: 2, column: 17 },
+ { offset: 17, line: 2, column: 18 },
+ ];
+
+ const map1 = await createConsumer(testMap1);
+
+ const remap1 = new WasmRemap(map1);
+
+ is(remap1.file, "min.js");
+ is(remap1.hasContentsOfAllSources(), false);
+ is(remap1.sources.length, 2);
+ is(remap1.sources[0], "/the/root/one.js");
+ is(remap1.sources[1], "/the/root/two.js");
+
+ const expectedEntries = testMap1Entries.slice(0);
+ remap1.eachMapping(function(entry) {
+ const expected = expectedEntries.shift();
+ is(entry.generatedLine, expected.offset);
+ is(entry.generatedColumn, 0);
+ is(entry.originalLine, expected.line);
+ is(entry.originalColumn, expected.column);
+ is(entry.name, null);
+ });
+
+ const pos1 = remap1.originalPositionFor({ line: 5, column: 0 });
+ is(pos1.line, 1);
+ is(pos1.column, 7);
+ is(pos1.source, "/the/root/one.js");
+
+ const pos2 = remap1.generatedPositionFor({
+ source: "/the/root/one.js",
+ line: 2,
+ column: 18,
+ });
+ is(pos2.line, 17);
+ is(pos2.column, 0);
+ is(pos2.lastColumn, undefined);
+
+ remap1.computeColumnSpans();
+ const pos3 = remap1.allGeneratedPositionsFor({
+ source: "/the/root/one.js",
+ line: 2,
+ column: 17,
+ });
+ is(pos3.length, 1);
+ is(pos3[0].line, 14);
+ is(pos3[0].column, 0);
+ is(pos3[0].lastColumn, 0);
+});
+
+add_task(async function contentPresents() {
+ const testMap2 = {
+ version: 3,
+ file: "none.js",
+ names: [],
+ sources: ["zero.js"],
+ mappings: "",
+ sourcesContent: ["//test"],
+ };
+
+ const map2 = await createConsumer(testMap2);
+ const remap2 = new WasmRemap(map2);
+ is(remap2.file, "none.js");
+ ok(remap2.hasContentsOfAllSources());
+ is(remap2.sourceContentFor("zero.js"), "//test");
+});
+
+add_task(async function readAndTransposeWasmMap() {
+ const source = {
+ id: "wasm.js",
+ sourceMapBaseURL: "wasm:http://example.com/whatever/:min.js",
+ sourceMapURL: `${URL_ROOT}fixtures/wasm.js.map`,
+ isWasm: true,
+ };
+
+ const urls = await getOriginalURLs(source);
+ Assert.deepEqual(urls, [
+ {
+ id: "wasm.js/originalSource-63954a1c231200652c0d99c6a69cd178",
+ url: `${URL_ROOT}fixtures/one.js`,
+ },
+ ]);
+
+ const { line, column } = await getOriginalLocation({
+ sourceId: source.id,
+ line: 5,
+ });
+ is(line, 1);
+ is(column, 7);
+});
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/absolute.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/absolute.js
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/absolute.js
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/absolute.js
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/absolute.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/absolute.js.map
similarity index 90%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/absolute.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/absolute.js.map
index 4786aabcae30..0597515870db 100644
--- a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/absolute.js.map
+++ b/devtools/client/shared/source-map-loader/test/browser/fixtures/absolute.js.map
@@ -6,5 +6,5 @@
"names": [],
"mappings": ";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;ACtCA;AACA,QAAO,SAAS;AAChB;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;ACfA;AACA;AACA;;;;;;;ACFA;AACA;AACA;;AAEA,mBAAkB;;;;;;;ACJlB;AACA;AACA",
"file": "absolute.js",
- "sourceRoot": "http://example.com/cheese/"
+ "sourceRoot": "https://example.com/cheese/"
}
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/bundle.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/bundle.js
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/bundle.js
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/bundle.js
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/bundle.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/bundle.js.map
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/bundle.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/bundle.js.map
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/empty.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/empty.js
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/empty.js
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/empty.js
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/empty.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/empty.js.map
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/empty.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/empty.js.map
diff --git a/devtools/client/shared/source-map-loader/test/browser/fixtures/if.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/if.js
new file mode 100644
index 000000000000..4ee69b19ef4c
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/fixtures/if.js
@@ -0,0 +1,12 @@
+function componentWillReceiveProps(nextProps) {
+ console.log("start");
+ const { selectedSource } = nextProps;
+
+ if (
+ nextProps.startPanelSize !== this.props.startPanelSize ||
+ nextProps.endPanelSize !== this.props.endPanelSize
+ ) {
+ this.state.editor.codeMirror.setSize();
+ }
+ console.log("done");
+}
diff --git a/devtools/client/shared/source-map-loader/test/browser/fixtures/if.out.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/if.out.js
new file mode 100644
index 000000000000..9bb0752a9204
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/fixtures/if.out.js
@@ -0,0 +1,16 @@
+"use strict";
+
+function componentWillReceiveProps(nextProps) {
+ console.log("start");
+ var selectedSource = nextProps.selectedSource;
+
+ if (
+ nextProps.startPanelSize !== this.props.startPanelSize ||
+ nextProps.endPanelSize !== this.props.endPanelSize
+ ) {
+ this.state.editor.codeMirror.setSize();
+ }
+ console.log("done");
+}
+
+//# sourceMappingURL=if.out.js.map
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.out.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/if.out.js.map
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/if.out.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/if.out.js.map
diff --git a/devtools/client/shared/source-map-loader/test/browser/fixtures/intermingled-sources.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/intermingled-sources.js
new file mode 100644
index 000000000000..c3d9a150bd3b
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/fixtures/intermingled-sources.js
@@ -0,0 +1,62 @@
+"use strict";
+
+var decl = (function() {
+ var _ref = _asyncToGenerator(
+ /*#__PURE__*/ regeneratorRuntime.mark(function _callee() {
+ return regeneratorRuntime.wrap(
+ function _callee$(_context) {
+ while (1) {
+ switch ((_context.prev = _context.next)) {
+ case 0:
+ console.log("2");
+
+ case 1:
+ case "end":
+ return _context.stop();
+ }
+ }
+ },
+ _callee,
+ this
+ );
+ })
+ );
+
+ return function decl() {
+ return _ref.apply(this, arguments);
+ };
+})();
+
+function _asyncToGenerator(fn) {
+ return function() {
+ var gen = fn.apply(this, arguments);
+ return new Promise(function(resolve, reject) {
+ function step(key, arg) {
+ try {
+ var info = gen[key](arg);
+ var value = info.value;
+ } catch (error) {
+ reject(error);
+ return;
+ }
+ if (info.done) {
+ resolve(value);
+ } else {
+ return Promise.resolve(value).then(
+ function(value) {
+ step("next", value);
+ },
+ function(err) {
+ step("throw", err);
+ }
+ );
+ }
+ }
+ return step("next");
+ });
+ };
+}
+
+console.log("1");
+
+console.log("3");
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/intermingled-sources.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/intermingled-sources.js.map
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/intermingled-sources.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/intermingled-sources.js.map
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/missingmap.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/missingmap.js
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/missingmap.js
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/missingmap.js
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/noroot.js
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot.js
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/noroot.js
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/noroot.js.map
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/noroot.js.map
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot2.js b/devtools/client/shared/source-map-loader/test/browser/fixtures/noroot2.js
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot2.js
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/noroot2.js
diff --git a/devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot2.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/noroot2.js.map
similarity index 100%
rename from devtools/client/debugger/packages/devtools-source-map/src/tests/fixtures/noroot2.js.map
rename to devtools/client/shared/source-map-loader/test/browser/fixtures/noroot2.js.map
diff --git a/devtools/client/shared/source-map-loader/test/browser/fixtures/wasm.js.map b/devtools/client/shared/source-map-loader/test/browser/fixtures/wasm.js.map
new file mode 100644
index 000000000000..828f6a9aa493
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/fixtures/wasm.js.map
@@ -0,0 +1,7 @@
+{
+ "version": 3,
+ "file": "wasm.js",
+ "names": [],
+ "sources": ["one.js"],
+ "mappings": "CAAC,IAAM"
+}
diff --git a/devtools/client/shared/source-map-loader/test/browser/head.js b/devtools/client/shared/source-map-loader/test/browser/head.js
new file mode 100644
index 000000000000..48cf853a73db
--- /dev/null
+++ b/devtools/client/shared/source-map-loader/test/browser/head.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* import-globals-from ../../../../shared/test/shared-head.js */
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
+ this
+);
+
+// source-map has to be loaded via a Browser Loader in order to be able to instantiate
+// a web worker and have access to Worker symbol in globals
+const { BrowserLoader } = ChromeUtils.import(
+ "resource://devtools/shared/loader/browser-loader.js"
+);
+const { require: browserRequire } = BrowserLoader({
+ baseURI: "resource://devtools/",
+ window,
+});
+delete window.getBrowserLoaderForWindow;
+
+const {
+ startSourceMapWorker,
+ getOriginalURLs,
+ getOriginalLocation,
+ getGeneratedLocation,
+ getGeneratedRangesForOriginal,
+ clearSourceMaps,
+} = browserRequire(
+ "resource://devtools/client/shared/source-map-loader/index.js"
+);
+
+startSourceMapWorker(
+ "resource://devtools/client/shared/source-map-loader/worker.js"
+);
+
+function fetchFixtureSourceMap(name) {
+ clearSourceMaps();
+
+ const source = {
+ id: `${name}.js`,
+ sourceMapURL: `${name}.js.map`,
+ sourceMapBaseURL: `${URL_ROOT_SSL}fixtures/${name}.js`,
+ };
+
+ return getOriginalURLs(source);
+}