Bug 1544530 - [sync 132] - Apply SourceMaps type to redux actions r=jlast
authorDavid Walsh <dwalsh@mozilla.com>
Tue, 16 Apr 2019 16:52:38 +0000
changeset 469774 4aab82c04e9c
parent 469773 0a9b60065774
child 469775 219832d78e12
push id35882
push usercbrindusan@mozilla.com
push dateWed, 17 Apr 2019 15:54:01 +0000
treeherdermozilla-central@37185c0ae520 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlast
bugs1544530
milestone68.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 1544530 - [sync 132] - Apply SourceMaps type to redux actions r=jlast Differential Revision: https://phabricator.services.mozilla.com/D27718
devtools/client/debugger/flow-typed/debugger-html.js
devtools/client/debugger/packages/devtools-source-map/src/index.js
devtools/client/debugger/packages/devtools-source-map/src/utils/getOriginalStackFrames.js
devtools/client/debugger/packages/devtools-source-map/src/utils/wasmXScopes.js
devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js
devtools/client/debugger/src/actions/breakpoints/remapLocations.js
devtools/client/debugger/src/actions/pause/mapFrames.js
devtools/client/debugger/src/actions/sources/newSources.js
devtools/client/debugger/src/actions/sources/prettyPrint.js
devtools/client/debugger/src/actions/types/index.js
devtools/client/debugger/src/types.js
devtools/client/debugger/src/utils/bootstrap.js
devtools/client/debugger/src/utils/pause/mapScopes/getApplicableBindingsForOriginalPosition.js
devtools/client/debugger/src/utils/pause/mapScopes/index.js
devtools/client/debugger/src/utils/pause/mapScopes/rangeMetadata.js
devtools/client/debugger/src/utils/source-maps.js
--- a/devtools/client/debugger/flow-typed/debugger-html.js
+++ b/devtools/client/debugger/flow-typed/debugger-html.js
@@ -102,16 +102,28 @@ declare module "debugger-html" {
     location: SourceLocation,
     source?: Source,
     scope: Scope,
     // FIXME Define this type more clearly
     this: Object
   };
 
   /**
+   * Original Frame
+   *
+   * @memberof types
+   * @static
+   */
+  declare type OriginalFrame = {
+    displayName: string,
+    location?: SourceLocation,
+    thread?: string
+  };
+
+  /**
    * why
    * @memberof types
    * @static
    */
   declare type Why = {
     type: string
   };
 
--- a/devtools/client/debugger/packages/devtools-source-map/src/index.js
+++ b/devtools/client/debugger/packages/devtools-source-map/src/index.js
@@ -3,17 +3,23 @@
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 const {
   workerUtils: { WorkerDispatcher }
 } = require("devtools-utils");
 
-import type { SourceLocation, Source, SourceId } from "../../../src/types";
+import type {
+  OriginalFrame,
+  Range,
+  SourceLocation,
+  Source,
+  SourceId
+} from "../../../src/types";
 import type { SourceMapConsumer } from "source-map";
 import type { locationOptions } from "./source-map";
 
 export const dispatcher = new WorkerDispatcher();
 
 const _getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
   queue: true
 });
@@ -82,39 +88,27 @@ export const getOriginalLocations = asyn
   options: locationOptions = {}
 ): Promise<SourceLocation[]> =>
   dispatcher.invoke("getOriginalLocations", locations, options);
 
 export const getGeneratedRangesForOriginal = async (
   sourceId: SourceId,
   url: string,
   mergeUnmappedRegions?: boolean
-): Promise<
-  Array<{
-    start: {
-      line: number,
-      column: number
-    },
-    end: {
-      line: number,
-      column: number
-    }
-  }>
-> =>
+): Promise<Range[]> =>
   dispatcher.invoke(
     "getGeneratedRangesForOriginal",
     sourceId,
     url,
     mergeUnmappedRegions
   );
 
 export const getFileGeneratedRange = async (
   originalSource: Source
-): Promise<?{ start: any, end: any }> =>
-  dispatcher.invoke("getFileGeneratedRange", originalSource);
+): Promise<Range> => dispatcher.invoke("getFileGeneratedRange", originalSource);
 
 export const getLocationScopes = dispatcher.task("getLocationScopes");
 
 export const getOriginalSourceText = async (
   originalSource: Source
 ): Promise<?{
   text: string,
   contentType: string
@@ -132,20 +126,18 @@ export const clearSourceMaps = async ():
   dispatcher.invoke("clearSourceMaps");
 
 export const hasMappedSource = async (
   location: SourceLocation
 ): Promise<boolean> => dispatcher.invoke("hasMappedSource", location);
 
 export const getOriginalStackFrames = async (
   generatedLocation: SourceLocation
-): Promise<?Array<{
-  displayName: string,
-  location?: SourceLocation
-}>> => dispatcher.invoke("getOriginalStackFrames", generatedLocation);
+): Promise<?Array<OriginalFrame>> =>
+  dispatcher.invoke("getOriginalStackFrames", generatedLocation);
 
 export {
   originalToGeneratedId,
   generatedToOriginalId,
   isGeneratedId,
   isOriginalId
 } from "./utils";
 
--- a/devtools/client/debugger/packages/devtools-source-map/src/utils/getOriginalStackFrames.js
+++ b/devtools/client/debugger/packages/devtools-source-map/src/utils/getOriginalStackFrames.js
@@ -1,26 +1,23 @@
 /* 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/>. */
 
 // @flow
 
-import type { SourceLocation } from "debugger-html";
+import type { OriginalFrame, SourceLocation } from "debugger-html";
 
 const { getWasmXScopes } = require("./wasmXScopes");
 
 // Returns expanded stack frames details based on the generated location.
 // The function return null if not information was found.
 async function getOriginalStackFrames(
   generatedLocation: SourceLocation
-): Promise<?Array<{
-  displayName: string,
-  location?: SourceLocation
-}>> {
+): Promise<?Array<OriginalFrame>> {
   const wasmXScopes = await getWasmXScopes(generatedLocation.sourceId);
   if (!wasmXScopes) {
     return null;
   }
 
   const scopes = wasmXScopes.search(generatedLocation);
   if (scopes.length === 0) {
     console.warn("Something wrong with debug data: none original frames found");
--- a/devtools/client/debugger/packages/devtools-source-map/src/utils/wasmXScopes.js
+++ b/devtools/client/debugger/packages/devtools-source-map/src/utils/wasmXScopes.js
@@ -1,16 +1,16 @@
 /* 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/>. */
 
 // @flow
 /* eslint camelcase: 0*/
 
-import type { SourceLocation, SourceId } from "debugger-html";
+import type { OriginalFrame, SourceLocation, SourceId } from "debugger-html";
 
 const { getSourceMap } = require("./sourceMapRequests");
 const { generatedToOriginalId } = require("./index");
 
 const xScopes = new Map();
 
 type XScopeItem = any;
 type XScopeItemsIndex = Map<string | number, XScopeItem>;
@@ -148,22 +148,17 @@ function filterScopes(
 
 class XScope {
   xScope: XScopeData;
 
   constructor(xScopeData: XScopeData) {
     this.xScope = xScopeData;
   }
 
-  search(
-    generatedLocation: SourceLocation
-  ): Array<{
-    displayName: string,
-    location?: SourceLocation
-  }> {
+  search(generatedLocation: SourceLocation): Array<OriginalFrame> {
     const { code_section_offset, debug_info, sources, idIndex } = this.xScope;
     const pc = generatedLocation.line - (code_section_offset || 0);
     const scopes = filterScopes(debug_info, pc, null, idIndex);
     scopes.reverse();
 
     return scopes.map(i => {
       if (!("file" in i)) {
         return {
--- a/devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js
+++ b/devtools/client/debugger/src/actions/breakpoints/breakpointPositions.js
@@ -1,43 +1,45 @@
 /* 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/>. */
 
 // @flow
 
-import { isOriginalId, originalToGeneratedId } from "devtools-source-map";
+import SourceMaps, {
+  isOriginalId,
+  originalToGeneratedId
+} from "devtools-source-map";
 import { uniqBy, zip } from "lodash";
 
 import {
   getSource,
   getSourceFromId,
   hasBreakpointPositions,
   getBreakpointPositionsForSource
 } from "../../selectors";
 
 import type {
   MappedLocation,
+  Range,
   SourceLocation,
   BreakpointPositions,
   Context
 } from "../../types";
 import { makeBreakpointId } from "../../utils/breakpoint";
 import {
   memoizeableAction,
   type MemoizedAction
 } from "../../utils/memoizableAction";
 
-import typeof SourceMaps from "../../../packages/devtools-source-map/src";
-
 // const requests = new Map();
 
 async function mapLocations(
   generatedLocations: SourceLocation[],
-  { sourceMaps }: { sourceMaps: SourceMaps }
+  { sourceMaps }: { sourceMaps: typeof SourceMaps }
 ) {
   const originalLocations = await sourceMaps.getOriginalLocations(
     generatedLocations
   );
 
   return zip(originalLocations, generatedLocations).map(
     ([location, generatedLocation]) => ({ location, generatedLocation })
   );
@@ -77,34 +79,38 @@ async function _setBreakpointPositions(c
   const { client, dispatch, getState, sourceMaps } = thunkArgs;
   let generatedSource = getSource(getState(), sourceId);
   if (!generatedSource) {
     return;
   }
 
   let results = {};
   if (isOriginalId(sourceId)) {
-    const ranges = await sourceMaps.getGeneratedRangesForOriginal(
+    // Explicitly typing ranges is required to work around the following issue
+    // https://github.com/facebook/flow/issues/5294
+    const ranges: Range[] = await sourceMaps.getGeneratedRangesForOriginal(
       sourceId,
       generatedSource.url,
       true
     );
     const generatedSourceId = originalToGeneratedId(sourceId);
     generatedSource = getSourceFromId(getState(), generatedSourceId);
 
     // Note: While looping here may not look ideal, in the vast majority of
     // cases, the number of ranges here should be very small, and is quite
     // likely to only be a single range.
     for (const range of ranges) {
       // Wrap infinite end positions to the next line to keep things simple
       // and because we know we don't care about the end-line whitespace
       // in this case.
       if (range.end.column === Infinity) {
-        range.end.line += 1;
-        range.end.column = 0;
+        range.end = {
+          line: range.end.line + 1,
+          column: 0
+        };
       }
 
       const bps = await client.getBreakpointPositions(generatedSource, range);
       for (const line in bps) {
         results[line] = (results[line] || []).concat(bps[line]);
       }
     }
   } else {
--- a/devtools/client/debugger/src/actions/breakpoints/remapLocations.js
+++ b/devtools/client/debugger/src/actions/breakpoints/remapLocations.js
@@ -1,20 +1,22 @@
 /* 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/>. */
 
 // @flow
 
+import typeof SourceMaps from "devtools-source-map";
+
 import type { Breakpoint } from "../../types";
 
 export default function remapLocations(
   breakpoints: Breakpoint[],
   sourceId: string,
-  sourceMaps: Object
+  sourceMaps: SourceMaps
 ) {
   const sourceBreakpoints: Promise<Breakpoint>[] = breakpoints.map(
     async breakpoint => {
       if (breakpoint.location.sourceId !== sourceId) {
         return breakpoint;
       }
       const location = await sourceMaps.getOriginalLocation(
         breakpoint.location
--- a/devtools/client/debugger/src/actions/pause/mapFrames.js
+++ b/devtools/client/debugger/src/actions/pause/mapFrames.js
@@ -11,51 +11,54 @@ import {
   getSourceFromId,
   getSelectedFrame
 } from "../../selectors";
 
 import assert from "../../utils/assert";
 import { findClosestFunction } from "../../utils/ast";
 import { setSymbols } from "../sources/symbols";
 
-import type { Frame, ThreadContext } from "../../types";
+import type { Frame, OriginalFrame, ThreadContext } from "../../types";
 import type { State } from "../../reducers/types";
 import type { ThunkArgs } from "../types";
 
-import { isGeneratedId } from "devtools-source-map";
+import SourceMaps, { isGeneratedId } from "devtools-source-map";
 
 function isFrameBlackboxed(state, frame) {
   const source = getSource(state, frame.location.sourceId);
   return source && source.isBlackBoxed;
 }
 
 function getSelectedFrameId(state, thread, frames) {
   let selectedFrame = getSelectedFrame(state, thread);
   if (selectedFrame && !isFrameBlackboxed(state, selectedFrame)) {
     return selectedFrame.id;
   }
 
   selectedFrame = frames.find(frame => !isFrameBlackboxed(state, frame));
   return selectedFrame && selectedFrame.id;
 }
 
-export function updateFrameLocation(frame: Frame, sourceMaps: any) {
+export function updateFrameLocation(
+  frame: Frame,
+  sourceMaps: typeof SourceMaps
+) {
   if (frame.isOriginal) {
     return Promise.resolve(frame);
   }
   return sourceMaps.getOriginalLocation(frame.location).then(loc => ({
     ...frame,
     location: loc,
     generatedLocation: frame.generatedLocation || frame.location
   }));
 }
 
 function updateFrameLocations(
   frames: Frame[],
-  sourceMaps: any
+  sourceMaps: typeof SourceMaps
 ): Promise<Frame[]> {
   if (!frames || frames.length == 0) {
     return Promise.resolve(frames);
   }
 
   return Promise.all(
     frames.map(frame => updateFrameLocation(frame, sourceMaps))
   );
@@ -102,42 +105,46 @@ function isWasmOriginalSourceFrame(frame
     frame.generatedLocation.sourceId
   );
 
   return Boolean(generatedSource && generatedSource.isWasm);
 }
 
 async function expandFrames(
   frames: Frame[],
-  sourceMaps: any,
+  sourceMaps: typeof SourceMaps,
   getState: () => State
 ): Promise<Frame[]> {
   const result = [];
   for (let i = 0; i < frames.length; ++i) {
     const frame = frames[i];
     if (frame.isOriginal || !isWasmOriginalSourceFrame(frame, getState)) {
       result.push(frame);
       continue;
     }
-    const originalFrames = await sourceMaps.getOriginalStackFrames(
-      frame.generatedLocation
-    );
+    const originalFrames: ?Array<
+      OriginalFrame
+    > = await sourceMaps.getOriginalStackFrames(frame.generatedLocation);
     if (!originalFrames) {
       result.push(frame);
       continue;
     }
 
     assert(originalFrames.length > 0, "Expected at least one original frame");
     // First entry has not specific location -- use one from original frame.
     originalFrames[0] = {
       ...originalFrames[0],
       location: frame.location
     };
 
     originalFrames.forEach((originalFrame, j) => {
+      if (!originalFrame.location || !originalFrame.thread) {
+        return;
+      }
+
       // Keep outer most frame with true actor ID, and generate uniquie
       // one for the nested frames.
       const id = j == 0 ? frame.id : `${frame.id}-originalFrame${j}`;
       result.push({
         id,
         thread: originalFrame.thread,
         displayName: originalFrame.displayName,
         location: originalFrame.location,
--- a/devtools/client/debugger/src/actions/sources/newSources.js
+++ b/devtools/client/debugger/src/actions/sources/newSources.js
@@ -96,18 +96,20 @@ function loadSourceMap(cx: Context, sour
       isOriginal(source) ||
       !source.sourceMapURL
     ) {
       return [];
     }
 
     let urls = null;
     try {
-      const urlInfo = { ...source };
-      if (!urlInfo.url) {
+      // Unable to correctly type the result of a spread on a union type.
+      // See https://github.com/facebook/flow/pull/7298
+      const urlInfo: Source = { ...(source: any) };
+      if (!urlInfo.url && typeof urlInfo.introductionUrl === "string") {
         // If the source was dynamically generated (via eval, dynamically
         // created script elements, and so forth), it won't have a URL, so that
         // it is not collapsed into other sources from the same place. The
         // introduction URL will include the point it was constructed at,
         // however, so use that for resolving any source maps in the source.
         urlInfo.url = urlInfo.introductionUrl;
       }
       urls = await sourceMaps.getOriginalURLs(urlInfo);
--- a/devtools/client/debugger/src/actions/sources/prettyPrint.js
+++ b/devtools/client/debugger/src/actions/sources/prettyPrint.js
@@ -1,14 +1,14 @@
 /* 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/>. */
 
 // @flow
-import { generatedToOriginalId } from "devtools-source-map";
+import SourceMaps, { generatedToOriginalId } from "devtools-source-map";
 
 import assert from "../../utils/assert";
 import { recordEvent } from "../../utils/telemetry";
 import { remapBreakpoints } from "../breakpoints";
 
 import { setSymbols } from "./symbols";
 import { prettyPrint } from "../../workers/pretty-print";
 import { getPrettySourceURL, isLoaded, isGenerated } from "../../utils/source";
@@ -24,17 +24,17 @@ import {
   getThreadContext
 } from "../../selectors";
 
 import type { Action, ThunkArgs } from "../types";
 import { selectSource } from "./select";
 import type { JsSource, Source, Context } from "../../types";
 
 export async function prettyPrintSource(
-  sourceMaps: any,
+  sourceMaps: typeof SourceMaps,
   prettySource: Source,
   generatedSource: any
 ) {
   const url = getPrettySourceURL(generatedSource.url);
   const { code, mappings } = await prettyPrint({
     source: generatedSource,
     url: url
   });
--- a/devtools/client/debugger/src/actions/types/index.js
+++ b/devtools/client/debugger/src/actions/types/index.js
@@ -1,14 +1,15 @@
 /* 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/>. */
 
 // @flow
 
+import typeof SourceMaps from "devtools-source-map";
 import type { WorkerList, MainThread, Context, ThreadId } from "../../types";
 import type { State } from "../../reducers/types";
 import type { MatchedLocations } from "../../reducers/file-search";
 import type { TreeNode } from "../../utils/sources-tree/types";
 import type { SearchOperation } from "../../reducers/project-text-search";
 
 import type { BreakpointAction } from "./BreakpointAction";
 import type { SourceAction } from "./SourceAction";
@@ -29,17 +30,17 @@ import type { Panel } from "../../client
  * @memberof actions/breakpoints
  * @static
  * @typedef {Object} ThunkArgs
  */
 export type ThunkArgs = {
   dispatch: (action: any) => Promise<any>,
   getState: () => State,
   client: typeof clientCommands,
-  sourceMaps: any,
+  sourceMaps: SourceMaps,
   panel: Panel
 };
 
 export type Thunk = ThunkArgs => any;
 
 export type ActionType = Object | Function;
 
 type ProjectTextSearchResult = {
--- a/devtools/client/debugger/src/types.js
+++ b/devtools/client/debugger/src/types.js
@@ -230,16 +230,22 @@ export type Frame = {
 export type ChromeFrame = {
   id: FrameId,
   displayName: string,
   scopeChain: any,
   generatedLocation: SourceLocation,
   location: ?SourceLocation
 };
 
+export type OriginalFrame = {
+  displayName: string,
+  location?: SourceLocation,
+  thread: string
+};
+
 /**
  * ContextMenuItem
  *
  * @memberof types
  * @static
  */
 export type ContextMenuItem = {
   id: string,
--- a/devtools/client/debugger/src/utils/bootstrap.js
+++ b/devtools/client/debugger/src/utils/bootstrap.js
@@ -5,29 +5,31 @@
 // @flow
 
 import React from "react";
 import { bindActionCreators, combineReducers } from "redux";
 import ReactDOM from "react-dom";
 const { Provider } = require("react-redux");
 
 import { isFirefoxPanel, isDevelopment, isTesting } from "devtools-environment";
-import { startSourceMapWorker, stopSourceMapWorker } from "devtools-source-map";
+import SourceMaps, {
+  startSourceMapWorker,
+  stopSourceMapWorker
+} from "devtools-source-map";
 import * as search from "../workers/search";
 import * as prettyPrint from "../workers/pretty-print";
 import * as parser from "../workers/parser";
 
 import configureStore from "../actions/utils/create-store";
 import reducers from "../reducers";
 import * as selectors from "../selectors";
 import App from "../components/App";
 import { asyncStore, prefs } from "./prefs";
 
 import type { Panel } from "../client/firefox/types";
-import typeof SourceMaps from "../../packages/devtools-source-map/src";
 
 function renderPanel(component, store) {
   const root = document.createElement("div");
   root.className = "launchpad-root theme-body";
   root.style.setProperty("flex", "1");
   const mount = document.querySelector("#mount");
   if (!mount) {
     return;
@@ -37,17 +39,17 @@ function renderPanel(component, store) {
   ReactDOM.render(
     React.createElement(Provider, { store }, React.createElement(component)),
     root
   );
 }
 
 export function bootstrapStore(
   client: any,
-  sourceMaps: SourceMaps,
+  sourceMaps: typeof SourceMaps,
   panel: Panel,
   initialState: Object
 ) {
   const createStore = configureStore({
     log: prefs.logging || isTesting(),
     timing: isDevelopment(),
     makeThunkArgs: (args, state) => {
       return { ...args, client, sourceMaps, panel };
--- a/devtools/client/debugger/src/utils/pause/mapScopes/getApplicableBindingsForOriginalPosition.js
+++ b/devtools/client/debugger/src/utils/pause/mapScopes/getApplicableBindingsForOriginalPosition.js
@@ -1,14 +1,16 @@
 /* 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/>. */
 
 // @flow
 
+import typeof SourceMaps from "devtools-source-map";
+
 import type { BindingLocationType, BindingType } from "../../../workers/parser";
 import { positionCmp } from "./positionCmp";
 import { filterSortedArray } from "./filtering";
 import { mappingContains } from "./mappingContains";
 
 import type { Source, SourceLocation, PartialPosition } from "../../../types";
 
 import type { GeneratedBindingLocation } from "./buildGeneratedBindingList";
@@ -29,17 +31,17 @@ export async function originalRangeStart
   source: Source,
   {
     start,
     end
   }: {
     start: SourceLocation,
     end: SourceLocation
   },
-  sourceMaps: any
+  sourceMaps: SourceMaps
 ) {
   const endPosition = await sourceMaps.getGeneratedLocation(end, source);
   const startPosition = await sourceMaps.getGeneratedLocation(start, source);
 
   // If the start and end positions collapse into eachother, it means that
   // the range in the original content didn't _start_ at the start position.
   // Since this likely means that the range doesn't logically apply to this
   // binding location, we skip it.
@@ -53,21 +55,21 @@ export async function getApplicableBindi
     start,
     end
   }: {
     start: SourceLocation,
     end: SourceLocation
   },
   bindingType: BindingType,
   locationType: BindingLocationType,
-  sourceMaps: any
+  sourceMaps: SourceMaps
 ): Promise<Array<ApplicableBinding>> {
   const ranges = await sourceMaps.getGeneratedRanges(start, source);
 
-  const resultRanges = ranges.map(mapRange => ({
+  const resultRanges: GeneratedRange[] = ranges.map(mapRange => ({
     start: {
       line: mapRange.line,
       column: mapRange.columnStart
     },
     end: {
       line: mapRange.line,
       // SourceMapConsumer's 'lastColumn' is inclusive, so we add 1 to make
       // it exclusive like all other locations.
@@ -86,18 +88,20 @@ export async function getApplicableBindi
     const endPosition = await sourceMaps.getGeneratedLocation(end, source);
     const startPosition = await sourceMaps.getGeneratedLocation(start, source);
 
     for (const range of resultRanges) {
       if (
         mappingContains(range, { start: startPosition, end: startPosition }) &&
         positionCmp(range.end, endPosition) < 0
       ) {
-        range.end.line = endPosition.line;
-        range.end.column = endPosition.column;
+        range.end = {
+          line: endPosition.line,
+          column: endPosition.column
+        };
         break;
       }
     }
   }
 
   return filterApplicableBindings(generatedAstBindings, resultRanges);
 }
 
--- a/devtools/client/debugger/src/utils/pause/mapScopes/index.js
+++ b/devtools/client/debugger/src/utils/pause/mapScopes/index.js
@@ -1,14 +1,16 @@
 /* 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/>. */
 
 // @flow
 
+import typeof SourceMaps from "devtools-source-map";
+
 import {
   getScopes,
   type SourceScope,
   type BindingData,
   type BindingLocation
 } from "../../../workers/parser";
 import type { RenderableScope } from "../scopes/getScope";
 import { locColumn } from "./locColumn";
@@ -195,17 +197,17 @@ function hasLineMappings(ranges) {
   return ranges.every(
     range => range.columnStart === 0 && range.columnEnd === Infinity
   );
 }
 
 function batchScopeMappings(
   originalAstScopes: Array<SourceScope>,
   source: Source,
-  sourceMaps: any
+  sourceMaps: SourceMaps
 ) {
   const precalculatedRanges = new Map();
   const precalculatedLocations = new Map();
 
   // Explicitly dispatch all of the sourcemap requests synchronously up front so
   // that they will be batched into a single request for the worker to process.
   for (const item of originalAstScopes) {
     for (const name of Object.keys(item.bindings)) {
--- a/devtools/client/debugger/src/utils/pause/mapScopes/rangeMetadata.js
+++ b/devtools/client/debugger/src/utils/pause/mapScopes/rangeMetadata.js
@@ -1,14 +1,16 @@
 /* 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/>. */
 
 // @flow
 
+import typeof SourceMaps from "devtools-source-map";
+
 import { locColumn } from "./locColumn";
 import { positionCmp } from "./positionCmp";
 import { filterSortedArray } from "./filtering";
 
 import type { SourceScope } from "../../../workers/parser";
 import type { PartialPosition, Frame, Source } from "../../../types";
 
 type SourceOriginalRange = {
@@ -29,17 +31,17 @@ export type MappedOriginalRange = {
   columnStart: number,
   columnEnd: number
 };
 
 export async function loadRangeMetadata(
   source: Source,
   frame: Frame,
   originalAstScopes: Array<SourceScope>,
-  sourceMaps: any
+  sourceMaps: SourceMaps
 ): Promise<Array<MappedOriginalRange>> {
   const originalRanges: Array<
     SourceOriginalRange
   > = await sourceMaps.getOriginalRanges(frame.location.sourceId, source.url);
 
   const sortedOriginalAstBindings = [];
   for (const item of originalAstScopes) {
     for (const name of Object.keys(item.bindings)) {
--- a/devtools/client/debugger/src/utils/source-maps.js
+++ b/devtools/client/debugger/src/utils/source-maps.js
@@ -1,25 +1,24 @@
 /* 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/>. */
 
 // @flow
 
-import { isOriginalId } from "devtools-source-map";
+import SourceMaps, { isOriginalId } from "devtools-source-map";
 import { getSource } from "../selectors";
 
 import type { SourceLocation, MappedLocation, Source } from "../types";
-import typeof SourceMaps from "../../packages/devtools-source-map/src";
 
 export async function getGeneratedLocation(
   state: Object,
   source: Source,
   location: SourceLocation,
-  sourceMaps: Object
+  sourceMaps: typeof SourceMaps
 ): Promise<SourceLocation> {
   if (!isOriginalId(location.sourceId)) {
     return location;
   }
 
   const { line, sourceId, column } = await sourceMaps.getGeneratedLocation(
     location,
     source
@@ -35,28 +34,28 @@ export async function getGeneratedLocati
     sourceId,
     column: column === 0 ? undefined : column,
     sourceUrl: generatedSource.url
   };
 }
 
 export async function getOriginalLocation(
   generatedLocation: SourceLocation,
-  sourceMaps: SourceMaps
+  sourceMaps: typeof SourceMaps
 ) {
   if (isOriginalId(generatedLocation.sourceId)) {
     return location;
   }
 
   return sourceMaps.getOriginalLocation(generatedLocation);
 }
 
 export async function getMappedLocation(
   state: Object,
-  sourceMaps: Object,
+  sourceMaps: typeof SourceMaps,
   location: SourceLocation
 ): Promise<MappedLocation> {
   const source = getSource(state, location.sourceId);
 
   if (!source) {
     throw new Error(`no source ${location.sourceId}`);
   }
 
@@ -67,39 +66,38 @@ export async function getMappedLocation(
       location,
       sourceMaps
     );
     return { location, generatedLocation };
   }
 
   const generatedLocation = location;
   const originalLocation = await sourceMaps.getOriginalLocation(
-    generatedLocation,
-    source
+    generatedLocation
   );
 
   return { location: originalLocation, generatedLocation };
 }
 
 export async function mapLocation(
   state: Object,
-  sourceMaps: Object,
+  sourceMaps: typeof SourceMaps,
   location: SourceLocation
 ): Promise<SourceLocation> {
   const source = getSource(state, location.sourceId);
 
   if (!source) {
     return location;
   }
 
   if (isOriginalId(location.sourceId)) {
     return getGeneratedLocation(state, source, location, sourceMaps);
   }
 
-  return sourceMaps.getOriginalLocation(location, source);
+  return sourceMaps.getOriginalLocation(location);
 }
 
 export function isOriginalSource(source: ?Source) {
   return source && isOriginalId(source.id);
 }
 
 export function getSelectedLocation(
   mappedLocation: MappedLocation,