/* 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 . */
// @flow
import {
getBreakpoint,
getSource,
getSourceActorsForSource
} from "../../selectors";
import { isGenerated } from "../source";
import { sortSelectedLocations } from "../location";
import assert from "../assert";
import { features } from "../prefs";
export * from "./astBreakpointLocation";
export * from "./breakpointPositions";
import type {
Source,
SourceActor,
SourceLocation,
SourceActorLocation,
PendingLocation,
Breakpoint,
BreakpointLocation,
PendingBreakpoint
} from "../../types";
import type { State } from "../../reducers/types";
// Return the first argument that is a string, or null if nothing is a
// string.
export function firstString(...args: string[]) {
for (const arg of args) {
if (typeof arg === "string") {
return arg;
}
}
return null;
}
// The ID for a Breakpoint is derived from its location in its Source.
export function makeBreakpointId(location: SourceLocation) {
const { sourceId, line, column } = location;
const columnString = column || "";
return `${sourceId}:${line}:${columnString}`;
}
export function getLocationWithoutColumn(location: SourceLocation) {
const { sourceId, line } = location;
return `${sourceId}:${line}`;
}
type AnySourceLocation = SourceLocation | PendingLocation;
export function makePendingLocationId(location: AnySourceLocation) {
assertPendingLocation(location);
const { sourceUrl, line, column } = location;
const sourceUrlString = sourceUrl || "";
const columnString = column || "";
return `${sourceUrlString}:${line}:${columnString}`;
}
export function makeBreakpointLocation(
state: State,
location: SourceLocation
): BreakpointLocation {
const source = getSource(state, location.sourceId);
if (!source) {
throw new Error("no source");
}
const breakpointLocation: any = {
line: location.line,
column: location.column
};
if (source.url) {
breakpointLocation.sourceUrl = source.url;
} else {
breakpointLocation.sourceId = getSourceActorsForSource(
state,
source.id
)[0].id;
}
return breakpointLocation;
}
export function makeSourceActorLocation(
sourceActor: SourceActor,
location: SourceLocation
) {
return {
sourceActor,
line: location.line,
column: location.column
};
}
// The ID for a BreakpointActor is derived from its location in its SourceActor.
export function makeBreakpointActorId(location: SourceActorLocation) {
const { sourceActor, line, column } = location;
const columnString = column || "";
return `${(sourceActor: any)}:${line}:${columnString}`;
}
export function assertBreakpoint(breakpoint: Breakpoint) {
assertLocation(breakpoint.location);
assertLocation(breakpoint.generatedLocation);
}
export function assertPendingBreakpoint(pendingBreakpoint: PendingBreakpoint) {
assertPendingLocation(pendingBreakpoint.location);
assertPendingLocation(pendingBreakpoint.generatedLocation);
}
export function assertLocation(location: SourceLocation) {
assertPendingLocation(location);
const { sourceId } = location;
assert(!!sourceId, "location must have a source id");
}
export function assertPendingLocation(location: PendingLocation) {
assert(!!location, "location must exist");
const { sourceUrl } = location;
// sourceUrl is null when the source does not have a url
assert(sourceUrl !== undefined, "location must have a source url");
assert(location.hasOwnProperty("line"), "location must have a line");
assert(
location.hasOwnProperty("column") != null,
"location must have a column"
);
}
// syncing
export function breakpointAtLocation(
breakpoints: Breakpoint[],
{ line, column }: SourceLocation
) {
return breakpoints.find(breakpoint => {
const sameLine = breakpoint.location.line === line;
if (!sameLine) {
return false;
}
// NOTE: when column breakpoints are disabled we want to find
// the first breakpoint
if (!features.columnBreakpoints) {
return true;
}
return breakpoint.location.column === column;
});
}
export function breakpointExists(state: State, location: SourceLocation) {
const currentBp = getBreakpoint(state, location);
return currentBp && !currentBp.disabled;
}
export function createXHRBreakpoint(
path: string,
method: string,
overrides?: Object = {}
) {
const properties = {
path,
method,
disabled: false,
loading: false,
text: L10N.getFormatStr("xhrBreakpoints.item.label", path)
};
return { ...properties, ...overrides };
}
function createPendingLocation(location: PendingLocation) {
const { sourceUrl, line, column } = location;
return { sourceUrl, line, column };
}
export function createPendingBreakpoint(bp: Breakpoint) {
const pendingLocation = createPendingLocation(bp.location);
const pendingGeneratedLocation = createPendingLocation(bp.generatedLocation);
assertPendingLocation(pendingLocation);
return {
options: bp.options,
disabled: bp.disabled,
location: pendingLocation,
astLocation: bp.astLocation,
generatedLocation: pendingGeneratedLocation
};
}
export function getSelectedText(
breakpoint: Breakpoint,
selectedSource: Source
) {
return selectedSource && isGenerated(selectedSource)
? breakpoint.text
: breakpoint.originalText;
}
export function sortSelectedBreakpoints(
breakpoints: Array,
selectedSource: ?Source
): Array {
return sortSelectedLocations(breakpoints, selectedSource);
}