Bug 1515951 - [release 112] Fixes flow typing support for reselect (#7573). r=bhackett
authorJason Laster <jlaster@mozilla.com>
Sun, 23 Dec 2018 14:46:07 -0500
changeset 452003 5bfef086654140a79a6164ff660fcc097603e7c8
parent 452002 796402f4fa52d5e3021b52d1aea86282b2c52a1d
child 452004 10dc48aa3b1e99cde812866d35e2c8f6ef39f942
push id35278
push useraiakab@mozilla.com
push dateThu, 27 Dec 2018 21:57:04 +0000
treeherdermozilla-central@a77e8f3efc4c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1515951
milestone66.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 1515951 - [release 112] Fixes flow typing support for reselect (#7573). r=bhackett
devtools/client/debugger/new/src/client/chrome/create.js
devtools/client/debugger/new/src/components/Editor/Footer.js
devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
devtools/client/debugger/new/src/reducers/ast.js
devtools/client/debugger/new/src/reducers/expressions.js
devtools/client/debugger/new/src/reducers/pause.js
devtools/client/debugger/new/src/reducers/sources.js
devtools/client/debugger/new/src/reducers/tabs.js
devtools/client/debugger/new/src/selectors/breakpointSources.js
devtools/client/debugger/new/src/selectors/breakpoints.js
devtools/client/debugger/new/src/selectors/getCallStackFrames.js
devtools/client/debugger/new/src/selectors/visibleBreakpoints.js
devtools/client/debugger/new/src/selectors/visibleColumnBreakpoints.js
devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js
devtools/client/debugger/new/src/utils/moz.build
--- a/devtools/client/debugger/new/src/client/chrome/create.js
+++ b/devtools/client/debugger/new/src/client/chrome/create.js
@@ -1,15 +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 type { SourceLocation, LoadedObject } from "../../types";
+import type { ChromeFrame, SourceLocation, LoadedObject } from "../../types";
 import type { ServerLocation } from "./types";
 
 export function fromServerLocation(
   serverLocation?: ServerLocation
 ): ?SourceLocation {
   if (serverLocation) {
     return {
       sourceId: serverLocation.scriptId,
@@ -22,17 +22,17 @@ export function fromServerLocation(
 
 export function toServerLocation(location: SourceLocation): ServerLocation {
   return {
     scriptId: location.sourceId,
     lineNumber: location.line - 1
   };
 }
 
-export function createFrame(frame: any) {
+export function createFrame(frame: any): ChromeFrame {
   return {
     id: frame.callFrameId,
     displayName: frame.functionName,
     scopeChain: frame.scopeChain,
     generatedLocation: frame.location,
     location: fromServerLocation(frame.location)
   };
 }
--- a/devtools/client/debugger/new/src/components/Editor/Footer.js
+++ b/devtools/client/debugger/new/src/components/Editor/Footer.js
@@ -243,22 +243,24 @@ class SourceFooter extends PureComponent
         {this.renderCursorPosition()}
       </div>
     );
   }
 }
 
 const mapStateToProps = state => {
   const selectedSource = getSelectedSource(state);
-  const selectedId = selectedSource.id;
 
   return {
     selectedSource,
     mappedSource: getGeneratedSource(state, selectedSource),
-    prettySource: getPrettySource(state, selectedId),
+    prettySource: getPrettySource(
+      state,
+      selectedSource ? selectedSource.id : null
+    ),
     endPanelCollapsed: getPaneCollapse(state, "end")
   };
 };
 
 export default connect(
   mapStateToProps,
   {
     togglePrettyPrint: actions.togglePrettyPrint,
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/Outline.js
@@ -256,22 +256,29 @@ export class Outline extends Component<P
         </div>
       </div>
     );
   }
 }
 
 const mapStateToProps = state => {
   const selectedSource = getSelectedSource(state);
-  const symbols = getSymbols(state, selectedSource);
+  const symbols = selectedSource ? getSymbols(state, selectedSource) : null;
+
   return {
     symbols,
     selectedSource,
     selectedLocation: getSelectedLocation(state),
-    getFunctionText: line => findFunctionText(line, selectedSource, symbols)
+    getFunctionText: line => {
+      if (selectedSource) {
+        return findFunctionText(line, selectedSource, symbols);
+      }
+
+      return null;
+    }
   };
 };
 
 export default connect(
   mapStateToProps,
   {
     selectLocation: actions.selectLocation,
     flashLineRange: actions.flashLineRange
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/Breakpoint.js
@@ -170,17 +170,17 @@ class Breakpoint extends PureComponent<P
       </div>
     );
   }
 }
 
 const getFormattedFrame = createSelector(
   getSelectedSource,
   getSelectedFrame,
-  (selectedSource: Source, frame: Frame): ?FormattedFrame => {
+  (selectedSource: ?Source, frame: ?Frame): ?FormattedFrame => {
     if (!frame) {
       return null;
     }
 
     return {
       ...frame,
       selectedLocation: getSelectedLocation(frame, selectedSource)
     };
--- a/devtools/client/debugger/new/src/reducers/ast.js
+++ b/devtools/client/debugger/new/src/reducers/ast.js
@@ -154,17 +154,17 @@ function update(
     }
   }
 }
 
 // NOTE: we'd like to have the app state fully typed
 // https://github.com/devtools-html/debugger.html/blob/master/src/reducers/sources.js#L179-L185
 type OuterState = { ast: Record<ASTState> };
 
-export function getSymbols(state: OuterState, source?: Source): ?Symbols {
+export function getSymbols(state: OuterState, source: ?Source): ?Symbols {
   if (!source) {
     return null;
   }
 
   return state.ast.symbols.get(source.id) || null;
 }
 
 export function hasSymbols(state: OuterState, source: Source): boolean {
@@ -172,17 +172,17 @@ export function hasSymbols(state: OuterS
 
   if (!symbols) {
     return false;
   }
 
   return !symbols.loading;
 }
 
-export function isSymbolsLoading(state: OuterState, source: Source): boolean {
+export function isSymbolsLoading(state: OuterState, source: ?Source): boolean {
   const symbols = getSymbols(state, source);
   if (!symbols) {
     return false;
   }
 
   return symbols.loading;
 }
 
--- a/devtools/client/debugger/new/src/reducers/expressions.js
+++ b/devtools/client/debugger/new/src/reducers/expressions.js
@@ -8,20 +8,21 @@
  * Expressions reducer
  * @module reducers/expressions
  */
 
 import makeRecord from "../utils/makeRecord";
 import { List, Map } from "immutable";
 import { omit, zip } from "lodash";
 
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 import { prefs } from "../utils/prefs";
 
 import type { Expression } from "../types";
+import type { Selector, State } from "../reducers/types";
 import type { Action } from "../actions/types";
 import type { Record } from "../utils/makeRecord";
 
 export type ExpressionState = {
   expressions: List<Expression>,
   expressionError: boolean,
   autocompleteMatches: Map<string, List<string>>,
   currentAutocompleteInput: string | null
@@ -153,45 +154,43 @@ function updateExpressionInList(
     return list.update(index, () => value);
   });
 
   storeExpressions(newState);
   return newState;
 }
 
 function deleteExpression(state: Record<ExpressionState>, input: string) {
-  const index = getExpressions({ expressions: state }).findIndex(
-    e => e.input == input
-  );
+  const index = state.expressions.findIndex(e => e.input == input);
   const newState = state.deleteIn(["expressions", index]);
   storeExpressions(newState);
   return newState;
 }
 
-type OuterState = { expressions: Record<ExpressionState> };
-
 const getExpressionsWrapper = state => state.expressions;
 
-export const getExpressions = createSelector(
+export const getExpressions: Selector<List<Expression>> = createSelector(
   getExpressionsWrapper,
   expressions => expressions.expressions
 );
 
-export const getAutocompleteMatches = createSelector(
+export const getAutocompleteMatches: Selector<
+  Map<string, List<string>>
+> = createSelector(
   getExpressionsWrapper,
   expressions => expressions.autocompleteMatches
 );
 
-export function getExpression(state: OuterState, input: string) {
+export function getExpression(state: State, input: string) {
   return getExpressions(state).find(exp => exp.input == input);
 }
 
-export function getAutocompleteMatchset(state: OuterState) {
+export function getAutocompleteMatchset(state: State) {
   const input = state.expressions.get("currentAutocompleteInput");
   return getAutocompleteMatches(state).get(input);
 }
 
-export const getExpressionError = createSelector(
+export const getExpressionError: Selector<boolean> = createSelector(
   getExpressionsWrapper,
   expressions => expressions.expressionError
 );
 
 export default update;
--- a/devtools/client/debugger/new/src/reducers/pause.js
+++ b/devtools/client/debugger/new/src/reducers/pause.js
@@ -5,25 +5,33 @@
 // @flow
 /* eslint complexity: ["error", 30]*/
 
 /**
  * Pause reducer
  * @module reducers/pause
  */
 
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 import { isGeneratedId } from "devtools-source-map";
 import { prefs } from "../utils/prefs";
 import { getSelectedSource } from "./sources";
 
 import type { OriginalScope } from "../utils/pause/mapScopes";
 import type { Action } from "../actions/types";
-import type { State } from "./types";
-import type { Why, Scope, SourceId, FrameId, MappedLocation } from "../types";
+import type { Selector, State } from "./types";
+import type {
+  Why,
+  Scope,
+  SourceId,
+  ChromeFrame,
+  Frame,
+  FrameId,
+  MappedLocation
+} from "../types";
 
 export type Command =
   | null
   | "stepOver"
   | "stepIn"
   | "stepOut"
   | "resume"
   | "rewind"
@@ -335,17 +343,17 @@ function getPauseLocation(state, action)
 // pick off the piece of state we're interested in. It's impossible
 // (right now) to type those wrapped functions.
 type OuterState = State;
 
 function getCurrentPauseState(state: OuterState): ThreadPauseState {
   return getThreadPauseState(state.pause, state.pause.currentThread);
 }
 
-export const getAllPopupObjectProperties = createSelector(
+export const getAllPopupObjectProperties: Selector<{}> = createSelector(
   getCurrentPauseState,
   pauseWrapper => pauseWrapper.loadedObjects
 );
 
 export function getPauseReason(state: OuterState): ?Why {
   return getCurrentPauseState(state).why;
 }
 
@@ -529,17 +537,17 @@ export function getSelectedFrameId(state
   return getCurrentPauseState(state).selectedFrameId;
 }
 
 export function getTopFrame(state: OuterState) {
   const frames = getFrames(state);
   return frames && frames[0];
 }
 
-export const getSelectedFrame = createSelector(
+export const getSelectedFrame: Selector<?Frame> = createSelector(
   getSelectedFrameId,
   getFrames,
   (selectedFrameId, frames) => {
     if (!frames) {
       return null;
     }
 
     return frames.find(frame => frame.id == selectedFrameId);
@@ -551,13 +559,13 @@ export function getDebuggeeUrl(state: Ou
 }
 
 export function getSkipPausing(state: OuterState) {
   return getCurrentPauseState(state).skipPausing;
 }
 
 // NOTE: currently only used for chrome
 export function getChromeScopes(state: OuterState) {
-  const frame = getSelectedFrame(state);
+  const frame: ?ChromeFrame = (getSelectedFrame(state): any);
   return frame ? frame.scopeChain : undefined;
 }
 
 export default update;
--- a/devtools/client/debugger/new/src/reducers/sources.js
+++ b/devtools/client/debugger/new/src/reducers/sources.js
@@ -4,29 +4,29 @@
 
 // @flow
 
 /**
  * Sources reducer
  * @module reducers/sources
  */
 
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 import {
   getPrettySourceURL,
   underRoot,
   getRelativeUrl,
   isGenerated,
   isOriginal as isOriginalSource
 } from "../utils/source";
 import { originalToGeneratedId } from "devtools-source-map";
 import { prefs } from "../utils/prefs";
 
 import type { Source, SourceId, SourceLocation } from "../types";
-import type { PendingSelectedLocation } from "./types";
+import type { PendingSelectedLocation, Selector } from "./types";
 import type { Action, DonePromiseAction } from "../actions/types";
 import type { LoadSourceAction } from "../actions/types/SourceAction";
 
 export type SourcesMap = { [string]: Source };
 
 type UrlsMap = { [string]: SourceId[] };
 
 export type SourcesState = {
@@ -340,29 +340,40 @@ export function getSourceByURL(state: Ou
 export function getSourcesByURLs(state: OuterState, urls: string[]) {
   return urls.map(url => getSourceByURL(state, url)).filter(Boolean);
 }
 
 export function getSourcesByURL(state: OuterState, url: string): Source[] {
   return getSourcesByUrlInSources(getSources(state), getUrls(state), url);
 }
 
-export function getGeneratedSource(state: OuterState, source: Source): Source {
+export function getGeneratedSource(
+  state: OuterState,
+  source: ?Source
+): ?Source {
+  if (!source) {
+    return null;
+  }
+
   if (isGenerated(source)) {
     return source;
   }
 
   return getSourceFromId(state, originalToGeneratedId(source.id));
 }
 
 export function getPendingSelectedLocation(state: OuterState) {
   return state.sources.pendingSelectedLocation;
 }
 
-export function getPrettySource(state: OuterState, id: string) {
+export function getPrettySource(state: OuterState, id: ?string) {
+  if (!id) {
+    return;
+  }
+
   const source = getSource(state, id);
   if (!source) {
     return;
   }
 
   return getSpecificSourceByURL(state, getPrettySourceURL(source.url), true);
 }
 
@@ -465,27 +476,27 @@ export function getSources(state: OuterS
 export function getUrls(state: OuterState) {
   return state.sources.urls;
 }
 
 export function getSourceList(state: OuterState): Source[] {
   return (Object.values(getSources(state)): any);
 }
 
-export const getSourceCount = createSelector(
+export const getSourceCount: Selector<number> = createSelector(
   getSources,
   sources => Object.keys(sources).length
 );
 
-export const getSelectedLocation = createSelector(
+export const getSelectedLocation: Selector<?SourceLocation> = createSelector(
   getSourcesState,
   sources => sources.selectedLocation
 );
 
-export const getSelectedSource = createSelector(
+export const getSelectedSource: Selector<?Source> = createSelector(
   getSelectedLocation,
   getSources,
   (selectedLocation: ?SourceLocation, sources: SourcesMap): ?Source => {
     if (!selectedLocation) {
       return;
     }
 
     return sources[selectedLocation.sourceId];
--- a/devtools/client/debugger/new/src/reducers/tabs.js
+++ b/devtools/client/debugger/new/src/reducers/tabs.js
@@ -4,32 +4,33 @@
 
 // @flow
 
 /**
  * Tabs reducer
  * @module reducers/tabs
  */
 
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 import { isOriginalId } from "devtools-source-map";
 import move from "lodash-move";
 
 import { asyncStore } from "../utils/prefs";
 import {
   getSource,
   getSources,
   getUrls,
   getSpecificSourceByURL,
   getSpecificSourceByUrlInSources
 } from "./sources";
 
 import type { Action } from "../actions/types";
 import type { SourcesState } from "./sources";
 import type { Source } from "../types";
+import type { Selector } from "./types";
 
 export type Tab = {
   url: string,
   framework?: string | null,
   isOriginal: boolean,
   sourceId?: string
 };
 export type TabList = Tab[];
@@ -189,25 +190,25 @@ export function getNewSelectedSourceId(
 // module for the UI, and all of those selectors should take the
 // top-level app state, so we'd have to "wrap" them to automatically
 // pick off the piece of state we're interested in. It's impossible
 // (right now) to type those wrapped functions.
 type OuterState = { tabs: TabList, sources: SourcesState };
 
 export const getTabs = (state: OuterState): TabList => state.tabs;
 
-export const getSourceTabs = createSelector(
+export const getSourceTabs: Selector<Tab[]> = createSelector(
   getTabs,
   getSources,
   getUrls,
   (tabs, sources, urls) =>
     tabs.filter(tab => getTabWithOrWithoutUrl(tab, sources, urls))
 );
 
-export const getSourcesForTabs = createSelector(
+export const getSourcesForTabs: Selector<Source[]> = createSelector(
   getSourceTabs,
   getSources,
   getUrls,
   (tabs, sources, urls) =>
     tabs.map(tab => getTabWithOrWithoutUrl(tab, sources, urls)).filter(Boolean)
 );
 
 function getTabWithOrWithoutUrl(tab, sources, urls) {
--- a/devtools/client/debugger/new/src/selectors/breakpointSources.js
+++ b/devtools/client/debugger/new/src/selectors/breakpointSources.js
@@ -1,48 +1,48 @@
 /* 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 { sortBy, uniq } from "lodash";
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 import {
   getSources,
   getBreakpointsList,
   getSelectedSource
 } from "../selectors";
 import { isGenerated, getFilename } from "../utils/source";
 import { getSelectedLocation } from "../utils/source-maps";
 
 import type {
   Source,
   Breakpoint,
   BreakpointId,
   SourceLocation
 } from "../types";
-import type { SourcesMap } from "../reducers/types";
+import type { Selector, SourcesMap } from "../reducers/types";
 
 export type BreakpointSources = Array<{
   source: Source,
   breakpoints: FormattedBreakpoint[]
 }>;
 
 export type FormattedBreakpoint = {|
   id: BreakpointId,
   condition: ?string,
   disabled: boolean,
   text: string,
   selectedLocation: SourceLocation
 |};
 
 function formatBreakpoint(
   breakpoint: Breakpoint,
-  selectedSource: Source
+  selectedSource: ?Source
 ): FormattedBreakpoint {
   const { id, condition, disabled } = breakpoint;
 
   return {
     id,
     condition,
     disabled,
     text:
@@ -50,51 +50,50 @@ function formatBreakpoint(
         ? breakpoint.text
         : breakpoint.originalText,
     selectedLocation: getSelectedLocation(breakpoint, selectedSource)
   };
 }
 
 function getBreakpointsForSource(
   source: Source,
-  selectedSource: Source,
+  selectedSource: ?Source,
   breakpoints: Breakpoint[]
 ) {
   return breakpoints
     .sort((a, b) => a.location.line - b.location.line)
     .filter(
       bp =>
         !bp.hidden &&
         !bp.loading &&
         (bp.text || bp.originalText || bp.condition || bp.disabled)
     )
     .map(bp => formatBreakpoint(bp, selectedSource))
     .filter(bp => bp.selectedLocation.sourceId == source.id);
 }
 
 function findBreakpointSources(
   sources: SourcesMap,
-  selectedSource: Source,
   breakpoints: Breakpoint[]
 ): Source[] {
   const sourceIds: string[] = uniq(breakpoints.map(bp => bp.location.sourceId));
 
   const breakpointSources = sourceIds
     .map(id => sources[id])
     .filter(source => source && !source.isBlackBoxed);
 
   return sortBy(breakpointSources, (source: Source) => getFilename(source));
 }
 
-export const getBreakpointSources = createSelector(
+export const getBreakpointSources: Selector<BreakpointSources> = createSelector(
   getBreakpointsList,
   getSources,
   getSelectedSource,
-  (breakpoints: Breakpoint[], sources: SourcesMap, selectedSource: Source) =>
-    findBreakpointSources(sources, selectedSource, breakpoints)
+  (breakpoints: Breakpoint[], sources: SourcesMap, selectedSource: ?Source) =>
+    findBreakpointSources(sources, breakpoints)
       .map(source => ({
         source,
         breakpoints: getBreakpointsForSource(
           source,
           selectedSource,
           breakpoints
         )
       }))
--- a/devtools/client/debugger/new/src/selectors/breakpoints.js
+++ b/devtools/client/debugger/new/src/selectors/breakpoints.js
@@ -1,28 +1,29 @@
 /* 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 { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 
 import type {
   BreakpointsState,
   XHRBreakpointsList
 } from "../reducers/breakpoints";
+import type { Selector } from "../reducers/types";
 
 type OuterState = { breakpoints: BreakpointsState };
 
 export function getXHRBreakpoints(state: OuterState): XHRBreakpointsList {
   return state.breakpoints.xhrBreakpoints;
 }
 
-export const shouldPauseOnAnyXHR = createSelector(
+export const shouldPauseOnAnyXHR: Selector<boolean> = createSelector(
   getXHRBreakpoints,
   xhrBreakpoints => {
     const emptyBp = xhrBreakpoints.find(({ path }) => path.length === 0);
     if (!emptyBp) {
       return false;
     }
 
     return !emptyBp.disabled;
--- a/devtools/client/debugger/new/src/selectors/getCallStackFrames.js
+++ b/devtools/client/debugger/new/src/selectors/getCallStackFrames.js
@@ -8,17 +8,17 @@ import {
   getSourceInSources
 } from "../reducers/sources";
 import { getFrames } from "../reducers/pause";
 import { annotateFrames } from "../utils/pause/frames";
 import { isOriginal } from "../utils/source";
 import { get } from "lodash";
 import type { Frame, Source } from "../types";
 import type { SourcesMap } from "../reducers/sources";
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 
 function getLocation(frame, isGeneratedSource) {
   return isGeneratedSource
     ? frame.generatedLocation || frame.location
     : frame.location;
 }
 
 function getSourceForFrame(sources, frame, isGeneratedSource) {
--- a/devtools/client/debugger/new/src/selectors/visibleBreakpoints.js
+++ b/devtools/client/debugger/new/src/selectors/visibleBreakpoints.js
@@ -1,25 +1,26 @@
 /* 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 { isGeneratedId } from "devtools-source-map";
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 import { uniqBy } from "lodash";
 
 import { getBreakpointsList } from "../reducers/breakpoints";
 import { getSelectedSource } from "../reducers/sources";
 
 import memoize from "../utils/memoize";
 import { sortBreakpoints } from "../utils/breakpoint";
 
 import type { Breakpoint, Source } from "../types";
+import type { Selector } from "../reducers/types";
 
 function getLocation(breakpoint, isGeneratedSource) {
   return isGeneratedSource
     ? breakpoint.generatedLocation || breakpoint.location
     : breakpoint.location;
 }
 
 const formatBreakpoint = memoize(function(breakpoint, selectedSource) {
@@ -31,46 +32,49 @@ const formatBreakpoint = memoize(functio
     location: getLocation(breakpoint, isGeneratedSource),
     condition,
     loading,
     disabled,
     hidden
   };
 });
 
-function isVisible(breakpoint, selectedSource) {
+function isVisible(breakpoint: Breakpoint, selectedSource: Source) {
   const sourceId = selectedSource.id;
   const isGeneratedSource = isGeneratedId(sourceId);
 
   const location = getLocation(breakpoint, isGeneratedSource);
   return location.sourceId === sourceId;
 }
 
 /*
  * Finds the breakpoints, which appear in the selected source.
  */
-export const getVisibleBreakpoints = createSelector(
+export const getVisibleBreakpoints: Selector<?(Breakpoint[])> = createSelector(
   getSelectedSource,
   getBreakpointsList,
-  (selectedSource: Source, breakpoints: Breakpoint[]) => {
-    if (!selectedSource) {
+  (selectedSource: ?Source, breakpoints: Breakpoint[]) => {
+    if (selectedSource == null) {
       return null;
     }
 
+    // FIXME: Even though selectedSource is checked above, it fails type
+    // checking for isVisible
+    const source: Source = selectedSource;
+
     return breakpoints
-      .filter(bp => isVisible(bp, selectedSource))
+      .filter(bp => isVisible(bp, source))
       .map(bp => formatBreakpoint(bp, selectedSource));
   }
 );
 
 /*
  * Finds the first breakpoint per line, which appear in the selected source.
  */
-export const getFirstVisibleBreakpoints = createSelector(
-  getVisibleBreakpoints,
-  breakpoints => {
-    if (!breakpoints) {
-      return null;
-    }
+export const getFirstVisibleBreakpoints: Selector<
+  Breakpoint[]
+> = createSelector(getVisibleBreakpoints, breakpoints => {
+  if (!breakpoints) {
+    return [];
+  }
 
-    return uniqBy(sortBreakpoints(breakpoints), bp => bp.location.line);
-  }
-);
+  return (uniqBy(sortBreakpoints(breakpoints), bp => bp.location.line): any);
+});
--- a/devtools/client/debugger/new/src/selectors/visibleColumnBreakpoints.js
+++ b/devtools/client/debugger/new/src/selectors/visibleColumnBreakpoints.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/>. */
 
 import { groupBy, get, sortedUniqBy } from "lodash";
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 
 import { getViewport } from "../selectors";
 import { getVisibleBreakpoints } from "./visibleBreakpoints";
 import { getVisiblePausePoints } from "./visiblePausePoints";
 import { makeLocationId } from "../utils/breakpoint";
 
 import type { SourceLocation } from "../types";
 
--- a/devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js
+++ b/devtools/client/debugger/new/src/selectors/visibleSelectedFrame.js
@@ -2,31 +2,35 @@
  * 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 { getSelectedLocation } from "../reducers/sources";
 import { getSelectedFrame } from "../reducers/pause";
 import { isOriginalId } from "devtools-source-map";
-import { createSelector } from "../utils/createSelector";
+import { createSelector } from "reselect";
 
 import type { Frame, SourceLocation } from "../types";
+import type { Selector } from "../reducers/types";
 
-function getLocation(frame: Frame, location?: SourceLocation) {
+function getLocation(frame: Frame, location: ?SourceLocation) {
   if (!location) {
     return frame.location;
   }
 
   return !isOriginalId(location.sourceId)
     ? frame.generatedLocation || frame.location
     : frame.location;
 }
 
-export const getVisibleSelectedFrame = createSelector(
+export const getVisibleSelectedFrame: Selector<?{
+  id: string,
+  location: SourceLocation
+}> = createSelector(
   getSelectedLocation,
   getSelectedFrame,
   (selectedLocation, selectedFrame) => {
     if (!selectedFrame) {
       return null;
     }
 
     const { id } = selectedFrame;
--- a/devtools/client/debugger/new/src/utils/moz.build
+++ b/devtools/client/debugger/new/src/utils/moz.build
@@ -13,17 +13,16 @@ DIRS += [
 DebuggerModules(
     'assert.js',
     'ast.js',
     'asyncStoreHelper.js',
     'bootstrap.js',
     'build-query.js',
     'clipboard.js',
     'connect.js',
-    'createSelector.js',
     'dbg.js',
     'defer.js',
     'DevToolsUtils.js',
     'expressions.js',
     'fromJS.js',
     'function.js',
     'indentation.js',
     'isMinified.js',