Bug 1531350 - [release 128] Update debugging-the-debugger.md (#8021). r=dwalsh
authorAlex Rosenfeld <arosenfeld2003@mac.com>
Thu, 28 Feb 2019 14:36:17 -0500
changeset 520005 0291de30d95876833df4a415a4a5502d1168130f
parent 520004 b68f9ac11c4f3f78d857212395bb93e12469cbbd
child 520006 2856ab932b13e044656067702612b36c1f40d13a
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdwalsh
bugs1531350
milestone67.0a1
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
Bug 1531350 - [release 128] Update debugging-the-debugger.md (#8021). r=dwalsh
devtools/client/shared/source-map/index.js
devtools/client/shared/source-map/worker.js
--- a/devtools/client/shared/source-map/index.js
+++ b/devtools/client/shared/source-map/index.js
@@ -79,17 +79,17 @@ return /******/ (function(modules) { // 
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.isOriginalId = exports.isGeneratedId = exports.generatedToOriginalId = exports.originalToGeneratedId = exports.getOriginalStackFrames = exports.hasMappedSource = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getLocationScopes = exports.getFileGeneratedRange = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = undefined;
+exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.isOriginalId = exports.isGeneratedId = exports.generatedToOriginalId = exports.originalToGeneratedId = exports.getOriginalStackFrames = exports.hasMappedSource = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getLocationScopes = exports.getFileGeneratedRange = exports.getGeneratedRangesForOriginal = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = undefined;
 
 var _utils = __webpack_require__(67);
 
 Object.defineProperty(exports, "originalToGeneratedId", {
   enumerable: true,
   get: function () {
     return _utils.originalToGeneratedId;
   }
@@ -154,16 +154,18 @@ const getOriginalRanges = exports.getOri
 const getGeneratedRanges = exports.getGeneratedRanges = async (location, originalSource) => _getGeneratedRanges(location, originalSource);
 
 const getGeneratedLocation = exports.getGeneratedLocation = async (location, originalSource) => _getGeneratedLocation(location, originalSource);
 
 const getAllGeneratedLocations = exports.getAllGeneratedLocations = async (location, originalSource) => _getAllGeneratedLocations(location, originalSource);
 
 const getOriginalLocation = exports.getOriginalLocation = async (location, options = {}) => _getOriginalLocation(location, options);
 
+const getGeneratedRangesForOriginal = exports.getGeneratedRangesForOriginal = async (sourceId, url, mergeUnmappedRegions) => dispatcher.invoke("getGeneratedRangesForOriginal", sourceId, url, mergeUnmappedRegions);
+
 const getFileGeneratedRange = exports.getFileGeneratedRange = async originalSource => dispatcher.invoke("getFileGeneratedRange", originalSource);
 
 const getLocationScopes = exports.getLocationScopes = dispatcher.task("getLocationScopes");
 
 const getOriginalSourceText = exports.getOriginalSourceText = async originalSource => dispatcher.invoke("getOriginalSourceText", originalSource);
 
 const applySourceMap = exports.applySourceMap = async (generatedId, url, code, mappings) => dispatcher.invoke("applySourceMap", generatedId, url, code, mappings);
 
--- a/devtools/client/shared/source-map/worker.js
+++ b/devtools/client/shared/source-map/worker.js
@@ -6907,16 +6907,17 @@ const {
   getOriginalURLs,
   hasOriginalURL,
   getOriginalRanges,
   getGeneratedRanges,
   getGeneratedLocation,
   getAllGeneratedLocations,
   getOriginalLocation,
   getOriginalSourceText,
+  getGeneratedRangesForOriginal,
   getFileGeneratedRange,
   hasMappedSource,
   clearSourceMaps,
   applySourceMap
 } = __webpack_require__(739);
 
 const { getOriginalStackFrames } = __webpack_require__(759);
 const { setAssetRootURL } = __webpack_require__(367);
@@ -6933,16 +6934,17 @@ self.onmessage = workerHandler({
   hasOriginalURL,
   getOriginalRanges,
   getGeneratedRanges,
   getGeneratedLocation,
   getAllGeneratedLocations,
   getOriginalLocation,
   getOriginalSourceText,
   getOriginalStackFrames,
+  getGeneratedRangesForOriginal,
   getFileGeneratedRange,
   hasMappedSource,
   applySourceMap,
   clearSourceMaps
 });
 
 /***/ }),
 
@@ -7225,16 +7227,123 @@ async function getOriginalSourceText(ori
   }
 
   return {
     text,
     contentType: getContentType(originalSource.url || "")
   };
 }
 
+/**
+ * Find the set of ranges on the generated file that map from the original
+ * file's locations.
+ *
+ * @param sourceId - The original ID of the file we are processing.
+ * @param url - The original URL of the file we are processing.
+ * @param mergeUnmappedRegions - If unmapped regions are encountered between
+ *   two mappings for the given original file, allow the two mappings to be
+ *   merged anyway. This is useful if you are more interested in the general
+ *   contiguous ranges associated with a file, rather than the specifics of
+ *   the ranges provided by the sourcemap.
+ */
+const GENERATED_MAPPINGS = new WeakMap();
+async function getGeneratedRangesForOriginal(sourceId, url, mergeUnmappedRegions = false) {
+  assert(isOriginalId(sourceId), "Source is not an original source");
+
+  const map = await getSourceMap(originalToGeneratedId(sourceId));
+  if (!map) {
+    return [];
+  }
+
+  if (!COMPUTED_SPANS.has(map)) {
+    COMPUTED_SPANS.add(map);
+    map.computeColumnSpans();
+  }
+
+  const cachedGeneratedMappingsForOriginal = GENERATED_MAPPINGS.get(map);
+  if (cachedGeneratedMappingsForOriginal) {
+    return cachedGeneratedMappingsForOriginal;
+  }
+
+  // Gather groups of mappings on the generated file, with new groups created
+  // if we cross a mapping for a different file.
+  let currentGroup = [];
+  const originalGroups = [currentGroup];
+  map.eachMapping(mapping => {
+    if (mapping.source === url) {
+      currentGroup.push({
+        start: {
+          line: mapping.generatedLine,
+          column: mapping.generatedColumn
+        },
+        end: {
+          line: mapping.generatedLine,
+          // The lastGeneratedColumn value is an inclusive value so we add
+          // one to it to get the exclusive end position.
+          column: mapping.lastGeneratedColumn + 1
+        }
+      });
+    } else if (typeof mapping.source === "string" && currentGroup.length > 0) {
+      // If there is a URL, but it is for a _different_ file, we create a
+      // new group of mappings so that we can tell
+      currentGroup = [];
+      originalGroups.push(currentGroup);
+    }
+  }, null, SourceMapConsumer.GENERATED_ORDER);
+
+  const generatedMappingsForOriginal = [];
+  if (mergeUnmappedRegions) {
+    // If we don't care about excluding unmapped regions, then we just need to
+    // create a range that is the fully encompasses each group, ignoring the
+    // empty space between each individual range.
+    for (const group of originalGroups) {
+      if (group.length > 0) {
+        generatedMappingsForOriginal.push({
+          start: group[0].start,
+          end: group[group.length - 1].end
+        });
+      }
+    }
+  } else {
+    let lastEntry;
+    for (const group of originalGroups) {
+      lastEntry = null;
+      for (const { start, end } of group) {
+        const lastEnd = lastEntry ? wrappedMappingPosition(lastEntry.end) : null;
+
+        // If this entry comes immediately after the previous one, extend the
+        // range of the previous entry instead of adding a new one.
+        if (lastEntry && lastEnd && lastEnd.line === start.line && lastEnd.column === start.column) {
+          lastEntry.end = end;
+        } else {
+          const newEntry = { start, end };
+          generatedMappingsForOriginal.push(newEntry);
+          lastEntry = newEntry;
+        }
+      }
+    }
+  }
+
+  GENERATED_MAPPINGS.set(map, generatedMappingsForOriginal);
+  return generatedMappingsForOriginal;
+}
+
+function wrappedMappingPosition(pos) {
+  if (pos.column !== Infinity) {
+    return pos;
+  }
+
+  // If the end of the entry consumes the whole line, treat it as wrapping to
+  // the next line.
+  return {
+    line: pos.line + 1,
+    column: 0
+  };
+}
+
 async function getFileGeneratedRange(originalSource) {
   assert(isOriginalId(originalSource.id), "Source is not an original source");
 
   const map = await getSourceMap(originalToGeneratedId(originalSource.id));
   if (!map) {
     return;
   }
 
@@ -7286,16 +7395,17 @@ module.exports = {
   getOriginalURLs,
   hasOriginalURL,
   getOriginalRanges,
   getGeneratedRanges,
   getGeneratedLocation,
   getAllGeneratedLocations,
   getOriginalLocation,
   getOriginalSourceText,
+  getGeneratedRangesForOriginal,
   getFileGeneratedRange,
   applySourceMap,
   clearSourceMaps,
   hasMappedSource
 };
 
 /***/ }),