forked from mirrors/gecko-dev
Bug 1387477 - report source map errors due to missing sources; r=jdescottes
MozReview-Commit-ID: 5UbkJH8fvLn --HG-- extra : rebase_source : 3242c0bcfcb5d04343c1a724fe78904d5f52e567
This commit is contained in:
parent
ef291aef27
commit
ef9552735d
10 changed files with 262 additions and 43 deletions
|
|
@ -174,6 +174,7 @@ devtools/client/debugger/test/mochitest/code_worker-source-map.js
|
|||
devtools/client/framework/test/code_ugly*
|
||||
devtools/client/inspector/markup/test/events_bundle.js
|
||||
devtools/client/netmonitor/test/xhr_bundle.js
|
||||
devtools/client/webconsole/new-console-output/test/mochitest/code_bundle_nosource.js
|
||||
devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
|
||||
devtools/server/tests/unit/setBreakpoint*
|
||||
devtools/server/tests/unit/sourcemapped.js
|
||||
|
|
|
|||
|
|
@ -549,17 +549,42 @@ Toolbox.prototype = {
|
|||
// Provide a wrapper for the service that reports errors more nicely.
|
||||
this._sourceMapService = new Proxy(service, {
|
||||
get: (target, name) => {
|
||||
if (name === "getOriginalURLs") {
|
||||
return (urlInfo) => {
|
||||
return target.getOriginalURLs(urlInfo)
|
||||
.catch(text => {
|
||||
let message = L10N.getFormatStr("toolbox.sourceMapFailure",
|
||||
text, urlInfo.url, urlInfo.sourceMapURL);
|
||||
this.target.logErrorInPage(message, "source map");
|
||||
});
|
||||
};
|
||||
switch (name) {
|
||||
case "getOriginalURLs":
|
||||
return (urlInfo) => {
|
||||
return target.getOriginalURLs(urlInfo)
|
||||
.catch(text => {
|
||||
let message = L10N.getFormatStr("toolbox.sourceMapFailure",
|
||||
text, urlInfo.url,
|
||||
urlInfo.sourceMapURL);
|
||||
this.target.logErrorInPage(message, "source map");
|
||||
// It's ok to swallow errors here, because a null
|
||||
// result just means that no source map was found.
|
||||
return null;
|
||||
});
|
||||
};
|
||||
|
||||
case "getOriginalSourceText":
|
||||
return (originalSource) => {
|
||||
return target.getOriginalSourceText(originalSource)
|
||||
.catch(text => {
|
||||
let message = L10N.getFormatStr("toolbox.sourceMapSourceFailure",
|
||||
text, originalSource.url);
|
||||
this.target.logErrorInPage(message, "source map");
|
||||
// Also replace the result with the error text.
|
||||
// Note that this result has to have the same form
|
||||
// as whatever the upstream getOriginalSourceText
|
||||
// returns.
|
||||
return {
|
||||
text: message,
|
||||
contentType: "text/plain",
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
default:
|
||||
return target[name];
|
||||
}
|
||||
return target[name];
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -184,3 +184,10 @@ toolbox.allToolsButton.tooltip=Select another tool
|
|||
# The URL that caused DevTools to try to fetch a source map: %2$S
|
||||
# The URL of the source map itself: %3$S
|
||||
toolbox.sourceMapFailure=Source map error: %1$S\nResource URL: %2$S\nSource Map URL: %3$S
|
||||
|
||||
# LOCALIZATION NOTE (toolbox.sourceMapSourceFailure): This is shown in
|
||||
# the web console when there is a failure to fetch or parse an
|
||||
# original source that was mentioned in a source map.
|
||||
# The text of the error: %1$S
|
||||
# The URL of the source: %2$S
|
||||
toolbox.sourceMapSourceFailure=Error while fetching an original source: %1$S\nSource URL: %2$S
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
code_bundle_nosource.js
|
||||
code_bundle_nosource.js.map
|
||||
head.js
|
||||
test-batching.html
|
||||
test-console.html
|
||||
|
|
@ -53,6 +55,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
|||
[browser_webconsole_observer_notifications.js]
|
||||
[browser_webconsole_shows_reqs_in_netmonitor.js]
|
||||
[browser_webconsole_sourcemap_error.js]
|
||||
[browser_webconsole_sourcemap_nosource.js]
|
||||
[browser_webconsole_stacktrace_location_debugger_link.js]
|
||||
[browser_webconsole_stacktrace_location_scratchpad_link.js]
|
||||
[browser_webconsole_string.js]
|
||||
|
|
|
|||
|
|
@ -40,35 +40,3 @@ add_task(function* () {
|
|||
yield toolbox.selectTool("webconsole");
|
||||
yield testOpenInDebugger(hud, toolbox, "document.bar");
|
||||
});
|
||||
|
||||
function* testOpenInDebugger(hud, toolbox, text) {
|
||||
info(`Testing message with text "${text}"`);
|
||||
let messageNode = yield waitFor(() => findMessage(hud, text));
|
||||
let frameLinkNode = messageNode.querySelector(".message-location .frame-link");
|
||||
ok(frameLinkNode, "The message does have a location link");
|
||||
yield checkClickOnNode(hud, toolbox, frameLinkNode);
|
||||
}
|
||||
|
||||
function* checkClickOnNode(hud, toolbox, frameLinkNode) {
|
||||
info("checking click on node location");
|
||||
|
||||
let url = frameLinkNode.getAttribute("data-url");
|
||||
ok(url, `source url found ("${url}")`);
|
||||
|
||||
let line = frameLinkNode.getAttribute("data-line");
|
||||
ok(line, `source line found ("${line}")`);
|
||||
|
||||
let onSourceInDebuggerOpened = once(hud.ui, "source-in-debugger-opened");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
frameLinkNode.querySelector(".frame-link-filename"));
|
||||
|
||||
yield onSourceInDebuggerOpened;
|
||||
|
||||
let dbg = toolbox.getPanel("jsdebugger");
|
||||
is(
|
||||
dbg._selectors.getSelectedSource(dbg._getState()).get("url"),
|
||||
url,
|
||||
"expected source url"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that a missing original source is reported.
|
||||
|
||||
const JS_URL = URL_ROOT + "code_bundle_nosource.js";
|
||||
|
||||
const PAGE_URL = `data:text/html,
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Empty test page to test source map with missing original source</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="${JS_URL}"></script>
|
||||
</body>
|
||||
|
||||
</html>`;
|
||||
|
||||
add_task(function* () {
|
||||
// Force the new debugger UI, in case this gets uplifted with the old
|
||||
// debugger still turned on
|
||||
yield pushPref("devtools.debugger.new-debugger-frontend", true);
|
||||
yield pushPref("devtools.source-map.client-service.enabled", true);
|
||||
|
||||
const hud = yield openNewTabAndConsole(PAGE_URL);
|
||||
const toolbox = hud.ui.newConsoleOutput.toolbox;
|
||||
|
||||
info("Finding \"here\" message and waiting for source map to be applied");
|
||||
yield waitFor(() => {
|
||||
let node = findMessage(hud, "here");
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
let frameLinkNode = node.querySelector(".message-location .frame-link");
|
||||
let url = frameLinkNode.getAttribute("data-url");
|
||||
return url.includes("nosuchfile");
|
||||
});
|
||||
|
||||
yield testOpenInDebugger(hud, toolbox, "here");
|
||||
|
||||
info("Selecting the console again");
|
||||
yield toolbox.selectTool("webconsole");
|
||||
|
||||
const node = yield waitFor(() => findMessage(hud, "original source"));
|
||||
ok(node, "source map error is displayed in web console");
|
||||
});
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Original source code for the cross-domain source map test.
|
||||
// The generated file was made with
|
||||
// webpack --devtool nosources-source-map code_nosource.js code_bundle_nosource.js
|
||||
// ... and then the bundle was edited to change the source name.
|
||||
|
||||
|
||||
|
||||
function f() {
|
||||
console.log("here");
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
// Avoid script GC.
|
||||
window.f = f;
|
||||
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
//# sourceMappingURL=code_bundle_nosource.js.map
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 5f603779212cf1264c9b","nosuchfile.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AC7DA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA","file":"code_bundle_nosource.js","sourceRoot":""}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Original source code for the cross-domain source map test.
|
||||
// The generated file was made with
|
||||
// webpack --devtool nosources-source-map code_nosource.js code_bundle_nosource.js
|
||||
// ... and then the bundle was edited to change the source name.
|
||||
|
||||
"use strict";
|
||||
|
||||
function f() {
|
||||
console.log("here");
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
// Avoid script GC.
|
||||
window.f = f;
|
||||
|
|
@ -4,7 +4,8 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from ../../../../framework/test/shared-head.js */
|
||||
/* exported WCUL10n, openNewTabAndConsole, waitForMessages, waitFor, findMessage,
|
||||
openContextMenu, hideContextMenu, loadDocument, waitForNodeMutation */
|
||||
openContextMenu, hideContextMenu, loadDocument,
|
||||
waitForNodeMutation, testOpenInDebugger, checkClickOnNode */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
|
@ -203,3 +204,51 @@ function waitForNodeMutation(node, observeConfig = {}) {
|
|||
observer.observe(node, observeConfig);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a given message. When found, simulate a click on the
|
||||
* message's location, checking to make sure that the debugger opens
|
||||
* the corresponding URL.
|
||||
*
|
||||
* @param {Object} hud
|
||||
* The webconsole
|
||||
* @param {Object} toolbox
|
||||
* The toolbox
|
||||
* @param {String} text
|
||||
* The text to search for. This should be contained in the
|
||||
* message. The searching is done with @see findMessage.
|
||||
*/
|
||||
function* testOpenInDebugger(hud, toolbox, text) {
|
||||
info(`Finding message for open-in-debugger test; text is "${text}"`);
|
||||
let messageNode = yield waitFor(() => findMessage(hud, text));
|
||||
let frameLinkNode = messageNode.querySelector(".message-location .frame-link");
|
||||
ok(frameLinkNode, "The message does have a location link");
|
||||
yield checkClickOnNode(hud, toolbox, frameLinkNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for testOpenInDebugger.
|
||||
*/
|
||||
function* checkClickOnNode(hud, toolbox, frameLinkNode) {
|
||||
info("checking click on node location");
|
||||
|
||||
let url = frameLinkNode.getAttribute("data-url");
|
||||
ok(url, `source url found ("${url}")`);
|
||||
|
||||
let line = frameLinkNode.getAttribute("data-line");
|
||||
ok(line, `source line found ("${line}")`);
|
||||
|
||||
let onSourceInDebuggerOpened = once(hud.ui, "source-in-debugger-opened");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
frameLinkNode.querySelector(".frame-link-filename"));
|
||||
|
||||
yield onSourceInDebuggerOpened;
|
||||
|
||||
let dbg = toolbox.getPanel("jsdebugger");
|
||||
is(
|
||||
dbg._selectors.getSelectedSource(dbg._getState()).get("url"),
|
||||
url,
|
||||
"expected source url"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue