Backed out 5 changesets (bug 1541633) for devtools failures on browser_dbg-sourcemapped-breakpoint-console.js.

Backed out changeset 35fe7c48b49a (bug 1541633)
Backed out changeset 59019ae6bf3f (bug 1541633)
Backed out changeset 44ea34f63223 (bug 1541633)
Backed out changeset a8378192e3b6 (bug 1541633)
Backed out changeset de895ee6de42 (bug 1541633)

--HG--
extra : rebase_source : 9b3e5b34867298d1a5ffad2ade538c24ff045c1c
This commit is contained in:
Cosmin Sabou 2019-08-22 10:13:47 +03:00
Родитель df6c33c509
Коммит 5086a1bd98
51 изменённых файлов: 821 добавлений и 718 удалений

Просмотреть файл

@ -19,4 +19,3 @@
[options]
suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
module.name_mapper='^debugger-html$' -> '<PROJECT_ROOT>/src/types.js'

Просмотреть файл

@ -6775,9 +6775,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
err.metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -6810,14 +6808,22 @@ function workerHandler(publicInterface) {
if (response instanceof Promise) {
return response.then(val => ({
response: val
}), err => asErrorMessage(err));
}), // Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({
error: err.toString()
}));
}
return {
response
};
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: error.toString()
};
}
})).then(results => {
self.postMessage({
@ -6828,24 +6834,6 @@ function workerHandler(publicInterface) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined
};
}
module.exports = {
WorkerDispatcher,
workerHandler

Просмотреть файл

@ -613,9 +613,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
err.metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -648,14 +646,22 @@ function workerHandler(publicInterface) {
if (response instanceof Promise) {
return response.then(val => ({
response: val
}), err => asErrorMessage(err));
}), // Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({
error: err.toString()
}));
}
return {
response
};
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: error.toString()
};
}
})).then(results => {
self.postMessage({
@ -666,24 +672,6 @@ function workerHandler(publicInterface) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined
};
}
module.exports = {
WorkerDispatcher,
workerHandler

Просмотреть файл

@ -275,9 +275,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
err.metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -310,14 +308,22 @@ function workerHandler(publicInterface) {
if (response instanceof Promise) {
return response.then(val => ({
response: val
}), err => asErrorMessage(err));
}), // Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({
error: err.toString()
}));
}
return {
response
};
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: error.toString()
};
}
})).then(results => {
self.postMessage({
@ -328,24 +334,6 @@ function workerHandler(publicInterface) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined
};
}
module.exports = {
WorkerDispatcher,
workerHandler

34
devtools/client/debugger/dist/vendors.js поставляемый
Просмотреть файл

@ -1489,9 +1489,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
err.metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -1524,14 +1522,22 @@ function workerHandler(publicInterface) {
if (response instanceof Promise) {
return response.then(val => ({
response: val
}), err => asErrorMessage(err));
}), // Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({
error: err.toString()
}));
}
return {
response
};
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: error.toString()
};
}
})).then(results => {
self.postMessage({
@ -1542,24 +1548,6 @@ function workerHandler(publicInterface) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined
};
}
module.exports = {
WorkerDispatcher,
workerHandler

270
devtools/client/debugger/flow-typed/debugger-html.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,270 @@
/* 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
declare module "debugger-html" {
/**
* Breakpoint ID
*
* @memberof types
* @static
*/
declare type BreakpointId = string;
/**
* Source ID
*
* @memberof types
* @static
*/
declare type SourceId = string;
/**
* Actor ID
*
* @memberof types
* @static
*/
declare type ActorId = string;
/**
* Source File Location
*
* @memberof types
* @static
*/
declare type SourceLocation = {|
sourceId: SourceId,
line: number,
column?: number,
sourceUrl?: string
|};
/**
* Breakpoint
*
* @memberof types
* @static
*/
declare type Breakpoint = {
id: BreakpointId,
location: SourceLocation,
loading: boolean,
disabled: boolean,
text: string,
condition: ?string
};
/**
* Breakpoint Result is the return from an add/modify Breakpoint request
*
* @memberof types
* @static
*/
declare type BreakpointResult = {
id: ActorId,
actualLocation: SourceLocation
};
/**
* Source
*
* @memberof types
* @static
*/
declare type Source = {
id: SourceId,
url?: string,
sourceMapURL?: string,
isWasm: boolean,
text?: string,
contentType?: string
};
/**
* Frame ID
*
* @memberof types
* @static
*/
declare type FrameId = string;
/**
* Frame
* @memberof types
* @static
*/
declare type Frame = {
id: FrameId,
displayName: string,
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
};
/**
* Why is the Debugger Paused?
* This is the generic state handling the reason the debugger is paused.
* Reasons are usually related to "breakpoint" or "debuggerStatement"
* and should eventually be specified here as an enum. For now we will
* just offer it as a string.
* @memberof types
* @static
*/
declare type WhyPaused = {
type: string
};
declare type LoadedObject = {
objectId: string,
parentId: string,
name: string,
value: any
};
/**
* Pause
* @memberof types
* @static
*/
declare type Pause = {
frames: Frame[],
why: Why,
getIn: (string[]) => any,
loadedObjects?: LoadedObject[]
};
/**
* Expression
* @memberof types
* @static
*/
declare type Expression = {
id: number,
input: string
};
/**
* Grip
* @memberof types
* @static
*/
declare type Grip = {
actor: string,
class: string,
extensible: boolean,
frozen: boolean,
isGlobal: boolean,
ownPropertyLength: number,
preview: {
kind: string,
url: string
},
sealed: boolean,
type: string
};
/**
* SourceText
* @memberof types
* @static
*/
declare type SourceText = {
id: string,
text: string,
contentType: string
};
/**
* SourceScope
* @memberof types
* @static
*/
declare type SourceScope = {
type: string,
start: SourceLocation,
end: SourceLocation,
bindings: {
[name: string]: SourceLocation[]
}
};
/*
* MappedScopeBindings
* @memberof types
* @static
*/
declare type MappedScopeBindings = {
type: string,
bindings: {
[originalName: string]: string
}
};
/**
* Script
* This describes scripts which are sent to the debug server to be eval'd
* @memberof types
* @static
* FIXME: This needs a real type definition
*/
declare type Script = any;
declare type SyntheticScope = {
type: string,
bindingsNames: string[]
};
/**
* Scope
* @memberof types
* @static
*/
declare type Scope = {
actor: ActorId,
parent: Scope,
bindings: {
// FIXME Define these types more clearly
arguments: Array<Object>,
variables: Object
},
function: {
actor: ActorId,
class: string,
displayName: string,
location: SourceLocation,
// FIXME Define this type more clearly
parameterNames: Array<Object>
},
syntheticScopes?: {
scopes: SyntheticScope[],
groupIndex: number,
groupLength: number
},
type: string
};
}

Просмотреть файл

@ -12,9 +12,11 @@ import type {
OriginalFrame,
Range,
SourceLocation,
Source,
SourceId,
} from "../../../src/types";
import type { SourceMapInput, LocationOptions } from "./source-map";
import type { SourceMapConsumer } from "source-map";
import type { LocationOptions } from "./source-map";
export const dispatcher = new WorkerDispatcher();
@ -37,39 +39,44 @@ export const setAssetRootURL = async (assetRoot: string): Promise<void> =>
dispatcher.invoke("setAssetRootURL", assetRoot);
export const getOriginalURLs = async (
generatedSource: SourceMapInput
): Promise<?Array<{| id: SourceId, url: string |}>> =>
generatedSource: Source
): Promise<SourceMapConsumer> =>
dispatcher.invoke("getOriginalURLs", generatedSource);
export const hasOriginalURL = async (url: string): Promise<boolean> =>
dispatcher.invoke("hasOriginalURL", url);
export const getOriginalRanges = async (
sourceId: SourceId
sourceId: SourceId,
url: string
): Promise<
Array<{
line: number,
columnStart: number,
columnEnd: number,
}>
> => dispatcher.invoke("getOriginalRanges", sourceId);
> => dispatcher.invoke("getOriginalRanges", sourceId, url);
export const getGeneratedRanges = async (
location: SourceLocation
location: SourceLocation,
originalSource: Source
): Promise<
Array<{
line: number,
columnStart: number,
columnEnd: number,
}>
> => _getGeneratedRanges(location);
> => _getGeneratedRanges(location, originalSource);
export const getGeneratedLocation = async (
location: SourceLocation
): Promise<SourceLocation> => _getGeneratedLocation(location);
location: SourceLocation,
originalSource: Source
): Promise<SourceLocation> => _getGeneratedLocation(location, originalSource);
export const getAllGeneratedLocations = async (
location: SourceLocation
): Promise<Array<SourceLocation>> => _getAllGeneratedLocations(location);
location: SourceLocation,
originalSource: Source
): Promise<Array<SourceLocation>> =>
_getAllGeneratedLocations(location, originalSource);
export const getOriginalLocation = async (
location: SourceLocation,
@ -77,32 +84,36 @@ export const getOriginalLocation = async (
): Promise<SourceLocation> => _getOriginalLocation(location, options);
export const getOriginalLocations = async (
sourceId: SourceId,
locations: SourceLocation[],
options: LocationOptions = {}
): Promise<SourceLocation[]> =>
dispatcher.invoke("getOriginalLocations", locations, options);
dispatcher.invoke("getOriginalLocations", sourceId, locations, options);
export const getGeneratedRangesForOriginal = async (
sourceId: SourceId,
url: string,
mergeUnmappedRegions?: boolean
): Promise<Range[]> =>
dispatcher.invoke(
"getGeneratedRangesForOriginal",
sourceId,
url,
mergeUnmappedRegions
);
export const getFileGeneratedRange = async (
originalSourceId: SourceId
): Promise<Range> =>
dispatcher.invoke("getFileGeneratedRange", originalSourceId);
originalSource: Source
): Promise<Range> => dispatcher.invoke("getFileGeneratedRange", originalSource);
export const getLocationScopes = dispatcher.task("getLocationScopes");
export const getOriginalSourceText = async (
originalSourceId: SourceId
originalSource: Source
): Promise<?{
text: string,
contentType: string,
}> => dispatcher.invoke("getOriginalSourceText", originalSourceId);
}> => dispatcher.invoke("getOriginalSourceText", originalSource);
export const applySourceMap = async (
generatedId: string,
@ -115,6 +126,10 @@ export const applySourceMap = async (
export const clearSourceMaps = async (): Promise<void> =>
dispatcher.invoke("clearSourceMaps");
export const hasMappedSource = async (
location: SourceLocation
): Promise<boolean> => dispatcher.invoke("hasMappedSource", location);
export const getOriginalStackFrames = async (
generatedLocation: SourceLocation
): Promise<?Array<OriginalFrame>> =>

Просмотреть файл

@ -21,7 +21,6 @@ const {
} = require("./utils/fetchSourceMap");
const {
getSourceMap,
getSourceMapWithMetadata,
setSourceMap,
clearSourceMaps: clearSourceMapsRequests,
} = require("./utils/sourceMapRequests");
@ -34,7 +33,7 @@ const {
} = require("./utils");
const { clearWasmXScopes } = require("devtools-wasm-dwarf");
import type { SourceLocation, SourceId } from "debugger-html";
import type { SourceLocation, Source, SourceId } from "debugger-html";
type Range = {
start: {
@ -46,32 +45,24 @@ type Range = {
column: number,
},
};
export type SourceMapInput = {|
id: SourceId,
url: string,
sourceMapURL: string,
isWasm: boolean,
|};
export type LocationOptions = {
search?: "LEAST_UPPER_BOUND" | "GREATEST_LOWER_BOUND",
};
async function getOriginalURLs(
generatedSource: SourceMapInput
): Promise<?Array<{| id: SourceId, url: string |}>> {
await fetchSourceMap(generatedSource);
const data = await getSourceMapWithMetadata(generatedSource.id);
return data ? data.sources : null;
generatedSource: Source
): Promise<SourceMapConsumer> {
const map = await fetchSourceMap(generatedSource);
return map && map.sources;
}
const COMPUTED_SPANS = new WeakSet();
const SOURCE_MAPPINGS = new WeakMap();
async function getOriginalRanges(
sourceId: SourceId
sourceId: SourceId,
url: string
): Promise<
Array<{
line: number,
@ -84,12 +75,10 @@ async function getOriginalRanges(
}
const generatedSourceId = originalToGeneratedId(sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
if (!data) {
const map = await getSourceMap(generatedSourceId);
if (!map) {
return [];
}
const { map } = data;
const url = data.urlsById.get(sourceId);
let mappings = SOURCE_MAPPINGS.get(map);
if (!mappings) {
@ -139,7 +128,8 @@ async function getOriginalRanges(
* are mapped from the original range containing the location.
*/
async function getGeneratedRanges(
location: SourceLocation
location: SourceLocation,
originalSource: Source
): Promise<
Array<{
line: number,
@ -152,11 +142,10 @@ async function getGeneratedRanges(
}
const generatedSourceId = originalToGeneratedId(location.sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
if (!data) {
const map = await getSourceMap(generatedSourceId);
if (!map) {
return [];
}
const { urlsById, map } = data;
if (!COMPUTED_SPANS.has(map)) {
COMPUTED_SPANS.add(map);
@ -170,7 +159,7 @@ async function getGeneratedRanges(
// exact original location, making any bias value unnecessary, and then
// use that location for the call to 'allGeneratedPositionsFor'.
const genPos = map.generatedPositionFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column,
bias: SourceMapConsumer.GREATEST_LOWER_BOUND,
@ -199,21 +188,21 @@ async function getGeneratedRanges(
}
async function getGeneratedLocation(
location: SourceLocation
location: SourceLocation,
originalSource: Source
): Promise<SourceLocation> {
if (!isOriginalId(location.sourceId)) {
return location;
}
const generatedSourceId = originalToGeneratedId(location.sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
if (!data) {
const map = await getSourceMap(generatedSourceId);
if (!map) {
return location;
}
const { urlsById, map } = data;
const positions = map.allGeneratedPositionsFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column,
});
@ -231,7 +220,7 @@ async function getGeneratedLocation(
if (!match) {
match = map.generatedPositionFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column,
bias: SourceMapConsumer.LEAST_UPPER_BOUND,
@ -246,21 +235,21 @@ async function getGeneratedLocation(
}
async function getAllGeneratedLocations(
location: SourceLocation
location: SourceLocation,
originalSource: Source
): Promise<Array<SourceLocation>> {
if (!isOriginalId(location.sourceId)) {
return [];
}
const generatedSourceId = originalToGeneratedId(location.sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
if (!data) {
const map = await getSourceMap(generatedSourceId);
if (!map) {
return [];
}
const { urlsById, map } = data;
const positions = map.allGeneratedPositionsFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column,
});
@ -273,24 +262,22 @@ async function getAllGeneratedLocations(
}
async function getOriginalLocations(
sourceId: string,
locations: SourceLocation[],
options: LocationOptions = {}
): Promise<SourceLocation[]> {
const maps = {};
const results = [];
for (const location of locations) {
let map = maps[location.sourceId];
if (map === undefined) {
map = await getSourceMap(location.sourceId);
maps[location.sourceId] = map || null;
}
results.push(
map ? getOriginalLocationSync(map, location, options) : location
);
if (locations.some(location => location.sourceId != sourceId)) {
throw new Error("Generated locations must belong to the same source");
}
return results;
const map = await getSourceMap(sourceId);
if (!map) {
return locations;
}
return locations.map(location =>
getOriginalLocationSync(map, location, options)
);
}
function getOriginalLocationSync(
@ -353,42 +340,28 @@ async function getOriginalLocation(
}
async function getOriginalSourceText(
originalSourceId: SourceId
originalSource: Source
): Promise<?{
text: string,
contentType: string,
}> {
assert(isOriginalId(originalSourceId), "Source is not an original source");
assert(isOriginalId(originalSource.id), "Source is not an original source");
const generatedSourceId = originalToGeneratedId(originalSourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
if (!data) {
const generatedSourceId = originalToGeneratedId(originalSource.id);
const map = await getSourceMap(generatedSourceId);
if (!map) {
return null;
}
const { urlsById, map } = data;
const url = urlsById.get(originalSourceId);
let text = map.sourceContentFor(url);
let text = map.sourceContentFor(originalSource.url);
if (!text) {
try {
const response = await networkRequest(url, {
loadFromCache: false,
});
text = response.content;
} catch (err) {
// Wrapper logic renders a notification about the specific URL that
// failed to load, so we include it in the error metadata.
err.metadata = {
...err.metadata,
url,
};
throw err;
}
text = (await networkRequest(originalSource.url, { loadFromCache: false }))
.content;
}
return {
text,
contentType: getContentType(url || ""),
contentType: getContentType(originalSource.url || ""),
};
}
@ -407,17 +380,17 @@ async function getOriginalSourceText(
const GENERATED_MAPPINGS = new WeakMap();
async function getGeneratedRangesForOriginal(
sourceId: SourceId,
url: string,
mergeUnmappedRegions: boolean = false
): Promise<Range[]> {
assert(isOriginalId(sourceId), "Source is not an original source");
const data = await getSourceMapWithMetadata(originalToGeneratedId(sourceId));
const map = await getSourceMap(originalToGeneratedId(sourceId));
// NOTE: this is only needed for Flow
if (!data) {
if (!map) {
return [];
}
const { urlsById, map } = data;
const url = urlsById.get(sourceId);
if (!COMPUTED_SPANS.has(map)) {
COMPUTED_SPANS.add(map);
@ -535,27 +508,24 @@ function wrappedMappingPosition(pos: {
}
async function getFileGeneratedRange(
originalSourceId: SourceId
originalSource: Source
): Promise<?{ start: any, end: any }> {
assert(isOriginalId(originalSourceId), "Source is not an original source");
assert(isOriginalId(originalSource.id), "Source is not an original source");
const data = await getSourceMapWithMetadata(
originalToGeneratedId(originalSourceId)
);
if (!data) {
const map = await getSourceMap(originalToGeneratedId(originalSource.id));
if (!map) {
return;
}
const { urlsById, map } = data;
const start = map.generatedPositionFor({
source: urlsById.get(originalSourceId),
source: originalSource.url,
line: 1,
column: 0,
bias: SourceMapConsumer.LEAST_UPPER_BOUND,
});
const end = map.generatedPositionFor({
source: urlsById.get(originalSourceId),
source: originalSource.url,
line: Number.MAX_SAFE_INTEGER,
column: Number.MAX_SAFE_INTEGER,
bias: SourceMapConsumer.GREATEST_LOWER_BOUND,
@ -567,6 +537,15 @@ async function getFileGeneratedRange(
};
}
async function hasMappedSource(location: SourceLocation): Promise<boolean> {
if (isOriginalId(location.sourceId)) {
return true;
}
const loc = await getOriginalLocation(location);
return loc.sourceId !== location.sourceId;
}
function applySourceMap(
generatedId: string,
url: string,
@ -601,4 +580,5 @@ module.exports = {
getFileGeneratedRange,
applySourceMap,
clearSourceMaps,
hasMappedSource,
};

Просмотреть файл

@ -23,7 +23,7 @@ function getMap(_path) {
return fs.readFileSync(mapPath, "utf8");
}
async function setupBundleFixtureAndData(name) {
async function setupBundleFixture(name) {
const source = {
id: `${name}.js`,
sourceMapURL: `${name}.js.map`,
@ -37,16 +37,10 @@ async function setupBundleFixtureAndData(name) {
return getOriginalURLs(source);
}
async function setupBundleFixture(name) {
const data = await setupBundleFixtureAndData(name);
return data.map(item => item.url);
}
module.exports = {
formatLocations,
formatLocation,
setupBundleFixture,
setupBundleFixtureAndData,
getMap,
};

Просмотреть файл

@ -7,12 +7,13 @@ const networkRequest = require("devtools-utils/src/network-request");
const {
getOriginalURLs,
hasMappedSource,
getOriginalLocation,
getGeneratedRangesForOriginal,
clearSourceMaps,
} = require("../source-map");
const { setupBundleFixture, setupBundleFixtureAndData } = require("./helpers");
const { setupBundleFixture } = require("./helpers");
describe("source maps", () => {
beforeEach(() => {
@ -53,9 +54,12 @@ describe("source maps", () => {
describe("getGeneratedRangesForOriginal", () => {
test("the overall generated ranges on the source", async () => {
const data = await setupBundleFixtureAndData("intermingled-sources");
const urls = await setupBundleFixture("intermingled-sources");
const ranges = await getGeneratedRangesForOriginal(data[0].id);
const ranges = await getGeneratedRangesForOriginal(
"intermingled-sources.js/originalSource-01",
urls[0]
);
expect(ranges).toEqual([
{
@ -112,9 +116,13 @@ describe("source maps", () => {
});
test("the merged generated ranges on the source", async () => {
const data = await setupBundleFixtureAndData("intermingled-sources");
const urls = await setupBundleFixture("intermingled-sources");
const ranges = await getGeneratedRangesForOriginal(data[0].id, true);
const ranges = await getGeneratedRangesForOriginal(
"intermingled-sources.js/originalSource-01",
urls[0],
true
);
expect(ranges).toEqual([
{
@ -131,6 +139,27 @@ describe("source maps", () => {
});
});
describe("hasMappedSource", () => {
test("has original location", async () => {
await setupBundleFixture("bundle");
const location = {
sourceId: "bundle.js",
line: 49,
};
const isMapped = await hasMappedSource(location);
expect(isMapped).toBe(true);
});
test("does not have original location", async () => {
const location = {
sourceId: "bundle.js",
line: 94,
};
const isMapped = await hasMappedSource(location);
expect(isMapped).toBe(false);
});
});
describe("Error handling", () => {
test("missing map", async () => {
const source = {

Просмотреть файл

@ -110,12 +110,7 @@ describe("wasm source maps", () => {
const { getOriginalURLs, getOriginalLocation } = require("../source-map");
const urls = await getOriginalURLs(source);
expect(urls).toEqual([
{
id: "min.js/originalSource-2133f6ef6d6c464acad221082f398cf0",
url: "http://example.com/whatever/one.js",
},
]);
expect(urls).toEqual(["http://example.com/whatever/one.js"]);
const { line, column } = await getOriginalLocation({
sourceId: source.id,

Просмотреть файл

@ -4,8 +4,6 @@
// @flow
import type { SourceMapInput } from "../source-map";
const { networkRequest } = require("devtools-utils");
const { getSourceMap, setSourceMap } = require("./sourceMapRequests");
const { WasmRemap } = require("./wasmRemap");
@ -13,6 +11,8 @@ const { SourceMapConsumer } = require("source-map");
const { convertToJSON } = require("devtools-wasm-dwarf");
const { createConsumer } = require("./createConsumer");
import type { Source } from "debugger-html";
// URLs which have been seen in a completed source map request.
const originalURLs = new Set();
@ -24,7 +24,7 @@ function hasOriginalURL(url: string): boolean {
return originalURLs.has(url);
}
function _resolveSourceMapURL(source: SourceMapInput) {
function _resolveSourceMapURL(source: Source) {
const { url = "", sourceMapURL = "" } = source;
if (!url) {
@ -45,9 +45,7 @@ function _resolveSourceMapURL(source: SourceMapInput) {
return { sourceMapURL: resolvedString, baseURL };
}
async function _resolveAndFetch(
generatedSource: SourceMapInput
): SourceMapConsumer {
async function _resolveAndFetch(generatedSource: Source): SourceMapConsumer {
// Fetch the sourcemap over the network and create it.
const { sourceMapURL, baseURL } = _resolveSourceMapURL(generatedSource);
@ -75,7 +73,7 @@ async function _resolveAndFetch(
return map;
}
function fetchSourceMap(generatedSource: SourceMapInput): SourceMapConsumer {
function fetchSourceMap(generatedSource: Source): SourceMapConsumer {
const existingRequest = getSourceMap(generatedSource.id);
// If it has already been requested, return the request. Make sure

Просмотреть файл

@ -2,58 +2,22 @@
* 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/>. */
const { generatedToOriginalId } = require(".");
const sourceMapRequests = new Map();
function clearSourceMaps() {
sourceMapRequests.clear();
}
function getSourceMapWithMetadata(
generatedSourceId: string
): ?Promise<?{
map: SourceMapConsumer,
urlsById: Map<SourceId, url>,
sources: Array<{ id: SourceId, url: string }>,
}> {
function getSourceMap(generatedSourceId: string): ?Promise<SourceMapConsumer> {
return sourceMapRequests.get(generatedSourceId);
}
function getSourceMap(generatedSourceId: string): ?Promise<?SourceMapConsumer> {
const request = getSourceMapWithMetadata(generatedSourceId);
if (!request) {
return null;
}
return request.then(result => (result ? result.map : null));
}
function setSourceMap(generatedId: string, request) {
sourceMapRequests.set(
generatedId,
request.then(map => {
if (!map || !map.sources) {
return null;
}
const urlsById = new Map();
const sources = [];
for (const url of map.sources) {
const id = generatedToOriginalId(generatedId, url);
urlsById.set(id, url);
sources.push({ id, url });
}
return { map, urlsById, sources };
})
);
function setSourceMap(generatedId, request) {
sourceMapRequests.set(generatedId, request);
}
module.exports = {
clearSourceMaps,
getSourceMapWithMetadata,
getSourceMap,
setSourceMap,
};

Просмотреть файл

@ -15,6 +15,7 @@ const {
getOriginalSourceText,
getGeneratedRangesForOriginal,
getFileGeneratedRange,
hasMappedSource,
clearSourceMaps,
applySourceMap,
} = require("./source-map");
@ -42,6 +43,7 @@ self.onmessage = workerHandler({
getOriginalStackFrames,
getGeneratedRangesForOriginal,
getFileGeneratedRange,
hasMappedSource,
applySourceMap,
clearSourceMaps,
});

Просмотреть файл

@ -114,9 +114,7 @@ describe("worker utils", () => {
id: 53,
results: [
{
error: true,
message: "failed",
metadata: undefined,
error: "Error: failed",
},
],
});

Просмотреть файл

@ -83,9 +83,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
(err: any).metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -114,12 +112,16 @@ function workerHandler(publicInterface: Object) {
if (response instanceof Promise) {
return response.then(
val => ({ response: val }),
err => asErrorMessage(err)
// Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({ error: err.toString() })
);
}
return { response };
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return { error: error.toString() };
}
})
).then(results => {
@ -128,24 +130,6 @@ function workerHandler(publicInterface: Object) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata,
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined,
};
}
module.exports = {
WorkerDispatcher,
workerHandler,

Просмотреть файл

@ -2,8 +2,6 @@
* 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
const { convertToJSON } = require("./src/convertToJSON");
const { setAssetRootURL } = require("./src/wasmAsset");
const { getWasmXScopes, clearWasmXScopes } = require("./src/wasmXScopes");

Просмотреть файл

@ -1,7 +1,6 @@
/* 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*/

Просмотреть файл

@ -43,7 +43,10 @@ async function mapLocations(
return [];
}
const { sourceId } = generatedLocations[0];
const originalLocations = await sourceMaps.getOriginalLocations(
sourceId,
generatedLocations
);
@ -117,6 +120,7 @@ async function _setBreakpointPositions(cx, sourceId, line, thunkArgs) {
// https://github.com/facebook/flow/issues/5294
const ranges: Range[] = await sourceMaps.getGeneratedRangesForOriginal(
sourceId,
generatedSource.url,
true
);
const generatedSourceId = originalToGeneratedId(sourceId);

Просмотреть файл

@ -44,6 +44,7 @@ Array [
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "/examples/a",
"sourceMapURL": null,
"url": "http://localhost:8000/examples/a",
},
},
@ -126,6 +127,7 @@ Array [
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "/examples/a",
"sourceMapURL": null,
"url": "http://localhost:8000/examples/a",
},
},

Просмотреть файл

@ -36,7 +36,7 @@ export function toggleBlackBox(cx: Context, source: Source) {
let sourceId, range;
if (features.originalBlackbox && isOriginalId(source.id)) {
range = await sourceMaps.getFileGeneratedRange(source.id);
range = await sourceMaps.getFileGeneratedRange(source);
sourceId = originalToGeneratedId(source.id);
} else {
sourceId = source.id;

Просмотреть файл

@ -63,7 +63,7 @@ async function loadSource(
}
if (isOriginal(source)) {
const result = await sourceMaps.getOriginalSourceText(source.id);
const result = await sourceMaps.getOriginalSourceText(source);
if (!result) {
// The way we currently try to load and select a pending
// selected location, it is possible that we will try to fetch the

Просмотреть файл

@ -9,6 +9,7 @@
* @module actions/sources
*/
import { generatedToOriginalId } from "devtools-source-map";
import { flatten } from "lodash";
import {
@ -25,6 +26,7 @@ import { selectLocation, setBreakableLines } from "../sources";
import {
getRawSourceURL,
isPrettyURL,
isOriginal,
isUrlExtension,
isInlineScript,
} from "../../utils/source";
@ -33,7 +35,6 @@ import {
getSource,
getSourceFromId,
hasSourceActor,
getSourceByActorId,
getPendingSelectedLocation,
getPendingBreakpointsForSource,
getContext,
@ -46,6 +47,7 @@ import { validateNavigateContext, ContextError } from "../../utils/context";
import type {
Source,
SourceId,
Context,
OriginalSourceData,
GeneratedSourceData,
@ -53,17 +55,15 @@ import type {
} from "../../types";
import type { Action, ThunkArgs } from "../types";
function loadSourceMaps(cx: Context, sources: SourceActor[]) {
function loadSourceMaps(cx: Context, sources: Source[]) {
return async function({
dispatch,
sourceMaps,
}: ThunkArgs): Promise<?(Promise<Source>[])> {
try {
const sourceList = await Promise.all(
sources.map(async sourceActor => {
const originalSources = await dispatch(
loadSourceMap(cx, sourceActor)
);
sources.map(async ({ id }) => {
const originalSources = await dispatch(loadSourceMap(cx, id));
sourceQueue.queueSources(
originalSources.map(data => ({
type: "original",
@ -76,6 +76,13 @@ function loadSourceMaps(cx: Context, sources: SourceActor[]) {
await sourceQueue.flush();
// We would like to sync breakpoints after we are done
// loading source maps as sometimes generated and original
// files share the same paths.
for (const source of sources) {
dispatch(checkPendingBreakpoints(cx, source.id));
}
return flatten(sourceList);
} catch (error) {
if (!(error instanceof ContextError)) {
@ -89,61 +96,58 @@ function loadSourceMaps(cx: Context, sources: SourceActor[]) {
* @memberof actions/sources
* @static
*/
function loadSourceMap(cx: Context, sourceActor: SourceActor) {
function loadSourceMap(cx: Context, sourceId: SourceId) {
return async function({
dispatch,
getState,
sourceMaps,
}: ThunkArgs): Promise<OriginalSourceData[]> {
if (!prefs.clientSourceMapsEnabled || !sourceActor.sourceMapURL) {
}: ThunkArgs): Promise<Source[]> {
const source = getSource(getState(), sourceId);
if (
!prefs.clientSourceMapsEnabled ||
!source ||
isOriginal(source) ||
!source.sourceMapURL
) {
return [];
}
let data = null;
let urls = null;
try {
// Unable to correctly type the result of a spread on a union type.
// See https://github.com/facebook/flow/pull/7298
let url = sourceActor.url || "";
if (!sourceActor.url && typeof sourceActor.introductionUrl === "string") {
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.
url = sourceActor.introductionUrl;
}
// Ignore sourceMapURL on scripts that are part of HTML files, since
// we currently treat sourcemaps as Source-wide, not SourceActor-specific.
const source = getSourceByActorId(getState(), sourceActor.id);
if (source) {
data = await sourceMaps.getOriginalURLs({
// Using source ID here is historical and eventually we'll want to
// switch to all of this being per-source-actor.
id: source.id,
url,
sourceMapURL: sourceActor.sourceMapURL || "",
isWasm: sourceActor.introductionType === "wasm",
});
(urlInfo: any).url = urlInfo.introductionUrl;
}
urls = await sourceMaps.getOriginalURLs(urlInfo);
} catch (e) {
console.error(e);
}
if (!data) {
if (!urls) {
// If this source doesn't have a sourcemap, enable it for pretty printing
dispatch(
({
type: "CLEAR_SOURCE_ACTOR_MAP_URL",
type: "CLEAR_SOURCE_MAP_URL",
cx,
id: sourceActor.id,
sourceId,
}: Action)
);
return [];
}
validateNavigateContext(getState(), cx);
return data;
return urls.map(url => ({
id: generatedToOriginalId(source.id, url),
url,
}));
};
}
@ -268,10 +272,6 @@ export function newOriginalSources(sourceInfo: Array<OriginalSourceData>) {
await dispatch(checkNewSources(cx, sources));
for (const source of sources) {
dispatch(checkPendingBreakpoints(cx, source.id));
}
return sources;
};
}
@ -298,18 +298,19 @@ export function newGeneratedSources(sourceInfo: Array<GeneratedSourceData>) {
const newId = id || makeSourceId(source);
if (!getSource(getState(), newId) && !newSourcesObj[newId]) {
newSourcesObj[newId] = {
newSourcesObj[newId] = ({
id: newId,
url: source.url,
relativeUrl: source.url,
isPrettyPrinted: false,
extensionName: source.extensionName,
sourceMapURL: source.sourceMapURL,
introductionUrl: source.introductionUrl,
introductionType: source.introductionType,
isBlackBoxed: false,
isWasm: !!supportsWasm && source.introductionType === "wasm",
isExtension: (source.url && isUrlExtension(source.url)) || false,
};
}: any);
}
const actorId = stringToSourceActorId(source.actor);
@ -355,17 +356,6 @@ export function newGeneratedSources(sourceInfo: Array<GeneratedSourceData>) {
}
await dispatch(checkNewSources(cx, newSources));
(async () => {
await dispatch(loadSourceMaps(cx, newSourceActors));
// We would like to sync breakpoints after we are done
// loading source maps as sometimes generated and original
// files share the same paths.
for (const source of newSources) {
dispatch(checkPendingBreakpoints(cx, source.id));
}
})();
return resultIds.map(id => getSourceFromId(getState(), id));
};
}
@ -383,6 +373,7 @@ function checkNewSources(cx, sources: Source[]) {
}
dispatch(restoreBlackBoxedSources(cx, sources));
dispatch(loadSourceMaps(cx, sources));
return sources;
};

Просмотреть файл

@ -16,12 +16,13 @@ import { getSourcesForTabs } from "../../reducers/tabs";
import { setSymbols } from "./symbols";
import { setInScopeLines } from "../ast";
import { closeActiveSearch, updateActiveFileSearch } from "../ui";
import { isFulfilled } from "../../utils/async-value";
import { togglePrettyPrint } from "./prettyPrint";
import { addTab, closeTab } from "../tabs";
import { loadSourceText } from "./loadSourceText";
import { prefs } from "../../utils/prefs";
import { isMinified } from "../../utils/source";
import { shouldPrettyPrint, isMinified } from "../../utils/source";
import { createLocation } from "../../utils/location";
import { mapLocation } from "../../utils/source-maps";
@ -32,7 +33,6 @@ import {
getActiveSearch,
getSelectedLocation,
getSelectedSource,
canPrettyPrintSource,
} from "../../selectors";
import type {
@ -169,12 +169,19 @@ export function selectLocation(
return;
}
const sourceWithContent = getSourceWithContent(getState(), source.id);
const sourceContent =
sourceWithContent.content && isFulfilled(sourceWithContent.content)
? sourceWithContent.content.value
: null;
if (
keepContext &&
prefs.autoPrettyPrint &&
!getPrettySource(getState(), loadedSource.id) &&
canPrettyPrintSource(getState(), loadedSource.id) &&
shouldPrettyPrint(
loadedSource,
sourceContent || { type: "text", value: "", contentType: undefined }
) &&
isMinified(sourceWithContent)
) {
await dispatch(togglePrettyPrint(cx, loadedSource.id));

Просмотреть файл

@ -69,7 +69,7 @@ describe("loadSourceText", () => {
getGeneratedRangesForOriginal: async () => [
{ start: { line: 1, column: 0 }, end: { line: 1, column: 1 } },
],
getOriginalLocations: async items =>
getOriginalLocations: async (sourceId, items) =>
items.map(item => ({
...item,
sourceId:

Просмотреть файл

@ -19,7 +19,6 @@ const {
getSourceByURL,
} = selectors;
import sourceQueue from "../../../utils/source-queue";
import { generatedToOriginalId } from "devtools-source-map";
import { mockCommandClient } from "../../tests/helpers/mockCommandClient";
@ -64,12 +63,7 @@ describe("sources - new sources", () => {
mockCommandClient,
{},
{
getOriginalURLs: async source => [
{
id: generatedToOriginalId(source.id, "magic.js"),
url: "magic.js",
},
],
getOriginalURLs: async () => ["magic.js"],
getOriginalLocations: async items => items,
}
);
@ -130,13 +124,8 @@ describe("sources - new sources", () => {
// simulate a hang loading foo.js.map
return new Promise(_ => {});
}
const url = source.id.replace(".js", ".cljs");
return [
{
id: generatedToOriginalId(source.id, url),
url: url,
},
];
return [source.id.replace(".js", ".cljs")];
},
getOriginalLocations: async items => items,
getGeneratedLocation: location => location,

Просмотреть файл

@ -31,7 +31,7 @@ const mockCommandClient = {
};
const sourceMaps = {
getOriginalSourceText: async id => ({
getOriginalSourceText: async ({ id }) => ({
id,
text: sourceTexts[id],
contentType: "text/javascript",

Просмотреть файл

@ -11,6 +11,7 @@ import {
} from "./helpers/breakpoints.js";
import { mockCommandClient } from "./helpers/mockCommandClient";
import { asyncStore } from "../../utils/prefs";
function loadInitialState(opts = {}) {
@ -56,15 +57,15 @@ function mockClient(bpPos = {}) {
function mockSourceMaps() {
return {
...sourceMaps,
getOriginalSourceText: async id => ({
id,
getOriginalSourceText: async source => ({
id: source.id,
text: "",
contentType: "text/javascript",
}),
getGeneratedRangesForOriginal: async () => [
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } },
],
getOriginalLocations: async items => items,
getOriginalLocations: async (sourceId, items) => items,
};
}
@ -375,27 +376,18 @@ describe("adding sources", () => {
it("corresponding breakpoints are added to the original source", async () => {
const sourceURL = makeSourceURL("bar.js");
const store = createStore(mockClient({ "5": [2] }), loadInitialState(), {
getOriginalURLs: async source => [
{
id: sourceMaps.generatedToOriginalId(source.id, sourceURL),
url: sourceURL,
},
],
getOriginalSourceText: async () => ({ text: "" }),
getGeneratedLocation: async location => ({
getOriginalURLs: async () => [sourceURL],
getOriginalSourceText: async () => ({ source: "" }),
getGeneratedLocation: async (location, _source) => ({
line: location.line,
column: location.column,
sourceId: location.sourceId,
sourceId: _source.id,
}),
getOriginalLocation: async location => location,
getGeneratedRangesForOriginal: async () => [
{ start: { line: 0, column: 0 }, end: { line: 10, column: 10 } },
],
getOriginalLocations: async items =>
items.map(item => ({
...item,
sourceId: sourceMaps.generatedToOriginalId(item.sourceId, sourceURL),
})),
getOriginalLocations: async (sourceId, items) => items,
});
const { getState, dispatch } = store;

Просмотреть файл

@ -4,7 +4,7 @@
// @flow
import type { Source, SourceLocation, Context } from "../../types";
import type { SourceId, Source, SourceLocation, Context } from "../../types";
import type { PromiseAction } from "../utils/middleware/promise";
import type { SourceBase } from "../../reducers/sources";
@ -32,6 +32,11 @@ export type SourceAction =
+cx: Context,
+sources: Array<SourceBase>,
|}
| {|
+type: "CLEAR_SOURCE_MAP_URL",
+cx: Context,
+sourceId: SourceId,
|}
| {|
+type: "SET_SELECTED_LOCATION",
+cx: Context,

Просмотреть файл

@ -4,7 +4,6 @@
// @flow
import type { Context } from "../../types";
import { type PromiseAction } from "../utils/middleware/promise";
import type {
SourceActorId,
@ -19,11 +18,6 @@ export type SourceActorsRemoveAction = {|
type: "REMOVE_SOURCE_ACTORS",
items: Array<SourceActor>,
|};
export type SourceActorClearMapAction = {|
+type: "CLEAR_SOURCE_ACTOR_MAP_URL",
+cx: Context,
+id: SourceActorId,
|};
export type SourceActorBreakpointColumnsAction = PromiseAction<
{|
@ -46,5 +40,4 @@ export type SourceActorAction =
| SourceActorsInsertAction
| SourceActorsRemoveAction
| SourceActorBreakpointColumnsAction
| SourceActorBreakableLinesAction
| SourceActorClearMapAction;
| SourceActorBreakableLinesAction;

Просмотреть файл

@ -7,16 +7,13 @@
import { Component } from "react";
import { connect } from "../../utils/connect";
import { showMenu } from "devtools-contextmenu";
import { isOriginalId } from "devtools-source-map";
import { getSourceLocationFromMouseEvent } from "../../utils/editor";
import { isPretty } from "../../utils/source";
import {
getPrettySource,
getIsPaused,
getCurrentThread,
getThreadContext,
isSourceWithMap,
} from "../../selectors";
import { editorMenuItems, editorItemActions } from "./menus/editor";
@ -31,7 +28,7 @@ type Props = {
editorActions: EditorItemActions,
clearContextMenu: () => void,
editor: SourceEditor,
hasMappedLocation: boolean,
hasPrettySource: boolean,
isPaused: boolean,
selectedSource: SourceWithContent,
};
@ -52,7 +49,7 @@ class EditorMenu extends Component<Props> {
editor,
selectedSource,
editorActions,
hasMappedLocation,
hasPrettySource,
isPaused,
contextMenu: event,
} = props;
@ -70,7 +67,7 @@ class EditorMenu extends Component<Props> {
cx,
editorActions,
selectedSource,
hasMappedLocation,
hasPrettySource,
location,
isPaused,
selectionText: editor.codeMirror.getSelection().trim(),
@ -87,11 +84,7 @@ class EditorMenu extends Component<Props> {
const mapStateToProps = (state, props) => ({
cx: getThreadContext(state),
isPaused: getIsPaused(state, getCurrentThread(state)),
hasMappedLocation:
(isOriginalId(props.selectedSource.id) ||
isSourceWithMap(state, props.selectedSource.id) ||
isPretty(props.selectedSource)) &&
!getPrettySource(state, props.selectedSource.id),
hasPrettySource: !!getPrettySource(state, props.selectedSource.id),
});
const mapDispatchToProps = dispatch => ({

Просмотреть файл

@ -14,16 +14,15 @@ import {
getContext,
} from "../../selectors";
import { isFulfilled } from "../../utils/async-value";
import {
isPretty,
getFilename,
isOriginal,
shouldBlackbox,
} from "../../utils/source";
import {
getGeneratedSource,
canPrettyPrintSource,
} from "../../reducers/sources";
import { getGeneratedSource } from "../../reducers/sources";
import { shouldShowPrettyPrint } from "../../utils/editor";
import { PaneToggleButton } from "../shared/Button";
import AccessibleImage from "../shared/AccessibleImage";
@ -43,7 +42,6 @@ type Props = {
mappedSource: Source,
endPanelCollapsed: boolean,
horizontal: boolean,
canPrettyPrint: boolean,
togglePrettyPrint: typeof actions.togglePrettyPrint,
toggleBlackBox: typeof actions.toggleBlackBox,
jumpToMappedLocation: typeof actions.jumpToMappedLocation,
@ -86,12 +84,7 @@ class SourceFooter extends PureComponent<Props, State> {
}
prettyPrintButton() {
const {
cx,
selectedSource,
canPrettyPrint,
togglePrettyPrint,
} = this.props;
const { cx, selectedSource, togglePrettyPrint } = this.props;
if (!selectedSource) {
return;
@ -105,7 +98,16 @@ class SourceFooter extends PureComponent<Props, State> {
);
}
if (!canPrettyPrint) {
const sourceContent =
selectedSource.content && isFulfilled(selectedSource.content)
? selectedSource.content.value
: null;
if (
!shouldShowPrettyPrint(
selectedSource,
sourceContent || { type: "text", value: "", contentType: undefined }
)
) {
return;
}
@ -278,9 +280,6 @@ const mapStateToProps = state => {
selectedSource ? selectedSource.id : null
),
endPanelCollapsed: getPaneCollapse(state, "end"),
canPrettyPrint: selectedSource
? canPrettyPrintSource(state, selectedSource.id)
: false,
};
};

Просмотреть файл

@ -9,6 +9,7 @@ import { isOriginalId } from "devtools-source-map";
import { copyToTheClipboard } from "../../../utils/clipboard";
import {
isPretty,
getRawSourceURL,
getFilename,
shouldBlackbox,
@ -28,6 +29,10 @@ import type {
ThreadContext,
} from "../../../types";
function isMapped(selectedSource) {
return isOriginalId(selectedSource.id) || !!selectedSource.sourceMapURL;
}
export const continueToHereItem = (
cx: ThreadContext,
location: SourceLocation,
@ -83,7 +88,7 @@ const jumpToMappedLocationItem = (
cx: Context,
selectedSource: Source,
location: SourceLocation,
hasMappedLocation: boolean,
hasPrettySource: boolean,
editorActions: EditorItemActions
) => ({
id: "node-menu-jump",
@ -94,7 +99,8 @@ const jumpToMappedLocationItem = (
: L10N.getStr("original")
),
accesskey: L10N.getStr("editor.jumpToMappedLocation1.accesskey"),
disabled: !hasMappedLocation,
disabled:
(!isMapped(selectedSource) && !isPretty(selectedSource)) || hasPrettySource,
click: () => editorActions.jumpToMappedLocation(cx, location),
});
@ -165,7 +171,7 @@ export function editorMenuItems({
selectedSource,
location,
selectionText,
hasMappedLocation,
hasPrettySource,
isTextSelected,
isPaused,
}: {
@ -174,7 +180,7 @@ export function editorMenuItems({
selectedSource: SourceWithContent,
location: SourceLocation,
selectionText: string,
hasMappedLocation: boolean,
hasPrettySource: boolean,
isTextSelected: boolean,
isPaused: boolean,
}) {
@ -190,7 +196,7 @@ export function editorMenuItems({
cx,
selectedSource,
location,
hasMappedLocation,
hasPrettySource,
editorActions
),
continueToHereItem(cx, location, isPaused, editorActions),

Просмотреть файл

@ -83,7 +83,8 @@ describe("SourcesTree", () => {
const newSource = createMockSource(
"server1.conn13.child1/43",
"http://mdn.com/four.js",
true
true,
""
);
const newThreadSources = {
@ -148,7 +149,8 @@ describe("SourcesTree", () => {
"server1.conn13.child1/41": createMockSource(
"server1.conn13.child1/41",
"http://mdn.com/three.js",
true
true,
""
),
},
};
@ -175,7 +177,8 @@ describe("SourcesTree", () => {
const newSource = createMockSource(
"server1.conn13.child1/43",
"http://mdn.com/four.js",
true
true,
""
);
const newThreadSources = {
@ -224,7 +227,8 @@ describe("SourcesTree", () => {
const mockSource = createMockSource(
"server1.conn13.child1/41",
"http://mdn.com/three.js",
false
false,
null
);
await component.setProps({
...props,
@ -359,26 +363,32 @@ function generateDefaults(overrides: Object) {
"server1.conn13.child1/39": createMockSource(
"server1.conn13.child1/39",
"http://mdn.com/one.js",
false
false,
null
),
"server1.conn13.child1/40": createMockSource(
"server1.conn13.child1/40",
"http://mdn.com/two.js",
false
false,
null
),
"server1.conn13.child1/41": createMockSource(
"server1.conn13.child1/41",
"http://mdn.com/three.js",
false
false,
null
),
"server1.conn13.child1/42/originalSource-sha": createMockSource(
"server1.conn13.child1/42/originalSource-sha",
"http://mdn.com/four.js",
false
false,
null
),
"server1.conn13.child1/42": createMockSource(
"server1.conn13.child1/42",
"http://mdn.com/four.js"
"http://mdn.com/four.js",
false,
"data:application/json?charset=utf?dsffewrsf"
),
},
};
@ -420,10 +430,11 @@ function render(overrides = {}) {
return { component, props, defaultState, instance };
}
function createMockSource(id, url, isBlackBoxed = false) {
function createMockSource(id, url, isBlackBoxed = false, sourceMapURL = null) {
return {
...makeMockSource(url, id),
isBlackBoxed,
sourceMapURL,
};
}

Просмотреть файл

@ -144,6 +144,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/three.js",
"sourceMapURL": null,
"url": "http://mdn.com/three.js",
},
"name": "three.js",
@ -163,6 +164,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/four.js",
"sourceMapURL": "data:application/json?charset=utf?dsffewrsf",
"url": "http://mdn.com/four.js",
},
"name": "four.js",
@ -180,6 +182,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/four.js",
"sourceMapURL": null,
"url": "http://mdn.com/four.js",
},
"name": "four.js",
@ -197,6 +200,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/one.js",
"sourceMapURL": null,
"url": "http://mdn.com/one.js",
},
"name": "one.js",
@ -214,6 +218,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/three.js",
"sourceMapURL": null,
"url": "http://mdn.com/three.js",
},
"name": "three.js",
@ -231,6 +236,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/two.js",
"sourceMapURL": null,
"url": "http://mdn.com/two.js",
},
"name": "two.js",
@ -257,6 +263,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/four.js",
"sourceMapURL": "data:application/json?charset=utf?dsffewrsf",
"url": "http://mdn.com/four.js",
},
"name": "four.js",
@ -274,6 +281,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/four.js",
"sourceMapURL": null,
"url": "http://mdn.com/four.js",
},
"name": "four.js",
@ -291,6 +299,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/one.js",
"sourceMapURL": null,
"url": "http://mdn.com/one.js",
},
"name": "one.js",
@ -308,6 +317,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/three.js",
"sourceMapURL": null,
"url": "http://mdn.com/three.js",
},
"name": "three.js",
@ -325,6 +335,7 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
"isPrettyPrinted": false,
"isWasm": false,
"relativeUrl": "http://mdn.com/two.js",
"sourceMapURL": null,
"url": "http://mdn.com/two.js",
},
"name": "two.js",

Просмотреть файл

@ -109,31 +109,11 @@ export default function update(
case "SET_SOURCE_ACTOR_BREAKABLE_LINES":
state = updateBreakableLines(state, action);
break;
case "CLEAR_SOURCE_ACTOR_MAP_URL":
state = clearSourceActorMapURL(state, action.id);
break;
}
return state;
}
function clearSourceActorMapURL(
state: SourceActorsState,
id: SourceActorId
): SourceActorsState {
if (!hasResource(state, id)) {
return state;
}
return updateResources(state, [
{
id,
sourceMapURL: "",
},
]);
}
function updateBreakpointColumns(
state: SourceActorsState,
action: SourceActorBreakpointColumnsAction

Просмотреть файл

@ -17,8 +17,6 @@ import {
isGenerated,
isOriginal as isOriginalSource,
getPlainUrl,
isPretty,
isJavaScript,
} from "../utils/source";
import {
createInitial,
@ -39,14 +37,7 @@ import {
} from "../utils/resource";
import { findPosition } from "../utils/breakpoint/breakpointPositions";
import {
pending,
fulfilled,
rejected,
asSettled,
isFulfilled,
} from "../utils/async-value";
import * as asyncValue from "../utils/async-value";
import type { AsyncValue, SettledValue } from "../utils/async-value";
import { originalToGeneratedId } from "devtools-source-map";
import { prefs } from "../utils/prefs";
@ -89,6 +80,7 @@ type PlainUrlsMap = { [string]: string[] };
export type SourceBase = {|
+id: SourceId,
+url: string,
+sourceMapURL?: string,
+isBlackBoxed: boolean,
+isPrettyPrinted: boolean,
+relativeUrl: string,
@ -158,6 +150,8 @@ function update(
let location = null;
switch (action.type) {
case "CLEAR_SOURCE_MAP_URL":
return clearSourceMaps(state, action.sourceId);
case "ADD_SOURCE":
return addSources(state, [action.source]);
@ -266,7 +260,7 @@ const resourceAsSourceBase = memoizeResourceShallow(
const resourceAsSourceWithContent = memoizeResourceShallow(
({ content, ...source }: SourceResource): SourceWithContent => ({
...source,
content: asSettled(content),
content: asyncValue.asSettled(content),
})
);
@ -423,17 +417,17 @@ function updateLoadedState(
let content;
if (action.status === "start") {
content = pending();
content = asyncValue.pending();
} else if (action.status === "error") {
content = rejected(action.error);
content = asyncValue.rejected(action.error);
} else if (typeof action.value.text === "string") {
content = fulfilled({
content = asyncValue.fulfilled({
type: "text",
value: action.value.text,
contentType: action.value.contentType,
});
} else {
content = fulfilled({
content = asyncValue.fulfilled({
type: "wasm",
value: action.value.text,
});
@ -450,6 +444,25 @@ function updateLoadedState(
};
}
function clearSourceMaps(
state: SourcesState,
sourceId: SourceId
): SourcesState {
if (!hasResource(state.sources, sourceId)) {
return state;
}
return {
...state,
sources: updateResources(state.sources, [
{
id: sourceId,
sourceMapURL: "",
},
]),
};
}
/*
* Update a source when its state changes
* e.g. the text was loaded, it was blackboxed
@ -776,7 +789,7 @@ export function getSourceContent(
id: SourceId
): SettledValue<SourceContent> | null {
const { content } = getResource(state.sources.sources, id);
return asSettled(content);
return asyncValue.asSettled(content);
}
export function getSelectedSourceId(state: OuterState) {
@ -913,39 +926,6 @@ export function canLoadSource(
return actors.length != 0;
}
export function isSourceWithMap(
state: OuterState & SourceActorOuterState,
id: SourceId
): boolean {
return getSourceActorsForSource(state, id).some(
soureActor => soureActor.sourceMapURL
);
}
export function canPrettyPrintSource(
state: OuterState & SourceActorOuterState,
id: SourceId
): boolean {
const source: SourceWithContent = getSourceWithContent(state, id);
if (
!source ||
isPretty(source) ||
isOriginalSource(source) ||
(prefs.clientSourceMapsEnabled && isSourceWithMap(state, id))
) {
return false;
}
const sourceContent =
source.content && isFulfilled(source.content) ? source.content.value : null;
if (!sourceContent || !isJavaScript(source, sourceContent)) {
return false;
}
return true;
}
export function getBreakpointPositions(
state: OuterState
): BreakpointPositionsMap {

Просмотреть файл

@ -253,11 +253,12 @@ export type ChromeFrame = {
location: ?SourceLocation,
};
export type OriginalFrame = {|
export type OriginalFrame = {
displayName: string,
variables?: Object,
location?: SourceLocation,
|};
thread: string,
};
/**
* ContextMenuItem
@ -400,6 +401,7 @@ export type SourceWithContentAndType<+Content: SourceContent> = $ReadOnly<{
export type Source = {
+id: SourceId,
+url: string,
+sourceMapURL?: string,
+isBlackBoxed: boolean,
+isPrettyPrinted: boolean,
+relativeUrl: string,

Просмотреть файл

@ -11,13 +11,19 @@ export * from "../ui";
export { onMouseOver } from "./token-events";
import { createEditor } from "./create-editor";
import { shouldPrettyPrint } from "../source";
import { findNext, findPrev } from "./source-search";
import { isWasm, lineToWasmOffset, wasmOffsetToLine } from "../wasm";
import type { AstLocation } from "../../workers/parser";
import type { EditorPosition, EditorRange } from "../editor/types";
import type { SearchModifiers, Source, SourceLocation } from "../../types";
import type {
SearchModifiers,
Source,
SourceContent,
SourceLocation,
} from "../../types";
type Editor = Object;
let editor: ?Editor;
@ -57,6 +63,10 @@ export function endOperation() {
codeMirror.endOperation();
}
export function shouldShowPrettyPrint(source: Source, content: SourceContent) {
return shouldPrettyPrint(source, content);
}
export function traverseResults(
e: Event,
ctx: any,

Просмотреть файл

@ -5,6 +5,7 @@
// @flow
import {
shouldShowPrettyPrint,
traverseResults,
toEditorLine,
toEditorPosition,
@ -21,7 +22,19 @@ import {
getCursorLine,
} from "../index";
import { makeMockSource } from "../../test-mockup";
import { makeMockSource, makeMockSourceAndContent } from "../../test-mockup";
describe("shouldShowPrettyPrint", () => {
it("shows pretty print for a source", () => {
const { content, ...source } = makeMockSourceAndContent(
"http://example.com/index.js",
"test-id-123",
"text/javascript",
"some text here"
);
expect(shouldShowPrettyPrint(source, content)).toEqual(true);
});
});
describe("traverseResults", () => {
const e: any = { stopPropagation: jest.fn(), preventDefault: jest.fn() };

Просмотреть файл

@ -38,8 +38,8 @@ export async function originalRangeStartsInside(
},
sourceMaps: SourceMaps
) {
const endPosition = await sourceMaps.getGeneratedLocation(end);
const startPosition = await sourceMaps.getGeneratedLocation(start);
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.
@ -62,7 +62,7 @@ export async function getApplicableBindingsForOriginalPosition(
locationType: BindingLocationType,
sourceMaps: SourceMaps
): Promise<Array<ApplicableBinding>> {
const ranges = await sourceMaps.getGeneratedRanges(start);
const ranges = await sourceMaps.getGeneratedRanges(start, source);
const resultRanges: GeneratedRange[] = ranges.map(mapRange => ({
start: {
@ -85,8 +85,8 @@ export async function getApplicableBindingsForOriginalPosition(
// var _mod = require("mod"); // mapped from import statement
// var _mod2 = interop(_mod); // entirely unmapped
if (bindingType === "import" && locationType !== "ref") {
const endPosition = await sourceMaps.getGeneratedLocation(end);
const startPosition = await sourceMaps.getGeneratedLocation(start);
const endPosition = await sourceMaps.getGeneratedLocation(end, source);
const startPosition = await sourceMaps.getGeneratedLocation(start, source);
for (const range of resultRanges) {
if (

Просмотреть файл

@ -70,6 +70,7 @@ export async function buildMappedScopes(
}
const originalRanges = await loadRangeMetadata(
source,
frame,
originalAstScopes,
sourceMaps
@ -224,15 +225,15 @@ function batchScopeMappings(
for (const loc of locs) {
precalculatedRanges.set(
buildLocationKey(loc.start),
sourceMaps.getGeneratedRanges(loc.start)
sourceMaps.getGeneratedRanges(loc.start, source)
);
precalculatedLocations.set(
buildLocationKey(loc.start),
sourceMaps.getGeneratedLocation(loc.start)
sourceMaps.getGeneratedLocation(loc.start, source)
);
precalculatedLocations.set(
buildLocationKey(loc.end),
sourceMaps.getGeneratedLocation(loc.end)
sourceMaps.getGeneratedLocation(loc.end, source)
);
}
}
@ -240,21 +241,21 @@ function batchScopeMappings(
}
return {
async getGeneratedRanges(pos) {
async getGeneratedRanges(pos, s) {
const key = buildLocationKey(pos);
if (!precalculatedRanges.has(key)) {
if (s !== source || !precalculatedRanges.has(key)) {
log("Bad precalculated mapping");
return sourceMaps.getGeneratedRanges(pos);
return sourceMaps.getGeneratedRanges(pos, s);
}
return precalculatedRanges.get(key);
},
async getGeneratedLocation(pos) {
async getGeneratedLocation(pos, s) {
const key = buildLocationKey(pos);
if (!precalculatedLocations.has(key)) {
if (s !== source || !precalculatedLocations.has(key)) {
log("Bad precalculated mapping");
return sourceMaps.getGeneratedLocation(pos);
return sourceMaps.getGeneratedLocation(pos, s);
}
return precalculatedLocations.get(key);
},

Просмотреть файл

@ -11,7 +11,7 @@ import { positionCmp } from "./positionCmp";
import { filterSortedArray } from "./filtering";
import type { SourceScope } from "../../../workers/parser";
import type { PartialPosition, Frame } from "../../../types";
import type { PartialPosition, Frame, Source } from "../../../types";
type SourceOriginalRange = {
line: number,
@ -33,12 +33,14 @@ export type MappedOriginalRange = {
};
export async function loadRangeMetadata(
source: Source,
frame: Frame,
originalAstScopes: Array<SourceScope>,
sourceMaps: SourceMaps
): Promise<Array<MappedOriginalRange>> {
const originalRanges: Array<SourceOriginalRange> = await sourceMaps.getOriginalRanges(
frame.location.sourceId
frame.location.sourceId,
source.url
);
const sortedOriginalAstBindings = [];

Просмотреть файл

@ -20,7 +20,8 @@ export async function getGeneratedLocation(
}
const { line, sourceId, column } = await sourceMaps.getGeneratedLocation(
location
location,
source
);
const generatedSource = getSource(state, sourceId);

Просмотреть файл

@ -20,7 +20,7 @@ import { renderWasmText } from "./wasm";
import { toEditorLine } from "./editor";
export { isMinified } from "./isMinified";
import { getURL, getFileExtension } from "./sources-tree";
import { features } from "./prefs";
import { prefs, features } from "./prefs";
import type {
SourceId,
@ -78,6 +78,23 @@ export function shouldBlackbox(source: ?Source) {
return true;
}
export function shouldPrettyPrint(
source: Source,
content: SourceContent
): boolean {
if (
!source ||
isPretty(source) ||
!isJavaScript(source, content) ||
isOriginal(source) ||
(prefs.clientSourceMapsEnabled && source.sourceMapURL)
) {
return false;
}
return true;
}
/**
* Returns true if the specified url and/or content type are specific to
* javascript files.

Просмотреть файл

@ -89,6 +89,7 @@ function makeFrame({ id, sourceId }: Object, opts: Object = {}) {
function createSourceObject(
filename: string,
props: {
sourceMapURL?: string,
introductionType?: string,
introductionUrl?: string,
isBlackBoxed?: boolean,

Просмотреть файл

@ -1144,14 +1144,14 @@ Toolbox.prototype = {
};
case "getOriginalSourceText":
return originalSourceId => {
return originalSource => {
return target
.getOriginalSourceText(originalSourceId)
.catch(error => {
.getOriginalSourceText(originalSource)
.catch(text => {
const message = L10N.getFormatStr(
"toolbox.sourceMapSourceFailure",
error.message,
error.metadata ? error.metadata.url : "<unknown>"
text,
originalSource.url
);
this.target.logWarningInPage(message, "source map");
// Also replace the result with the error text.

Просмотреть файл

@ -487,9 +487,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
err.metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -522,14 +520,22 @@ function workerHandler(publicInterface) {
if (response instanceof Promise) {
return response.then(val => ({
response: val
}), err => asErrorMessage(err));
}), // Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({
error: err.toString()
}));
}
return {
response
};
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: error.toString()
};
}
})).then(results => {
self.postMessage({
@ -540,24 +546,6 @@ function workerHandler(publicInterface) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined
};
}
module.exports = {
WorkerDispatcher,
workerHandler
@ -598,7 +586,7 @@ Object.defineProperty(exports, "isOriginalId", {
return _utils.isOriginalId;
}
});
exports.default = exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.getOriginalStackFrames = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getFileGeneratedRange = exports.getGeneratedRangesForOriginal = exports.getOriginalLocations = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = void 0;
exports.default = exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.getOriginalStackFrames = exports.hasMappedSource = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getLocationScopes = exports.getFileGeneratedRange = exports.getGeneratedRangesForOriginal = exports.getOriginalLocations = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = void 0;
var _utils = __webpack_require__(64);
@ -646,19 +634,19 @@ const hasOriginalURL = async url => dispatcher.invoke("hasOriginalURL", url);
exports.hasOriginalURL = hasOriginalURL;
const getOriginalRanges = async sourceId => dispatcher.invoke("getOriginalRanges", sourceId);
const getOriginalRanges = async (sourceId, url) => dispatcher.invoke("getOriginalRanges", sourceId, url);
exports.getOriginalRanges = getOriginalRanges;
const getGeneratedRanges = async location => _getGeneratedRanges(location);
const getGeneratedRanges = async (location, originalSource) => _getGeneratedRanges(location, originalSource);
exports.getGeneratedRanges = getGeneratedRanges;
const getGeneratedLocation = async location => _getGeneratedLocation(location);
const getGeneratedLocation = async (location, originalSource) => _getGeneratedLocation(location, originalSource);
exports.getGeneratedLocation = getGeneratedLocation;
const getAllGeneratedLocations = async location => _getAllGeneratedLocations(location);
const getAllGeneratedLocations = async (location, originalSource) => _getAllGeneratedLocations(location, originalSource);
exports.getAllGeneratedLocations = getAllGeneratedLocations;
@ -666,19 +654,21 @@ const getOriginalLocation = async (location, options = {}) => _getOriginalLocati
exports.getOriginalLocation = getOriginalLocation;
const getOriginalLocations = async (locations, options = {}) => dispatcher.invoke("getOriginalLocations", locations, options);
const getOriginalLocations = async (sourceId, locations, options = {}) => dispatcher.invoke("getOriginalLocations", sourceId, locations, options);
exports.getOriginalLocations = getOriginalLocations;
const getGeneratedRangesForOriginal = async (sourceId, mergeUnmappedRegions) => dispatcher.invoke("getGeneratedRangesForOriginal", sourceId, mergeUnmappedRegions);
const getGeneratedRangesForOriginal = async (sourceId, url, mergeUnmappedRegions) => dispatcher.invoke("getGeneratedRangesForOriginal", sourceId, url, mergeUnmappedRegions);
exports.getGeneratedRangesForOriginal = getGeneratedRangesForOriginal;
const getFileGeneratedRange = async originalSourceId => dispatcher.invoke("getFileGeneratedRange", originalSourceId);
const getFileGeneratedRange = async originalSource => dispatcher.invoke("getFileGeneratedRange", originalSource);
exports.getFileGeneratedRange = getFileGeneratedRange;
const getLocationScopes = dispatcher.task("getLocationScopes");
exports.getLocationScopes = getLocationScopes;
const getOriginalSourceText = async originalSourceId => dispatcher.invoke("getOriginalSourceText", originalSourceId);
const getOriginalSourceText = async originalSource => dispatcher.invoke("getOriginalSourceText", originalSource);
exports.getOriginalSourceText = getOriginalSourceText;
@ -690,6 +680,10 @@ const clearSourceMaps = async () => dispatcher.invoke("clearSourceMaps");
exports.clearSourceMaps = clearSourceMaps;
const hasMappedSource = async location => dispatcher.invoke("hasMappedSource", location);
exports.hasMappedSource = hasMappedSource;
const getOriginalStackFrames = async generatedLocation => dispatcher.invoke("getOriginalStackFrames", generatedLocation);
exports.getOriginalStackFrames = getOriginalStackFrames;

Просмотреть файл

@ -76,64 +76,27 @@ return /******/ (function(modules) { // webpackBootstrap
/******/ ({
/***/ 104:
/***/ (function(module, exports, __webpack_require__) {
/***/ (function(module, exports) {
/* 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/>. */
const {
generatedToOriginalId
} = __webpack_require__(64);
const sourceMapRequests = new Map();
function clearSourceMaps() {
sourceMapRequests.clear();
}
function getSourceMapWithMetadata(generatedSourceId) {
function getSourceMap(generatedSourceId) {
return sourceMapRequests.get(generatedSourceId);
}
function getSourceMap(generatedSourceId) {
const request = getSourceMapWithMetadata(generatedSourceId);
if (!request) {
return null;
}
return request.then(result => result ? result.map : null);
}
function setSourceMap(generatedId, request) {
sourceMapRequests.set(generatedId, request.then(map => {
if (!map || !map.sources) {
return null;
}
const urlsById = new Map();
const sources = [];
for (const url of map.sources) {
const id = generatedToOriginalId(generatedId, url);
urlsById.set(id, url);
sources.push({
id,
url
});
}
return {
map,
urlsById,
sources
};
}));
sourceMapRequests.set(generatedId, request);
}
module.exports = {
clearSourceMaps,
getSourceMapWithMetadata,
getSourceMap,
setSourceMap
};
@ -548,9 +511,7 @@ WorkerDispatcher.prototype = {
const [, resolve, reject] = items[i];
if (resultData.error) {
const err = new Error(resultData.message);
err.metadata = resultData.metadata;
reject(err);
reject(resultData.error);
} else {
resolve(resultData.response);
}
@ -583,14 +544,22 @@ function workerHandler(publicInterface) {
if (response instanceof Promise) {
return response.then(val => ({
response: val
}), err => asErrorMessage(err));
}), // Error can't be sent via postMessage, so be sure to
// convert to string.
err => ({
error: err.toString()
}));
}
return {
response
};
} catch (error) {
return asErrorMessage(error);
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: error.toString()
};
}
})).then(results => {
self.postMessage({
@ -601,24 +570,6 @@ function workerHandler(publicInterface) {
};
}
function asErrorMessage(error) {
if (typeof error === "object" && error && "message" in error) {
// Error can't be sent via postMessage, so be sure to convert to
// string.
return {
error: true,
message: error.message,
metadata: error.metadata
};
}
return {
error: true,
message: error == null ? error : error.toString(),
metadata: undefined
};
}
module.exports = {
WorkerDispatcher,
workerHandler
@ -1387,6 +1338,7 @@ const {
getOriginalSourceText,
getGeneratedRangesForOriginal,
getFileGeneratedRange,
hasMappedSource,
clearSourceMaps,
applySourceMap
} = __webpack_require__(391);
@ -1421,6 +1373,7 @@ self.onmessage = workerHandler({
getOriginalStackFrames,
getGeneratedRangesForOriginal,
getFileGeneratedRange,
hasMappedSource,
applySourceMap,
clearSourceMaps
});
@ -1461,7 +1414,6 @@ const {
const {
getSourceMap,
getSourceMapWithMetadata,
setSourceMap,
clearSourceMaps: clearSourceMapsRequests
} = __webpack_require__(104);
@ -1479,30 +1431,25 @@ const {
} = __webpack_require__(510);
async function getOriginalURLs(generatedSource) {
await fetchSourceMap(generatedSource);
const data = await getSourceMapWithMetadata(generatedSource.id);
return data ? data.sources : null;
const map = await fetchSourceMap(generatedSource);
return map && map.sources;
}
const COMPUTED_SPANS = new WeakSet();
const SOURCE_MAPPINGS = new WeakMap();
async function getOriginalRanges(sourceId) {
async function getOriginalRanges(sourceId, url) {
if (!isOriginalId(sourceId)) {
return [];
}
const generatedSourceId = originalToGeneratedId(sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
const map = await getSourceMap(generatedSourceId);
if (!data) {
if (!map) {
return [];
}
const {
map
} = data;
const url = data.urlsById.get(sourceId);
let mappings = SOURCE_MAPPINGS.get(map);
if (!mappings) {
@ -1548,23 +1495,18 @@ async function getOriginalRanges(sourceId) {
*/
async function getGeneratedRanges(location) {
async function getGeneratedRanges(location, originalSource) {
if (!isOriginalId(location.sourceId)) {
return [];
}
const generatedSourceId = originalToGeneratedId(location.sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
const map = await getSourceMap(generatedSourceId);
if (!data) {
if (!map) {
return [];
}
const {
urlsById,
map
} = data;
if (!COMPUTED_SPANS.has(map)) {
COMPUTED_SPANS.add(map);
map.computeColumnSpans();
@ -1577,7 +1519,7 @@ async function getGeneratedRanges(location) {
const genPos = map.generatedPositionFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column,
bias: SourceMapConsumer.GREATEST_LOWER_BOUND
@ -1601,24 +1543,20 @@ async function getGeneratedRanges(location) {
});
}
async function getGeneratedLocation(location) {
async function getGeneratedLocation(location, originalSource) {
if (!isOriginalId(location.sourceId)) {
return location;
}
const generatedSourceId = originalToGeneratedId(location.sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
const map = await getSourceMap(generatedSourceId);
if (!data) {
if (!map) {
return location;
}
const {
urlsById,
map
} = data;
const positions = map.allGeneratedPositionsFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column
}); // Prior to source-map 0.7, the source-map module returned the earliest
@ -1636,7 +1574,7 @@ async function getGeneratedLocation(location) {
if (!match) {
match = map.generatedPositionFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column,
bias: SourceMapConsumer.LEAST_UPPER_BOUND
@ -1650,24 +1588,20 @@ async function getGeneratedLocation(location) {
};
}
async function getAllGeneratedLocations(location) {
async function getAllGeneratedLocations(location, originalSource) {
if (!isOriginalId(location.sourceId)) {
return [];
}
const generatedSourceId = originalToGeneratedId(location.sourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
const map = await getSourceMap(generatedSourceId);
if (!data) {
if (!map) {
return [];
}
const {
urlsById,
map
} = data;
const positions = map.allGeneratedPositionsFor({
source: urlsById.get(location.sourceId),
source: originalSource.url,
line: location.line,
column: location.column == null ? 0 : location.column
});
@ -1681,22 +1615,18 @@ async function getAllGeneratedLocations(location) {
}));
}
async function getOriginalLocations(locations, options = {}) {
const maps = {};
const results = [];
for (const location of locations) {
let map = maps[location.sourceId];
if (map === undefined) {
map = await getSourceMap(location.sourceId);
maps[location.sourceId] = map || null;
}
results.push(map ? getOriginalLocationSync(map, location, options) : location);
async function getOriginalLocations(sourceId, locations, options = {}) {
if (locations.some(location => location.sourceId != sourceId)) {
throw new Error("Generated locations must belong to the same source");
}
return results;
const map = await getSourceMap(sourceId);
if (!map) {
return locations;
}
return locations.map(location => getOriginalLocationSync(map, location, options));
}
function getOriginalLocationSync(map, location, {
@ -1757,41 +1687,26 @@ async function getOriginalLocation(location, options = {}) {
return getOriginalLocationSync(map, location, options);
}
async function getOriginalSourceText(originalSourceId) {
assert(isOriginalId(originalSourceId), "Source is not an original source");
const generatedSourceId = originalToGeneratedId(originalSourceId);
const data = await getSourceMapWithMetadata(generatedSourceId);
async function getOriginalSourceText(originalSource) {
assert(isOriginalId(originalSource.id), "Source is not an original source");
const generatedSourceId = originalToGeneratedId(originalSource.id);
const map = await getSourceMap(generatedSourceId);
if (!data) {
if (!map) {
return null;
}
const {
urlsById,
map
} = data;
const url = urlsById.get(originalSourceId);
let text = map.sourceContentFor(url);
let text = map.sourceContentFor(originalSource.url);
if (!text) {
try {
const response = await networkRequest(url, {
loadFromCache: false
});
text = response.content;
} catch (err) {
// Wrapper logic renders a notification about the specific URL that
// failed to load, so we include it in the error metadata.
err.metadata = { ...err.metadata,
url
};
throw err;
}
text = (await networkRequest(originalSource.url, {
loadFromCache: false
})).content;
}
return {
text,
contentType: getContentType(url || "")
contentType: getContentType(originalSource.url || "")
};
}
/**
@ -1810,20 +1725,14 @@ async function getOriginalSourceText(originalSourceId) {
const GENERATED_MAPPINGS = new WeakMap();
async function getGeneratedRangesForOriginal(sourceId, mergeUnmappedRegions = false) {
async function getGeneratedRangesForOriginal(sourceId, url, mergeUnmappedRegions = false) {
assert(isOriginalId(sourceId), "Source is not an original source");
const data = await getSourceMapWithMetadata(originalToGeneratedId(sourceId)); // NOTE: this is only needed for Flow
const map = await getSourceMap(originalToGeneratedId(sourceId)); // NOTE: this is only needed for Flow
if (!data) {
if (!map) {
return [];
}
const {
urlsById,
map
} = data;
const url = urlsById.get(sourceId);
if (!COMPUTED_SPANS.has(map)) {
COMPUTED_SPANS.add(map);
map.computeColumnSpans();
@ -1927,26 +1836,22 @@ function wrappedMappingPosition(pos) {
};
}
async function getFileGeneratedRange(originalSourceId) {
assert(isOriginalId(originalSourceId), "Source is not an original source");
const data = await getSourceMapWithMetadata(originalToGeneratedId(originalSourceId));
async function getFileGeneratedRange(originalSource) {
assert(isOriginalId(originalSource.id), "Source is not an original source");
const map = await getSourceMap(originalToGeneratedId(originalSource.id));
if (!data) {
if (!map) {
return;
}
const {
urlsById,
map
} = data;
const start = map.generatedPositionFor({
source: urlsById.get(originalSourceId),
source: originalSource.url,
line: 1,
column: 0,
bias: SourceMapConsumer.LEAST_UPPER_BOUND
});
const end = map.generatedPositionFor({
source: urlsById.get(originalSourceId),
source: originalSource.url,
line: Number.MAX_SAFE_INTEGER,
column: Number.MAX_SAFE_INTEGER,
bias: SourceMapConsumer.GREATEST_LOWER_BOUND
@ -1957,6 +1862,15 @@ async function getFileGeneratedRange(originalSourceId) {
};
}
async function hasMappedSource(location) {
if (isOriginalId(location.sourceId)) {
return true;
}
const loc = await getOriginalLocation(location);
return loc.sourceId !== location.sourceId;
}
function applySourceMap(generatedId, url, code, mappings) {
const generator = new SourceMapGenerator({
file: url
@ -1986,7 +1900,8 @@ module.exports = {
getGeneratedRangesForOriginal,
getFileGeneratedRange,
applySourceMap,
clearSourceMaps
clearSourceMaps,
hasMappedSource
};
/***/ }),
@ -3839,9 +3754,9 @@ const {
const {
createConsumer
} = __webpack_require__(179); // URLs which have been seen in a completed source map request.
} = __webpack_require__(179);
// URLs which have been seen in a completed source map request.
const originalURLs = new Set();
function clearOriginalURLs() {

Просмотреть файл

@ -366,10 +366,14 @@ StyleEditorUI.prototype = {
this._removeStyleSheetEditor(editor);
editor = null;
for (const { id: originalId, url: originalURL } of sources) {
for (const source of sources) {
const generatedId = sourceMapService.generatedToOriginalId(
id,
source
);
const original = new OriginalSource(
originalURL,
originalId,
source,
generatedId,
sourceMapService
);

Просмотреть файл

@ -46,7 +46,10 @@ OriginalSource.prototype = {
getText: function() {
if (!this._sourcePromise) {
this._sourcePromise = this._sourceMapService
.getOriginalSourceText(this._sourceId)
.getOriginalSourceText({
id: this._sourceId,
url: this._url,
})
.then(contents => {
// Make it look like a long string actor.
return {