author | Wes Kocher <wkocher@mozilla.com> |
Wed, 20 Jul 2016 12:56:46 -0700 | |
changeset 306084 | c6e4b6a744697056dcebe1cf298ed3b7de85311c |
parent 306083 | 3367c6049a4f1a7f94532da415bba9e5e348e883 |
child 306085 | 8f018f9e7725f4566f24dc6e5a8d8fa627a01a1c |
push id | 79765 |
push user | cbook@mozilla.com |
push date | Thu, 21 Jul 2016 14:26:34 +0000 |
treeherder | mozilla-inbound@ab54bfc55266 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 670002 |
milestone | 50.0a1 |
backs out | aab8baf2c5f54cf16b69b197094719fc0f0eae23 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
deleted file mode 100644 --- a/devtools/client/framework/location-store.js +++ /dev/null @@ -1,103 +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 http://mozilla.org/MPL/2.0/. */ -"use strict"; - -const SOURCE_TOKEN = "<:>"; - -function LocationStore (store) { - this._store = store || new Map(); -} - -/** - * Method to get a promised location from the Store. - * @param location - * @returns Promise<Object> - */ -LocationStore.prototype.get = function (location) { - this._safeAccessInit(location.url); - return this._store.get(location.url).get(location); -}; - -/** - * Method to set a promised location to the Store - * @param location - * @param promisedLocation - */ -LocationStore.prototype.set = function (location, promisedLocation = null) { - this._safeAccessInit(location.url); - this._store.get(location.url).set(serialize(location), promisedLocation); -}; - -/** - * Utility method to verify if key exists in Store before accessing it. - * If not, initializing it. - * @param url - * @private - */ -LocationStore.prototype._safeAccessInit = function (url) { - if (!this._store.has(url)) { - this._store.set(url, new Map()); - } -}; - -/** - * Utility proxy method to Map.clear() method - */ -LocationStore.prototype.clear = function () { - this._store.clear(); -}; - -/** - * Retrieves an object containing all locations to be resolved when `source-updated` - * event is triggered. - * @param url - * @returns {Array<String>} - */ -LocationStore.prototype.getByURL = function (url){ - if (this._store.has(url)) { - return [...this._store.get(url).keys()]; - } - return []; -}; - -/** - * Invalidates the stale location promises from the store when `source-updated` - * event is triggered, and when FrameView unsubscribes from a location. - * @param url - */ -LocationStore.prototype.clearByURL = function (url) { - this._safeAccessInit(url); - this._store.set(url, new Map()); -}; - -exports.LocationStore = LocationStore; -exports.serialize = serialize; -exports.deserialize = deserialize; - -/** - * Utility method to serialize the source - * @param source - * @returns {string} - */ -function serialize(source) { - let { url, line, column } = source; - line = line || 0; - column = column || 0; - return `${url}${SOURCE_TOKEN}${line}${SOURCE_TOKEN}${column}`; -}; - -/** - * Utility method to serialize the source - * @param source - * @returns Object - */ -function deserialize(source) { - let [ url, line, column ] = source.split(SOURCE_TOKEN); - line = parseInt(line); - column = parseInt(column); - if (column === 0) { - return { url, line }; - } - return { url, line, column }; -};
--- a/devtools/client/framework/moz.build +++ b/devtools/client/framework/moz.build @@ -11,22 +11,21 @@ TEST_HARNESS_FILES.xpcshell.devtools.cli DevToolsModules( 'about-devtools-toolbox.js', 'attach-thread.js', 'browser-menus.js', 'devtools-browser.js', 'devtools.js', 'gDevTools.jsm', - 'location-store.js', 'menu-item.js', 'menu.js', 'selection.js', 'sidebar.js', - 'source-map-service.js', + 'source-location.js', 'target-from-url.js', 'target.js', 'toolbox-highlighter-utils.js', 'toolbox-hosts.js', 'toolbox-options.js', 'toolbox.js', 'ToolboxProcess.jsm', )
rename from devtools/client/framework/source-map-service.js rename to devtools/client/framework/source-location.js --- a/devtools/client/framework/source-map-service.js +++ b/devtools/client/framework/source-location.js @@ -1,171 +1,98 @@ /* 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/. */ "use strict"; const { Task } = require("devtools/shared/task"); -const EventEmitter = require("devtools/shared/event-emitter"); -const { LocationStore, serialize, deserialize } = require("./location-store"); +const { assert } = require("devtools/shared/DevToolsUtils"); /** * A manager class that wraps a TabTarget and listens to source changes * from source maps and resolves non-source mapped locations to the source mapped * versions and back and forth, and creating smart elements with a location that * auto-update when the source changes (from pretty printing, source maps loading, etc) * * @param {TabTarget} target */ - -function SourceMapService(target) { - this._target = target; - this._locationStore = new LocationStore(); - this._isInitialResolve = true; - - EventEmitter.decorate(this); +function SourceLocationController(target) { + this.target = target; + this.locations = new Set(); this._onSourceUpdated = this._onSourceUpdated.bind(this); - this._resolveLocation = this._resolveLocation.bind(this); - this._resolveAndUpdate = this._resolveAndUpdate.bind(this); - this.subscribe = this.subscribe.bind(this); - this.unsubscribe = this.unsubscribe.bind(this); this.reset = this.reset.bind(this); this.destroy = this.destroy.bind(this); target.on("source-updated", this._onSourceUpdated); target.on("navigate", this.reset); target.on("will-navigate", this.reset); target.on("close", this.destroy); } -/** - * Clears the store containing the cached resolved locations and promises - */ -SourceMapService.prototype.reset = function () { - this._isInitialResolve = true; - this._locationStore.clear(); -}; - -SourceMapService.prototype.destroy = function () { - this.reset(); - this._target.off("source-updated", this._onSourceUpdated); - this._target.off("navigate", this.reset); - this._target.off("will-navigate", this.reset); - this._target.off("close", this.destroy); - this._isInitialResolve = null; - this._target = this._locationStore = null; +SourceLocationController.prototype.reset = function () { + this.locations.clear(); }; -/** - * Sets up listener for the callback to update the FrameView and tries to resolve location - * @param location - * @param callback - */ -SourceMapService.prototype.subscribe = function (location, callback) { - this.on(serialize(location), callback); - this._locationStore.set(location); - if (this._isInitialResolve) { - this._resolveAndUpdate(location); - this._isInitialResolve = false; - } -}; - -/** - * Removes the listener for the location and clears cached locations - * @param location - * @param callback - */ -SourceMapService.prototype.unsubscribe = function (location, callback) { - this.off(serialize(location), callback); - this._locationStore.clearByURL(location.url); +SourceLocationController.prototype.destroy = function () { + this.locations.clear(); + this.target.off("source-updated", this._onSourceUpdated); + this.target.off("navigate", this.reset); + this.target.off("will-navigate", this.reset); + this.target.off("close", this.destroy); + this.target = this.locations = null; }; /** - * Tries to resolve the location and if successful, - * emits the resolved location and caches it - * @param location - * @private + * Add this `location` to be observed and register a callback + * whenever the underlying source is updated. + * + * @param {Object} location + * An object with a {String} url, {Number} line, and optionally + * a {Number} column. + * @param {Function} callback */ -SourceMapService.prototype._resolveAndUpdate = function (location) { - this._resolveLocation(location).then(resolvedLocation => { - // We try to source map the first console log to initiate the source-updated event from - // target. The isSameLocation check is to make sure we don't update the frame, if the - // location is not source-mapped. - if (resolvedLocation) { - if (this._isInitialResolve) { - if (!isSameLocation(location, resolvedLocation)) { - this.emit(serialize(location), location, resolvedLocation); - return; - } - } - this.emit(serialize(location), location, resolvedLocation); - } - }); +SourceLocationController.prototype.bindLocation = function (location, callback) { + assert(location.url, "Location must have a url."); + assert(location.line, "Location must have a line."); + this.locations.add({ location, callback }); }; /** - * Validates the location model, - * checks if there is existing promise to resolve location, if so returns cached promise - * if not promised to resolve, - * tries to resolve location and returns a promised location - * @param location - * @return Promise<Object> - * @private + * Called when a new source occurs (a normal source, source maps) or an updated + * source (pretty print) occurs. + * + * @param {String} eventName + * @param {Object} sourceEvent */ -SourceMapService.prototype._resolveLocation = Task.async(function* (location) { - // Location must have a url and a line - if (!location.url || !location.line) { - return null; - } - const cachedLocation = this._locationStore.get(location); - if (cachedLocation) { - return cachedLocation; - } else { - const promisedLocation = resolveLocation(this._target, location); - if (promisedLocation) { - this._locationStore.set(location, promisedLocation); - return promisedLocation; - } - } -}); - -/** - * Checks if the `source-updated` event is fired from the target. - * Checks to see if location store has the source url in its cache, - * if so, tries to update each stale location in the store. - * @param _ - * @param sourceEvent - * @private - */ -SourceMapService.prototype._onSourceUpdated = function (_, sourceEvent) { +SourceLocationController.prototype._onSourceUpdated = function (_, sourceEvent) { let { type, source } = sourceEvent; // If we get a new source, and it's not a source map, abort; - // we can have no actionable updates as this is just a new normal source. + // we can ahve no actionable updates as this is just a new normal source. // Also abort if there's no `url`, which means it's unsourcemappable anyway, // like an eval script. if (!source.url || type === "newSource" && !source.isSourceMapped) { return; } - let sourceUrl = null; - if (source.generatedUrl && source.isSourceMapped) { - sourceUrl = source.generatedUrl; - } else if (source.url && source.isPrettyPrinted) { - sourceUrl = source.url; - } - const locationsToResolve = this._locationStore.getByURL(sourceUrl); - if (locationsToResolve.length) { - this._locationStore.clearByURL(sourceUrl); - for (let location of locationsToResolve) { - this._resolveAndUpdate(deserialize(location)); + + for (let locationItem of this.locations) { + if (isSourceRelated(locationItem.location, source)) { + this._updateSource(locationItem); } } }; -exports.SourceMapService = SourceMapService; +SourceLocationController.prototype._updateSource = Task.async(function* (locationItem) { + let newLocation = yield resolveLocation(this.target, locationItem.location); + if (newLocation) { + let previousLocation = Object.assign({}, locationItem.location); + Object.assign(locationItem.location, newLocation); + locationItem.callback(previousLocation, newLocation); + } +}); /** * Take a TabTarget and a location, containing a `url`, `line`, and `column`, resolve * the location to the latest location (so a source mapped location, or if pretty print * status has been updated) * * @param {TabTarget} target * @param {Object} location @@ -173,28 +100,38 @@ exports.SourceMapService = SourceMapServ */ function resolveLocation(target, location) { return Task.spawn(function* () { let newLocation = yield target.resolveLocation({ url: location.url, line: location.line, column: location.column || Infinity }); + // Source or mapping not found, so don't do anything if (newLocation.error) { return null; } return newLocation; }); } /** - * Returns if the original location and resolved location are the same - * @param location - * @param resolvedLocation - * @returns {boolean} + * Takes a serialized SourceActor form and returns a boolean indicating + * if this source is related to this location, like if a location is a generated source, + * and the source map is loaded subsequently, the new source mapped SourceActor + * will be considered related to this location. Same with pretty printing new sources. + * + * @param {Object} location + * @param {Object} source + * @return {Boolean} */ -function isSameLocation(location, resolvedLocation) { - return location.url === resolvedLocation.url && - location.line === resolvedLocation.line && - location.column === resolvedLocation.column; -}; +function isSourceRelated(location, source) { + // Mapping location to subsequently loaded source map + return source.generatedUrl === location.url || + // Mapping source map loc to source map + source.url === location.url; +} + +exports.SourceLocationController = SourceLocationController; +exports.resolveLocation = resolveLocation; +exports.isSourceRelated = isSourceRelated;
--- a/devtools/client/framework/toolbox.js +++ b/devtools/client/framework/toolbox.js @@ -6,17 +6,16 @@ const MAX_ORDINAL = 99; const SPLITCONSOLE_ENABLED_PREF = "devtools.toolbox.splitconsoleEnabled"; const SPLITCONSOLE_HEIGHT_PREF = "devtools.toolbox.splitconsoleHeight"; const OS_HISTOGRAM = "DEVTOOLS_OS_ENUMERATED_PER_USER"; const OS_IS_64_BITS = "DEVTOOLS_OS_IS_64_BITS_PER_USER"; const SCREENSIZE_HISTOGRAM = "DEVTOOLS_SCREEN_RESOLUTION_ENUMERATED_PER_USER"; const HTML_NS = "http://www.w3.org/1999/xhtml"; -const { SourceMapService } = require("./source-map-service"); var {Cc, Ci, Cu} = require("chrome"); var promise = require("promise"); var defer = require("devtools/shared/defer"); var Services = require("Services"); var {Task} = require("devtools/shared/task"); var {gDevTools} = require("devtools/client/framework/devtools"); var EventEmitter = require("devtools/shared/event-emitter"); @@ -114,19 +113,16 @@ const ToolboxButtons = exports.ToolboxBu * Type of host that will host the toolbox (e.g. sidebar, window) * @param {object} hostOptions * Options for host specifically */ function Toolbox(target, selectedTool, hostType, hostOptions) { this._target = target; this._toolPanels = new Map(); this._telemetry = new Telemetry(); - if (Services.prefs.getBoolPref("devtools.sourcemap.locations.enabled")) { - this._sourceMapService = new SourceMapService(this._target); - } this._initInspector = null; this._inspector = null; // Map of frames (id => frame-info) and currently selected frame id. this.frameMap = new Map(); this.selectedFrameId = null; @@ -2031,21 +2027,16 @@ Toolbox.prototype = { gDevTools.off("tool-registered", this._toolRegistered); gDevTools.off("tool-unregistered", this._toolUnregistered); gDevTools.off("pref-changed", this._prefChanged); this._lastFocusedElement = null; - if (this._sourceMapService) { - this._sourceMapService.destroy(); - this._sourceMapService = null; - } - if (this.webconsolePanel) { this._saveSplitConsoleHeight(); this.webconsolePanel.removeEventListener("resize", this._saveSplitConsoleHeight); } this.closeButton.removeEventListener("click", this.destroy, true); this.textboxContextMenuPopup.removeEventListener("popupshowing", this._updateTextboxMenuItems, true);
--- a/devtools/client/preferences/devtools.js +++ b/devtools/client/preferences/devtools.js @@ -291,19 +291,16 @@ pref("devtools.webconsole.timestampMessa // Web Console automatic multiline mode: |true| if you want incomplete statements // to automatically trigger multiline editing (equivalent to shift + enter). pref("devtools.webconsole.autoMultiline", true); // Enable the experimental webconsole frontend (work in progress) pref("devtools.webconsole.new-frontend-enabled", false); -// Enable the experimental support for source maps in console (work in progress) -pref("devtools.sourcemap.locations.enabled", false); - // The number of lines that are displayed in the web console. pref("devtools.hud.loglimit", 1000); // The number of lines that are displayed in the web console for the Net, // CSS, JS and Web Developer categories. These defaults should be kept in sync // with DEFAULT_LOG_LIMIT in the webconsole frontend. pref("devtools.hud.loglimit.network", 1000); pref("devtools.hud.loglimit.cssparser", 1000);
--- a/devtools/client/shared/components/frame.js +++ b/devtools/client/shared/components/frame.js @@ -29,135 +29,59 @@ module.exports = createClass({ // Option to display a function name even if it's anonymous. showAnonymousFunctionName: PropTypes.bool, // Option to display a host name after the source link. showHost: PropTypes.bool, // Option to display a host name if the filename is empty or just '/' showEmptyPathAsHost: PropTypes.bool, // Option to display a full source instead of just the filename. showFullSourceUrl: PropTypes.bool, - // Service to enable the source map feature for console. - sourceMapService: PropTypes.object, }, getDefaultProps() { return { showFunctionName: false, showAnonymousFunctionName: false, showHost: false, showEmptyPathAsHost: false, showFullSourceUrl: false, }; }, - componentWillMount() { - const sourceMapService = this.props.sourceMapService; - if (sourceMapService) { - const source = this.getSource(); - sourceMapService.subscribe(source, this.onSourceUpdated); - } - }, - - componentWillUnmount() { - const sourceMapService = this.props.sourceMapService; - if (sourceMapService) { - const source = this.getSource(); - sourceMapService.unsubscribe(source, this.onSourceUpdated); - } - }, - - /** - * Component method to update the FrameView when a resolved location is available - * @param event - * @param location - */ - onSourceUpdated(event, location, resolvedLocation) { - const frame = this.getFrame(resolvedLocation); - this.setState({ - frame, - isSourceMapped: true, - }); - }, - - /** - * Utility method to convert the Frame object to the - * Source Object model required by SourceMapService - * @param frame - * @returns {{url: *, line: *, column: *}} - */ - getSource(frame) { - frame = frame || this.props.frame; - const { source, line, column } = frame; - return { - url: source, - line, - column, - }; - }, - - /** - * Utility method to convert the Source object model to the - * Frame object model required by FrameView class. - * @param source - * @returns {{source: *, line: *, column: *, functionDisplayName: *}} - */ - getFrame(source) { - const { url, line, column } = source; - return { - source: url, - line, - column, - functionDisplayName: this.props.frame.functionDisplayName, - }; - }, - render() { - let frame, isSourceMapped; let { onClick, + frame, showFunctionName, showAnonymousFunctionName, showHost, showEmptyPathAsHost, showFullSourceUrl } = this.props; - if (this.state && this.state.isSourceMapped) { - frame = this.state.frame; - isSourceMapped = this.state.isSourceMapped; - } else { - frame = this.props.frame; - } - let source = frame.source ? String(frame.source) : ""; let line = frame.line != void 0 ? Number(frame.line) : null; let column = frame.column != void 0 ? Number(frame.column) : null; const { short, long, host } = getSourceNames(source); // Reparse the URL to determine if we should link this; `getSourceNames` // has already cached this indirectly. We don't want to attempt to // link to "self-hosted" and "(unknown)". However, we do want to link // to Scratchpad URIs. - // Source mapped sources might not necessary linkable, but they - // are still valid in the debugger. - const isLinkable = !!(isScratchpadScheme(source) || parseURL(source)) || isSourceMapped; + const isLinkable = !!(isScratchpadScheme(source) || parseURL(source)); const elements = []; const sourceElements = []; let sourceEl; let tooltip = long; - - // If the source is linkable and line > 0 - const shouldDisplayLine = isLinkable && line; - // Exclude all falsy values, including `0`, as even // a number 0 for line doesn't make sense, and should not be displayed. // If source isn't linkable, don't attempt to append line and column // info, as this probably doesn't make sense. - if (shouldDisplayLine) { + if (isLinkable && line) { tooltip += `:${line}`; // Intentionally exclude 0 if (column) { tooltip += `:${column}`; } } let attributes = { @@ -175,35 +99,26 @@ module.exports = createClass({ elements.push( dom.span({ className: "frame-link-function-display-name" }, functionDisplayName) ); } } let displaySource = showFullSourceUrl ? long : short; - // SourceMapped locations might not be parsed properly by parseURL. - // Eg: sourcemapped location could be /folder/file.coffee instead of a url - // and so the url parser would not parse non-url locations properly - // Check for "/" in displaySource. If "/" is in displaySource, take everything after last "/". - if (isSourceMapped) { - displaySource = displaySource.lastIndexOf("/") < 0 ? - displaySource : - displaySource.slice(displaySource.lastIndexOf("/") + 1); - } else if (showEmptyPathAsHost && (displaySource === "" || displaySource === "/")) { + if (showEmptyPathAsHost && (displaySource === "" || displaySource === "/")) { displaySource = host; - } sourceElements.push(dom.span({ className: "frame-link-filename", }, displaySource)); // If source is linkable, and we have a line number > 0 - if (shouldDisplayLine) { + if (isLinkable && line) { let lineInfo = `:${line}`; // Add `data-line` attribute for testing attributes["data-line"] = line; // Intentionally exclude 0 if (column) { lineInfo += `:${column}`; // Add `data-column` attribute for testing @@ -214,17 +129,17 @@ module.exports = createClass({ } // If source is not a URL (self-hosted, eval, etc.), don't make // it an anchor link, as we can't link to it. if (isLinkable) { sourceEl = dom.a({ onClick: e => { e.preventDefault(); - onClick(this.getSource(frame)); + onClick(frame); }, href: source, className: "frame-link-source", draggable: false, title: l10n.getFormatStr("frame.viewsourceindebugger", tooltip) }, sourceElements); } else { sourceEl = dom.span({
--- a/devtools/client/webconsole/webconsole.js +++ b/devtools/client/webconsole/webconsole.js @@ -2526,61 +2526,55 @@ WebConsoleFrame.prototype = { locationNode.className = "message-location devtools-monospace"; if (!url) { url = ""; } let fullURL = url.split(" -> ").pop(); // Make the location clickable. - let onClick = ({ url, line }) => { + let onClick = () => { let category = locationNode.closest(".message").category; let target = null; if (/^Scratchpad\/\d+$/.test(url)) { target = "scratchpad"; } else if (category === CATEGORY_CSS) { target = "styleeditor"; } else if (category === CATEGORY_JS || category === CATEGORY_WEBDEV) { target = "jsdebugger"; - } else if (/\.js$/.test(url)) { + } else if (/\.js$/.test(fullURL)) { // If it ends in .js, let's attempt to open in debugger // anyway, as this falls back to normal view-source. target = "jsdebugger"; - } else { - // Point everything else to debugger, if source not available, - // it will fall back to view-source. - target = "jsdebugger"; } switch (target) { case "scratchpad": this.owner.viewSourceInScratchpad(url, line); return; case "jsdebugger": - this.owner.viewSourceInDebugger(url, line); + this.owner.viewSourceInDebugger(fullURL, line); return; case "styleeditor": - this.owner.viewSourceInStyleEditor(url, line); + this.owner.viewSourceInStyleEditor(fullURL, line); return; } // No matching tool found; use old school view-source - this.owner.viewSource(url, line); + this.owner.viewSource(fullURL, line); }; - const toolbox = gDevTools.getToolbox(this.owner.target); this.ReactDOM.render(this.FrameView({ frame: { source: fullURL, line, column }, showEmptyPathAsHost: true, onClick, - sourceMapService: toolbox ? toolbox._sourceMapService : null, }), locationNode); return locationNode; }, /** * Adjusts the category and severity of the given message. *
--- a/devtools/server/actors/utils/TabSources.js +++ b/devtools/server/actors/utils/TabSources.js @@ -240,17 +240,17 @@ TabSources.prototype = { } } if (url in this._sourceMappedSourceActors) { return this._sourceMappedSourceActors[url]; } } - throw new Error("getSourceActorByURL: could not find source for " + url); + throw new Error("getSourceByURL: could not find source for " + url); return null; }, /** * Returns true if the URL likely points to a minified resource, false * otherwise. * * @param String aURL
--- a/devtools/server/actors/webbrowser.js +++ b/devtools/server/actors/webbrowser.js @@ -2086,47 +2086,51 @@ TabActor.prototype = { * @param {String} request.url * @param {Number} request.line * @param {Number?} request.column * @return {Promise<Object>} */ onResolveLocation(request) { let { url, line } = request; let column = request.column || 0; - const scripts = this.threadActor.dbg.findScripts({ url }); + let actor = this.sources.getSourceActorByURL(url); + + if (actor) { + // Get the generated source actor if this is source mapped + let generatedActor = actor.generatedSource ? + this.sources.createNonSourceMappedActor(actor.generatedSource) : + actor; + let generatedLocation = new GeneratedLocation( + generatedActor, line, column); - if (!scripts[0] || !scripts[0].source) { - return promise.resolve({ - from: this.actorID, - type: "resolveLocation", - error: "SOURCE_NOT_FOUND" + return this.sources.getOriginalLocation(generatedLocation).then(loc => { + // If no map found, return this packet + if (loc.originalLine == null) { + return { + from: this.actorID, + type: "resolveLocation", + error: "MAP_NOT_FOUND" + }; + } + + loc = loc.toJSON(); + return { + from: this.actorID, + url: loc.source.url, + column: loc.column, + line: loc.line + }; }); } - const source = scripts[0].source; - const generatedActor = this.sources.createNonSourceMappedActor(source); - let generatedLocation = new GeneratedLocation( - generatedActor, line, column); - return this.sources.getOriginalLocation(generatedLocation).then(loc => { - // If no map found, return this packet - if (loc.originalLine == null) { - return { - from: this.actorID, - type: "resolveLocation", - error: "MAP_NOT_FOUND" - }; - } - - loc = loc.toJSON(); - return { - from: this.actorID, - url: loc.source.url, - column: loc.column, - line: loc.line - }; + // Fall back to this packet when source is not found + return promise.resolve({ + from: this.actorID, + type: "resolveLocation", + error: "SOURCE_NOT_FOUND" }); }, }; /** * The request types this actor can handle. */ TabActor.prototype.requestTypes = {