mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
280
devtools/client/debugger/content/actions/sources.js
Normal file
280
devtools/client/debugger/content/actions/sources.js
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
const constants = require("../constants");
|
||||
const promise = require("promise");
|
||||
const Services = require("Services");
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const { PROMISE, HISTOGRAM_ID } = require("devtools/client/shared/redux/middleware/promise");
|
||||
const { getSource, getSourceText } = require("../queries");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
|
||||
const NEW_SOURCE_IGNORED_URLS = ["debugger eval code", "XStringBundle"];
|
||||
const FETCH_SOURCE_RESPONSE_DELAY = 200; // ms
|
||||
|
||||
function getSourceClient(source) {
|
||||
return gThreadClient.source(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for the debugger client's unsolicited newSource notification.
|
||||
*/
|
||||
function newSource(source) {
|
||||
return dispatch => {
|
||||
// Ignore bogus scripts, e.g. generated from 'clientEvaluate' packets.
|
||||
if (NEW_SOURCE_IGNORED_URLS.indexOf(source.url) != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Signal that a new source has been added.
|
||||
window.emit(EVENTS.NEW_SOURCE);
|
||||
|
||||
return dispatch({
|
||||
type: constants.ADD_SOURCE,
|
||||
source: source
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function selectSource(source, opts) {
|
||||
return (dispatch, getState) => {
|
||||
if (!gThreadClient) {
|
||||
// No connection, do nothing. This happens when the debugger is
|
||||
// shut down too fast and it tries to display a default source.
|
||||
return;
|
||||
}
|
||||
|
||||
source = getSource(getState(), source.actor);
|
||||
|
||||
// Make sure to start a request to load the source text.
|
||||
dispatch(loadSourceText(source));
|
||||
|
||||
dispatch({
|
||||
type: constants.SELECT_SOURCE,
|
||||
source: source,
|
||||
opts: opts
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function loadSources() {
|
||||
return {
|
||||
type: constants.LOAD_SOURCES,
|
||||
[PROMISE]: Task.spawn(function* () {
|
||||
const response = yield gThreadClient.getSources();
|
||||
|
||||
// Top-level breakpoints may pause the entire loading process
|
||||
// because scripts are executed as they are loaded, so the
|
||||
// engine may pause in the middle of loading all the sources.
|
||||
// This is relatively harmless, as individual `newSource`
|
||||
// notifications are fired for each script and they will be
|
||||
// added to the UI through that.
|
||||
if (!response.sources) {
|
||||
dumpn(
|
||||
"Error getting sources, probably because a top-level " +
|
||||
"breakpoint was hit while executing them"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore bogus scripts, e.g. generated from 'clientEvaluate' packets.
|
||||
return response.sources.filter(source => {
|
||||
return NEW_SOURCE_IGNORED_URLS.indexOf(source.url) === -1;
|
||||
});
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the black boxed status of the given source.
|
||||
*
|
||||
* @param Object aSource
|
||||
* The source form.
|
||||
* @param bool aBlackBoxFlag
|
||||
* True to black box the source, false to un-black box it.
|
||||
* @returns Promise
|
||||
* A promize that resolves to [aSource, isBlackBoxed] or rejects to
|
||||
* [aSource, error].
|
||||
*/
|
||||
function blackbox(source, shouldBlackBox) {
|
||||
const client = getSourceClient(source);
|
||||
|
||||
return {
|
||||
type: constants.BLACKBOX,
|
||||
source: source,
|
||||
[PROMISE]: Task.spawn(function* () {
|
||||
yield shouldBlackBox ? client.blackBox() : client.unblackBox();
|
||||
return {
|
||||
isBlackBoxed: shouldBlackBox
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the pretty printing of a source's text. All subsequent calls to
|
||||
* |getText| will return the pretty-toggled text. Nothing will happen for
|
||||
* non-javascript files.
|
||||
*
|
||||
* @param Object aSource
|
||||
* The source form from the RDP.
|
||||
* @returns Promise
|
||||
* A promise that resolves to [aSource, prettyText] or rejects to
|
||||
* [aSource, error].
|
||||
*/
|
||||
function togglePrettyPrint(source) {
|
||||
return (dispatch, getState) => {
|
||||
const sourceClient = getSourceClient(source);
|
||||
const wantPretty = !source.isPrettyPrinted;
|
||||
|
||||
return dispatch({
|
||||
type: constants.TOGGLE_PRETTY_PRINT,
|
||||
source: source,
|
||||
[PROMISE]: Task.spawn(function* () {
|
||||
let response;
|
||||
|
||||
// Only attempt to pretty print JavaScript sources.
|
||||
const sourceText = getSourceText(getState(), source.actor);
|
||||
const contentType = sourceText ? sourceText.contentType : null;
|
||||
if (!SourceUtils.isJavaScript(source.url, contentType)) {
|
||||
throw new Error("Can't prettify non-javascript files.");
|
||||
}
|
||||
|
||||
if (wantPretty) {
|
||||
response = yield sourceClient.prettyPrint(Prefs.editorTabSize);
|
||||
}
|
||||
else {
|
||||
response = yield sourceClient.disablePrettyPrint();
|
||||
}
|
||||
|
||||
// Remove the cached source AST from the Parser, to avoid getting
|
||||
// wrong locations when searching for functions.
|
||||
DebuggerController.Parser.clearSource(source.url);
|
||||
|
||||
return {
|
||||
isPrettyPrinted: wantPretty,
|
||||
text: response.source,
|
||||
contentType: response.contentType
|
||||
};
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function loadSourceText(source) {
|
||||
return (dispatch, getState) => {
|
||||
// Fetch the source text only once.
|
||||
let textInfo = getSourceText(getState(), source.actor);
|
||||
if (textInfo) {
|
||||
// It's already loaded or is loading
|
||||
return promise.resolve(textInfo);
|
||||
}
|
||||
|
||||
const sourceClient = getSourceClient(source);
|
||||
|
||||
return dispatch({
|
||||
type: constants.LOAD_SOURCE_TEXT,
|
||||
source: source,
|
||||
[PROMISE]: Task.spawn(function* () {
|
||||
let transportType = gClient.localTransport ? "_LOCAL" : "_REMOTE";
|
||||
let histogramId = "DEVTOOLS_DEBUGGER_DISPLAY_SOURCE" + transportType + "_MS";
|
||||
let histogram = Services.telemetry.getHistogramById(histogramId);
|
||||
let startTime = Date.now();
|
||||
|
||||
const response = yield sourceClient.source();
|
||||
|
||||
histogram.add(Date.now() - startTime);
|
||||
|
||||
// Automatically pretty print if enabled and the test is
|
||||
// detected to be "minified"
|
||||
if (Prefs.autoPrettyPrint &&
|
||||
!source.isPrettyPrinted &&
|
||||
SourceUtils.isMinified(source.actor, response.source)) {
|
||||
dispatch(togglePrettyPrint(source));
|
||||
}
|
||||
|
||||
return { text: response.source,
|
||||
contentType: response.contentType };
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts fetching all the sources, silently.
|
||||
*
|
||||
* @param array aUrls
|
||||
* The urls for the sources to fetch. If fetching a source's text
|
||||
* takes too long, it will be discarded.
|
||||
* @return object
|
||||
* A promise that is resolved after source texts have been fetched.
|
||||
*/
|
||||
function getTextForSources(actors) {
|
||||
return (dispatch, getState) => {
|
||||
let deferred = promise.defer();
|
||||
let pending = new Set(actors);
|
||||
let fetched = [];
|
||||
|
||||
// Can't use promise.all, because if one fetch operation is rejected, then
|
||||
// everything is considered rejected, thus no other subsequent source will
|
||||
// be getting fetched. We don't want that. Something like Q's allSettled
|
||||
// would work like a charm here.
|
||||
|
||||
// Try to fetch as many sources as possible.
|
||||
for (let actor of actors) {
|
||||
let source = getSource(getState(), actor);
|
||||
dispatch(loadSourceText(source)).then(({ text, contentType }) => {
|
||||
onFetch([source, text, contentType]);
|
||||
}, err => {
|
||||
onError(source, err);
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(onTimeout, FETCH_SOURCE_RESPONSE_DELAY);
|
||||
|
||||
/* Called if fetching a source takes too long. */
|
||||
function onTimeout() {
|
||||
pending = new Set();
|
||||
maybeFinish();
|
||||
}
|
||||
|
||||
/* Called if fetching a source finishes successfully. */
|
||||
function onFetch([aSource, aText, aContentType]) {
|
||||
// If fetching the source has previously timed out, discard it this time.
|
||||
if (!pending.has(aSource.actor)) {
|
||||
return;
|
||||
}
|
||||
pending.delete(aSource.actor);
|
||||
fetched.push([aSource.actor, aText, aContentType]);
|
||||
maybeFinish();
|
||||
}
|
||||
|
||||
/* Called if fetching a source failed because of an error. */
|
||||
function onError([aSource, aError]) {
|
||||
pending.delete(aSource.actor);
|
||||
maybeFinish();
|
||||
}
|
||||
|
||||
/* Called every time something interesting happens while fetching sources. */
|
||||
function maybeFinish() {
|
||||
if (pending.size == 0) {
|
||||
// Sort the fetched sources alphabetically by their url.
|
||||
deferred.resolve(fetched.sort(([aFirst], [aSecond]) => aFirst > aSecond));
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
newSource,
|
||||
selectSource,
|
||||
loadSources,
|
||||
blackbox,
|
||||
togglePrettyPrint,
|
||||
loadSourceText,
|
||||
getTextForSources
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue