forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			227 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* 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";
 | 
						|
 | 
						|
/**
 | 
						|
 * Tries to open a Stylesheet file in the Style Editor. If the file is not
 | 
						|
 * found, it is opened in source view instead.
 | 
						|
 * Returns a promise resolving to a boolean indicating whether or not
 | 
						|
 * the source was able to be displayed in the StyleEditor, as the built-in
 | 
						|
 * Firefox View Source is the fallback.
 | 
						|
 *
 | 
						|
 * @param {Toolbox} toolbox
 | 
						|
 * @param {string} sourceURL
 | 
						|
 * @param {number} sourceLine
 | 
						|
 *
 | 
						|
 * @return {Promise<boolean>}
 | 
						|
 */
 | 
						|
exports.viewSourceInStyleEditor = async function(
 | 
						|
  toolbox,
 | 
						|
  stylesheetFrontOrGeneratedURL,
 | 
						|
  generatedLine,
 | 
						|
  generatedColumn
 | 
						|
) {
 | 
						|
  const panel = await toolbox.loadTool("styleeditor");
 | 
						|
 | 
						|
  let stylesheetFront;
 | 
						|
  if (typeof stylesheetFrontOrGeneratedURL === "string") {
 | 
						|
    stylesheetFront = panel.getStylesheetFrontForGeneratedURL(
 | 
						|
      stylesheetFrontOrGeneratedURL
 | 
						|
    );
 | 
						|
  } else {
 | 
						|
    stylesheetFront = stylesheetFrontOrGeneratedURL;
 | 
						|
  }
 | 
						|
 | 
						|
  const originalLocation = stylesheetFront
 | 
						|
    ? await getOriginalLocation(
 | 
						|
        toolbox,
 | 
						|
        stylesheetFront.resourceId,
 | 
						|
        generatedLine,
 | 
						|
        generatedColumn
 | 
						|
      )
 | 
						|
    : null;
 | 
						|
 | 
						|
  try {
 | 
						|
    if (originalLocation) {
 | 
						|
      await panel.selectOriginalSheet(
 | 
						|
        originalLocation.sourceId,
 | 
						|
        originalLocation.line,
 | 
						|
        originalLocation.column
 | 
						|
      );
 | 
						|
      await toolbox.selectTool("styleeditor");
 | 
						|
      return true;
 | 
						|
    } else if (stylesheetFront) {
 | 
						|
      await panel.selectStyleSheet(
 | 
						|
        stylesheetFront,
 | 
						|
        generatedLine,
 | 
						|
        generatedColumn
 | 
						|
      );
 | 
						|
      await toolbox.selectTool("styleeditor");
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  } catch (e) {
 | 
						|
    console.error("Failed to view source in style editor", e);
 | 
						|
  }
 | 
						|
 | 
						|
  exports.viewSource(
 | 
						|
    toolbox,
 | 
						|
    typeof stylesheetFrontOrGeneratedURL === "string"
 | 
						|
      ? stylesheetFrontOrGeneratedURL
 | 
						|
      : stylesheetFrontOrGeneratedURL.href ||
 | 
						|
          stylesheetFrontOrGeneratedURL.nodeHref,
 | 
						|
    generatedLine
 | 
						|
  );
 | 
						|
  return false;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Tries to open a JavaScript file in the Debugger. If the file is not found,
 | 
						|
 * it is opened in source view instead. Either the source URL or source actor ID
 | 
						|
 * can be specified. If both are specified, the source actor ID is used.
 | 
						|
 *
 | 
						|
 * Returns a promise resolving to a boolean indicating whether or not
 | 
						|
 * the source was able to be displayed in the Debugger, as the built-in Firefox
 | 
						|
 * View Source is the fallback.
 | 
						|
 *
 | 
						|
 * @param {Toolbox} toolbox
 | 
						|
 * @param {string} sourceURL
 | 
						|
 * @param {number} sourceLine
 | 
						|
 * @param {number} sourceColumn
 | 
						|
 * @param {string} sourceID
 | 
						|
 * @param {(string|object)} [reason=unknown]
 | 
						|
 *
 | 
						|
 * @return {Promise<boolean>}
 | 
						|
 */
 | 
						|
exports.viewSourceInDebugger = async function(
 | 
						|
  toolbox,
 | 
						|
  generatedURL,
 | 
						|
  generatedLine,
 | 
						|
  generatedColumn,
 | 
						|
  sourceActorId,
 | 
						|
  reason = "unknown"
 | 
						|
) {
 | 
						|
  const location = await getViewSourceInDebuggerLocation(
 | 
						|
    toolbox,
 | 
						|
    generatedURL,
 | 
						|
    generatedLine,
 | 
						|
    generatedColumn,
 | 
						|
    sourceActorId
 | 
						|
  );
 | 
						|
 | 
						|
  if (location) {
 | 
						|
    const { id, line, column } = location;
 | 
						|
 | 
						|
    const dbg = await toolbox.selectTool("jsdebugger", reason);
 | 
						|
    try {
 | 
						|
      await dbg.selectSource(id, line, column);
 | 
						|
      return true;
 | 
						|
    } catch (err) {
 | 
						|
      console.error("Failed to view source in debugger", err);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  exports.viewSource(toolbox, generatedURL, generatedLine);
 | 
						|
  return false;
 | 
						|
};
 | 
						|
 | 
						|
async function getViewSourceInDebuggerLocation(
 | 
						|
  toolbox,
 | 
						|
  generatedURL,
 | 
						|
  generatedLine,
 | 
						|
  generatedColumn,
 | 
						|
  sourceActorId
 | 
						|
) {
 | 
						|
  const dbg = await toolbox.loadTool("jsdebugger");
 | 
						|
 | 
						|
  const generatedSource = sourceActorId
 | 
						|
    ? dbg.getSourceByActorId(sourceActorId)
 | 
						|
    : dbg.getSourceByURL(generatedURL);
 | 
						|
  if (
 | 
						|
    !generatedSource ||
 | 
						|
    // Note: We're not entirely sure when this can happen, so we may want
 | 
						|
    // to revisit that at some point.
 | 
						|
    dbg.getSourceActorsForSource(generatedSource.id).length === 0
 | 
						|
  ) {
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  const generatedLocation = {
 | 
						|
    id: generatedSource.id,
 | 
						|
    line: generatedLine,
 | 
						|
    column: generatedColumn,
 | 
						|
  };
 | 
						|
 | 
						|
  const originalLocation = await getOriginalLocation(
 | 
						|
    toolbox,
 | 
						|
    generatedLocation.id,
 | 
						|
    generatedLocation.line,
 | 
						|
    generatedLocation.column
 | 
						|
  );
 | 
						|
 | 
						|
  if (!originalLocation) {
 | 
						|
    return generatedLocation;
 | 
						|
  }
 | 
						|
 | 
						|
  const originalSource = dbg.getSource(originalLocation.sourceId);
 | 
						|
 | 
						|
  if (!originalSource) {
 | 
						|
    return generatedLocation;
 | 
						|
  }
 | 
						|
 | 
						|
  return {
 | 
						|
    id: originalSource.id,
 | 
						|
    line: originalLocation.line,
 | 
						|
    column: originalLocation.column,
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
async function getOriginalLocation(
 | 
						|
  toolbox,
 | 
						|
  generatedID,
 | 
						|
  generatedLine,
 | 
						|
  generatedColumn
 | 
						|
) {
 | 
						|
  // If there is no line number, then there's no chance that we'll get back
 | 
						|
  // a useful original location.
 | 
						|
  if (typeof generatedLine !== "number") {
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  let originalLocation = null;
 | 
						|
  try {
 | 
						|
    originalLocation = await toolbox.sourceMapService.getOriginalLocation({
 | 
						|
      sourceId: generatedID,
 | 
						|
      line: generatedLine,
 | 
						|
      column: generatedColumn,
 | 
						|
    });
 | 
						|
    if (originalLocation && originalLocation.sourceId === generatedID) {
 | 
						|
      originalLocation = null;
 | 
						|
    }
 | 
						|
  } catch (err) {
 | 
						|
    console.error(
 | 
						|
      "Failed to resolve sourcemapped location for the given source location",
 | 
						|
      { generatedID, generatedLine, generatedColumn },
 | 
						|
      err
 | 
						|
    );
 | 
						|
  }
 | 
						|
  return originalLocation;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Open a link in Firefox's View Source.
 | 
						|
 *
 | 
						|
 * @param {Toolbox} toolbox
 | 
						|
 * @param {string} sourceURL
 | 
						|
 * @param {number} sourceLine
 | 
						|
 *
 | 
						|
 * @return {Promise}
 | 
						|
 */
 | 
						|
exports.viewSource = async function(toolbox, sourceURL, sourceLine) {
 | 
						|
  const utils = toolbox.gViewSourceUtils;
 | 
						|
  utils.viewSource({
 | 
						|
    URL: sourceURL,
 | 
						|
    lineNumber: sourceLine || 0,
 | 
						|
  });
 | 
						|
};
 |