/* 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 { createSelector } from "devtools/client/shared/vendor/reselect";
import { getPrettySourceURL, isPretty, isJavaScript } from "../utils/source";
import { findPosition } from "../utils/breakpoint/breakpointPositions"; import { isFulfilled } from "../utils/async-value";
import { originalToGeneratedId } from "devtools/client/shared/source-map-loader/index"; import { prefs } from "../utils/prefs"; import { UNDEFINED_LOCATION, NO_LOCATION } from "../reducers/sources";
import {
hasSourceActor,
getSourceActor,
getBreakableLinesForSourceActors,
isSourceActorWithSourceMap,
} from "./source-actors"; import { getSourceTextContent } from "./sources-content";
export function hasSource(state, id) { return state.sources.mutableSources.has(id);
}
export function getSource(state, id) { return state.sources.mutableSources.get(id);
}
export function getSourceFromId(state, id) { const source = getSource(state, id); if (!source) {
console.warn(`source ${id} does not exist`);
} return source;
}
export function getSourceByActorId(state, actorId) { if (!hasSourceActor(state, actorId)) { returnnull;
}
// This is used by tabs selectors
export function getSpecificSourceByURL(state, url, isOriginal) { const foundSources = getSourcesByURL(state, url); return foundSources.find(source => source.isOriginal == isOriginal);
}
function getOriginalSourceByURL(state, url) { return getSpecificSourceByURL(state, url, true);
}
export function getGeneratedSourceByURL(state, url) { return getSpecificSourceByURL(state, url, false);
}
export function getGeneratedSource(state, source) { if (!source) { returnnull;
}
// This is only used by Project Search and tests.
export function getSourceList(state) { return [...state.sources.mutableSources.values()];
}
// This is only used by tests and create.js
export function getSourceCount(state) { return state.sources.mutableSources.size;
}
export function getSelectedLocation(state) { return state.sources.selectedLocation;
}
/** * Return the "mapped" location for the currently selected location: * - When selecting a location in an original source, returns * the related location in the bundle source. * * - When selecting a location in a bundle source, returns * the related location in the original source. This may return undefined * while we are still computing this information. (we need to query the asynchronous SourceMap service) * * - Otherwise, when selecting a location in a source unrelated to source map * or a pretty printed source, returns null.
*/
export function getSelectedMappedSource(state) { const selectedLocation = getSelectedLocation(state); if (!selectedLocation) { returnnull;
}
// Don't map pretty printed to its related compressed source if (selectedLocation.source.isPrettyPrinted) { returnnull;
}
// If we are on a bundle with a functional source-map, // the `selectLocation` action should compute the `selectedOriginalLocation` field. if (
!selectedLocation.source.isOriginal &&
isSourceActorWithSourceMap(state, selectedLocation.sourceActor.id)
) { const { selectedOriginalLocation } = state.sources; // Return undefined if we are still loading the source map. // `selectedOriginalLocation` will be set to undefined instead of null if (
selectedOriginalLocation &&
selectedOriginalLocation != UNDEFINED_LOCATION &&
selectedOriginalLocation != NO_LOCATION
) { return selectedOriginalLocation.source;
} returnnull;
}
const mappedSource = getGeneratedSource(state, selectedLocation.source); // getGeneratedSource will return the exact same source object on sources // that don't map to any original source. In this case, return null // as that's most likely a regular source, not using source maps. if (mappedSource == selectedLocation.source) { returnnull;
} return mappedSource || null;
}
/** * Helps knowing if we are still computing the mapped location for the currently selected source.
*/
export function isSelectedMappedSourceLoading(state) { const { selectedOriginalLocation } = state.sources; // This `selectedOriginalLocation` attribute is set to UNDEFINED_LOCATION when selecting a new source attribute // and later on, when the source map is processed, it will switch to either a valid location object, or NO_LOCATION if no valid one if found. return selectedOriginalLocation === UNDEFINED_LOCATION;
}
// This is used by tests and pause reducers
export function getSelectedSourceId(state) { const source = getSelectedSource(state); return source?.id;
}
export function getShouldSelectOriginalLocation(state) { return state.sources.shouldSelectOriginalLocation;
}
export function getShouldHighlightSelectedLocation(state) { return state.sources.shouldHighlightSelectedLocation;
}
export function getShouldScrollToSelectedLocation(state) { return state.sources.shouldScrollToSelectedLocation;
}
/** * Gets the first source actor for the source and/or thread * provided. * * @param {Object} state * @param {String} sourceId * The source used * @param {String} [threadId] * The thread to check, this is optional. * @param {Object} sourceActor *
*/
export function getFirstSourceActorForGeneratedSource(
state,
sourceId,
threadId
) {
let source = getSource(state, sourceId); // The source may have been removed if we are being called by async code if (!source) { returnnull;
} if (source.isOriginal) {
source = getSource(state, originalToGeneratedId(source.id));
} const actors = getSourceActorsForSource(state, source.id); if (threadId) { return actors.find(actorInfo => actorInfo.thread == threadId) || null;
} return actors[0] || null;
}
/** * Get the source actor of the source * * @param {Object} state * @param {String} id * The source id * @return {Array<Object>} * List of source actors
*/
export function getSourceActorsForSource(state, id) { return state.sources.mutableSourceActors.get(id) || [];
}
if (!isJavaScript(source, sourceContent) && !source.isHTML) { return L10N.getStr("sourceFooter.prettyPrint.isNotJavascriptMessage");
}
return L10N.getStr("sourceTabs.prettyPrint");
}
export function getBreakpointPositionsForSource(state, sourceId) { return state.sources.mutableBreakpointPositions.get(sourceId);
}
// This is only used by one test
export function hasBreakpointPositions(state, sourceId) { return !!getBreakpointPositionsForSource(state, sourceId);
}
export function getBreakableLines(state, sourceId) { if (!sourceId) { returnnull;
} const source = getSource(state, sourceId); if (!source) { returnnull;
}
if (source.isOriginal) { return state.sources.mutableOriginalBreakableLines.get(sourceId);
}
const sourceActors = getSourceActorsForSource(state, sourceId); if (!sourceActors.length) { returnnull;
}
// We pull generated file breakable lines directly from the source actors // so that breakable lines can be added as new source actors on HTML loads. return getBreakableLinesForSourceActors(state, sourceActors, source.isHTML);
}
export function isSourceOverridden(toolboxState, source) { if (!source || !source.url) { returnfalse;
} return !!toolboxState.networkOverrides.mutableOverrides[source.url];
}
/** * Compute the list of source actors and source objects to be removed * when removing a given target/thread. * * @param {String} threadActorID * The thread to be removed. * @return {Object} * An object with two arrays: * - actors: list of source actor objects to remove * - sources: list of source objects to remove
*/
export function getSourcesToRemoveForThread(state, threadActorID) { const sourcesToRemove = []; const actorsToRemove = [];
for (const [
sourceId,
actorsForSource,
] of state.sources.mutableSourceActors.entries()) {
let removedActorsCount = 0; // Find all actors for the current source which belongs to the given thread actor for (const actor of actorsForSource) { if (actor.thread == threadActorID) {
actorsToRemove.push(actor);
removedActorsCount++;
}
}
// If we are about to remove all source actors for the current source, // or if for some unexpected reason we have a source with no actors, // notify the caller to also remove this source. if (
removedActorsCount == actorsForSource.length ||
!actorsForSource.length
) {
sourcesToRemove.push(state.sources.mutableSources.get(sourceId));
// Also remove any original sources related to this generated source const originalSourceIds =
state.sources.mutableOriginalSources.get(sourceId); if (originalSourceIds?.length > 0) { for (const originalSourceId of originalSourceIds) {
sourcesToRemove.push(
state.sources.mutableSources.get(originalSourceId)
);
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.