зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1561435 - Format remaining devtools/, a=automatic-formatting, CLOSED TREE
# ignore-this-changeset Differential Revision: https://phabricator.services.mozilla.com/D35894 --HG-- extra : source : 4722b924e08478f5337ab509718bd66906bf472f extra : amend_source : a5baa1aab21639fdba44537e3a10b179b0073cb4
This commit is contained in:
Родитель
66e8f7440d
Коммит
b8157dfaaf
|
@ -39,12 +39,6 @@ testing/marionette/prefs/marionette.js
|
|||
toolkit/components/telemetry/datareporting-prefs.js
|
||||
toolkit/components/telemetry/healthreport-prefs.js
|
||||
|
||||
# Ignore all devtools directories for now, except the debugger.
|
||||
devtools/docs/**
|
||||
devtools/platform/**
|
||||
devtools/shared/**
|
||||
devtools/startup/**
|
||||
|
||||
# Ignore testing pref files which aren't parsed normally.
|
||||
testing/profiles/**/user.js
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
var gCount = 0;
|
||||
const MAX = 10;
|
||||
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
var inspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
|
||||
// Emulate 10 simultaneously-debugged windows from 3 separate client connections.
|
||||
var requestor = (count) => ({
|
||||
var requestor = count => ({
|
||||
url: "http://foo/bar/" + count,
|
||||
connection: "conn" + (count % 3),
|
||||
});
|
||||
|
@ -23,7 +23,7 @@ function run_test() {
|
|||
function test_nesting() {
|
||||
Assert.equal(inspector.eventLoopNestLevel, 0);
|
||||
|
||||
Services.tm.dispatchToMainThread({ run: enterEventLoop});
|
||||
Services.tm.dispatchToMainThread({ run: enterEventLoop });
|
||||
|
||||
Assert.equal(inspector.enterNestedEventLoop(requestor(gCount)), 0);
|
||||
Assert.equal(inspector.eventLoopNestLevel, 0);
|
||||
|
@ -32,28 +32,32 @@ function test_nesting() {
|
|||
|
||||
function enterEventLoop() {
|
||||
if (gCount++ < MAX) {
|
||||
Services.tm.dispatchToMainThread({ run: enterEventLoop});
|
||||
Services.tm.dispatchToMainThread({ run: enterEventLoop });
|
||||
|
||||
Object.create(requestor(gCount));
|
||||
|
||||
Assert.equal(inspector.eventLoopNestLevel, gCount);
|
||||
Assert.equal(inspector.lastNestRequestor.url, requestor(gCount - 1).url);
|
||||
Assert.equal(inspector.lastNestRequestor.connection,
|
||||
requestor(gCount - 1).connection);
|
||||
Assert.equal(
|
||||
inspector.lastNestRequestor.connection,
|
||||
requestor(gCount - 1).connection
|
||||
);
|
||||
Assert.equal(inspector.enterNestedEventLoop(requestor(gCount)), gCount);
|
||||
} else {
|
||||
Assert.equal(gCount, MAX + 1);
|
||||
Services.tm.dispatchToMainThread({ run: exitEventLoop});
|
||||
Services.tm.dispatchToMainThread({ run: exitEventLoop });
|
||||
}
|
||||
}
|
||||
|
||||
function exitEventLoop() {
|
||||
if (inspector.lastNestRequestor != null) {
|
||||
Assert.equal(inspector.lastNestRequestor.url, requestor(gCount - 1).url);
|
||||
Assert.equal(inspector.lastNestRequestor.connection,
|
||||
requestor(gCount - 1).connection);
|
||||
Assert.equal(
|
||||
inspector.lastNestRequestor.connection,
|
||||
requestor(gCount - 1).connection
|
||||
);
|
||||
if (gCount-- > 1) {
|
||||
Services.tm.dispatchToMainThread({ run: exitEventLoop});
|
||||
Services.tm.dispatchToMainThread({ run: exitEventLoop });
|
||||
}
|
||||
|
||||
Assert.equal(inspector.exitNestedEventLoop(), gCount);
|
||||
|
|
|
@ -11,10 +11,17 @@
|
|||
var { Ci, Cc, Cu, components } = require("chrome");
|
||||
var Services = require("Services");
|
||||
var flags = require("./flags");
|
||||
var {getStack, callFunctionWithAsyncStack} = require("devtools/shared/platform/stack");
|
||||
var {
|
||||
getStack,
|
||||
callFunctionWithAsyncStack,
|
||||
} = require("devtools/shared/platform/stack");
|
||||
|
||||
loader.lazyRequireGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm",
|
||||
true
|
||||
);
|
||||
|
||||
// Using this name lets the eslint plugin know about lazy defines in
|
||||
// this file.
|
||||
|
@ -37,7 +44,7 @@ for (const key of Object.keys(ThreadSafeDevToolsUtils)) {
|
|||
exports.isCPOW = function(debuggerObject) {
|
||||
try {
|
||||
return Cu.isCrossProcessWrapper(debuggerObject.unsafeDereference());
|
||||
} catch (e) { }
|
||||
} catch (e) {}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -310,8 +317,9 @@ exports.isSafeJSObject = function(obj) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Cu.getGlobalForObject(obj) ==
|
||||
Cu.getGlobalForObject(exports.isSafeJSObject)) {
|
||||
if (
|
||||
Cu.getGlobalForObject(obj) == Cu.getGlobalForObject(exports.isSafeJSObject)
|
||||
) {
|
||||
// obj is not a cross-compartment wrapper.
|
||||
return true;
|
||||
}
|
||||
|
@ -399,7 +407,7 @@ DevToolsUtils.defineLazyGetter(this, "AppConstants", () => {
|
|||
/**
|
||||
* No operation. The empty function.
|
||||
*/
|
||||
exports.noop = function() { };
|
||||
exports.noop = function() {};
|
||||
|
||||
let assertionFailureCount = 0;
|
||||
|
||||
|
@ -434,9 +442,10 @@ function reallyAssert(condition, message) {
|
|||
* If assertions are not enabled, then this function is a no-op.
|
||||
*/
|
||||
Object.defineProperty(exports, "assert", {
|
||||
get: () => (AppConstants.DEBUG_JS_MODULES || flags.testing)
|
||||
? reallyAssert
|
||||
: exports.noop,
|
||||
get: () =>
|
||||
AppConstants.DEBUG_JS_MODULES || flags.testing
|
||||
? reallyAssert
|
||||
: exports.noop,
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -503,13 +512,18 @@ DevToolsUtils.defineLazyGetter(this, "NetworkHelper", () => {
|
|||
* without relying on caching when we can (not for eval, etc.):
|
||||
* http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
|
||||
*/
|
||||
function mainThreadFetch(urlIn, aOptions = { loadFromCache: true,
|
||||
policy: Ci.nsIContentPolicy.TYPE_OTHER,
|
||||
window: null,
|
||||
charset: null,
|
||||
principal: null,
|
||||
cacheKey: 0 }) {
|
||||
return new Promise((resolve, reject) =>{
|
||||
function mainThreadFetch(
|
||||
urlIn,
|
||||
aOptions = {
|
||||
loadFromCache: true,
|
||||
policy: Ci.nsIContentPolicy.TYPE_OTHER,
|
||||
window: null,
|
||||
charset: null,
|
||||
principal: null,
|
||||
cacheKey: 0,
|
||||
}
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Create a channel.
|
||||
const url = urlIn.split(" -> ").pop();
|
||||
let channel;
|
||||
|
@ -527,16 +541,19 @@ function mainThreadFetch(urlIn, aOptions = { loadFromCache: true,
|
|||
|
||||
// When loading from cache, the cacheKey allows us to target a specific
|
||||
// SHEntry and offer ways to restore POST requests from cache.
|
||||
if (aOptions.loadFromCache &&
|
||||
aOptions.cacheKey != 0 && channel instanceof Ci.nsICacheInfoChannel) {
|
||||
if (
|
||||
aOptions.loadFromCache &&
|
||||
aOptions.cacheKey != 0 &&
|
||||
channel instanceof Ci.nsICacheInfoChannel
|
||||
) {
|
||||
channel.cacheKey = aOptions.cacheKey;
|
||||
}
|
||||
|
||||
if (aOptions.window) {
|
||||
// Respect private browsing.
|
||||
channel.loadGroup = aOptions.window.docShell
|
||||
.QueryInterface(Ci.nsIDocumentLoader)
|
||||
.loadGroup;
|
||||
channel.loadGroup = aOptions.window.docShell.QueryInterface(
|
||||
Ci.nsIDocumentLoader
|
||||
).loadGroup;
|
||||
}
|
||||
|
||||
const onResponse = (stream, status, request) => {
|
||||
|
@ -560,16 +577,26 @@ function mainThreadFetch(urlIn, aOptions = { loadFromCache: true,
|
|||
// implementation of the "decode" algorithm
|
||||
// (https://encoding.spec.whatwg.org/#decode) exposed to JS.
|
||||
let bomCharset = null;
|
||||
if (available >= 3 && source.codePointAt(0) == 0xef &&
|
||||
source.codePointAt(1) == 0xbb && source.codePointAt(2) == 0xbf) {
|
||||
if (
|
||||
available >= 3 &&
|
||||
source.codePointAt(0) == 0xef &&
|
||||
source.codePointAt(1) == 0xbb &&
|
||||
source.codePointAt(2) == 0xbf
|
||||
) {
|
||||
bomCharset = "UTF-8";
|
||||
source = source.slice(3);
|
||||
} else if (available >= 2 && source.codePointAt(0) == 0xfe &&
|
||||
source.codePointAt(1) == 0xff) {
|
||||
} else if (
|
||||
available >= 2 &&
|
||||
source.codePointAt(0) == 0xfe &&
|
||||
source.codePointAt(1) == 0xff
|
||||
) {
|
||||
bomCharset = "UTF-16BE";
|
||||
source = source.slice(2);
|
||||
} else if (available >= 2 && source.codePointAt(0) == 0xff &&
|
||||
source.codePointAt(1) == 0xfe) {
|
||||
} else if (
|
||||
available >= 2 &&
|
||||
source.codePointAt(0) == 0xff &&
|
||||
source.codePointAt(1) == 0xfe
|
||||
) {
|
||||
bomCharset = "UTF-16LE";
|
||||
source = source.slice(2);
|
||||
}
|
||||
|
@ -600,7 +627,10 @@ function mainThreadFetch(urlIn, aOptions = { loadFromCache: true,
|
|||
});
|
||||
} catch (ex) {
|
||||
const uri = request.originalURI;
|
||||
if (ex.name === "NS_BASE_STREAM_CLOSED" && uri instanceof Ci.nsIFileURL) {
|
||||
if (
|
||||
ex.name === "NS_BASE_STREAM_CLOSED" &&
|
||||
uri instanceof Ci.nsIFileURL
|
||||
) {
|
||||
// Empty files cause NS_BASE_STREAM_CLOSED exception. Use OS.File to
|
||||
// differentiate between empty files and other errors (bug 1170864).
|
||||
// This can be removed when bug 982654 is fixed.
|
||||
|
@ -642,7 +672,11 @@ function mainThreadFetch(urlIn, aOptions = { loadFromCache: true,
|
|||
* @param {Object} options - The options object passed to @method fetch.
|
||||
* @return {nsIChannel} - The newly created channel. Throws on failure.
|
||||
*/
|
||||
function newChannelForURL(url, { policy, window, principal }, recursing = false) {
|
||||
function newChannelForURL(
|
||||
url,
|
||||
{ policy, window, principal },
|
||||
recursing = false
|
||||
) {
|
||||
const securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
|
||||
let uri;
|
||||
|
@ -679,8 +713,7 @@ function newChannelForURL(url, { policy, window, principal }, recursing = false)
|
|||
// and it may not be correct.
|
||||
let prin = principal;
|
||||
if (!prin) {
|
||||
prin = Services.scriptSecurityManager
|
||||
.createCodebasePrincipal(uri, {});
|
||||
prin = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
|
||||
}
|
||||
|
||||
channelOptions.loadingPrincipal = prin;
|
||||
|
@ -698,8 +731,11 @@ function newChannelForURL(url, { policy, window, principal }, recursing = false)
|
|||
// can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
|
||||
// supported by Windows, so we also need to handle the exception here if
|
||||
// parsing the URL above doesn't throw.
|
||||
return newChannelForURL("file://" + url, { policy, window, principal },
|
||||
/* recursing */ true);
|
||||
return newChannelForURL(
|
||||
"file://" + url,
|
||||
{ policy, window, principal },
|
||||
/* recursing */ true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +784,7 @@ exports.openFileStream = function(filePath) {
|
|||
exports.saveFileStream = function(filePath, istream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const ostream = FileUtils.openSafeFileOutputStream(filePath);
|
||||
NetUtil.asyncCopy(istream, ostream, (status) => {
|
||||
NetUtil.asyncCopy(istream, ostream, status => {
|
||||
if (!components.isSuccessCode(status)) {
|
||||
reject(new Error(`Could not save "${filePath}"`));
|
||||
return;
|
||||
|
@ -782,7 +818,7 @@ exports.showSaveFileDialog = function(parentWindow, suggestedFilename) {
|
|||
fp.appendFilters(fp.filterAll);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fp.open((result) => {
|
||||
fp.open(result => {
|
||||
if (result == Ci.nsIFilePicker.returnCancel) {
|
||||
reject();
|
||||
} else {
|
||||
|
@ -800,14 +836,16 @@ exports.showSaveFileDialog = function(parentWindow, suggestedFilename) {
|
|||
function errorOnFlag(exports, name) {
|
||||
Object.defineProperty(exports, name, {
|
||||
get: () => {
|
||||
const msg = `Cannot get the flag ${name}. ` +
|
||||
`Use the "devtools/shared/flags" module instead`;
|
||||
const msg =
|
||||
`Cannot get the flag ${name}. ` +
|
||||
`Use the "devtools/shared/flags" module instead`;
|
||||
console.error(msg);
|
||||
throw new Error(msg);
|
||||
},
|
||||
set: () => {
|
||||
const msg = `Cannot set the flag ${name}. ` +
|
||||
`Use the "devtools/shared/flags" module instead`;
|
||||
const msg =
|
||||
`Cannot set the flag ${name}. ` +
|
||||
`Use the "devtools/shared/flags" module instead`;
|
||||
console.error(msg);
|
||||
throw new Error(msg);
|
||||
},
|
||||
|
|
|
@ -9,14 +9,22 @@
|
|||
*/
|
||||
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
var { Loader, Require, resolveURI, unload } =
|
||||
ChromeUtils.import("resource://devtools/shared/base-loader.js");
|
||||
var { requireRawId } = ChromeUtils.import("resource://devtools/shared/loader-plugin-raw.jsm");
|
||||
var { Loader, Require, resolveURI, unload } = ChromeUtils.import(
|
||||
"resource://devtools/shared/base-loader.js"
|
||||
);
|
||||
var { requireRawId } = ChromeUtils.import(
|
||||
"resource://devtools/shared/loader-plugin-raw.jsm"
|
||||
);
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DevToolsLoader", "devtools", "BuiltinProvider",
|
||||
"require", "loader",
|
||||
// Export StructuredCloneHolder for its use from builtin-modules
|
||||
"StructuredCloneHolder"];
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"DevToolsLoader",
|
||||
"devtools",
|
||||
"BuiltinProvider",
|
||||
"require",
|
||||
"loader",
|
||||
// Export StructuredCloneHolder for its use from builtin-modules
|
||||
"StructuredCloneHolder",
|
||||
];
|
||||
|
||||
/**
|
||||
* Providers are different strategies for loading the devtools.
|
||||
|
@ -31,9 +39,9 @@ BuiltinProvider.prototype = {
|
|||
load: function() {
|
||||
const paths = {
|
||||
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
|
||||
"devtools": "resource://devtools",
|
||||
devtools: "resource://devtools",
|
||||
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
|
||||
"acorn": "resource://devtools/shared/acorn",
|
||||
acorn: "resource://devtools/shared/acorn",
|
||||
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
|
||||
"acorn/util/walk": "resource://devtools/shared/acorn/walk.js",
|
||||
// ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
|
||||
|
@ -171,7 +179,9 @@ DevToolsLoader.prototype = {
|
|||
this.require = Require(this._provider.loader, { id: "devtools" });
|
||||
|
||||
// Fetch custom pseudo modules and globals
|
||||
const { modules, globals } = this.require("devtools/shared/builtin-modules");
|
||||
const { modules, globals } = this.require(
|
||||
"devtools/shared/builtin-modules"
|
||||
);
|
||||
|
||||
// When creating a Loader for the browser toolbox, we have to use
|
||||
// Promise-backend.js, as a Loader module. Instead of Promise.jsm which
|
||||
|
@ -193,7 +203,10 @@ DevToolsLoader.prototype = {
|
|||
|
||||
// Register custom globals to the current loader instance
|
||||
globals.loader.id = this.id;
|
||||
Object.defineProperties(loader.globals, Object.getOwnPropertyDescriptors(globals));
|
||||
Object.defineProperties(
|
||||
loader.globals,
|
||||
Object.getOwnPropertyDescriptors(globals)
|
||||
);
|
||||
|
||||
// Expose lazy helpers on loader
|
||||
this.lazyGetter = globals.loader.lazyGetter;
|
||||
|
@ -206,8 +219,12 @@ DevToolsLoader.prototype = {
|
|||
// created for objects in the recording/replaying process.
|
||||
if (globals.isReplaying) {
|
||||
const oldHook = this._provider.loader.requireHook;
|
||||
const ReplayInspector = this.require("devtools/server/actors/replay/inspector");
|
||||
this._provider.loader.requireHook = ReplayInspector.wrapRequireHook(oldHook);
|
||||
const ReplayInspector = this.require(
|
||||
"devtools/server/actors/replay/inspector"
|
||||
);
|
||||
this._provider.loader.requireHook = ReplayInspector.wrapRequireHook(
|
||||
oldHook
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -9,8 +9,11 @@ const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
|||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
ChromeUtils.defineModuleGetter(this,
|
||||
"Reflect", "resource://gre/modules/reflect.jsm");
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"Reflect",
|
||||
"resource://gre/modules/reflect.jsm"
|
||||
);
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Parser", "ParserHelpers", "SyntaxTreeVisitor"];
|
||||
|
||||
|
@ -141,8 +144,13 @@ SyntaxTreesPool.prototype = {
|
|||
* @see SyntaxTree.prototype.getIdentifierAt
|
||||
*/
|
||||
getIdentifierAt({ line, column, scriptIndex, ignoreLiterals }) {
|
||||
return this._call("getIdentifierAt",
|
||||
scriptIndex, line, column, ignoreLiterals)[0];
|
||||
return this._call(
|
||||
"getIdentifierAt",
|
||||
scriptIndex,
|
||||
line,
|
||||
column,
|
||||
ignoreLiterals
|
||||
)[0];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -232,7 +240,9 @@ SyntaxTreesPool.prototype = {
|
|||
// Language features may be added, in which case the recursive methods
|
||||
// need to be updated. If an exception is thrown here, file a bug.
|
||||
DevToolsUtils.reportException(
|
||||
`Syntax tree visitor for ${this._url}`, e);
|
||||
`Syntax tree visitor for ${this._url}`,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
this._cache.set(requestId, results);
|
||||
|
@ -442,8 +452,10 @@ var ParserHelpers = {
|
|||
const { loc: parentLocation, type: parentType } = node._parent;
|
||||
const { loc: nodeLocation } = node;
|
||||
if (!nodeLocation) {
|
||||
if (parentType == "FunctionDeclaration" ||
|
||||
parentType == "FunctionExpression") {
|
||||
if (
|
||||
parentType == "FunctionDeclaration" ||
|
||||
parentType == "FunctionExpression"
|
||||
) {
|
||||
// e.g. "function foo() {}" or "{ bar: function foo() {} }"
|
||||
// The location is unavailable for the identifier node "foo".
|
||||
const loc = Cu.cloneInto(parentLocation, {});
|
||||
|
@ -516,8 +528,12 @@ var ParserHelpers = {
|
|||
*/
|
||||
nodeContainsPoint(node, line, column) {
|
||||
const { start: s, end: e } = this.getNodeLocation(node);
|
||||
return s.line == line && e.line == line &&
|
||||
s.column <= column && e.column >= column;
|
||||
return (
|
||||
s.line == line &&
|
||||
e.line == line &&
|
||||
s.column <= column &&
|
||||
e.column >= column
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -708,8 +724,9 @@ var ParserHelpers = {
|
|||
// directly as an evaluation string. Otherwise, construct the property
|
||||
// access chain, since the value might have changed.
|
||||
if (!this._getObjectExpressionPropertyKeyForValue(node)) {
|
||||
const propertyChain =
|
||||
this._getObjectExpressionPropertyChain(node._parent);
|
||||
const propertyChain = this._getObjectExpressionPropertyChain(
|
||||
node._parent
|
||||
);
|
||||
const propertyLeaf = node.name;
|
||||
return [...propertyChain, propertyLeaf].join(".");
|
||||
}
|
||||
|
|
|
@ -81,7 +81,9 @@ exports.isCPOW = function() {
|
|||
* Report that |who| threw an exception, |exception|.
|
||||
*/
|
||||
exports.reportException = function reportException(who, exception) {
|
||||
const msg = `${who} threw an exception: ${exports.safeErrorString(exception)}`;
|
||||
const msg = `${who} threw an exception: ${exports.safeErrorString(
|
||||
exception
|
||||
)}`;
|
||||
dump(msg + "\n");
|
||||
|
||||
if (typeof console !== "undefined" && console && console.error) {
|
||||
|
@ -142,8 +144,12 @@ exports.safeErrorString = function(error) {
|
|||
|
||||
// Append additional line and column number information to the output,
|
||||
// since it might not be part of the stringified error.
|
||||
if (typeof error.lineNumber == "number" && typeof error.columnNumber == "number") {
|
||||
errorString += "Line: " + error.lineNumber + ", column: " + error.columnNumber;
|
||||
if (
|
||||
typeof error.lineNumber == "number" &&
|
||||
typeof error.columnNumber == "number"
|
||||
) {
|
||||
errorString +=
|
||||
"Line: " + error.lineNumber + ", column: " + error.columnNumber;
|
||||
}
|
||||
|
||||
return errorString;
|
||||
|
@ -174,9 +180,11 @@ exports.zip = function(a, b) {
|
|||
return b;
|
||||
}
|
||||
const pairs = [];
|
||||
for (let i = 0, aLength = a.length, bLength = b.length;
|
||||
i < aLength || i < bLength;
|
||||
i++) {
|
||||
for (
|
||||
let i = 0, aLength = a.length, bLength = b.length;
|
||||
i < aLength || i < bLength;
|
||||
i++
|
||||
) {
|
||||
pairs.push([a[i], b[i]]);
|
||||
}
|
||||
return pairs;
|
||||
|
@ -219,8 +227,7 @@ exports.compose = function compose(...funcs) {
|
|||
return (...args) => {
|
||||
const initialValue = funcs[funcs.length - 1](...args);
|
||||
const leftFuncs = funcs.slice(0, -1);
|
||||
return leftFuncs.reduceRight((composed, f) => f(composed),
|
||||
initialValue);
|
||||
return leftFuncs.reduceRight((composed, f) => f(composed), initialValue);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -311,7 +318,7 @@ exports.flatten = function(lists) {
|
|||
* promise in the list of given promises to be rejected.
|
||||
*/
|
||||
exports.settleAll = values => {
|
||||
if (values === null || typeof (values[Symbol.iterator]) != "function") {
|
||||
if (values === null || typeof values[Symbol.iterator] != "function") {
|
||||
throw new Error("settleAll() expects an iterable.");
|
||||
}
|
||||
|
||||
|
@ -353,7 +360,7 @@ exports.settleAll = values => {
|
|||
checkForCompletion();
|
||||
};
|
||||
|
||||
if (value && typeof (value.then) == "function") {
|
||||
if (value && typeof value.then == "function") {
|
||||
value.then(resolver, rejecter);
|
||||
} else {
|
||||
// Given value is not a promise, forward it as a resolution value.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {AddonManager} = require("resource://gre/modules/AddonManager.jsm");
|
||||
const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
|
||||
const Services = require("Services");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
|
@ -44,10 +44,8 @@ class ADBAddon extends EventEmitter {
|
|||
this._status = ADB_ADDON_STATES.UNKNOWN;
|
||||
|
||||
const addonsListener = {};
|
||||
addonsListener.onEnabled =
|
||||
addonsListener.onDisabled =
|
||||
addonsListener.onInstalled =
|
||||
addonsListener.onUninstalled = () => this.updateInstallStatus();
|
||||
addonsListener.onEnabled = addonsListener.onDisabled = addonsListener.onInstalled = addonsListener.onUninstalled = () =>
|
||||
this.updateInstallStatus();
|
||||
AddonManager.addAddonListener(addonsListener);
|
||||
|
||||
this.updateInstallStatus();
|
||||
|
@ -109,7 +107,9 @@ class ADBAddon extends EventEmitter {
|
|||
*/
|
||||
async install(source) {
|
||||
if (!source) {
|
||||
throw new Error("Missing mandatory `source` parameter for adb-addon.install");
|
||||
throw new Error(
|
||||
"Missing mandatory `source` parameter for adb-addon.install"
|
||||
);
|
||||
}
|
||||
|
||||
const addon = await this._getAddon();
|
||||
|
@ -121,10 +121,9 @@ class ADBAddon extends EventEmitter {
|
|||
if (addon && addon.userDisabled) {
|
||||
await addon.enable();
|
||||
} else {
|
||||
const install = await AddonManager.getInstallForURL(
|
||||
this._getXpiLink(),
|
||||
{telemetryInfo: {source}}
|
||||
);
|
||||
const install = await AddonManager.getInstallForURL(this._getXpiLink(), {
|
||||
telemetryInfo: { source },
|
||||
});
|
||||
install.addListener(this);
|
||||
install.install();
|
||||
}
|
||||
|
@ -199,7 +198,7 @@ class ADBAddon extends EventEmitter {
|
|||
}
|
||||
|
||||
// Expected AddonManager install listener.
|
||||
onInstallEnded({addon}) {
|
||||
onInstallEnded({ addon }) {
|
||||
addon.enable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,24 @@
|
|||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||
loader.lazyImporter(this, "ExtensionParent", "resource://gre/modules/ExtensionParent.jsm");
|
||||
loader.lazyImporter(
|
||||
this,
|
||||
"ExtensionParent",
|
||||
"resource://gre/modules/ExtensionParent.jsm"
|
||||
);
|
||||
loader.lazyRequireGetter(this, "Services");
|
||||
loader.lazyRequireGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm",
|
||||
true
|
||||
);
|
||||
loader.lazyGetter(this, "UNPACKED_ROOT_PATH", () => {
|
||||
return OS.Path.join(OS.Constants.Path.localProfileDir, "adb");
|
||||
});
|
||||
|
@ -35,18 +47,24 @@ const MANIFEST = "manifest.json";
|
|||
*/
|
||||
async function readFromExtension(fileUri) {
|
||||
return new Promise(resolve => {
|
||||
NetUtil.asyncFetch({
|
||||
uri: fileUri,
|
||||
loadUsingSystemPrincipal: true,
|
||||
}, (input) => {
|
||||
try {
|
||||
const string = NetUtil.readInputStreamToString(input, input.available());
|
||||
resolve(JSON.parse(string));
|
||||
} catch (e) {
|
||||
dumpn(`Could not read ${fileUri} in the extension: ${e}`);
|
||||
resolve(null);
|
||||
NetUtil.asyncFetch(
|
||||
{
|
||||
uri: fileUri,
|
||||
loadUsingSystemPrincipal: true,
|
||||
},
|
||||
input => {
|
||||
try {
|
||||
const string = NetUtil.readInputStreamToString(
|
||||
input,
|
||||
input.available()
|
||||
);
|
||||
resolve(JSON.parse(string));
|
||||
} catch (e) {
|
||||
dumpn(`Could not read ${fileUri} in the extension: ${e}`);
|
||||
resolve(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -67,21 +85,24 @@ async function unpackFile(file) {
|
|||
const basePath = file.substring(file.lastIndexOf("/") + 1);
|
||||
const filePath = OS.Path.join(UNPACKED_ROOT_PATH, basePath);
|
||||
await new Promise((resolve, reject) => {
|
||||
NetUtil.asyncFetch({
|
||||
uri: policy.getURL(file),
|
||||
loadUsingSystemPrincipal: true,
|
||||
}, (input) => {
|
||||
try {
|
||||
// Since we have to use NetUtil to read, probably it's okay to use for
|
||||
// writing, rather than bouncing to OS.File...?
|
||||
const outputFile = new FileUtils.File(filePath);
|
||||
const output = FileUtils.openAtomicFileOutputStream(outputFile);
|
||||
NetUtil.asyncCopy(input, output, resolve);
|
||||
} catch (e) {
|
||||
dumpn(`Could not unpack file ${file} in the extension: ${e}`);
|
||||
reject(e);
|
||||
NetUtil.asyncFetch(
|
||||
{
|
||||
uri: policy.getURL(file),
|
||||
loadUsingSystemPrincipal: true,
|
||||
},
|
||||
input => {
|
||||
try {
|
||||
// Since we have to use NetUtil to read, probably it's okay to use for
|
||||
// writing, rather than bouncing to OS.File...?
|
||||
const outputFile = new FileUtils.File(filePath);
|
||||
const output = FileUtils.openAtomicFileOutputStream(outputFile);
|
||||
NetUtil.asyncCopy(input, output, resolve);
|
||||
} catch (e) {
|
||||
dumpn(`Could not unpack file ${file} in the extension: ${e}`);
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
});
|
||||
// Mark binaries as executable.
|
||||
await OS.File.setPermissions(filePath, { unixMode: 0o744 });
|
||||
|
@ -172,7 +193,7 @@ async function isManifestUnpacked() {
|
|||
* Uses OS.File since this is a local file.
|
||||
*/
|
||||
async function getManifestFromUnpacked() {
|
||||
if (!await isManifestUnpacked()) {
|
||||
if (!(await isManifestUnpacked())) {
|
||||
throw new Error("Manifest doesn't exist at unpacked path");
|
||||
}
|
||||
|
||||
|
@ -182,8 +203,7 @@ async function getManifestFromUnpacked() {
|
|||
let data;
|
||||
try {
|
||||
data = JSON.parse(json);
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -191,7 +211,7 @@ async function getManifestFromUnpacked() {
|
|||
* Check state of binary unpacking, including the location and manifest.
|
||||
*/
|
||||
async function isUnpacked() {
|
||||
if (!await isManifestUnpacked()) {
|
||||
if (!(await isManifestUnpacked())) {
|
||||
dumpn("Needs unpacking, no manifest found");
|
||||
return false;
|
||||
}
|
||||
|
@ -201,7 +221,7 @@ async function isUnpacked() {
|
|||
if (manifestInExtension.version != unpackedManifest.version) {
|
||||
dumpn(
|
||||
`Needs unpacking, extension version ${manifestInExtension.version} != ` +
|
||||
`unpacked version ${unpackedManifest.version}`
|
||||
`unpacked version ${unpackedManifest.version}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
@ -217,8 +237,7 @@ async function isUnpacked() {
|
|||
* File object for the binary.
|
||||
*/
|
||||
async function getFileForBinary() {
|
||||
if (!await isUnpacked() &&
|
||||
!await extractFiles()) {
|
||||
if (!(await isUnpacked()) && !(await extractFiles())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,9 @@ class AdbDevice {
|
|||
|
||||
// Filter to lines with "firefox-debugger-socket"
|
||||
let socketInfos = rawSocketInfo.split(/\r?\n/);
|
||||
socketInfos = socketInfos.filter(l => l.includes("firefox-debugger-socket"));
|
||||
socketInfos = socketInfos.filter(l =>
|
||||
l.includes("firefox-debugger-socket")
|
||||
);
|
||||
|
||||
// It's possible to have multiple lines with the same path, so de-dupe them
|
||||
const socketPaths = new Set();
|
||||
|
|
|
@ -10,8 +10,18 @@ const EventEmitter = require("devtools/shared/event-emitter");
|
|||
const { getFileForBinary } = require("./adb-binary");
|
||||
const { setTimeout } = require("resource://gre/modules/Timer.jsm");
|
||||
|
||||
loader.lazyRequireGetter(this, "runCommand", "devtools/shared/adb/commands/index", true);
|
||||
loader.lazyRequireGetter(this, "check", "devtools/shared/adb/adb-running-checker", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"runCommand",
|
||||
"devtools/shared/adb/commands/index",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"check",
|
||||
"devtools/shared/adb/adb-running-checker",
|
||||
true
|
||||
);
|
||||
|
||||
// Waits until a predicate returns true or re-tries the predicate calls
|
||||
// |retry| times, we wait for 100ms between each calls.
|
||||
|
@ -51,18 +61,23 @@ class AdbProcess extends EventEmitter {
|
|||
|
||||
async _runProcess(process, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
process.runAsync(params, params.length, {
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "process-finished":
|
||||
resolve();
|
||||
break;
|
||||
case "process-failed":
|
||||
reject();
|
||||
break;
|
||||
}
|
||||
process.runAsync(
|
||||
params,
|
||||
params.length,
|
||||
{
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "process-finished":
|
||||
resolve();
|
||||
break;
|
||||
case "process-failed":
|
||||
reject();
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
}, false);
|
||||
false
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -85,7 +100,9 @@ class AdbProcess extends EventEmitter {
|
|||
dumpn("Didn't find ADB process running, restarting");
|
||||
|
||||
this._didRunInitially = true;
|
||||
const process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
|
||||
const process = Cc["@mozilla.org/process/util;1"].createInstance(
|
||||
Ci.nsIProcess
|
||||
);
|
||||
|
||||
// FIXME: Bug 1481691 - We should avoid extracting files every time.
|
||||
const adbFile = await this._getAdbFile();
|
||||
|
@ -98,8 +115,7 @@ class AdbProcess extends EventEmitter {
|
|||
try {
|
||||
await this._runProcess(process, params);
|
||||
isStarted = await waitUntil(check);
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (isStarted) {
|
||||
onSuccessfulStart();
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { RuntimeTypes } = require("devtools/client/webide/modules/runtime-types");
|
||||
const {
|
||||
RuntimeTypes,
|
||||
} = require("devtools/client/webide/modules/runtime-types");
|
||||
const { prepareTCPConnection } = require("devtools/shared/adb/commands/index");
|
||||
const { shell } = require("devtools/shared/adb/commands/index");
|
||||
|
||||
|
@ -94,9 +96,9 @@ class AdbRuntime {
|
|||
// If using path base socket, it is "/data/data/<package>...""
|
||||
// Until Fennec 62 only supports path based UNIX domain socket, but
|
||||
// Fennec 63+ supports both path based and abstract socket.
|
||||
return this._socketPath.startsWith("@") ?
|
||||
this._socketPath.substr(1).split("/")[0] :
|
||||
this._socketPath.split("/")[3];
|
||||
return this._socketPath.startsWith("@")
|
||||
? this._socketPath.substr(1).split("/")[0]
|
||||
: this._socketPath.split("/")[3];
|
||||
}
|
||||
}
|
||||
exports.AdbRuntime = AdbRuntime;
|
||||
|
|
|
@ -8,8 +8,9 @@ const { Cu } = require("chrome");
|
|||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
function createTCPSocket(location, port, options) {
|
||||
const { TCPSocket } =
|
||||
Cu.getGlobalForObject(Cu.import("resource://gre/modules/Services.jsm", {}));
|
||||
const { TCPSocket } = Cu.getGlobalForObject(
|
||||
Cu.import("resource://gre/modules/Services.jsm", {})
|
||||
);
|
||||
|
||||
return new TCPSocket(location, port, options);
|
||||
}
|
||||
|
@ -63,8 +64,7 @@ class AdbSocket {
|
|||
}
|
||||
|
||||
close() {
|
||||
if (this.s.readyState === "open" ||
|
||||
this.s.readyState === "connecting") {
|
||||
if (this.s.readyState === "open" || this.s.readyState === "connecting") {
|
||||
this.s.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,25 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { clearInterval, setInterval } = require("resource://gre/modules/Timer.jsm");
|
||||
const {
|
||||
clearInterval,
|
||||
setInterval,
|
||||
} = require("resource://gre/modules/Timer.jsm");
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { adbProcess } = require("devtools/shared/adb/adb-process");
|
||||
const { adbAddon } = require("devtools/shared/adb/adb-addon");
|
||||
const AdbDevice = require("devtools/shared/adb/adb-device");
|
||||
const { AdbRuntime } = require("devtools/shared/adb/adb-runtime");
|
||||
const { TrackDevicesCommand } = require("devtools/shared/adb/commands/track-devices");
|
||||
loader.lazyRequireGetter(this, "check", "devtools/shared/adb/adb-running-checker", true);
|
||||
const {
|
||||
TrackDevicesCommand,
|
||||
} = require("devtools/shared/adb/commands/track-devices");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"check",
|
||||
"devtools/shared/adb/adb-running-checker",
|
||||
true
|
||||
);
|
||||
|
||||
// Duration in milliseconds of the runtime polling. We resort to polling here because we
|
||||
// have no event to know when a runtime started on an already discovered ADB device.
|
||||
|
@ -37,8 +47,14 @@ class Adb extends EventEmitter {
|
|||
this._onNoDevicesDetected = this._onNoDevicesDetected.bind(this);
|
||||
|
||||
this._trackDevicesCommand.on("device-connected", this._onDeviceConnected);
|
||||
this._trackDevicesCommand.on("device-disconnected", this._onDeviceDisconnected);
|
||||
this._trackDevicesCommand.on("no-devices-detected", this._onNoDevicesDetected);
|
||||
this._trackDevicesCommand.on(
|
||||
"device-disconnected",
|
||||
this._onDeviceDisconnected
|
||||
);
|
||||
this._trackDevicesCommand.on(
|
||||
"no-devices-detected",
|
||||
this._onNoDevicesDetected
|
||||
);
|
||||
adbAddon.on("update", this._updateAdbProcess);
|
||||
}
|
||||
|
||||
|
@ -87,7 +103,10 @@ class Adb extends EventEmitter {
|
|||
|
||||
// Device runtimes are detected by running a shell command and checking for
|
||||
// "firefox-debugger-socket" in the list of currently running processes.
|
||||
this._timer = setInterval(this.updateRuntimes.bind(this), UPDATE_RUNTIMES_INTERVAL);
|
||||
this._timer = setInterval(
|
||||
this.updateRuntimes.bind(this),
|
||||
UPDATE_RUNTIMES_INTERVAL
|
||||
);
|
||||
}
|
||||
|
||||
async _stopTracking() {
|
||||
|
@ -138,7 +157,7 @@ class Adb extends EventEmitter {
|
|||
}
|
||||
|
||||
async _getDeviceRuntimes(device) {
|
||||
const socketPaths = [...await device.getRuntimeSocketPaths()];
|
||||
const socketPaths = [...(await device.getRuntimeSocketPaths())];
|
||||
const runtimes = [];
|
||||
for (const socketPath of socketPaths) {
|
||||
const runtime = new AdbRuntime(device, socketPath);
|
||||
|
|
|
@ -13,19 +13,17 @@ const { dumpn } = require("devtools/shared/DevToolsUtils");
|
|||
const listDevices = function() {
|
||||
dumpn("listDevices");
|
||||
|
||||
return this.runCommand("host:devices").then(
|
||||
function onSuccess(data) {
|
||||
const lines = data.split("\n");
|
||||
const res = [];
|
||||
lines.forEach(function(line) {
|
||||
if (line.length == 0) {
|
||||
return;
|
||||
}
|
||||
const [ device ] = line.split("\t");
|
||||
res.push(device);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
);
|
||||
return this.runCommand("host:devices").then(function onSuccess(data) {
|
||||
const lines = data.split("\n");
|
||||
const res = [];
|
||||
lines.forEach(function(line) {
|
||||
if (line.length == 0) {
|
||||
return;
|
||||
}
|
||||
const [device] = line.split("\t");
|
||||
res.push(device);
|
||||
});
|
||||
return res;
|
||||
});
|
||||
};
|
||||
exports.listDevices = listDevices;
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
"use strict";
|
||||
|
||||
const { dumpn } = require("devtools/shared/DevToolsUtils");
|
||||
const { ConnectionManager } = require("devtools/shared/client/connection-manager");
|
||||
const {
|
||||
ConnectionManager,
|
||||
} = require("devtools/shared/client/connection-manager");
|
||||
const { runCommand } = require("./run-command");
|
||||
|
||||
// sends adb forward deviceId, localPort and devicePort
|
||||
|
@ -14,20 +16,21 @@ const forwardPort = function(deviceId, localPort, devicePort) {
|
|||
// Send "host-serial:<serial-number>:<request>",
|
||||
// with <request> set to "forward:<local>;<remote>"
|
||||
// See https://android.googlesource.com/platform/system/core/+/jb-dev/adb/SERVICES.TXT
|
||||
return runCommand(`host-serial:${ deviceId }:forward:${ localPort };${ devicePort }`)
|
||||
.then(function onSuccess(data) {
|
||||
return data;
|
||||
});
|
||||
return runCommand(
|
||||
`host-serial:${deviceId}:forward:${localPort};${devicePort}`
|
||||
).then(function onSuccess(data) {
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
// Prepare TCP connection for provided device id and socket path.
|
||||
// The returned value is a port number of localhost for the connection.
|
||||
const prepareTCPConnection = async function(deviceId, socketPath) {
|
||||
const port = ConnectionManager.getFreeTCPPort();
|
||||
const local = `tcp:${ port }`;
|
||||
const local = `tcp:${port}`;
|
||||
const remote = socketPath.startsWith("@")
|
||||
? `localabstract:${ socketPath.substring(1) }`
|
||||
: `localfilesystem:${ socketPath }`;
|
||||
? `localabstract:${socketPath.substring(1)}`
|
||||
: `localfilesystem:${socketPath}`;
|
||||
await forwardPort(deviceId, local, remote);
|
||||
return port;
|
||||
};
|
||||
|
|
|
@ -65,11 +65,13 @@ const shell = async function(deviceId, command) {
|
|||
break;
|
||||
}
|
||||
ignoreResponseCode = true;
|
||||
// eslint-disable-next-lined no-fallthrough
|
||||
// eslint-disable-next-lined no-fallthrough
|
||||
case "decode-shell":
|
||||
const decoder = new TextDecoder();
|
||||
const text = new Uint8Array(client.getBuffer(data),
|
||||
ignoreResponseCode ? 4 : 0);
|
||||
const text = new Uint8Array(
|
||||
client.getBuffer(data),
|
||||
ignoreResponseCode ? 4 : 0
|
||||
);
|
||||
stdout += decoder.decode(text);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -110,7 +110,10 @@ class TrackDevicesCommand extends EventEmitter {
|
|||
});
|
||||
|
||||
// Fire events if needed.
|
||||
const deviceIds = new Set([...this._devices.keys(), ...newDevices.keys()]);
|
||||
const deviceIds = new Set([
|
||||
...this._devices.keys(),
|
||||
...newDevices.keys(),
|
||||
]);
|
||||
for (const deviceId of deviceIds) {
|
||||
const currentStatus = this._devices.get(deviceId);
|
||||
const newStatus = newDevices.get(deviceId);
|
||||
|
@ -137,7 +140,9 @@ class TrackDevicesCommand extends EventEmitter {
|
|||
}
|
||||
|
||||
_fireConnectionEventIfNeeded(deviceId, currentStatus, newStatus) {
|
||||
const isCurrentOnline = !!(currentStatus && currentStatus !== ADB_STATUS_OFFLINE);
|
||||
const isCurrentOnline = !!(
|
||||
currentStatus && currentStatus !== ADB_STATUS_OFFLINE
|
||||
);
|
||||
const isNewOnline = !!(newStatus && newStatus !== ADB_STATUS_OFFLINE);
|
||||
|
||||
if (isCurrentOnline === isNewOnline) {
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ExtensionTestUtils } = ChromeUtils.import("resource://testing-common/ExtensionXPCShellUtils.jsm");
|
||||
const { ExtensionTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/ExtensionXPCShellUtils.jsm"
|
||||
);
|
||||
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
|
||||
const { getFileForBinary } = require("devtools/shared/adb/adb-binary");
|
||||
const { check } = require("devtools/shared/adb/adb-running-checker");
|
||||
|
@ -11,30 +13,16 @@ const { adbProcess } = require("devtools/shared/adb/adb-process");
|
|||
const { TrackDevicesCommand } = require("devtools/shared/adb/commands/index");
|
||||
|
||||
const ADB_JSON = {
|
||||
"Linux": {
|
||||
"x86": [
|
||||
"linux/adb",
|
||||
],
|
||||
"x86_64": [
|
||||
"linux64/adb",
|
||||
],
|
||||
Linux: {
|
||||
x86: ["linux/adb"],
|
||||
x86_64: ["linux64/adb"],
|
||||
},
|
||||
"Darwin": {
|
||||
"x86_64": [
|
||||
"mac64/adb",
|
||||
],
|
||||
Darwin: {
|
||||
x86_64: ["mac64/adb"],
|
||||
},
|
||||
"WINNT": {
|
||||
"x86": [
|
||||
"win32/adb.exe",
|
||||
"win32/AdbWinApi.dll",
|
||||
"win32/AdbWinUsbApi.dll",
|
||||
],
|
||||
"x86_64": [
|
||||
"win32/adb.exe",
|
||||
"win32/AdbWinApi.dll",
|
||||
"win32/AdbWinUsbApi.dll",
|
||||
],
|
||||
WINNT: {
|
||||
x86: ["win32/adb.exe", "win32/AdbWinApi.dll", "win32/AdbWinUsbApi.dll"],
|
||||
x86_64: ["win32/adb.exe", "win32/AdbWinApi.dll", "win32/AdbWinUsbApi.dll"],
|
||||
},
|
||||
};
|
||||
let extension_version = 1.0;
|
||||
|
@ -43,8 +31,9 @@ ExtensionTestUtils.init(this);
|
|||
|
||||
function readAdbMockContent() {
|
||||
const adbMockFile = do_get_file("adb.py", false);
|
||||
const s = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
const s = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
|
||||
Ci.nsIFileInputStream
|
||||
);
|
||||
s.init(adbMockFile, -1, -1, false);
|
||||
try {
|
||||
return NetUtil.readInputStreamToString(s, s.available());
|
||||
|
@ -152,92 +141,97 @@ add_task(async function testExtract() {
|
|||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task({
|
||||
skip_if: () => mozinfo.os == "win", // bug 1482008
|
||||
}, async function testStartAndStop() {
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: (extension_version++).toString(),
|
||||
applications: {
|
||||
gecko: { id: "adb@mozilla.org" },
|
||||
add_task(
|
||||
{
|
||||
skip_if: () => mozinfo.os == "win", // bug 1482008
|
||||
},
|
||||
async function testStartAndStop() {
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: (extension_version++).toString(),
|
||||
applications: {
|
||||
gecko: { id: "adb@mozilla.org" },
|
||||
},
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"adb.json": JSON.stringify(ADB_JSON),
|
||||
"linux/adb": adbMock,
|
||||
"linux64/adb": adbMock,
|
||||
"mac64/adb": adbMock,
|
||||
"win32/adb.exe": adbMock,
|
||||
"win32/AdbWinApi.dll": "dummy",
|
||||
"win32/AdbWinUsbApi.dll": "dummy",
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
// Call start() once and call stop() afterwards.
|
||||
await adbProcess.start();
|
||||
ok(adbProcess.ready);
|
||||
ok(await check(), "adb is now running");
|
||||
|
||||
await adbProcess.stop();
|
||||
ok(!adbProcess.ready);
|
||||
ok(!(await check()), "adb is no longer running");
|
||||
|
||||
// Call start() twice and call stop() afterwards.
|
||||
await adbProcess.start();
|
||||
await adbProcess.start();
|
||||
ok(adbProcess.ready);
|
||||
ok(await check(), "adb is now running");
|
||||
|
||||
await adbProcess.stop();
|
||||
ok(!adbProcess.ready);
|
||||
ok(!(await check()), "adb is no longer running");
|
||||
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task({
|
||||
skip_if: () => mozinfo.os == "win", // bug 1482008
|
||||
}, async function testTrackDevices() {
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: (extension_version++).toString(),
|
||||
applications: {
|
||||
gecko: { id: "adb@mozilla.org" },
|
||||
files: {
|
||||
"adb.json": JSON.stringify(ADB_JSON),
|
||||
"linux/adb": adbMock,
|
||||
"linux64/adb": adbMock,
|
||||
"mac64/adb": adbMock,
|
||||
"win32/adb.exe": adbMock,
|
||||
"win32/AdbWinApi.dll": "dummy",
|
||||
"win32/AdbWinUsbApi.dll": "dummy",
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"adb.json": JSON.stringify(ADB_JSON),
|
||||
"linux/adb": adbMock,
|
||||
"linux64/adb": adbMock,
|
||||
"mac64/adb": adbMock,
|
||||
"win32/adb.exe": adbMock,
|
||||
"win32/AdbWinApi.dll": "dummy",
|
||||
"win32/AdbWinUsbApi.dll": "dummy",
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
await adbProcess.start();
|
||||
ok(adbProcess.ready);
|
||||
|
||||
ok(await check(), "adb is now running");
|
||||
|
||||
const receivedDeviceId = await new Promise(resolve => {
|
||||
const trackDevicesCommand = new TrackDevicesCommand();
|
||||
trackDevicesCommand.on("device-connected", deviceId => {
|
||||
resolve(deviceId);
|
||||
});
|
||||
trackDevicesCommand.run();
|
||||
});
|
||||
|
||||
equal(receivedDeviceId, "1234567890");
|
||||
await extension.startup();
|
||||
|
||||
await adbProcess.stop();
|
||||
ok(!adbProcess.ready);
|
||||
// Call start() once and call stop() afterwards.
|
||||
await adbProcess.start();
|
||||
ok(adbProcess.ready);
|
||||
ok(await check(), "adb is now running");
|
||||
|
||||
await extension.unload();
|
||||
});
|
||||
await adbProcess.stop();
|
||||
ok(!adbProcess.ready);
|
||||
ok(!(await check()), "adb is no longer running");
|
||||
|
||||
// Call start() twice and call stop() afterwards.
|
||||
await adbProcess.start();
|
||||
await adbProcess.start();
|
||||
ok(adbProcess.ready);
|
||||
ok(await check(), "adb is now running");
|
||||
|
||||
await adbProcess.stop();
|
||||
ok(!adbProcess.ready);
|
||||
ok(!(await check()), "adb is no longer running");
|
||||
|
||||
await extension.unload();
|
||||
}
|
||||
);
|
||||
|
||||
add_task(
|
||||
{
|
||||
skip_if: () => mozinfo.os == "win", // bug 1482008
|
||||
},
|
||||
async function testTrackDevices() {
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
version: (extension_version++).toString(),
|
||||
applications: {
|
||||
gecko: { id: "adb@mozilla.org" },
|
||||
},
|
||||
},
|
||||
files: {
|
||||
"adb.json": JSON.stringify(ADB_JSON),
|
||||
"linux/adb": adbMock,
|
||||
"linux64/adb": adbMock,
|
||||
"mac64/adb": adbMock,
|
||||
"win32/adb.exe": adbMock,
|
||||
"win32/AdbWinApi.dll": "dummy",
|
||||
"win32/AdbWinUsbApi.dll": "dummy",
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
await adbProcess.start();
|
||||
ok(adbProcess.ready);
|
||||
|
||||
ok(await check(), "adb is now running");
|
||||
|
||||
const receivedDeviceId = await new Promise(resolve => {
|
||||
const trackDevicesCommand = new TrackDevicesCommand();
|
||||
trackDevicesCommand.on("device-connected", deviceId => {
|
||||
resolve(deviceId);
|
||||
});
|
||||
trackDevicesCommand.run();
|
||||
});
|
||||
|
||||
equal(receivedDeviceId, "1234567890");
|
||||
|
||||
await adbProcess.stop();
|
||||
ok(!adbProcess.ready);
|
||||
|
||||
await extension.unload();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -73,70 +73,90 @@ function withStore(type, onsuccess, onerror) {
|
|||
function getItem(itemKey) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req;
|
||||
withStore("readonly", (store) => {
|
||||
store.transaction.oncomplete = function onComplete() {
|
||||
let value = req.result;
|
||||
if (value === undefined) {
|
||||
value = null;
|
||||
}
|
||||
resolve(value);
|
||||
};
|
||||
req = store.get(itemKey);
|
||||
req.onerror = function getItemOnError() {
|
||||
reject("Error in asyncStorage.getItem(): ", req.error.name);
|
||||
};
|
||||
}, reject);
|
||||
withStore(
|
||||
"readonly",
|
||||
store => {
|
||||
store.transaction.oncomplete = function onComplete() {
|
||||
let value = req.result;
|
||||
if (value === undefined) {
|
||||
value = null;
|
||||
}
|
||||
resolve(value);
|
||||
};
|
||||
req = store.get(itemKey);
|
||||
req.onerror = function getItemOnError() {
|
||||
reject("Error in asyncStorage.getItem(): ", req.error.name);
|
||||
};
|
||||
},
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function setItem(itemKey, value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
withStore("readwrite", (store) => {
|
||||
store.transaction.oncomplete = resolve;
|
||||
const req = store.put(value, itemKey);
|
||||
req.onerror = function setItemOnError() {
|
||||
reject("Error in asyncStorage.setItem(): ", req.error.name);
|
||||
};
|
||||
}, reject);
|
||||
withStore(
|
||||
"readwrite",
|
||||
store => {
|
||||
store.transaction.oncomplete = resolve;
|
||||
const req = store.put(value, itemKey);
|
||||
req.onerror = function setItemOnError() {
|
||||
reject("Error in asyncStorage.setItem(): ", req.error.name);
|
||||
};
|
||||
},
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function removeItem(itemKey) {
|
||||
return new Promise((resolve, reject) => {
|
||||
withStore("readwrite", (store) => {
|
||||
store.transaction.oncomplete = resolve;
|
||||
const req = store.delete(itemKey);
|
||||
req.onerror = function removeItemOnError() {
|
||||
reject("Error in asyncStorage.removeItem(): ", req.error.name);
|
||||
};
|
||||
}, reject);
|
||||
withStore(
|
||||
"readwrite",
|
||||
store => {
|
||||
store.transaction.oncomplete = resolve;
|
||||
const req = store.delete(itemKey);
|
||||
req.onerror = function removeItemOnError() {
|
||||
reject("Error in asyncStorage.removeItem(): ", req.error.name);
|
||||
};
|
||||
},
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function clear() {
|
||||
return new Promise((resolve, reject) => {
|
||||
withStore("readwrite", (store) => {
|
||||
store.transaction.oncomplete = resolve;
|
||||
const req = store.clear();
|
||||
req.onerror = function clearOnError() {
|
||||
reject("Error in asyncStorage.clear(): ", req.error.name);
|
||||
};
|
||||
}, reject);
|
||||
withStore(
|
||||
"readwrite",
|
||||
store => {
|
||||
store.transaction.oncomplete = resolve;
|
||||
const req = store.clear();
|
||||
req.onerror = function clearOnError() {
|
||||
reject("Error in asyncStorage.clear(): ", req.error.name);
|
||||
};
|
||||
},
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function length() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req;
|
||||
withStore("readonly", (store) => {
|
||||
store.transaction.oncomplete = function onComplete() {
|
||||
resolve(req.result);
|
||||
};
|
||||
req = store.count();
|
||||
req.onerror = function lengthOnError() {
|
||||
reject("Error in asyncStorage.length(): ", req.error.name);
|
||||
};
|
||||
}, reject);
|
||||
withStore(
|
||||
"readonly",
|
||||
store => {
|
||||
store.transaction.oncomplete = function onComplete() {
|
||||
resolve(req.result);
|
||||
};
|
||||
req = store.count();
|
||||
req.onerror = function lengthOnError() {
|
||||
reject("Error in asyncStorage.length(): ", req.error.name);
|
||||
};
|
||||
},
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -148,33 +168,37 @@ function key(n) {
|
|||
}
|
||||
|
||||
let req;
|
||||
withStore("readonly", (store) => {
|
||||
store.transaction.oncomplete = function onComplete() {
|
||||
const cursor = req.result;
|
||||
resolve(cursor ? cursor.key : null);
|
||||
};
|
||||
let advanced = false;
|
||||
req = store.openCursor();
|
||||
req.onsuccess = function keyOnSuccess() {
|
||||
const cursor = req.result;
|
||||
if (!cursor) {
|
||||
// this means there weren"t enough keys
|
||||
return;
|
||||
}
|
||||
if (n === 0 || advanced) {
|
||||
// Either 1) we have the first key, return it if that's what they
|
||||
// wanted, or 2) we"ve got the nth key.
|
||||
return;
|
||||
}
|
||||
withStore(
|
||||
"readonly",
|
||||
store => {
|
||||
store.transaction.oncomplete = function onComplete() {
|
||||
const cursor = req.result;
|
||||
resolve(cursor ? cursor.key : null);
|
||||
};
|
||||
let advanced = false;
|
||||
req = store.openCursor();
|
||||
req.onsuccess = function keyOnSuccess() {
|
||||
const cursor = req.result;
|
||||
if (!cursor) {
|
||||
// this means there weren"t enough keys
|
||||
return;
|
||||
}
|
||||
if (n === 0 || advanced) {
|
||||
// Either 1) we have the first key, return it if that's what they
|
||||
// wanted, or 2) we"ve got the nth key.
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, ask the cursor to skip ahead n records
|
||||
advanced = true;
|
||||
cursor.advance(n);
|
||||
};
|
||||
req.onerror = function keyOnError() {
|
||||
reject("Error in asyncStorage.key(): ", req.error.name);
|
||||
};
|
||||
}, reject);
|
||||
// Otherwise, ask the cursor to skip ahead n records
|
||||
advanced = true;
|
||||
cursor.advance(n);
|
||||
};
|
||||
req.onerror = function keyOnError() {
|
||||
reject("Error in asyncStorage.key(): ", req.error.name);
|
||||
};
|
||||
},
|
||||
reject
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,25 @@ const { Constructor: CC, manager: Cm } = Components;
|
|||
const systemPrincipal = CC("@mozilla.org/systemprincipal;1", "nsIPrincipal")();
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const { normalize, dirname } = ChromeUtils.import("resource://gre/modules/osfile/ospath_unix.jsm");
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { normalize, dirname } = ChromeUtils.import(
|
||||
"resource://gre/modules/osfile/ospath_unix.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "resProto",
|
||||
"@mozilla.org/network/protocol;1?name=resource",
|
||||
"nsIResProtocolHandler");
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
"resProto",
|
||||
"@mozilla.org/network/protocol;1?name=resource",
|
||||
"nsIResProtocolHandler"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm"
|
||||
);
|
||||
|
||||
const { defineLazyGetter } = XPCOMUtils;
|
||||
|
||||
|
@ -58,8 +69,8 @@ function readURI(uri) {
|
|||
|
||||
const stream = NetUtil.newChannel({
|
||||
uri: NetUtil.newURI(uri, "UTF-8"),
|
||||
loadUsingSystemPrincipal: true}
|
||||
).open();
|
||||
loadUsingSystemPrincipal: true,
|
||||
}).open();
|
||||
const count = stream.available();
|
||||
const data = NetUtil.readInputStreamToString(stream, count, {
|
||||
charset: "UTF-8",
|
||||
|
@ -74,7 +85,9 @@ function readURI(uri) {
|
|||
function join(base, ...paths) {
|
||||
// If this is an absolute URL, we need to normalize only the path portion,
|
||||
// or we wind up stripping too many slashes and producing invalid URLs.
|
||||
const match = /^((?:resource|file|chrome)\:\/\/[^\/]*|jar:[^!]+!)(.*)/.exec(base);
|
||||
const match = /^((?:resource|file|chrome)\:\/\/[^\/]*|jar:[^!]+!)(.*)/.exec(
|
||||
base
|
||||
);
|
||||
if (match) {
|
||||
return match[1] + normalize([match[2], ...paths].join("/"));
|
||||
}
|
||||
|
@ -100,8 +113,8 @@ function Sandbox(options) {
|
|||
wantComponents: false,
|
||||
sandboxName: options.name,
|
||||
sandboxPrototype: "prototype" in options ? options.prototype : {},
|
||||
invisibleToDebugger: "invisibleToDebugger" in options ?
|
||||
options.invisibleToDebugger : false,
|
||||
invisibleToDebugger:
|
||||
"invisibleToDebugger" in options ? options.invisibleToDebugger : false,
|
||||
freshCompartment: options.freshCompartment || false,
|
||||
};
|
||||
|
||||
|
@ -169,7 +182,10 @@ function load(loader, module) {
|
|||
descriptors.define = define;
|
||||
}
|
||||
if ("DOMParser" in globals) {
|
||||
descriptors.DOMParser = Object.getOwnPropertyDescriptor(globals, "DOMParser");
|
||||
descriptors.DOMParser = Object.getOwnPropertyDescriptor(
|
||||
globals,
|
||||
"DOMParser"
|
||||
);
|
||||
}
|
||||
Object.defineProperties(sandbox, descriptors);
|
||||
} else {
|
||||
|
@ -188,12 +204,19 @@ function load(loader, module) {
|
|||
// loadSubScript sometime throws string errors, which includes no stack.
|
||||
// At least provide the current stack by re-throwing a real Error object.
|
||||
if (typeof error == "string") {
|
||||
if (error.startsWith("Error creating URI") ||
|
||||
error.startsWith("Error opening input stream (invalid filename?)")) {
|
||||
throw new Error(`Module \`${module.id}\` is not found at ${module.uri}`);
|
||||
if (
|
||||
error.startsWith("Error creating URI") ||
|
||||
error.startsWith("Error opening input stream (invalid filename?)")
|
||||
) {
|
||||
throw new Error(
|
||||
`Module \`${module.id}\` is not found at ${module.uri}`
|
||||
);
|
||||
}
|
||||
throw new Error(`Error while loading module \`${module.id}\` at ${module.uri}:` +
|
||||
"\n" + error);
|
||||
throw new Error(
|
||||
`Error while loading module \`${module.id}\` at ${module.uri}:` +
|
||||
"\n" +
|
||||
error
|
||||
);
|
||||
}
|
||||
// Otherwise just re-throw everything else which should have a stack
|
||||
throw error;
|
||||
|
@ -246,8 +269,8 @@ function resolve(id, base) {
|
|||
function compileMapping(paths) {
|
||||
// Make mapping array that is sorted from longest path to shortest path.
|
||||
const mapping = Object.keys(paths)
|
||||
.sort((a, b) => b.length - a.length)
|
||||
.map(path => [path, paths[path]]);
|
||||
.sort((a, b) => b.length - a.length)
|
||||
.map(path => [path, paths[path]]);
|
||||
|
||||
const PATTERN = /([.\\?+*(){}[\]^$])/g;
|
||||
const escapeMeta = str => str.replace(PATTERN, "\\$1");
|
||||
|
@ -326,7 +349,7 @@ function lazyRequire(obj, moduleId, ...args) {
|
|||
|
||||
for (let props of args) {
|
||||
if (typeof props !== "object") {
|
||||
props = {[props]: props};
|
||||
props = { [props]: props };
|
||||
}
|
||||
|
||||
for (const [fromName, toName] of Object.entries(props)) {
|
||||
|
@ -355,15 +378,16 @@ function lazyRequireModule(obj, moduleId, prop = moduleId) {
|
|||
// of `require` that is allowed to load only a modules that are associated
|
||||
// with it during link time.
|
||||
function Require(loader, requirer) {
|
||||
const {
|
||||
modules, mapping, mappingCache, requireHook,
|
||||
} = loader;
|
||||
const { modules, mapping, mappingCache, requireHook } = loader;
|
||||
|
||||
function require(id) {
|
||||
if (!id) {
|
||||
// Throw if `id` is not passed.
|
||||
throw Error("You must provide a module name when calling require() from "
|
||||
+ requirer.id, requirer.uri);
|
||||
throw Error(
|
||||
"You must provide a module name when calling require() from " +
|
||||
requirer.id,
|
||||
requirer.uri
|
||||
);
|
||||
}
|
||||
|
||||
if (requireHook) {
|
||||
|
@ -432,8 +456,11 @@ function Require(loader, requirer) {
|
|||
function getRequirements(id) {
|
||||
if (!id) {
|
||||
// Throw if `id` is not passed.
|
||||
throw Error("you must provide a module name when calling require() from "
|
||||
+ requirer.id, requirer.uri);
|
||||
throw Error(
|
||||
"you must provide a module name when calling require() from " +
|
||||
requirer.id,
|
||||
requirer.uri
|
||||
);
|
||||
}
|
||||
|
||||
let requirement, uri;
|
||||
|
@ -459,8 +486,15 @@ function Require(loader, requirer) {
|
|||
|
||||
// Throw if `uri` can not be resolved.
|
||||
if (!uri) {
|
||||
throw Error("Module: Can not resolve '" + id + "' module required by " +
|
||||
requirer.id + " located at " + requirer.uri, requirer.uri);
|
||||
throw Error(
|
||||
"Module: Can not resolve '" +
|
||||
id +
|
||||
"' module required by " +
|
||||
requirer.id +
|
||||
" located at " +
|
||||
requirer.uri,
|
||||
requirer.uri
|
||||
);
|
||||
}
|
||||
|
||||
return { uri: uri, requirement: requirement };
|
||||
|
@ -488,8 +522,12 @@ function Require(loader, requirer) {
|
|||
function Module(id, uri) {
|
||||
return Object.create(null, {
|
||||
id: { enumerable: true, value: id },
|
||||
exports: { enumerable: true, writable: true, value: Object.create(null),
|
||||
configurable: true },
|
||||
exports: {
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: Object.create(null),
|
||||
configurable: true,
|
||||
},
|
||||
uri: { value: uri },
|
||||
});
|
||||
}
|
||||
|
@ -545,9 +583,15 @@ function Loader(options) {
|
|||
let modules = {
|
||||
"@loader/unload": destructor,
|
||||
"@loader/options": options,
|
||||
"chrome": { Cc, Ci, Cu, Cr, Cm,
|
||||
CC: bind(CC, Components), components: Components,
|
||||
ChromeWorker,
|
||||
chrome: {
|
||||
Cc,
|
||||
Ci,
|
||||
Cu,
|
||||
Cr,
|
||||
Cm,
|
||||
CC: bind(CC, Components),
|
||||
components: Components,
|
||||
ChromeWorker,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -586,8 +630,11 @@ function Loader(options) {
|
|||
// the sandbox directly. Note that this will not work for callers who
|
||||
// depend on being able to add globals after the loader was created.
|
||||
for (const name of getOwnIdentifiers(globals)) {
|
||||
Object.defineProperty(sharedGlobalSandbox, name,
|
||||
Object.getOwnPropertyDescriptor(globals, name));
|
||||
Object.defineProperty(
|
||||
sharedGlobalSandbox,
|
||||
name,
|
||||
Object.getOwnPropertyDescriptor(globals, name)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,9 +653,15 @@ function Loader(options) {
|
|||
// Map of module sandboxes indexed by module URIs.
|
||||
sandboxes: { enumerable: false, value: {} },
|
||||
// Whether the modules loaded should be ignored by the debugger
|
||||
invisibleToDebugger: { enumerable: false,
|
||||
value: options.invisibleToDebugger || false },
|
||||
requireHook: { enumerable: false, writable: true, value: options.requireHook },
|
||||
invisibleToDebugger: {
|
||||
enumerable: false,
|
||||
value: options.invisibleToDebugger || false,
|
||||
},
|
||||
requireHook: {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: options.requireHook,
|
||||
},
|
||||
};
|
||||
|
||||
return Object.create(null, returnObj);
|
||||
|
|
|
@ -165,11 +165,18 @@ function defineLazyServiceGetter(object, name, contract, interfaceName) {
|
|||
* An object which acts on behalf of the module to be imported until
|
||||
* the module has been imported.
|
||||
*/
|
||||
function defineLazyModuleGetter(object, name, resource, symbol,
|
||||
preLambda, postLambda, proxy) {
|
||||
function defineLazyModuleGetter(
|
||||
object,
|
||||
name,
|
||||
resource,
|
||||
symbol,
|
||||
preLambda,
|
||||
postLambda,
|
||||
proxy
|
||||
) {
|
||||
proxy = proxy || {};
|
||||
|
||||
if (typeof (preLambda) === "function") {
|
||||
if (typeof preLambda === "function") {
|
||||
preLambda.apply(proxy);
|
||||
}
|
||||
|
||||
|
@ -178,7 +185,7 @@ function defineLazyModuleGetter(object, name, resource, symbol,
|
|||
try {
|
||||
ChromeUtils.import(resource, temp);
|
||||
|
||||
if (typeof (postLambda) === "function") {
|
||||
if (typeof postLambda === "function") {
|
||||
postLambda.apply(proxy);
|
||||
}
|
||||
} catch (ex) {
|
||||
|
@ -247,13 +254,17 @@ defineLazyGetter(exports.modules, "Debugger", () => {
|
|||
if (global.Debugger) {
|
||||
return global.Debugger;
|
||||
}
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm");
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import(
|
||||
"resource://gre/modules/jsdebugger.jsm"
|
||||
);
|
||||
addDebuggerToGlobal(global);
|
||||
return global.Debugger;
|
||||
});
|
||||
|
||||
defineLazyGetter(exports.modules, "ChromeDebugger", () => {
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm");
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import(
|
||||
"resource://gre/modules/jsdebugger.jsm"
|
||||
);
|
||||
addDebuggerToGlobal(debuggerSandbox);
|
||||
return debuggerSandbox.Debugger;
|
||||
});
|
||||
|
@ -265,7 +276,9 @@ defineLazyGetter(exports.modules, "RecordReplayControl", () => {
|
|||
if (global.RecordReplayControl) {
|
||||
return global.RecordReplayControl;
|
||||
}
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm");
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import(
|
||||
"resource://gre/modules/jsdebugger.jsm"
|
||||
);
|
||||
addDebuggerToGlobal(global);
|
||||
return global.RecordReplayControl;
|
||||
});
|
||||
|
@ -279,7 +292,10 @@ defineLazyGetter(exports.modules, "InspectorUtils", () => {
|
|||
});
|
||||
|
||||
defineLazyGetter(exports.modules, "Timer", () => {
|
||||
const {setTimeout, clearTimeout} = require("resource://gre/modules/Timer.jsm");
|
||||
const {
|
||||
setTimeout,
|
||||
clearTimeout,
|
||||
} = require("resource://gre/modules/Timer.jsm");
|
||||
// Do not return Cu.import result, as DevTools loader would freeze Timer.jsm globals...
|
||||
return {
|
||||
setTimeout,
|
||||
|
@ -377,7 +393,9 @@ lazyGlobal("WebSocket", () => {
|
|||
return Services.appShell.hiddenDOMWindow.WebSocket;
|
||||
});
|
||||
lazyGlobal("indexedDB", () => {
|
||||
return require("devtools/shared/indexed-db").createDevToolsIndexedDB(indexedDB);
|
||||
return require("devtools/shared/indexed-db").createDevToolsIndexedDB(
|
||||
indexedDB
|
||||
);
|
||||
});
|
||||
lazyGlobal("isReplaying", () => {
|
||||
return exports.modules.Debugger.recordReplayProcessKind() == "Middleman";
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cr} = require("chrome");
|
||||
const { Cc, Ci, Cr } = require("chrome");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
|
||||
|
@ -100,8 +100,9 @@ var ConnectionManager = {
|
|||
return [...this._connections];
|
||||
},
|
||||
getFreeTCPPort: function() {
|
||||
const serv = Cc["@mozilla.org/network/server-socket;1"]
|
||||
.createInstance(Ci.nsIServerSocket);
|
||||
const serv = Cc["@mozilla.org/network/server-socket;1"].createInstance(
|
||||
Ci.nsIServerSocket
|
||||
);
|
||||
serv.init(-1, true, -1);
|
||||
const port = serv.port;
|
||||
serv.close();
|
||||
|
@ -251,8 +252,10 @@ Connection.prototype = {
|
|||
return;
|
||||
}
|
||||
clearTimeout(this._timeoutID);
|
||||
if (this.status == Connection.Status.CONNECTED ||
|
||||
this.status == Connection.Status.CONNECTING) {
|
||||
if (
|
||||
this.status == Connection.Status.CONNECTED ||
|
||||
this.status == Connection.Status.CONNECTING
|
||||
) {
|
||||
this.log("disconnecting");
|
||||
this._setStatus(Connection.Status.DISCONNECTING);
|
||||
if (this._client) {
|
||||
|
@ -309,26 +312,32 @@ Connection.prototype = {
|
|||
},
|
||||
|
||||
_clientConnect: function() {
|
||||
this._getTransport().then(transport => {
|
||||
if (!transport) {
|
||||
return;
|
||||
this._getTransport().then(
|
||||
transport => {
|
||||
if (!transport) {
|
||||
return;
|
||||
}
|
||||
this._client = new DebuggerClient(transport);
|
||||
this._client.once("closed", this._onDisconnected);
|
||||
this._client.connect().then(this._onConnected);
|
||||
},
|
||||
e => {
|
||||
// If we're continuously trying to connect, we expect the connection to be
|
||||
// rejected a couple times, so don't log these.
|
||||
if (
|
||||
!this.keepConnecting ||
|
||||
e.result !== Cr.NS_ERROR_CONNECTION_REFUSED
|
||||
) {
|
||||
console.error(e);
|
||||
}
|
||||
// In some cases, especially on Mac, the openOutputStream call in
|
||||
// DebuggerClient.socketConnect may throw NS_ERROR_NOT_INITIALIZED.
|
||||
// It occurs when we connect agressively to the simulator,
|
||||
// and keep trying to open a socket to the server being started in
|
||||
// the simulator.
|
||||
this._onDisconnected();
|
||||
}
|
||||
this._client = new DebuggerClient(transport);
|
||||
this._client.once("closed", this._onDisconnected);
|
||||
this._client.connect().then(this._onConnected);
|
||||
}, e => {
|
||||
// If we're continuously trying to connect, we expect the connection to be
|
||||
// rejected a couple times, so don't log these.
|
||||
if (!this.keepConnecting || e.result !== Cr.NS_ERROR_CONNECTION_REFUSED) {
|
||||
console.error(e);
|
||||
}
|
||||
// In some cases, especially on Mac, the openOutputStream call in
|
||||
// DebuggerClient.socketConnect may throw NS_ERROR_NOT_INITIALIZED.
|
||||
// It occurs when we connect agressively to the simulator,
|
||||
// and keep trying to open a socket to the server being started in
|
||||
// the simulator.
|
||||
this._onDisconnected();
|
||||
});
|
||||
);
|
||||
},
|
||||
|
||||
get status() {
|
||||
|
@ -360,9 +369,11 @@ Connection.prototype = {
|
|||
this.log("disconnected (unexpected)");
|
||||
break;
|
||||
case Connection.Status.CONNECTING:
|
||||
this.log("connection error. Possible causes: USB port not connected, port not " +
|
||||
"forwarded (adb forward), wrong host or port, remote debugging not " +
|
||||
"enabled on the device.");
|
||||
this.log(
|
||||
"connection error. Possible causes: USB port not connected, port not " +
|
||||
"forwarded (adb forward), wrong host or port, remote debugging not " +
|
||||
"enabled on the device."
|
||||
);
|
||||
break;
|
||||
default:
|
||||
this.log("disconnected");
|
||||
|
@ -377,7 +388,9 @@ Connection.prototype = {
|
|||
},
|
||||
|
||||
_onTimeout: function() {
|
||||
this.log("connection timeout. Possible causes: didn't click on 'accept' (prompt).");
|
||||
this.log(
|
||||
"connection timeout. Possible causes: didn't click on 'accept' (prompt)."
|
||||
);
|
||||
this.emit(Connection.Events.TIMEOUT);
|
||||
this.disconnect();
|
||||
},
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
const promise = require("devtools/shared/deprecated-sync-thenables");
|
||||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { getStack, callFunctionWithAsyncStack } = require("devtools/shared/platform/stack");
|
||||
const {
|
||||
getStack,
|
||||
callFunctionWithAsyncStack,
|
||||
} = require("devtools/shared/platform/stack");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const {
|
||||
ThreadStateTypes,
|
||||
|
@ -15,12 +18,30 @@ const {
|
|||
UnsolicitedPauses,
|
||||
} = require("./constants");
|
||||
|
||||
loader.lazyRequireGetter(this, "Authentication", "devtools/shared/security/auth");
|
||||
loader.lazyRequireGetter(this, "DebuggerSocket", "devtools/shared/security/socket", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"Authentication",
|
||||
"devtools/shared/security/auth"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"DebuggerSocket",
|
||||
"devtools/shared/security/socket",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
|
||||
|
||||
loader.lazyRequireGetter(this, "RootFront", "devtools/shared/fronts/root", true);
|
||||
loader.lazyRequireGetter(this, "ObjectClient", "devtools/shared/client/object-client");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"RootFront",
|
||||
"devtools/shared/fronts/root",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"ObjectClient",
|
||||
"devtools/shared/client/object-client"
|
||||
);
|
||||
loader.lazyRequireGetter(this, "Front", "devtools/shared/protocol", true);
|
||||
|
||||
/**
|
||||
|
@ -46,7 +67,7 @@ function DebuggerClient(transport) {
|
|||
* the connection's root actor.
|
||||
*/
|
||||
this.mainRoot = null;
|
||||
this.expectReply("root", (packet) => {
|
||||
this.expectReply("root", packet => {
|
||||
this.mainRoot = new RootFront(this, packet);
|
||||
|
||||
// Root Front is a special case, managing itself as it doesn't have any parent.
|
||||
|
@ -98,22 +119,25 @@ DebuggerClient.requester = function(packetSkeleton, config = {}) {
|
|||
outgoingPacket = before.call(this, outgoingPacket);
|
||||
}
|
||||
|
||||
return this.request(outgoingPacket, DevToolsUtils.makeInfallible((response) => {
|
||||
if (after) {
|
||||
const { from } = response;
|
||||
response = after.call(this, response);
|
||||
if (!response.from) {
|
||||
response.from = from;
|
||||
return this.request(
|
||||
outgoingPacket,
|
||||
DevToolsUtils.makeInfallible(response => {
|
||||
if (after) {
|
||||
const { from } = response;
|
||||
response = after.call(this, response);
|
||||
if (!response.from) {
|
||||
response.from = from;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The callback is always the last parameter.
|
||||
const thisCallback = args[maxPosition + 1];
|
||||
if (thisCallback) {
|
||||
thisCallback(response);
|
||||
}
|
||||
return response;
|
||||
}, "DebuggerClient.requester request callback"));
|
||||
// The callback is always the last parameter.
|
||||
const thisCallback = args[maxPosition + 1];
|
||||
if (thisCallback) {
|
||||
thisCallback(response);
|
||||
}
|
||||
return response;
|
||||
}, "DebuggerClient.requester request callback")
|
||||
);
|
||||
}, "DebuggerClient.requester");
|
||||
};
|
||||
|
||||
|
@ -294,9 +318,14 @@ DebuggerClient.prototype = {
|
|||
};
|
||||
|
||||
if (this._closed) {
|
||||
const msg = "'" + type + "' request packet to " +
|
||||
"'" + packet.to + "' " +
|
||||
"can't be sent as the connection is closed.";
|
||||
const msg =
|
||||
"'" +
|
||||
type +
|
||||
"' request packet to " +
|
||||
"'" +
|
||||
packet.to +
|
||||
"' " +
|
||||
"can't be sent as the connection is closed.";
|
||||
const resp = { error: "connectionClosed", message: msg };
|
||||
return promise.reject(safeOnResponse(resp));
|
||||
}
|
||||
|
@ -531,24 +560,28 @@ DebuggerClient.prototype = {
|
|||
if (!packet.from) {
|
||||
DevToolsUtils.reportException(
|
||||
"onPacket",
|
||||
new Error("Server did not specify an actor, dropping packet: " +
|
||||
JSON.stringify(packet)));
|
||||
new Error(
|
||||
"Server did not specify an actor, dropping packet: " +
|
||||
JSON.stringify(packet)
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for "forwardingCancelled" here instead of using a front to handle it.
|
||||
// This is necessary because we might receive this event while the client is closing,
|
||||
// and the fronts have already been removed by that point.
|
||||
if (this.mainRoot &&
|
||||
packet.from == this.mainRoot.actorID &&
|
||||
packet.type == "forwardingCancelled") {
|
||||
if (
|
||||
this.mainRoot &&
|
||||
packet.from == this.mainRoot.actorID &&
|
||||
packet.type == "forwardingCancelled"
|
||||
) {
|
||||
this.purgeRequests(packet.prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
// support older browsers for Fx69+ for using the old thread client
|
||||
if (!this.traits.hasThreadFront &&
|
||||
packet.from.includes("context")) {
|
||||
if (!this.traits.hasThreadFront && packet.from.includes("context")) {
|
||||
this.sendToDeprecatedThreadClient(packet);
|
||||
return;
|
||||
}
|
||||
|
@ -565,8 +598,10 @@ DebuggerClient.prototype = {
|
|||
// See if we have a handler function waiting for a reply from this
|
||||
// actor. (Don't count unsolicited notifications or pauses as
|
||||
// replies.)
|
||||
if (this._activeRequests.has(packet.from) &&
|
||||
!(packet.type in UnsolicitedNotifications)) {
|
||||
if (
|
||||
this._activeRequests.has(packet.from) &&
|
||||
!(packet.type in UnsolicitedNotifications)
|
||||
) {
|
||||
activeRequest = this._activeRequests.get(packet.from);
|
||||
this._activeRequests.delete(packet.from);
|
||||
}
|
||||
|
@ -585,8 +620,11 @@ DebuggerClient.prototype = {
|
|||
if (activeRequest) {
|
||||
const emitReply = () => activeRequest.emit("json-reply", packet);
|
||||
if (activeRequest.stack) {
|
||||
callFunctionWithAsyncStack(emitReply, activeRequest.stack,
|
||||
"DevTools RDP");
|
||||
callFunctionWithAsyncStack(
|
||||
emitReply,
|
||||
activeRequest.stack,
|
||||
"DevTools RDP"
|
||||
);
|
||||
} else {
|
||||
emitReply();
|
||||
}
|
||||
|
@ -611,9 +649,13 @@ DebuggerClient.prototype = {
|
|||
// See if we have a handler function waiting for a reply from this
|
||||
// actor. (Don't count unsolicited notifications or pauses as
|
||||
// replies.)
|
||||
if (this._activeRequests.has(packet.from) &&
|
||||
!(packet.type == ThreadStateTypes.paused &&
|
||||
packet.why.type in UnsolicitedPauses)) {
|
||||
if (
|
||||
this._activeRequests.has(packet.from) &&
|
||||
!(
|
||||
packet.type == ThreadStateTypes.paused &&
|
||||
packet.why.type in UnsolicitedPauses
|
||||
)
|
||||
) {
|
||||
activeRequest = this._activeRequests.get(packet.from);
|
||||
this._activeRequests.delete(packet.from);
|
||||
}
|
||||
|
@ -624,9 +666,11 @@ DebuggerClient.prototype = {
|
|||
this._attemptNextRequest(packet.from);
|
||||
|
||||
// Packets that indicate thread state changes get special treatment.
|
||||
if (packet.type in ThreadStateTypes &&
|
||||
deprecatedThreadClient &&
|
||||
typeof deprecatedThreadClient._onThreadState == "function") {
|
||||
if (
|
||||
packet.type in ThreadStateTypes &&
|
||||
deprecatedThreadClient &&
|
||||
typeof deprecatedThreadClient._onThreadState == "function"
|
||||
) {
|
||||
deprecatedThreadClient._onThreadState(packet);
|
||||
}
|
||||
|
||||
|
@ -677,8 +721,11 @@ DebuggerClient.prototype = {
|
|||
if (!actor) {
|
||||
DevToolsUtils.reportException(
|
||||
"onBulkPacket",
|
||||
new Error("Server did not specify an actor, dropping bulk packet: " +
|
||||
JSON.stringify(packet)));
|
||||
new Error(
|
||||
"Server did not specify an actor, dropping bulk packet: " +
|
||||
JSON.stringify(packet)
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -751,11 +798,19 @@ DebuggerClient.prototype = {
|
|||
// to expectReply, so that there is no request object.
|
||||
let msg;
|
||||
if (request.request) {
|
||||
msg = "'" + request.request.type + "' " + type + " request packet" +
|
||||
" to '" + request.actor + "' " +
|
||||
"can't be sent as the connection just closed.";
|
||||
msg =
|
||||
"'" +
|
||||
request.request.type +
|
||||
"' " +
|
||||
type +
|
||||
" request packet" +
|
||||
" to '" +
|
||||
request.actor +
|
||||
"' " +
|
||||
"can't be sent as the connection just closed.";
|
||||
} else {
|
||||
msg = "server side packet can't be received as the connection just closed.";
|
||||
msg =
|
||||
"server side packet can't be received as the connection just closed.";
|
||||
}
|
||||
const packet = { error: "connectionClosed", message: msg };
|
||||
request.emit("json-reply", packet);
|
||||
|
@ -838,14 +893,16 @@ DebuggerClient.prototype = {
|
|||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return DevToolsUtils.settleAll(requests).catch(() => {
|
||||
// One of the requests might have failed, but ignore that situation here and pipe
|
||||
// both success and failure through the same path. The important part is just that
|
||||
// we waited.
|
||||
}).then(() => {
|
||||
// Repeat, more requests may have started in response to those we just waited for
|
||||
return this.waitForRequestsToSettle();
|
||||
});
|
||||
return DevToolsUtils.settleAll(requests)
|
||||
.catch(() => {
|
||||
// One of the requests might have failed, but ignore that situation here and pipe
|
||||
// both success and failure through the same path. The important part is just that
|
||||
// we waited.
|
||||
})
|
||||
.then(() => {
|
||||
// Repeat, more requests may have started in response to those we just waited for
|
||||
return this.waitForRequestsToSettle();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
|
||||
const {
|
||||
arg,
|
||||
DebuggerClient,
|
||||
} = require("devtools/shared/client/debugger-client");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const {ThreadStateTypes} = require("devtools/shared/client/constants");
|
||||
const { ThreadStateTypes } = require("devtools/shared/client/constants");
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
|
@ -78,36 +81,39 @@ ThreadClient.prototype = {
|
|||
* than proceeding forwards. This parameter has no effect if the
|
||||
* server does not support rewinding.
|
||||
*/
|
||||
_doResume: DebuggerClient.requester({
|
||||
type: "resume",
|
||||
resumeLimit: arg(0),
|
||||
rewind: arg(1),
|
||||
}, {
|
||||
before: function(packet) {
|
||||
this._assertPaused("resume");
|
||||
|
||||
// Put the client in a tentative "resuming" state so we can prevent
|
||||
// further requests that should only be sent in the paused state.
|
||||
this._previousState = this._state;
|
||||
this._state = "resuming";
|
||||
|
||||
return packet;
|
||||
_doResume: DebuggerClient.requester(
|
||||
{
|
||||
type: "resume",
|
||||
resumeLimit: arg(0),
|
||||
rewind: arg(1),
|
||||
},
|
||||
after: function(response) {
|
||||
if (response.error && this._state == "resuming") {
|
||||
// There was an error resuming, update the state to the new one
|
||||
// reported by the server, if given (only on wrongState), otherwise
|
||||
// reset back to the previous state.
|
||||
if (response.state) {
|
||||
this._state = ThreadStateTypes[response.state];
|
||||
} else {
|
||||
this._state = this._previousState;
|
||||
{
|
||||
before: function(packet) {
|
||||
this._assertPaused("resume");
|
||||
|
||||
// Put the client in a tentative "resuming" state so we can prevent
|
||||
// further requests that should only be sent in the paused state.
|
||||
this._previousState = this._state;
|
||||
this._state = "resuming";
|
||||
|
||||
return packet;
|
||||
},
|
||||
after: function(response) {
|
||||
if (response.error && this._state == "resuming") {
|
||||
// There was an error resuming, update the state to the new one
|
||||
// reported by the server, if given (only on wrongState), otherwise
|
||||
// reset back to the previous state.
|
||||
if (response.state) {
|
||||
this._state = ThreadStateTypes[response.state];
|
||||
} else {
|
||||
this._state = this._previousState;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete this._previousState;
|
||||
return response;
|
||||
},
|
||||
}),
|
||||
delete this._previousState;
|
||||
return response;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Reconfigure the thread actor.
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
|
||||
const {
|
||||
arg,
|
||||
DebuggerClient,
|
||||
} = require("devtools/shared/client/debugger-client");
|
||||
|
||||
/**
|
||||
* Environment clients are used to manipulate the lexical environment actors.
|
||||
|
@ -22,7 +25,6 @@ function EnvironmentClient(client, form) {
|
|||
exports.EnvironmentClient = EnvironmentClient;
|
||||
|
||||
EnvironmentClient.prototype = {
|
||||
|
||||
get actor() {
|
||||
return this._form.actor;
|
||||
},
|
||||
|
|
|
@ -86,8 +86,9 @@ function eventSource(proto) {
|
|||
if (!listener) {
|
||||
this._listeners[name] = [];
|
||||
} else {
|
||||
this._listeners[name] =
|
||||
this._listeners[name].filter(l => l.key != listener);
|
||||
this._listeners[name] = this._listeners[name].filter(
|
||||
l => l.key != listener
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
|
||||
const {
|
||||
arg,
|
||||
DebuggerClient,
|
||||
} = require("devtools/shared/client/debugger-client");
|
||||
/**
|
||||
* A LongStringClient provides a way to access "very long" strings from the
|
||||
* debugger server.
|
||||
|
|
|
@ -4,9 +4,20 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
|
||||
loader.lazyRequireGetter(this, "PropertyIteratorClient", "devtools/shared/client/property-iterator-client");
|
||||
loader.lazyRequireGetter(this, "SymbolIteratorClient", "devtools/shared/client/symbol-iterator-client");
|
||||
const {
|
||||
arg,
|
||||
DebuggerClient,
|
||||
} = require("devtools/shared/client/debugger-client");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PropertyIteratorClient",
|
||||
"devtools/shared/client/property-iterator-client"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"SymbolIteratorClient",
|
||||
"devtools/shared/client/symbol-iterator-client"
|
||||
);
|
||||
|
||||
/**
|
||||
* Grip clients are used to retrieve information about the relevant object.
|
||||
|
@ -46,16 +57,21 @@ ObjectClient.prototype = {
|
|||
type: "threadGrip",
|
||||
}),
|
||||
|
||||
getDefinitionSite: DebuggerClient.requester({
|
||||
type: "definitionSite",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class != "Function") {
|
||||
throw new Error("getDefinitionSite is only valid for function grips.");
|
||||
}
|
||||
return packet;
|
||||
getDefinitionSite: DebuggerClient.requester(
|
||||
{
|
||||
type: "definitionSite",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class != "Function") {
|
||||
throw new Error(
|
||||
"getDefinitionSite is only valid for function grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the names of a function's formal parameters.
|
||||
|
@ -65,16 +81,21 @@ ObjectClient.prototype = {
|
|||
* { parameterNames:[<parameterName>, ...] }
|
||||
* where each <parameterName> is the name of a parameter.
|
||||
*/
|
||||
getParameterNames: DebuggerClient.requester({
|
||||
type: "parameterNames",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Function") {
|
||||
throw new Error("getParameterNames is only valid for function grips.");
|
||||
}
|
||||
return packet;
|
||||
getParameterNames: DebuggerClient.requester(
|
||||
{
|
||||
type: "parameterNames",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Function") {
|
||||
throw new Error(
|
||||
"getParameterNames is only valid for function grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the names of the properties defined on the object and not its
|
||||
|
@ -113,17 +134,25 @@ ObjectClient.prototype = {
|
|||
* before dispatching them.
|
||||
* @param onResponse function Called with the client instance.
|
||||
*/
|
||||
enumProperties: DebuggerClient.requester({
|
||||
type: "enumProperties",
|
||||
options: arg(0),
|
||||
}, {
|
||||
after: function(response) {
|
||||
if (response.iterator) {
|
||||
return { iterator: new PropertyIteratorClient(this._client, response.iterator) };
|
||||
}
|
||||
return response;
|
||||
enumProperties: DebuggerClient.requester(
|
||||
{
|
||||
type: "enumProperties",
|
||||
options: arg(0),
|
||||
},
|
||||
}),
|
||||
{
|
||||
after: function(response) {
|
||||
if (response.iterator) {
|
||||
return {
|
||||
iterator: new PropertyIteratorClient(
|
||||
this._client,
|
||||
response.iterator
|
||||
),
|
||||
};
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request a PropertyIteratorClient instance to enumerate entries in a
|
||||
|
@ -131,48 +160,63 @@ ObjectClient.prototype = {
|
|||
*
|
||||
* @param onResponse function Called with the request's response.
|
||||
*/
|
||||
enumEntries: DebuggerClient.requester({
|
||||
type: "enumEntries",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (!["Map", "WeakMap", "Set", "WeakSet", "Storage"].includes(this._grip.class)) {
|
||||
throw new Error("enumEntries is only valid for Map/Set/Storage-like grips.");
|
||||
}
|
||||
return packet;
|
||||
enumEntries: DebuggerClient.requester(
|
||||
{
|
||||
type: "enumEntries",
|
||||
},
|
||||
after: function(response) {
|
||||
if (response.iterator) {
|
||||
return {
|
||||
iterator: new PropertyIteratorClient(this._client, response.iterator),
|
||||
};
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (
|
||||
!["Map", "WeakMap", "Set", "WeakSet", "Storage"].includes(
|
||||
this._grip.class
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
"enumEntries is only valid for Map/Set/Storage-like grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
after: function(response) {
|
||||
if (response.iterator) {
|
||||
return {
|
||||
iterator: new PropertyIteratorClient(
|
||||
this._client,
|
||||
response.iterator
|
||||
),
|
||||
};
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request a SymbolIteratorClient instance to enumerate symbols in an object.
|
||||
*
|
||||
* @param onResponse function Called with the request's response.
|
||||
*/
|
||||
enumSymbols: DebuggerClient.requester({
|
||||
type: "enumSymbols",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.type !== "object") {
|
||||
throw new Error("enumSymbols is only valid for objects grips.");
|
||||
}
|
||||
return packet;
|
||||
enumSymbols: DebuggerClient.requester(
|
||||
{
|
||||
type: "enumSymbols",
|
||||
},
|
||||
after: function(response) {
|
||||
if (response.iterator) {
|
||||
return {
|
||||
iterator: new SymbolIteratorClient(this._client, response.iterator),
|
||||
};
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.type !== "object") {
|
||||
throw new Error("enumSymbols is only valid for objects grips.");
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
after: function(response) {
|
||||
if (response.iterator) {
|
||||
return {
|
||||
iterator: new SymbolIteratorClient(this._client, response.iterator),
|
||||
};
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the property descriptor of the object's specified property.
|
||||
|
@ -234,98 +278,121 @@ ObjectClient.prototype = {
|
|||
*
|
||||
* @param onResponse function Called with the request's response.
|
||||
*/
|
||||
getScope: DebuggerClient.requester({
|
||||
type: "scope",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Function") {
|
||||
throw new Error("scope is only valid for function grips.");
|
||||
}
|
||||
return packet;
|
||||
getScope: DebuggerClient.requester(
|
||||
{
|
||||
type: "scope",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Function") {
|
||||
throw new Error("scope is only valid for function grips.");
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the promises directly depending on the current promise.
|
||||
*/
|
||||
getDependentPromises: DebuggerClient.requester({
|
||||
type: "dependentPromises",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error("getDependentPromises is only valid for promise " +
|
||||
"grips.");
|
||||
}
|
||||
return packet;
|
||||
getDependentPromises: DebuggerClient.requester(
|
||||
{
|
||||
type: "dependentPromises",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error(
|
||||
"getDependentPromises is only valid for promise " + "grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the stack to the promise's allocation point.
|
||||
*/
|
||||
getPromiseAllocationStack: DebuggerClient.requester({
|
||||
type: "allocationStack",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error("getAllocationStack is only valid for promise grips.");
|
||||
}
|
||||
return packet;
|
||||
getPromiseAllocationStack: DebuggerClient.requester(
|
||||
{
|
||||
type: "allocationStack",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error(
|
||||
"getAllocationStack is only valid for promise grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the stack to the promise's fulfillment point.
|
||||
*/
|
||||
getPromiseFulfillmentStack: DebuggerClient.requester({
|
||||
type: "fulfillmentStack",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error("getPromiseFulfillmentStack is only valid for " +
|
||||
"promise grips.");
|
||||
}
|
||||
return packet;
|
||||
getPromiseFulfillmentStack: DebuggerClient.requester(
|
||||
{
|
||||
type: "fulfillmentStack",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error(
|
||||
"getPromiseFulfillmentStack is only valid for " + "promise grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the stack to the promise's rejection point.
|
||||
*/
|
||||
getPromiseRejectionStack: DebuggerClient.requester({
|
||||
type: "rejectionStack",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error("getPromiseRejectionStack is only valid for " +
|
||||
"promise grips.");
|
||||
}
|
||||
return packet;
|
||||
getPromiseRejectionStack: DebuggerClient.requester(
|
||||
{
|
||||
type: "rejectionStack",
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Promise") {
|
||||
throw new Error(
|
||||
"getPromiseRejectionStack is only valid for " + "promise grips."
|
||||
);
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
/**
|
||||
* Request the target and handler internal slots of a proxy.
|
||||
*/
|
||||
getProxySlots: DebuggerClient.requester({
|
||||
type: "proxySlots",
|
||||
}, {
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Proxy") {
|
||||
throw new Error("getProxySlots is only valid for proxy grips.");
|
||||
}
|
||||
return packet;
|
||||
getProxySlots: DebuggerClient.requester(
|
||||
{
|
||||
type: "proxySlots",
|
||||
},
|
||||
after: function(response) {
|
||||
// Before Firefox 68 (bug 1392760), the proxySlots request didn't exist.
|
||||
// The proxy target and handler were directly included in the grip.
|
||||
if (response.error === "unrecognizedPacketType") {
|
||||
const {proxyTarget, proxyHandler} = this._grip;
|
||||
return {proxyTarget, proxyHandler};
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}),
|
||||
{
|
||||
before: function(packet) {
|
||||
if (this._grip.class !== "Proxy") {
|
||||
throw new Error("getProxySlots is only valid for proxy grips.");
|
||||
}
|
||||
return packet;
|
||||
},
|
||||
after: function(response) {
|
||||
// Before Firefox 68 (bug 1392760), the proxySlots request didn't exist.
|
||||
// The proxy target and handler were directly included in the grip.
|
||||
if (response.error === "unrecognizedPacketType") {
|
||||
const { proxyTarget, proxyHandler } = this._grip;
|
||||
return { proxyTarget, proxyHandler };
|
||||
}
|
||||
return response;
|
||||
},
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
module.exports = ObjectClient;
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
|
||||
const {
|
||||
arg,
|
||||
DebuggerClient,
|
||||
} = require("devtools/shared/client/debugger-client");
|
||||
|
||||
/**
|
||||
* A PropertyIteratorClient provides a way to access to property names and
|
||||
|
@ -46,10 +49,13 @@ PropertyIteratorClient.prototype = {
|
|||
* @param callback Function
|
||||
* The function called when we receive the property names.
|
||||
*/
|
||||
names: DebuggerClient.requester({
|
||||
type: "names",
|
||||
indexes: arg(0),
|
||||
}, {}),
|
||||
names: DebuggerClient.requester(
|
||||
{
|
||||
type: "names",
|
||||
indexes: arg(0),
|
||||
},
|
||||
{}
|
||||
),
|
||||
|
||||
/**
|
||||
* Get a set of following property value(s).
|
||||
|
@ -61,11 +67,14 @@ PropertyIteratorClient.prototype = {
|
|||
* @param callback Function
|
||||
* The function called when we receive the property values.
|
||||
*/
|
||||
slice: DebuggerClient.requester({
|
||||
type: "slice",
|
||||
start: arg(0),
|
||||
count: arg(1),
|
||||
}, {}),
|
||||
slice: DebuggerClient.requester(
|
||||
{
|
||||
type: "slice",
|
||||
start: arg(0),
|
||||
count: arg(1),
|
||||
},
|
||||
{}
|
||||
),
|
||||
|
||||
/**
|
||||
* Get all the property values.
|
||||
|
@ -73,9 +82,12 @@ PropertyIteratorClient.prototype = {
|
|||
* @param callback Function
|
||||
* The function called when we receive the property values.
|
||||
*/
|
||||
all: DebuggerClient.requester({
|
||||
type: "all",
|
||||
}, {}),
|
||||
all: DebuggerClient.requester(
|
||||
{
|
||||
type: "all",
|
||||
},
|
||||
{}
|
||||
),
|
||||
};
|
||||
|
||||
module.exports = PropertyIteratorClient;
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
|
||||
const {
|
||||
arg,
|
||||
DebuggerClient,
|
||||
} = require("devtools/shared/client/debugger-client");
|
||||
|
||||
/**
|
||||
* A SymbolIteratorClient provides a way to access to symbols
|
||||
|
@ -44,11 +47,14 @@ SymbolIteratorClient.prototype = {
|
|||
* @param callback Function
|
||||
* The function called when we receive the symbols.
|
||||
*/
|
||||
slice: DebuggerClient.requester({
|
||||
type: "slice",
|
||||
start: arg(0),
|
||||
count: arg(1),
|
||||
}, {}),
|
||||
slice: DebuggerClient.requester(
|
||||
{
|
||||
type: "slice",
|
||||
start: arg(0),
|
||||
count: arg(1),
|
||||
},
|
||||
{}
|
||||
),
|
||||
|
||||
/**
|
||||
* Get all the symbols.
|
||||
|
@ -56,9 +62,12 @@ SymbolIteratorClient.prototype = {
|
|||
* @param callback Function
|
||||
* The function called when we receive the symbols.
|
||||
*/
|
||||
all: DebuggerClient.requester({
|
||||
type: "all",
|
||||
}, {}),
|
||||
all: DebuggerClient.requester(
|
||||
{
|
||||
type: "all",
|
||||
},
|
||||
{}
|
||||
),
|
||||
};
|
||||
|
||||
module.exports = SymbolIteratorClient;
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
"use strict";
|
||||
|
||||
const { ThreadStateTypes } = require("devtools/shared/client/constants");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { threadSpec } = require("devtools/shared/specs/thread");
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
|
@ -198,7 +201,7 @@ class ThreadClient extends FrontClassWithSpec(threadSpec) {
|
|||
async getSources() {
|
||||
let sources = [];
|
||||
try {
|
||||
({sources} = await super.sources());
|
||||
({ sources } = await super.sources());
|
||||
} catch (e) {
|
||||
// we may have closed the connection
|
||||
console.log(`getSources failed. Connection may have closed: ${e}`);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {Ci} = require("chrome");
|
||||
const { Ci } = require("chrome");
|
||||
const Services = require("Services");
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
@ -28,9 +28,13 @@ ContentObserver.prototype = {
|
|||
*/
|
||||
startListening: function() {
|
||||
Services.obs.addObserver(
|
||||
this._onContentGlobalCreated, "content-document-global-created");
|
||||
this._onContentGlobalCreated,
|
||||
"content-document-global-created"
|
||||
);
|
||||
Services.obs.addObserver(
|
||||
this._onInnerWindowDestroyed, "inner-window-destroyed");
|
||||
this._onInnerWindowDestroyed,
|
||||
"inner-window-destroyed"
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -38,9 +42,13 @@ ContentObserver.prototype = {
|
|||
*/
|
||||
stopListening: function() {
|
||||
Services.obs.removeObserver(
|
||||
this._onContentGlobalCreated, "content-document-global-created");
|
||||
this._onContentGlobalCreated,
|
||||
"content-document-global-created"
|
||||
);
|
||||
Services.obs.removeObserver(
|
||||
this._onInnerWindowDestroyed, "inner-window-destroyed");
|
||||
this._onInnerWindowDestroyed,
|
||||
"inner-window-destroyed"
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,11 +5,21 @@
|
|||
"use strict";
|
||||
|
||||
const Services = require("Services");
|
||||
const {getCSSLexer} = require("devtools/shared/css/lexer");
|
||||
const {cssColors} = require("devtools/shared/css/color-db");
|
||||
const { getCSSLexer } = require("devtools/shared/css/lexer");
|
||||
const { cssColors } = require("devtools/shared/css/color-db");
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS_ANGLEUNIT", "devtools/shared/css/constants", true);
|
||||
loader.lazyRequireGetter(this, "getAngleValueInDegrees", "devtools/shared/css/parsing-utils", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"CSS_ANGLEUNIT",
|
||||
"devtools/shared/css/constants",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"getAngleValueInDegrees",
|
||||
"devtools/shared/css/parsing-utils",
|
||||
true
|
||||
);
|
||||
|
||||
const COLOR_UNIT_PREF = "devtools.defaultColorUnit";
|
||||
|
||||
|
@ -83,11 +93,11 @@ module.exports.colorUtils = {
|
|||
* Values used in COLOR_UNIT_PREF
|
||||
*/
|
||||
CssColor.COLORUNIT = {
|
||||
"authored": "authored",
|
||||
"hex": "hex",
|
||||
"name": "name",
|
||||
"rgb": "rgb",
|
||||
"hsl": "hsl",
|
||||
authored: "authored",
|
||||
hex: "hex",
|
||||
name: "name",
|
||||
rgb: "rgb",
|
||||
hsl: "hsl",
|
||||
};
|
||||
|
||||
CssColor.prototype = {
|
||||
|
@ -106,8 +116,8 @@ CssColor.prototype = {
|
|||
// Specifically exclude the case where the color is
|
||||
// case-insensitive. This makes it so that "#000" isn't
|
||||
// considered "upper case" for the purposes of color cycling.
|
||||
this._colorUnitUppercase = (color === color.toUpperCase()) &&
|
||||
(color !== color.toLowerCase());
|
||||
this._colorUnitUppercase =
|
||||
color === color.toUpperCase() && color !== color.toLowerCase();
|
||||
},
|
||||
|
||||
get colorUnit() {
|
||||
|
@ -131,8 +141,10 @@ CssColor.prototype = {
|
|||
* @param {String} color The color to use
|
||||
*/
|
||||
setAuthoredUnitFromColor: function(color) {
|
||||
if (Services.prefs.getCharPref(COLOR_UNIT_PREF) ===
|
||||
CssColor.COLORUNIT.authored) {
|
||||
if (
|
||||
Services.prefs.getCharPref(COLOR_UNIT_PREF) ===
|
||||
CssColor.COLORUNIT.authored
|
||||
) {
|
||||
this._colorUnit = classifyColor(color);
|
||||
this._setColorUnitUppercase(color);
|
||||
}
|
||||
|
@ -195,7 +207,7 @@ CssColor.prototype = {
|
|||
if (tuple.a !== 1) {
|
||||
return this.hex;
|
||||
}
|
||||
const {r, g, b} = tuple;
|
||||
const { r, g, b } = tuple;
|
||||
return rgbToColorName(r, g, b) || this.hex;
|
||||
},
|
||||
|
||||
|
@ -209,9 +221,11 @@ CssColor.prototype = {
|
|||
}
|
||||
|
||||
let hex = this.longHex;
|
||||
if (hex.charAt(1) == hex.charAt(2) &&
|
||||
hex.charAt(3) == hex.charAt(4) &&
|
||||
hex.charAt(5) == hex.charAt(6)) {
|
||||
if (
|
||||
hex.charAt(1) == hex.charAt(2) &&
|
||||
hex.charAt(3) == hex.charAt(4) &&
|
||||
hex.charAt(5) == hex.charAt(6)
|
||||
) {
|
||||
hex = "#" + hex.charAt(1) + hex.charAt(3) + hex.charAt(5);
|
||||
}
|
||||
return hex;
|
||||
|
@ -224,12 +238,18 @@ CssColor.prototype = {
|
|||
}
|
||||
|
||||
let alphaHex = this.longAlphaHex;
|
||||
if (alphaHex.charAt(1) == alphaHex.charAt(2) &&
|
||||
alphaHex.charAt(3) == alphaHex.charAt(4) &&
|
||||
alphaHex.charAt(5) == alphaHex.charAt(6) &&
|
||||
alphaHex.charAt(7) == alphaHex.charAt(8)) {
|
||||
alphaHex = "#" + alphaHex.charAt(1) + alphaHex.charAt(3) +
|
||||
alphaHex.charAt(5) + alphaHex.charAt(7);
|
||||
if (
|
||||
alphaHex.charAt(1) == alphaHex.charAt(2) &&
|
||||
alphaHex.charAt(3) == alphaHex.charAt(4) &&
|
||||
alphaHex.charAt(5) == alphaHex.charAt(6) &&
|
||||
alphaHex.charAt(7) == alphaHex.charAt(8)
|
||||
) {
|
||||
alphaHex =
|
||||
"#" +
|
||||
alphaHex.charAt(1) +
|
||||
alphaHex.charAt(3) +
|
||||
alphaHex.charAt(5) +
|
||||
alphaHex.charAt(7);
|
||||
}
|
||||
return alphaHex;
|
||||
},
|
||||
|
@ -244,8 +264,12 @@ CssColor.prototype = {
|
|||
}
|
||||
|
||||
const tuple = this.getRGBATuple();
|
||||
return "#" + ((1 << 24) + (tuple.r << 16) + (tuple.g << 8) +
|
||||
(tuple.b << 0)).toString(16).substr(-6);
|
||||
return (
|
||||
"#" +
|
||||
((1 << 24) + (tuple.r << 16) + (tuple.g << 8) + (tuple.b << 0))
|
||||
.toString(16)
|
||||
.substr(-6)
|
||||
);
|
||||
},
|
||||
|
||||
get longAlphaHex() {
|
||||
|
@ -256,9 +280,15 @@ CssColor.prototype = {
|
|||
|
||||
const tuple = this.highResTuple;
|
||||
|
||||
return "#" + ((1 << 24) + (tuple.r << 16) + (tuple.g << 8) +
|
||||
(tuple.b << 0)).toString(16).substr(-6) +
|
||||
Math.round(tuple.a).toString(16).padStart(2, "0");
|
||||
return (
|
||||
"#" +
|
||||
((1 << 24) + (tuple.r << 16) + (tuple.g << 8) + (tuple.b << 0))
|
||||
.toString(16)
|
||||
.substr(-6) +
|
||||
Math.round(tuple.a)
|
||||
.toString(16)
|
||||
.padStart(2, "0")
|
||||
);
|
||||
},
|
||||
|
||||
get rgb() {
|
||||
|
@ -287,10 +317,17 @@ CssColor.prototype = {
|
|||
return this.authored;
|
||||
}
|
||||
const components = this.getRGBATuple();
|
||||
return "rgba(" + components.r + ", " +
|
||||
components.g + ", " +
|
||||
components.b + ", " +
|
||||
components.a + ")";
|
||||
return (
|
||||
"rgba(" +
|
||||
components.r +
|
||||
", " +
|
||||
components.g +
|
||||
", " +
|
||||
components.b +
|
||||
", " +
|
||||
components.a +
|
||||
")"
|
||||
);
|
||||
},
|
||||
|
||||
get hsl() {
|
||||
|
@ -407,8 +444,10 @@ CssColor.prototype = {
|
|||
color = this.rgb;
|
||||
}
|
||||
|
||||
if (this._colorUnitUppercase &&
|
||||
this.colorUnit != CssColor.COLORUNIT.authored) {
|
||||
if (
|
||||
this._colorUnitUppercase &&
|
||||
this.colorUnit != CssColor.COLORUNIT.authored
|
||||
) {
|
||||
color = color.toUpperCase();
|
||||
}
|
||||
|
||||
|
@ -432,7 +471,7 @@ CssColor.prototype = {
|
|||
* appropriate.
|
||||
*/
|
||||
_getHSLATuple: function() {
|
||||
const {r, g, b, a} = colorToRGBA(this.authored, this.cssColor4);
|
||||
const { r, g, b, a } = colorToRGBA(this.authored, this.cssColor4);
|
||||
|
||||
const [h, s, l] = rgbToHsl([r, g, b]);
|
||||
|
||||
|
@ -450,7 +489,7 @@ CssColor.prototype = {
|
|||
return this.authored;
|
||||
}
|
||||
|
||||
const {r, g, b} = this.getRGBATuple();
|
||||
const { r, g, b } = this.getRGBATuple();
|
||||
const [h, s, l] = rgbToHsl([r, g, b]);
|
||||
if (maybeAlpha !== undefined) {
|
||||
return "hsla(" + h + ", " + s + "%, " + l + "%, " + maybeAlpha + ")";
|
||||
|
@ -647,7 +686,10 @@ function hslToRGB([h, s, l]) {
|
|||
* name was not a valid color
|
||||
*/
|
||||
function hexToRGBA(name, highResolution) {
|
||||
let r, g, b, a = 1;
|
||||
let r,
|
||||
g,
|
||||
b,
|
||||
a = 1;
|
||||
|
||||
if (name.length === 3) {
|
||||
// short hex string (e.g. F0C)
|
||||
|
@ -685,7 +727,7 @@ function hexToRGBA(name, highResolution) {
|
|||
if (!highResolution) {
|
||||
a = Math.round(a * 10) / 10;
|
||||
}
|
||||
return {r, g, b, a};
|
||||
return { r, g, b, a };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -722,8 +764,10 @@ function getToken(lexer) {
|
|||
|
||||
while (true) {
|
||||
const token = lexer.nextToken();
|
||||
if (!token || (token.tokenType !== "comment" &&
|
||||
token.tokenType !== "whitespace")) {
|
||||
if (
|
||||
!token ||
|
||||
(token.tokenType !== "comment" && token.tokenType !== "whitespace")
|
||||
) {
|
||||
lexer._currentToken = token;
|
||||
return token;
|
||||
}
|
||||
|
@ -767,9 +811,9 @@ function expectSymbol(lexer, symbol) {
|
|||
}
|
||||
|
||||
const COLOR_COMPONENT_TYPE = {
|
||||
"integer": "integer",
|
||||
"number": "number",
|
||||
"percentage": "percentage",
|
||||
integer: "integer",
|
||||
number: "number",
|
||||
percentage: "percentage",
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -935,10 +979,16 @@ function parseHsl(lexer) {
|
|||
// version of parseColorComponent function for them. No need to check the
|
||||
// separator after 'lightness'. It will be checked in opacity value parsing.
|
||||
const separatorBeforeAlpha = hasComma ? commaSeparator : "/";
|
||||
if (parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
hasComma ? commaSeparator : "", hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage, "", hsl) &&
|
||||
parseColorOpacityAndCloseParen(lexer, separatorBeforeAlpha, a)) {
|
||||
if (
|
||||
parseColorComponent(
|
||||
lexer,
|
||||
COLOR_COMPONENT_TYPE.percentage,
|
||||
hasComma ? commaSeparator : "",
|
||||
hsl
|
||||
) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage, "", hsl) &&
|
||||
parseColorOpacityAndCloseParen(lexer, separatorBeforeAlpha, a)
|
||||
) {
|
||||
return [...hslToRGB(hsl), ...a];
|
||||
}
|
||||
|
||||
|
@ -980,18 +1030,32 @@ function parseOldStyleHsl(lexer, hasAlpha) {
|
|||
// The saturation and lightness are <percentage>, so reuse the <percentage>
|
||||
// version of parseColorComponent function for them. The opacity is <number>
|
||||
if (hasAlpha) {
|
||||
if (parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator, hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator, hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.number,
|
||||
closeParen, a)) {
|
||||
if (
|
||||
parseColorComponent(
|
||||
lexer,
|
||||
COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator,
|
||||
hsl
|
||||
) &&
|
||||
parseColorComponent(
|
||||
lexer,
|
||||
COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator,
|
||||
hsl
|
||||
) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.number, closeParen, a)
|
||||
) {
|
||||
return [...hslToRGB(hsl), ...a];
|
||||
}
|
||||
} else if (parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator, hsl) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage,
|
||||
closeParen, hsl)) {
|
||||
} else if (
|
||||
parseColorComponent(
|
||||
lexer,
|
||||
COLOR_COMPONENT_TYPE.percentage,
|
||||
commaSeparator,
|
||||
hsl
|
||||
) &&
|
||||
parseColorComponent(lexer, COLOR_COMPONENT_TYPE.percentage, closeParen, hsl)
|
||||
) {
|
||||
return [...hslToRGB(hsl), 1];
|
||||
}
|
||||
|
||||
|
@ -1022,9 +1086,10 @@ function parseRgb(lexer) {
|
|||
return null;
|
||||
}
|
||||
unGetToken(lexer);
|
||||
const type = (token.tokenType === "percentage") ?
|
||||
COLOR_COMPONENT_TYPE.percentage :
|
||||
COLOR_COMPONENT_TYPE.number;
|
||||
const type =
|
||||
token.tokenType === "percentage"
|
||||
? COLOR_COMPONENT_TYPE.percentage
|
||||
: COLOR_COMPONENT_TYPE.number;
|
||||
|
||||
// Parse R.
|
||||
if (!parseColorComponent(lexer, type, "", rgba)) {
|
||||
|
@ -1036,9 +1101,11 @@ function parseRgb(lexer) {
|
|||
// No need to check the separator after 'B'. It will be checked in 'A' values
|
||||
// parsing.
|
||||
const separatorBeforeAlpha = hasComma ? commaSeparator : "/";
|
||||
if (parseColorComponent(lexer, type, hasComma ? commaSeparator : "", rgba) &&
|
||||
parseColorComponent(lexer, type, "", rgba) &&
|
||||
parseColorOpacityAndCloseParen(lexer, separatorBeforeAlpha, rgba)) {
|
||||
if (
|
||||
parseColorComponent(lexer, type, hasComma ? commaSeparator : "", rgba) &&
|
||||
parseColorComponent(lexer, type, "", rgba) &&
|
||||
parseColorOpacityAndCloseParen(lexer, separatorBeforeAlpha, rgba)
|
||||
) {
|
||||
if (type === COLOR_COMPONENT_TYPE.percentage) {
|
||||
rgba[0] = Math.round(255 * rgba[0]);
|
||||
rgba[1] = Math.round(255 * rgba[1]);
|
||||
|
@ -1070,27 +1137,33 @@ function parseOldStyleRgb(lexer, hasAlpha) {
|
|||
const rgba = [];
|
||||
|
||||
const token = getToken(lexer);
|
||||
if (token.tokenType !== "percentage" &&
|
||||
(token.tokenType !== "number" || !token.isInteger)) {
|
||||
if (
|
||||
token.tokenType !== "percentage" &&
|
||||
(token.tokenType !== "number" || !token.isInteger)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
unGetToken(lexer);
|
||||
const type = (token.tokenType === "percentage") ?
|
||||
COLOR_COMPONENT_TYPE.percentage :
|
||||
COLOR_COMPONENT_TYPE.integer;
|
||||
const type =
|
||||
token.tokenType === "percentage"
|
||||
? COLOR_COMPONENT_TYPE.percentage
|
||||
: COLOR_COMPONENT_TYPE.integer;
|
||||
|
||||
// Parse R. G, B and A.
|
||||
if (hasAlpha) {
|
||||
if (!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, COLOR_COMPONENT_TYPE.number,
|
||||
closeParen, rgba)) {
|
||||
if (
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, COLOR_COMPONENT_TYPE.number, closeParen, rgba)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
} else if (!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, closeParen, rgba)) {
|
||||
} else if (
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, commaSeparator, rgba) ||
|
||||
!parseColorComponent(lexer, type, closeParen, rgba)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1120,11 +1193,11 @@ function colorToRGBA(name, useCssColor4ColorFunction = false) {
|
|||
|
||||
if (name in cssColors) {
|
||||
const result = cssColors[name];
|
||||
return {r: result[0], g: result[1], b: result[2], a: result[3]};
|
||||
return { r: result[0], g: result[1], b: result[2], a: result[3] };
|
||||
} else if (name === "transparent") {
|
||||
return {r: 0, g: 0, b: 0, a: 0};
|
||||
return { r: 0, g: 0, b: 0, a: 0 };
|
||||
} else if (name === "currentcolor") {
|
||||
return {r: 0, g: 0, b: 0, a: 1};
|
||||
return { r: 0, g: 0, b: 0, a: 1 };
|
||||
}
|
||||
|
||||
const lexer = getCSSLexer(name);
|
||||
|
@ -1142,8 +1215,11 @@ function colorToRGBA(name, useCssColor4ColorFunction = false) {
|
|||
}
|
||||
|
||||
const expectedFunctions = ["rgba", "rgb", "hsla", "hsl"];
|
||||
if (!func || func.tokenType !== "function" ||
|
||||
!expectedFunctions.includes(func.text)) {
|
||||
if (
|
||||
!func ||
|
||||
func.tokenType !== "function" ||
|
||||
!expectedFunctions.includes(func.text)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1151,8 +1227,10 @@ function colorToRGBA(name, useCssColor4ColorFunction = false) {
|
|||
|
||||
let vals;
|
||||
if (!useCssColor4ColorFunction) {
|
||||
const hasAlpha = (func.text === "rgba" || func.text === "hsla");
|
||||
vals = hsl ? parseOldStyleHsl(lexer, hasAlpha) : parseOldStyleRgb(lexer, hasAlpha);
|
||||
const hasAlpha = func.text === "rgba" || func.text === "hsla";
|
||||
vals = hsl
|
||||
? parseOldStyleHsl(lexer, hasAlpha)
|
||||
: parseOldStyleRgb(lexer, hasAlpha);
|
||||
} else {
|
||||
vals = hsl ? parseHsl(lexer) : parseRgb(lexer);
|
||||
}
|
||||
|
@ -1164,7 +1242,7 @@ function colorToRGBA(name, useCssColor4ColorFunction = false) {
|
|||
return null;
|
||||
}
|
||||
|
||||
return {r: vals[0], g: vals[1], b: vals[2], a: vals[3]};
|
||||
return { r: vals[0], g: vals[1], b: vals[2], a: vals[3] };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1188,8 +1266,10 @@ function isValidCSSColor(name, useCssColor4ColorFunction = false) {
|
|||
function calculateLuminance(rgba) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
rgba[i] /= 255;
|
||||
rgba[i] = (rgba[i] < 0.03928) ? (rgba[i] / 12.92) :
|
||||
Math.pow(((rgba[i] + 0.055) / 1.055), 2.4);
|
||||
rgba[i] =
|
||||
rgba[i] < 0.03928
|
||||
? rgba[i] / 12.92
|
||||
: Math.pow((rgba[i] + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
return 0.2126 * rgba[0] + 0.7152 * rgba[1] + 0.0722 * rgba[2];
|
||||
}
|
||||
|
@ -1204,9 +1284,9 @@ function calculateLuminance(rgba) {
|
|||
* @return {Array}
|
||||
* An array with combined [r,g,b,a] colors.
|
||||
*/
|
||||
function blendColors(foregroundColor, backgroundColor = [ 255, 255, 255, 1 ]) {
|
||||
const [ fgR, fgG, fgB, fgA ] = foregroundColor;
|
||||
const [ bgR, bgG, bgB, bgA ] = backgroundColor;
|
||||
function blendColors(foregroundColor, backgroundColor = [255, 255, 255, 1]) {
|
||||
const [fgR, fgG, fgB, fgA] = foregroundColor;
|
||||
const [bgR, bgG, bgB, bgA] = backgroundColor;
|
||||
if (fgA === 1) {
|
||||
return foregroundColor;
|
||||
}
|
||||
|
@ -1241,5 +1321,5 @@ function calculateContrastRatio(backgroundColor, textColor) {
|
|||
const textLuminance = calculateLuminance(textColor);
|
||||
const ratio = (textLuminance + 0.05) / (backgroundLuminance + 0.05);
|
||||
|
||||
return (ratio > 1.0) ? ratio : (1 / ratio);
|
||||
return ratio > 1.0 ? ratio : 1 / ratio;
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
* All CSS <angle> types that properties can support.
|
||||
*/
|
||||
exports.CSS_ANGLEUNIT = {
|
||||
"deg": "deg",
|
||||
"rad": "rad",
|
||||
"grad": "grad",
|
||||
"turn": "turn",
|
||||
deg: "deg",
|
||||
rad: "rad",
|
||||
grad: "grad",
|
||||
turn: "turn",
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -19,9 +19,9 @@ exports.CSS_ANGLEUNIT = {
|
|||
* Kept for backwards compatibility. Remove after Firefox 70.
|
||||
*/
|
||||
exports.CSS_TYPES = {
|
||||
"color": 2,
|
||||
"gradient": 4,
|
||||
"timing-function": 10,
|
||||
color: 2,
|
||||
gradient: 4,
|
||||
"timing-function": 10,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
* as known by the platform. It is run from ./mach_commands.py by running
|
||||
* `mach devtools-css-db`.
|
||||
*/
|
||||
var {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
||||
var {generateCssProperties} = require("devtools/server/actors/css-properties");
|
||||
var { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
||||
var {
|
||||
generateCssProperties,
|
||||
} = require("devtools/server/actors/css-properties");
|
||||
const InspectorUtils = require("InspectorUtils");
|
||||
|
||||
// xpcshell can output extra information, so place some delimiter text between
|
||||
|
@ -18,11 +20,13 @@ const InspectorUtils = require("InspectorUtils");
|
|||
dump("DEVTOOLS_CSS_DB_DELIMITER");
|
||||
|
||||
// Output JSON
|
||||
dump(JSON.stringify({
|
||||
cssProperties: cssProperties(),
|
||||
preferences: preferences(),
|
||||
pseudoElements: pseudoElements(),
|
||||
}));
|
||||
dump(
|
||||
JSON.stringify({
|
||||
cssProperties: cssProperties(),
|
||||
preferences: preferences(),
|
||||
pseudoElements: pseudoElements(),
|
||||
})
|
||||
);
|
||||
|
||||
dump("DEVTOOLS_CSS_DB_DELIMITER");
|
||||
|
||||
|
@ -53,7 +57,7 @@ function cssProperties() {
|
|||
function preferences() {
|
||||
const prefs = InspectorUtils.getCSSPropertyPrefs();
|
||||
const result = [];
|
||||
for (const {name, pref} of prefs) {
|
||||
for (const { name, pref } of prefs) {
|
||||
result.push([name, pref]);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -133,14 +133,14 @@ const NUMBER_SIGN = "#".charCodeAt(0);
|
|||
const PERCENT_SIGN = "%".charCodeAt(0);
|
||||
const PLUS_SIGN = "+".charCodeAt(0);
|
||||
const QUESTION_MARK = "?".charCodeAt(0);
|
||||
const QUOTATION_MARK = "\"".charCodeAt(0);
|
||||
const QUOTATION_MARK = '"'.charCodeAt(0);
|
||||
const REVERSE_SOLIDUS = "\\".charCodeAt(0);
|
||||
const RIGHT_PARENTHESIS = ")".charCodeAt(0);
|
||||
const SOLIDUS = "/".charCodeAt(0);
|
||||
const TILDE = "~".charCodeAt(0);
|
||||
const VERTICAL_LINE = "|".charCodeAt(0);
|
||||
|
||||
const UCS2_REPLACEMENT_CHAR = 0xFFFD;
|
||||
const UCS2_REPLACEMENT_CHAR = 0xfffd;
|
||||
|
||||
const kImpliedEOFCharacters = [
|
||||
UCS2_REPLACEMENT_CHAR,
|
||||
|
@ -160,7 +160,7 @@ const kImpliedEOFCharacters = [
|
|||
* @return {Number} the character or its replacement
|
||||
*/
|
||||
function ensureValidChar(c) {
|
||||
if (c >= 0x00110000 || (c & 0xFFF800) == 0xD800) {
|
||||
if (c >= 0x00110000 || (c & 0xfff800) == 0xd800) {
|
||||
// Out of range or a surrogate.
|
||||
return UCS2_REPLACEMENT_CHAR;
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ function ensureValidChar(c) {
|
|||
* the input string.
|
||||
*/
|
||||
function stringToCodes(str) {
|
||||
return Array.prototype.map.call(str, (c) => c.charCodeAt(0));
|
||||
return Array.prototype.map.call(str, c => c.charCodeAt(0));
|
||||
}
|
||||
|
||||
const IS_HEX_DIGIT = 0x01;
|
||||
|
@ -204,38 +204,150 @@ const SUIJX = S | U | I | J | X;
|
|||
|
||||
/* eslint-disable indent, indent-legacy, no-multi-spaces, comma-spacing, spaced-comment */
|
||||
const gLexTable = [
|
||||
// 00 01 02 03 04 05 06 07
|
||||
0, S, S, S, S, S, S, S,
|
||||
// 08 TAB LF 0B FF CR 0E 0F
|
||||
S, SH, V, S, V, V, S, S,
|
||||
// 10 11 12 13 14 15 16 17
|
||||
S, S, S, S, S, S, S, S,
|
||||
// 18 19 1A 1B 1C 1D 1E 1F
|
||||
S, S, S, S, S, S, S, S,
|
||||
//SPC ! " # $ % & '
|
||||
SH, SU, 0, SU, SU, SU, SU, 0,
|
||||
// ( ) * + , - . /
|
||||
S, S, SU, SU, SU, SUI, SU, SU,
|
||||
// 0 1 2 3 4 5 6 7
|
||||
SUIX, SUIX, SUIX, SUIX, SUIX, SUIX, SUIX, SUIX,
|
||||
// 8 9 : ; < = > ?
|
||||
SUIX, SUIX, SU, SU, SU, SU, SU, SU,
|
||||
// @ A B C D E F G
|
||||
SU,SUIJX,SUIJX,SUIJX,SUIJX,SUIJX,SUIJX, SUIJ,
|
||||
// H I J K L M N O
|
||||
SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ,
|
||||
// P Q R S T U V W
|
||||
SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ,
|
||||
// X Y Z [ \ ] ^ _
|
||||
SUIJ, SUIJ, SUIJ, SU, J, SU, SU, SUIJ,
|
||||
// ` a b c d e f g
|
||||
SU,SUIJX,SUIJX,SUIJX,SUIJX,SUIJX,SUIJX, SUIJ,
|
||||
// h i j k l m n o
|
||||
SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ,
|
||||
// p q r s t u v w
|
||||
SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ, SUIJ,
|
||||
// x y z { | } ~ 7F
|
||||
SUIJ, SUIJ, SUIJ, SU, SU, SU, SU, S,
|
||||
// 00 01 02 03 04 05 06 07
|
||||
0,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
// 08 TAB LF 0B FF CR 0E 0F
|
||||
S,
|
||||
SH,
|
||||
V,
|
||||
S,
|
||||
V,
|
||||
V,
|
||||
S,
|
||||
S,
|
||||
// 10 11 12 13 14 15 16 17
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
// 18 19 1A 1B 1C 1D 1E 1F
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
//SPC ! " # $ % & '
|
||||
SH,
|
||||
SU,
|
||||
0,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
0,
|
||||
// ( ) * + , - . /
|
||||
S,
|
||||
S,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
SUI,
|
||||
SU,
|
||||
SU,
|
||||
// 0 1 2 3 4 5 6 7
|
||||
SUIX,
|
||||
SUIX,
|
||||
SUIX,
|
||||
SUIX,
|
||||
SUIX,
|
||||
SUIX,
|
||||
SUIX,
|
||||
SUIX,
|
||||
// 8 9 : ; < = > ?
|
||||
SUIX,
|
||||
SUIX,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
// @ A B C D E F G
|
||||
SU,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJ,
|
||||
// H I J K L M N O
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
// P Q R S T U V W
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
// X Y Z [ \ ] ^ _
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SU,
|
||||
J,
|
||||
SU,
|
||||
SU,
|
||||
SUIJ,
|
||||
// ` a b c d e f g
|
||||
SU,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJX,
|
||||
SUIJ,
|
||||
// h i j k l m n o
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
// p q r s t u v w
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
// x y z { | } ~ 7F
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SUIJ,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
SU,
|
||||
S,
|
||||
];
|
||||
/* eslint-enable indent, indent-legacy, no-multi-spaces, comma-spacing, spaced-comment */
|
||||
|
||||
|
@ -304,16 +416,18 @@ function IsIdentStart(ch) {
|
|||
* identifier.
|
||||
*/
|
||||
function StartsIdent(aFirstChar, aSecondChar) {
|
||||
return IsIdentStart(aFirstChar) ||
|
||||
(aFirstChar == HYPHEN_MINUS && (aSecondChar == HYPHEN_MINUS ||
|
||||
IsIdentStart(aSecondChar)));
|
||||
return (
|
||||
IsIdentStart(aFirstChar) ||
|
||||
(aFirstChar == HYPHEN_MINUS &&
|
||||
(aSecondChar == HYPHEN_MINUS || IsIdentStart(aSecondChar)))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* True if 'ch' is a decimal digit.
|
||||
*/
|
||||
function IsDigit(ch) {
|
||||
return (ch >= DIGIT_ZERO) && (ch <= DIGIT_NINE);
|
||||
return ch >= DIGIT_ZERO && ch <= DIGIT_NINE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -351,12 +465,18 @@ function HexDigitValue(ch) {
|
|||
*/
|
||||
function MatchOperatorType(ch) {
|
||||
switch (ch) {
|
||||
case TILDE: return eCSSToken_Includes;
|
||||
case VERTICAL_LINE: return eCSSToken_Dashmatch;
|
||||
case CIRCUMFLEX_ACCENT: return eCSSToken_Beginsmatch;
|
||||
case DOLLAR_SIGN: return eCSSToken_Endsmatch;
|
||||
case ASTERISK: return eCSSToken_Containsmatch;
|
||||
default: return eCSSToken_Symbol;
|
||||
case TILDE:
|
||||
return eCSSToken_Includes;
|
||||
case VERTICAL_LINE:
|
||||
return eCSSToken_Dashmatch;
|
||||
case CIRCUMFLEX_ACCENT:
|
||||
return eCSSToken_Beginsmatch;
|
||||
case DOLLAR_SIGN:
|
||||
return eCSSToken_Endsmatch;
|
||||
case ASTERISK:
|
||||
return eCSSToken_Containsmatch;
|
||||
default:
|
||||
return eCSSToken_Symbol;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,16 +548,23 @@ Scanner.prototype = {
|
|||
|
||||
let eofChars = this.mEOFCharacters;
|
||||
|
||||
if (aPreserveBackslash &&
|
||||
(eofChars & (eEOFCharacters_DropBackslash |
|
||||
eEOFCharacters_ReplacementChar)) != 0) {
|
||||
eofChars &= ~(eEOFCharacters_DropBackslash |
|
||||
eEOFCharacters_ReplacementChar);
|
||||
if (
|
||||
aPreserveBackslash &&
|
||||
(eofChars &
|
||||
(eEOFCharacters_DropBackslash | eEOFCharacters_ReplacementChar)) !=
|
||||
0
|
||||
) {
|
||||
eofChars &= ~(
|
||||
eEOFCharacters_DropBackslash | eEOFCharacters_ReplacementChar
|
||||
);
|
||||
result += "\\";
|
||||
}
|
||||
|
||||
if ((eofChars & eEOFCharacters_DropBackslash) != 0 &&
|
||||
result.length > 0 && result.endsWith("\\")) {
|
||||
if (
|
||||
(eofChars & eEOFCharacters_DropBackslash) != 0 &&
|
||||
result.length > 0 &&
|
||||
result.endsWith("\\")
|
||||
) {
|
||||
result = result.slice(0, -1);
|
||||
}
|
||||
|
||||
|
@ -525,7 +652,7 @@ Scanner.prototype = {
|
|||
|
||||
case eCSSToken_Dimension:
|
||||
resultToken.text = constructText();
|
||||
/* Fall through. */
|
||||
/* Fall through. */
|
||||
case eCSSToken_Number:
|
||||
case eCSSToken_Percentage:
|
||||
resultToken.number = token.mNumber;
|
||||
|
@ -595,9 +722,11 @@ Scanner.prototype = {
|
|||
*/
|
||||
AdvanceLine: function() {
|
||||
// Advance over \r\n as a unit.
|
||||
if (this.mBuffer.charCodeAt(this.mOffset) == CARRIAGE_RETURN &&
|
||||
this.mOffset + 1 < this.mCount &&
|
||||
this.mBuffer.charCodeAt(this.mOffset + 1) == LINE_FEED) {
|
||||
if (
|
||||
this.mBuffer.charCodeAt(this.mOffset) == CARRIAGE_RETURN &&
|
||||
this.mOffset + 1 < this.mCount &&
|
||||
this.mBuffer.charCodeAt(this.mOffset + 1) == LINE_FEED
|
||||
) {
|
||||
this.mOffset += 2;
|
||||
} else {
|
||||
this.mOffset += 1;
|
||||
|
@ -616,7 +745,8 @@ Scanner.prototype = {
|
|||
SkipWhitespace: function() {
|
||||
for (;;) {
|
||||
const ch = this.Peek();
|
||||
if (!IsWhitespace(ch)) { // EOF counts as non-whitespace
|
||||
if (!IsWhitespace(ch)) {
|
||||
// EOF counts as non-whitespace
|
||||
break;
|
||||
}
|
||||
if (IsVertSpace(ch)) {
|
||||
|
@ -760,8 +890,10 @@ Scanner.prototype = {
|
|||
for (;;) {
|
||||
// Consume runs of unescaped characters in one go.
|
||||
let n = this.mOffset;
|
||||
while (n < this.mCount && IsOpenCharClass(this.mBuffer.charCodeAt(n),
|
||||
aClass)) {
|
||||
while (
|
||||
n < this.mCount &&
|
||||
IsOpenCharClass(this.mBuffer.charCodeAt(n), aClass)
|
||||
) {
|
||||
n++;
|
||||
}
|
||||
if (n > this.mOffset) {
|
||||
|
@ -849,8 +981,9 @@ Scanner.prototype = {
|
|||
|
||||
const ch = this.Peek();
|
||||
if (IsIdentChar(ch) || ch == REVERSE_SOLIDUS) {
|
||||
const type =
|
||||
StartsIdent(ch, this.Peek(1)) ? eCSSToken_ID : eCSSToken_Hash;
|
||||
const type = StartsIdent(ch, this.Peek(1))
|
||||
? eCSSToken_ID
|
||||
: eCSSToken_Hash;
|
||||
aToken.mIdent.length = 0;
|
||||
if (this.GatherText(IS_IDCHAR, aToken.mIdent)) {
|
||||
aToken.mType = type;
|
||||
|
@ -891,13 +1024,13 @@ Scanner.prototype = {
|
|||
// Sign of the exponent.
|
||||
let expSign = 1;
|
||||
|
||||
aToken.mHasSign = (c == PLUS_SIGN || c == HYPHEN_MINUS);
|
||||
aToken.mHasSign = c == PLUS_SIGN || c == HYPHEN_MINUS;
|
||||
if (aToken.mHasSign) {
|
||||
this.Advance();
|
||||
c = this.Peek();
|
||||
}
|
||||
|
||||
let gotDot = (c == FULL_STOP);
|
||||
let gotDot = c == FULL_STOP;
|
||||
|
||||
if (!gotDot) {
|
||||
// Scan the integer part of the mantissa.
|
||||
|
@ -907,7 +1040,7 @@ Scanner.prototype = {
|
|||
c = this.Peek();
|
||||
} while (IsDigit(c));
|
||||
|
||||
gotDot = (c == FULL_STOP) && IsDigit(this.Peek(1));
|
||||
gotDot = c == FULL_STOP && IsDigit(this.Peek(1));
|
||||
}
|
||||
|
||||
if (gotDot) {
|
||||
|
@ -928,9 +1061,11 @@ Scanner.prototype = {
|
|||
if (c == LATIN_SMALL_LETTER_E || c == LATIN_CAPITAL_LETTER_E) {
|
||||
const expSignChar = this.Peek(1);
|
||||
const nextChar = this.Peek(2);
|
||||
if (IsDigit(expSignChar) ||
|
||||
((expSignChar == HYPHEN_MINUS || expSignChar == PLUS_SIGN) &&
|
||||
IsDigit(nextChar))) {
|
||||
if (
|
||||
IsDigit(expSignChar) ||
|
||||
((expSignChar == HYPHEN_MINUS || expSignChar == PLUS_SIGN) &&
|
||||
IsDigit(nextChar))
|
||||
) {
|
||||
gotE = true;
|
||||
if (expSignChar == HYPHEN_MINUS) {
|
||||
expSign = -1;
|
||||
|
@ -1009,9 +1144,11 @@ Scanner.prototype = {
|
|||
|
||||
const ch = this.Peek();
|
||||
if (ch == -1) {
|
||||
this.AddEOFCharacters(aStop == QUOTATION_MARK ?
|
||||
eEOFCharacters_DoubleQuote :
|
||||
eEOFCharacters_SingleQuote);
|
||||
this.AddEOFCharacters(
|
||||
aStop == QUOTATION_MARK
|
||||
? eEOFCharacters_DoubleQuote
|
||||
: eEOFCharacters_SingleQuote
|
||||
);
|
||||
break; // EOF ends a string token with no error.
|
||||
}
|
||||
if (ch == aStop) {
|
||||
|
@ -1073,7 +1210,7 @@ Scanner.prototype = {
|
|||
} else {
|
||||
haveQues = true;
|
||||
low = low * 16 + 0x0;
|
||||
high = high * 16 + 0xF;
|
||||
high = high * 16 + 0xf;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
@ -1219,8 +1356,10 @@ Scanner.prototype = {
|
|||
aToken.mType = eCSSToken_Whitespace;
|
||||
return true;
|
||||
}
|
||||
if (ch == SOLIDUS && // !IsSVGMode() &&
|
||||
this.Peek(1) == ASTERISK) {
|
||||
if (
|
||||
ch == SOLIDUS && // !IsSVGMode() &&
|
||||
this.Peek(1) == ASTERISK
|
||||
) {
|
||||
this.SkipComment();
|
||||
aToken.mType = eCSSToken_Comment;
|
||||
return true;
|
||||
|
@ -1282,10 +1421,12 @@ Scanner.prototype = {
|
|||
}
|
||||
|
||||
// the other HTML-comment token
|
||||
if (ch == LESS_THAN_SIGN &&
|
||||
this.Peek(1) == EXCLAMATION_MARK &&
|
||||
this.Peek(2) == HYPHEN_MINUS &&
|
||||
this.Peek(3) == HYPHEN_MINUS) {
|
||||
if (
|
||||
ch == LESS_THAN_SIGN &&
|
||||
this.Peek(1) == EXCLAMATION_MARK &&
|
||||
this.Peek(2) == HYPHEN_MINUS &&
|
||||
this.Peek(3) == HYPHEN_MINUS
|
||||
) {
|
||||
this.Advance(4);
|
||||
aToken.mType = eCSSToken_HTMLComment;
|
||||
aToken.mIdent = stringToCodes("<!--");
|
||||
|
|
|
@ -13,20 +13,25 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {getCSSLexer} = require("devtools/shared/css/lexer");
|
||||
const { getCSSLexer } = require("devtools/shared/css/lexer");
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS_ANGLEUNIT", "devtools/shared/css/constants", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"CSS_ANGLEUNIT",
|
||||
"devtools/shared/css/constants",
|
||||
true
|
||||
);
|
||||
|
||||
const SELECTOR_ATTRIBUTE = exports.SELECTOR_ATTRIBUTE = 1;
|
||||
const SELECTOR_ELEMENT = exports.SELECTOR_ELEMENT = 2;
|
||||
const SELECTOR_PSEUDO_CLASS = exports.SELECTOR_PSEUDO_CLASS = 3;
|
||||
const SELECTOR_ATTRIBUTE = (exports.SELECTOR_ATTRIBUTE = 1);
|
||||
const SELECTOR_ELEMENT = (exports.SELECTOR_ELEMENT = 2);
|
||||
const SELECTOR_PSEUDO_CLASS = (exports.SELECTOR_PSEUDO_CLASS = 3);
|
||||
const CSS_BLOCKS = { "(": ")", "[": "]", "{": "}" };
|
||||
|
||||
// When commenting out a declaration, we put this character into the
|
||||
// comment opener so that future parses of the commented text know to
|
||||
// bypass the property name validity heuristic.
|
||||
const COMMENT_PARSING_HEURISTIC_BYPASS_CHAR =
|
||||
exports.COMMENT_PARSING_HEURISTIC_BYPASS_CHAR = "!";
|
||||
const COMMENT_PARSING_HEURISTIC_BYPASS_CHAR = (exports.COMMENT_PARSING_HEURISTIC_BYPASS_CHAR =
|
||||
"!");
|
||||
|
||||
/**
|
||||
* A generator function that lexes a CSS source string, yielding the
|
||||
|
@ -97,7 +102,7 @@ function cssTokenizerWithLineColumn(string) {
|
|||
line: lineNumber,
|
||||
column: columnNumber,
|
||||
};
|
||||
token.loc = {start: startLoc};
|
||||
token.loc = { start: startLoc };
|
||||
|
||||
result.push(token);
|
||||
prevToken = token;
|
||||
|
@ -153,8 +158,12 @@ function unescapeCSSComment(inputString) {
|
|||
* @return {array} Array of declarations of the same form as returned
|
||||
* by parseDeclarations.
|
||||
*/
|
||||
function parseCommentDeclarations(isCssPropertyKnown, commentText, startOffset,
|
||||
endOffset) {
|
||||
function parseCommentDeclarations(
|
||||
isCssPropertyKnown,
|
||||
commentText,
|
||||
startOffset,
|
||||
endOffset
|
||||
) {
|
||||
let commentOverride = false;
|
||||
if (commentText === "") {
|
||||
return [];
|
||||
|
@ -210,8 +219,13 @@ function parseCommentDeclarations(isCssPropertyKnown, commentText, startOffset,
|
|||
// seem worthwhile to support declarations in comments-in-comments
|
||||
// here, as there's no way to generate those using the tools, and
|
||||
// users would be crazy to write such things.
|
||||
const newDecls = parseDeclarationsInternal(isCssPropertyKnown, rewrittenText,
|
||||
false, true, commentOverride);
|
||||
const newDecls = parseDeclarationsInternal(
|
||||
isCssPropertyKnown,
|
||||
rewrittenText,
|
||||
false,
|
||||
true,
|
||||
commentOverride
|
||||
);
|
||||
for (const decl of newDecls) {
|
||||
decl.offsets[0] = rewrites[decl.offsets[0]];
|
||||
decl.offsets[1] = rewrites[decl.offsets[1]];
|
||||
|
@ -230,10 +244,14 @@ function parseCommentDeclarations(isCssPropertyKnown, commentText, startOffset,
|
|||
* parseDeclarations
|
||||
*/
|
||||
function getEmptyDeclaration() {
|
||||
return {name: "", value: "", priority: "",
|
||||
terminator: "",
|
||||
offsets: [undefined, undefined],
|
||||
colonOffsets: false};
|
||||
return {
|
||||
name: "",
|
||||
value: "",
|
||||
priority: "",
|
||||
terminator: "",
|
||||
offsets: [undefined, undefined],
|
||||
colonOffsets: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,8 +287,13 @@ function cssTrim(str) {
|
|||
* heuristic.
|
||||
*/
|
||||
/* eslint-disable complexity */
|
||||
function parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
||||
parseComments, inComment, commentOverride) {
|
||||
function parseDeclarationsInternal(
|
||||
isCssPropertyKnown,
|
||||
inputString,
|
||||
parseComments,
|
||||
inComment,
|
||||
commentOverride
|
||||
) {
|
||||
if (inputString === null || inputString === undefined) {
|
||||
throw new Error("empty input string");
|
||||
}
|
||||
|
@ -309,16 +332,23 @@ function parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
|||
lastProp.offsets[0] = token.startOffset;
|
||||
}
|
||||
lastProp.offsets[1] = token.endOffset;
|
||||
} else if (lastProp.name && !current && !importantState &&
|
||||
!lastProp.priority && lastProp.colonOffsets[1]) {
|
||||
} else if (
|
||||
lastProp.name &&
|
||||
!current &&
|
||||
!importantState &&
|
||||
!lastProp.priority &&
|
||||
lastProp.colonOffsets[1]
|
||||
) {
|
||||
// Whitespace appearing after the ":" is attributed to it.
|
||||
lastProp.colonOffsets[1] = token.endOffset;
|
||||
} else if (importantState === 1) {
|
||||
importantWS = true;
|
||||
}
|
||||
|
||||
if (token.tokenType === "symbol" &&
|
||||
currentBlocks[currentBlocks.length - 1] === token.text) {
|
||||
if (
|
||||
token.tokenType === "symbol" &&
|
||||
currentBlocks[currentBlocks.length - 1] === token.text
|
||||
) {
|
||||
// Closing the last block that was opened.
|
||||
currentBlocks.pop();
|
||||
current += token.text;
|
||||
|
@ -343,8 +373,11 @@ function parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
|||
|
||||
// When parsing a comment body, if the left-hand-side is not a
|
||||
// valid property name, then drop it and stop parsing.
|
||||
if (inComment && !commentOverride &&
|
||||
!isCssPropertyKnown(lastProp.name)) {
|
||||
if (
|
||||
inComment &&
|
||||
!commentOverride &&
|
||||
!isCssPropertyKnown(lastProp.name)
|
||||
) {
|
||||
lastProp.name = null;
|
||||
break;
|
||||
}
|
||||
|
@ -353,8 +386,11 @@ function parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
|||
// with colons)
|
||||
current += ":";
|
||||
}
|
||||
} else if (token.tokenType === "symbol" && token.text === ";" &&
|
||||
!currentBlocks.length) {
|
||||
} else if (
|
||||
token.tokenType === "symbol" &&
|
||||
token.text === ";" &&
|
||||
!currentBlocks.length
|
||||
) {
|
||||
lastProp.terminator = "";
|
||||
// When parsing a comment, if the name hasn't been set, then we
|
||||
// have probably just seen an ordinary semicolon used in text,
|
||||
|
@ -406,11 +442,16 @@ function parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
|||
}
|
||||
} else if (token.tokenType === "comment") {
|
||||
if (parseComments && !lastProp.name && !lastProp.value) {
|
||||
const commentText = inputString.substring(token.startOffset + 2,
|
||||
token.endOffset - 2);
|
||||
const newDecls = parseCommentDeclarations(isCssPropertyKnown, commentText,
|
||||
token.startOffset,
|
||||
token.endOffset);
|
||||
const commentText = inputString.substring(
|
||||
token.startOffset + 2,
|
||||
token.endOffset - 2
|
||||
);
|
||||
const newDecls = parseCommentDeclarations(
|
||||
isCssPropertyKnown,
|
||||
commentText,
|
||||
token.startOffset,
|
||||
token.endOffset
|
||||
);
|
||||
|
||||
// Insert the new declarations just before the final element.
|
||||
const lastDecl = declarations.pop();
|
||||
|
@ -505,20 +546,34 @@ function parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
|||
* on the object, which will hold the offsets of the start
|
||||
* and end of the enclosing comment.
|
||||
*/
|
||||
function parseDeclarations(isCssPropertyKnown, inputString,
|
||||
parseComments = false) {
|
||||
return parseDeclarationsInternal(isCssPropertyKnown, inputString,
|
||||
parseComments, false, false);
|
||||
function parseDeclarations(
|
||||
isCssPropertyKnown,
|
||||
inputString,
|
||||
parseComments = false
|
||||
) {
|
||||
return parseDeclarationsInternal(
|
||||
isCssPropertyKnown,
|
||||
inputString,
|
||||
parseComments,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like @see parseDeclarations, but removes properties that do not
|
||||
* have a name.
|
||||
*/
|
||||
function parseNamedDeclarations(isCssPropertyKnown, inputString,
|
||||
parseComments = false) {
|
||||
return parseDeclarations(isCssPropertyKnown, inputString, parseComments)
|
||||
.filter(item => !!item.name);
|
||||
function parseNamedDeclarations(
|
||||
isCssPropertyKnown,
|
||||
inputString,
|
||||
parseComments = false
|
||||
) {
|
||||
return parseDeclarations(
|
||||
isCssPropertyKnown,
|
||||
inputString,
|
||||
parseComments
|
||||
).filter(item => !!item.name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -640,8 +695,10 @@ function parsePseudoClassesAndAttributes(value) {
|
|||
* @return {Object} an object with 'value' and 'priority' properties.
|
||||
*/
|
||||
function parseSingleValue(isCssPropertyKnown, value) {
|
||||
const declaration = parseDeclarations(isCssPropertyKnown,
|
||||
"a: " + value + ";")[0];
|
||||
const declaration = parseDeclarations(
|
||||
isCssPropertyKnown,
|
||||
"a: " + value + ";"
|
||||
)[0];
|
||||
return {
|
||||
value: declaration ? declaration.value : "",
|
||||
priority: declaration ? declaration.priority : "",
|
||||
|
@ -662,7 +719,7 @@ function getAngleValueInDegrees(angleValue, angleUnit) {
|
|||
case CSS_ANGLEUNIT.grad:
|
||||
return angleValue * 0.9;
|
||||
case CSS_ANGLEUNIT.rad:
|
||||
return angleValue * 180 / Math.PI;
|
||||
return (angleValue * 180) / Math.PI;
|
||||
case CSS_ANGLEUNIT.turn:
|
||||
return angleValue * 360;
|
||||
default:
|
||||
|
|
|
@ -17,8 +17,11 @@ let db;
|
|||
try {
|
||||
db = require("devtools/shared/css/generated/properties-db");
|
||||
} catch (error) {
|
||||
console.error(`If this error is being displayed and "mach devtools-css-db" is not ` +
|
||||
`being run, then it needs to be fixed.`, error);
|
||||
console.error(
|
||||
`If this error is being displayed and "mach devtools-css-db" is not ` +
|
||||
`being run, then it needs to be fixed.`,
|
||||
error
|
||||
);
|
||||
db = {
|
||||
CSS_PROPERTIES: {},
|
||||
PSEUDO_ELEMENTS: [],
|
||||
|
|
|
@ -35,9 +35,11 @@ const { Cu, CC, Cc, Ci } = require("chrome");
|
|||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Services = require("Services");
|
||||
|
||||
const UDPSocket = CC("@mozilla.org/network/udp-socket;1",
|
||||
"nsIUDPSocket",
|
||||
"init");
|
||||
const UDPSocket = CC(
|
||||
"@mozilla.org/network/udp-socket;1",
|
||||
"nsIUDPSocket",
|
||||
"init"
|
||||
);
|
||||
|
||||
const SCAN_PORT = 50624;
|
||||
const UPDATE_PORT = 50625;
|
||||
|
@ -47,8 +49,9 @@ const REPLY_TIMEOUT = 5000;
|
|||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "converter", () => {
|
||||
const conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
const conv = Cc[
|
||||
"@mozilla.org/intl/scriptableunicodeconverter"
|
||||
].createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
conv.charset = "utf8";
|
||||
return conv;
|
||||
});
|
||||
|
@ -72,8 +75,11 @@ function log(msg) {
|
|||
function Transport(port) {
|
||||
EventEmitter.decorate(this);
|
||||
try {
|
||||
this.socket = new UDPSocket(port, false,
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
this.socket = new UDPSocket(
|
||||
port,
|
||||
false,
|
||||
Services.scriptSecurityManager.getSystemPrincipal()
|
||||
);
|
||||
this.socket.joinMulticast(ADDRESS);
|
||||
this.socket.asyncListen(this);
|
||||
} catch (e) {
|
||||
|
@ -82,7 +88,6 @@ function Transport(port) {
|
|||
}
|
||||
|
||||
Transport.prototype = {
|
||||
|
||||
/**
|
||||
* Send a object to some UDP port.
|
||||
* @param object object
|
||||
|
@ -119,14 +124,14 @@ Transport.prototype = {
|
|||
return;
|
||||
}
|
||||
if (logging) {
|
||||
log("Recv on " + this.socket.port + ":\n" +
|
||||
JSON.stringify(object, null, 2));
|
||||
log(
|
||||
"Recv on " + this.socket.port + ":\n" + JSON.stringify(object, null, 2)
|
||||
);
|
||||
}
|
||||
this.emit("message", object);
|
||||
},
|
||||
|
||||
onStopListening: function() {},
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -143,7 +148,6 @@ function LocalDevice() {
|
|||
LocalDevice.UNKNOWN = "unknown";
|
||||
|
||||
LocalDevice.prototype = {
|
||||
|
||||
_get: function() {
|
||||
// Without Settings API, just generate a name and stop, since the value
|
||||
// can't be persisted.
|
||||
|
@ -160,8 +164,9 @@ LocalDevice.prototype = {
|
|||
// TODO: Bug 1180997: Find the right way to expose an editable name
|
||||
this.name = sysInfo.get("device");
|
||||
} else {
|
||||
this.name = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService)
|
||||
.myHostName;
|
||||
this.name = Cc["@mozilla.org/network/dns-service;1"].getService(
|
||||
Ci.nsIDNSService
|
||||
).myHostName;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -173,7 +178,6 @@ LocalDevice.prototype = {
|
|||
this._name = name;
|
||||
log("Device: " + this._name);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
function Discovery() {
|
||||
|
@ -201,7 +205,6 @@ function Discovery() {
|
|||
}
|
||||
|
||||
Discovery.prototype = {
|
||||
|
||||
/**
|
||||
* Add a new service offered by this device.
|
||||
* @param service string
|
||||
|
@ -272,8 +275,10 @@ Discovery.prototype = {
|
|||
_waitForReplies: function() {
|
||||
clearTimeout(this._expectingReplies.timer);
|
||||
this._expectingReplies.from = new Set(this.getRemoteDevices());
|
||||
this._expectingReplies.timer =
|
||||
setTimeout(this._purgeMissingDevices, this.replyTimeout);
|
||||
this._expectingReplies.timer = setTimeout(
|
||||
this._purgeMissingDevices,
|
||||
this.replyTimeout
|
||||
);
|
||||
},
|
||||
|
||||
get Transport() {
|
||||
|
@ -385,8 +390,9 @@ Discovery.prototype = {
|
|||
// Second, loop over the services in the received update
|
||||
for (const service in update.services) {
|
||||
// Detect if this is a new device for this service
|
||||
const newDevice = !this.remoteServices[service] ||
|
||||
!this.remoteServices[service][remoteDevice];
|
||||
const newDevice =
|
||||
!this.remoteServices[service] ||
|
||||
!this.remoteServices[service][remoteDevice];
|
||||
|
||||
// Look up the service info we may have received previously from the same
|
||||
// remote device
|
||||
|
@ -407,8 +413,10 @@ Discovery.prototype = {
|
|||
|
||||
// If we've seen this service from the remote device, but the details have
|
||||
// changed, announce the update
|
||||
if (!newDevice &&
|
||||
JSON.stringify(oldDeviceInfo) != JSON.stringify(newDeviceInfo)) {
|
||||
if (
|
||||
!newDevice &&
|
||||
JSON.stringify(oldDeviceInfo) != JSON.stringify(newDeviceInfo)
|
||||
) {
|
||||
log("UPDATED " + service + ", DEVICE " + remoteDevice);
|
||||
this.emit(service + "-device-updated", remoteDevice, newDeviceInfo);
|
||||
}
|
||||
|
@ -430,7 +438,6 @@ Discovery.prototype = {
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
var discovery = new Discovery();
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { require } =
|
||||
ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
||||
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
||||
const Services = require("Services");
|
||||
const defer = require("devtools/shared/defer");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const discovery = require("devtools/shared/discovery/discovery");
|
||||
const { setTimeout, clearTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||
const { setTimeout, clearTimeout } = ChromeUtils.import(
|
||||
"resource://gre/modules/Timer.jsm"
|
||||
);
|
||||
|
||||
Services.prefs.setBoolPref("devtools.discovery.log", true);
|
||||
|
||||
|
@ -36,7 +37,6 @@ function TestTransport(port) {
|
|||
}
|
||||
|
||||
TestTransport.prototype = {
|
||||
|
||||
send: function(object, port) {
|
||||
log("Send to " + port + ":\n" + JSON.stringify(object, null, 2));
|
||||
if (!gTestTransports[port]) {
|
||||
|
@ -61,7 +61,6 @@ TestTransport.prototype = {
|
|||
},
|
||||
|
||||
onStopListening: function(socket, status) {},
|
||||
|
||||
};
|
||||
|
||||
// Use TestTransport instead of the usual Transport
|
||||
|
@ -104,10 +103,14 @@ add_task(async function() {
|
|||
deepEqual(discovery.getRemoteDevicesWithService("penguins"), ["test-device"]);
|
||||
deepEqual(discovery.getRemoteDevices(), ["test-device"]);
|
||||
|
||||
deepEqual(discovery.getRemoteService("devtools", "test-device"),
|
||||
{ port: 1234, host: "localhost" });
|
||||
deepEqual(discovery.getRemoteService("penguins", "test-device"),
|
||||
{ tux: true, host: "localhost" });
|
||||
deepEqual(discovery.getRemoteService("devtools", "test-device"), {
|
||||
port: 1234,
|
||||
host: "localhost",
|
||||
});
|
||||
deepEqual(discovery.getRemoteService("penguins", "test-device"), {
|
||||
tux: true,
|
||||
host: "localhost",
|
||||
});
|
||||
|
||||
discovery.removeService("devtools");
|
||||
await scanForChange("devtools", "removed");
|
||||
|
|
|
@ -5,7 +5,7 @@ module.exports = {
|
|||
FILTER_REJECT: 2,
|
||||
FILTER_SKIP: 3,
|
||||
|
||||
SHOW_ALL: 0xFFFFFFFF,
|
||||
SHOW_ALL: 0xffffffff,
|
||||
SHOW_ELEMENT: 0x00000001,
|
||||
SHOW_ATTRIBUTE: 0x00000002,
|
||||
SHOW_TEXT: 0x00000004,
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const BAD_LISTENER = "The event listener must be a function, or an object that has " +
|
||||
"`EventEmitter.handler` Symbol.";
|
||||
const BAD_LISTENER =
|
||||
"The event listener must be a function, or an object that has " +
|
||||
"`EventEmitter.handler` Symbol.";
|
||||
|
||||
const eventListeners = Symbol("EventEmitter/listeners");
|
||||
const onceOriginalListener = Symbol("EventEmitter/once-original-listener");
|
||||
|
@ -85,7 +86,10 @@ class EventEmitter {
|
|||
// So we iterate all the listeners to check if any of them is a wrapper to
|
||||
// the `listener` given.
|
||||
for (const value of listenersForType.values()) {
|
||||
if (onceOriginalListener in value && value[onceOriginalListener] === listener) {
|
||||
if (
|
||||
onceOriginalListener in value &&
|
||||
value[onceOriginalListener] === listener
|
||||
) {
|
||||
listenersForType.delete(value);
|
||||
break;
|
||||
}
|
||||
|
@ -270,7 +274,7 @@ class EventEmitter {
|
|||
|
||||
module.exports = EventEmitter;
|
||||
|
||||
const isEventHandler = (listener) =>
|
||||
const isEventHandler = listener =>
|
||||
listener && handler in listener && typeof listener[handler] === "function";
|
||||
|
||||
const Services = require("Services");
|
||||
|
@ -299,8 +303,7 @@ function serialize(target) {
|
|||
}
|
||||
|
||||
// Number / String
|
||||
if (typeof target === "string" ||
|
||||
typeof target === "number") {
|
||||
if (typeof target === "string" || typeof target === "number") {
|
||||
return truncate(target, MAXLEN);
|
||||
}
|
||||
|
||||
|
@ -329,9 +332,11 @@ function serialize(target) {
|
|||
}
|
||||
|
||||
// Window
|
||||
if (target.constructor &&
|
||||
target.constructor.name &&
|
||||
target.constructor.name === "Window") {
|
||||
if (
|
||||
target.constructor &&
|
||||
target.constructor.name &&
|
||||
target.constructor.name === "Window"
|
||||
) {
|
||||
return `window (${target.location.origin})`;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,10 +110,12 @@ function pointEquals(pointA, pointB) {
|
|||
|
||||
// Return whether two breakpoint positions are the same.
|
||||
function positionEquals(posA, posB) {
|
||||
return posA.kind == posB.kind
|
||||
&& posA.script == posB.script
|
||||
&& posA.offset == posB.offset
|
||||
&& posA.frameIndex == posB.frameIndex;
|
||||
return (
|
||||
posA.kind == posB.kind &&
|
||||
posA.script == posB.script &&
|
||||
posA.offset == posB.offset &&
|
||||
posA.frameIndex == posB.frameIndex
|
||||
);
|
||||
}
|
||||
|
||||
// Return whether an execution point matching posB also matches posA.
|
||||
|
@ -123,8 +125,12 @@ function positionSubsumes(posA, posB) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (posA.kind == "Break" && posB.kind == "OnStep" &&
|
||||
posA.script == posB.script && posA.offset == posB.offset) {
|
||||
if (
|
||||
posA.kind == "Break" &&
|
||||
posB.kind == "OnStep" &&
|
||||
posA.script == posB.script &&
|
||||
posA.offset == posB.offset
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,18 @@
|
|||
|
||||
const { components } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { actorActorSpec, actorRegistrySpec } = require("devtools/shared/specs/actor-registry");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
actorActorSpec,
|
||||
actorRegistrySpec,
|
||||
} = require("devtools/shared/specs/actor-registry");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
class ActorActorFront extends FrontClassWithSpec(actorActorSpec) {
|
||||
}
|
||||
class ActorActorFront extends FrontClassWithSpec(actorActorSpec) {}
|
||||
|
||||
exports.ActorActorFront = ActorActorFront;
|
||||
registerFront(ActorActorFront);
|
||||
|
@ -24,22 +29,32 @@ function request(uri) {
|
|||
reject(e);
|
||||
}
|
||||
|
||||
NetUtil.asyncFetch({
|
||||
uri,
|
||||
loadUsingSystemPrincipal: true,
|
||||
}, (stream, status, req) => {
|
||||
if (!components.isSuccessCode(status)) {
|
||||
reject(new Error("Request failed with status code = "
|
||||
+ status
|
||||
+ " after NetUtil.asyncFetch for url = "
|
||||
+ uri));
|
||||
return;
|
||||
}
|
||||
NetUtil.asyncFetch(
|
||||
{
|
||||
uri,
|
||||
loadUsingSystemPrincipal: true,
|
||||
},
|
||||
(stream, status, req) => {
|
||||
if (!components.isSuccessCode(status)) {
|
||||
reject(
|
||||
new Error(
|
||||
"Request failed with status code = " +
|
||||
status +
|
||||
" after NetUtil.asyncFetch for url = " +
|
||||
uri
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const source = NetUtil.readInputStreamToString(stream, stream.available());
|
||||
stream.close();
|
||||
resolve(source);
|
||||
});
|
||||
const source = NetUtil.readInputStreamToString(
|
||||
stream,
|
||||
stream.available()
|
||||
);
|
||||
stream.close();
|
||||
resolve(source);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -52,10 +67,9 @@ class ActorRegistryFront extends FrontClassWithSpec(actorRegistrySpec) {
|
|||
}
|
||||
|
||||
registerActor(uri, options) {
|
||||
return request(uri, options)
|
||||
.then(sourceText => {
|
||||
return super.registerActor(sourceText, uri, options);
|
||||
});
|
||||
return request(uri, options).then(sourceText => {
|
||||
return super.registerActor(sourceText, uri, options);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {addonsSpec} = require("devtools/shared/specs/addon/addons");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { addonsSpec } = require("devtools/shared/specs/addon/addons");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class AddonsFront extends FrontClassWithSpec(addonsSpec) {
|
||||
constructor(client) {
|
||||
|
|
|
@ -7,13 +7,17 @@ const {
|
|||
webExtensionInspectedWindowSpec,
|
||||
} = require("devtools/shared/specs/addon/webextension-inspected-window");
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the WebExtensionInspectedWindowActor.
|
||||
*/
|
||||
class WebExtensionInspectedWindowFront extends
|
||||
FrontClassWithSpec(webExtensionInspectedWindowSpec) {
|
||||
class WebExtensionInspectedWindowFront extends FrontClassWithSpec(
|
||||
webExtensionInspectedWindowSpec
|
||||
) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ class AnimationPlayerFront extends FrontClassWithSpec(animationPlayerSpec) {
|
|||
* update the local knowledge of the state.
|
||||
*/
|
||||
onChanged(partialState) {
|
||||
const {state} = this.reconstructState(partialState);
|
||||
const { state } = this.reconstructState(partialState);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ class AnimationPlayerFront extends FrontClassWithSpec(animationPlayerSpec) {
|
|||
getCurrentState() {
|
||||
this.currentStateHasChanged = false;
|
||||
return super.getCurrentState().then(partialData => {
|
||||
const {state, hasChanged} = this.reconstructState(partialData);
|
||||
const { state, hasChanged } = this.reconstructState(partialData);
|
||||
this.currentStateHasChanged = hasChanged;
|
||||
return state;
|
||||
});
|
||||
|
@ -112,7 +112,7 @@ class AnimationPlayerFront extends FrontClassWithSpec(animationPlayerSpec) {
|
|||
}
|
||||
|
||||
data.absoluteValues = this.calculateAbsoluteValues(data);
|
||||
return {state: data, hasChanged};
|
||||
return { state: data, hasChanged };
|
||||
}
|
||||
|
||||
calculateAbsoluteValues(data) {
|
||||
|
@ -155,22 +155,28 @@ class AnimationPlayerFront extends FrontClassWithSpec(animationPlayerSpec) {
|
|||
// the graph duration as double of the delay amount. In case of no delay, handle
|
||||
// the duration as 1ms which is short enough so as to make the scrubber movable
|
||||
// and the limited duration is prioritized.
|
||||
endTime = (absoluteDelay > 0 ? absoluteDelay * 2 : 1);
|
||||
endTime = absoluteDelay > 0 ? absoluteDelay * 2 : 1;
|
||||
} else {
|
||||
endTime = absoluteDelay +
|
||||
toRate(duration * (iterationCount || 1)) +
|
||||
absoluteEndDelay;
|
||||
endTime =
|
||||
absoluteDelay +
|
||||
toRate(duration * (iterationCount || 1)) +
|
||||
absoluteEndDelay;
|
||||
}
|
||||
|
||||
const absoluteCreatedTime =
|
||||
isPositivePlaybackRate ? createdTime : createdTime - endTime;
|
||||
const absoluteCurrentTimeAtCreated =
|
||||
isPositivePlaybackRate ? currentTimeAtCreated : endTime - currentTimeAtCreated;
|
||||
const animationCurrentTime =
|
||||
isPositivePlaybackRate ? currentTime : endTime - currentTime;
|
||||
const absoluteCurrentTime = absoluteCreatedTime + toRate(animationCurrentTime);
|
||||
const absoluteCreatedTime = isPositivePlaybackRate
|
||||
? createdTime
|
||||
: createdTime - endTime;
|
||||
const absoluteCurrentTimeAtCreated = isPositivePlaybackRate
|
||||
? currentTimeAtCreated
|
||||
: endTime - currentTimeAtCreated;
|
||||
const animationCurrentTime = isPositivePlaybackRate
|
||||
? currentTime
|
||||
: endTime - currentTime;
|
||||
const absoluteCurrentTime =
|
||||
absoluteCreatedTime + toRate(animationCurrentTime);
|
||||
const absoluteStartTime = absoluteCreatedTime + Math.min(absoluteDelay, 0);
|
||||
const absoluteStartTimeAtCreated = absoluteCreatedTime + absoluteCurrentTimeAtCreated;
|
||||
const absoluteStartTimeAtCreated =
|
||||
absoluteCreatedTime + absoluteCurrentTimeAtCreated;
|
||||
// To show whole graph with endDelay, we add negative endDelay amount to endTime.
|
||||
const endTimeWithNegativeEndDelay = endTime - Math.min(absoluteEndDelay, 0);
|
||||
const absoluteEndTime = absoluteCreatedTime + endTimeWithNegativeEndDelay;
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
"use strict";
|
||||
|
||||
const { arrayBufferSpec } = require("devtools/shared/specs/array-buffer");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
/**
|
||||
* A ArrayBufferClient provides a way to access ArrayBuffer from the
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {changesSpec} = require("devtools/shared/specs/changes");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { changesSpec } = require("devtools/shared/specs/changes");
|
||||
|
||||
/**
|
||||
* ChangesFront, the front object for the ChangesActor
|
||||
|
|
|
@ -3,13 +3,24 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS_PROPERTIES_DB",
|
||||
"devtools/shared/css/properties-db", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"CSS_PROPERTIES_DB",
|
||||
"devtools/shared/css/properties-db",
|
||||
true
|
||||
);
|
||||
|
||||
loader.lazyRequireGetter(this, "cssColors",
|
||||
"devtools/shared/css/color-db", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"cssColors",
|
||||
"devtools/shared/css/color-db",
|
||||
true
|
||||
);
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { cssPropertiesSpec } = require("devtools/shared/specs/css-properties");
|
||||
|
||||
/**
|
||||
|
@ -22,10 +33,17 @@ var NON_ASCII = "[^\\x00-\\x7F]";
|
|||
var ESCAPE = "\\\\[^\n\r]";
|
||||
var FIRST_CHAR = ["[_a-z]", NON_ASCII, ESCAPE].join("|");
|
||||
var TRAILING_CHAR = ["[_a-z0-9-]", NON_ASCII, ESCAPE].join("|");
|
||||
var IS_VARIABLE_TOKEN = new RegExp(`^--(${FIRST_CHAR})(${TRAILING_CHAR})*$`,
|
||||
"i");
|
||||
var IS_VARIABLE_TOKEN = new RegExp(
|
||||
`^--(${FIRST_CHAR})(${TRAILING_CHAR})*$`,
|
||||
"i"
|
||||
);
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS_TYPES", "devtools/shared/css/constants", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"CSS_TYPES",
|
||||
"devtools/shared/css/constants",
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Check that this is a CSS variable.
|
||||
|
@ -85,15 +103,18 @@ function CssProperties(db) {
|
|||
this.pseudoElements = db.pseudoElements;
|
||||
|
||||
// supported feature
|
||||
this.cssColor4ColorFunction = hasFeature(db.supportedFeature,
|
||||
"css-color-4-color-function");
|
||||
this.cssColor4ColorFunction = hasFeature(
|
||||
db.supportedFeature,
|
||||
"css-color-4-color-function"
|
||||
);
|
||||
|
||||
this.isKnown = this.isKnown.bind(this);
|
||||
this.isInherited = this.isInherited.bind(this);
|
||||
this.supportsType = this.supportsType.bind(this);
|
||||
this.isValidOnClient = this.isValidOnClient.bind(this);
|
||||
this.supportsCssColor4ColorFunction =
|
||||
this.supportsCssColor4ColorFunction.bind(this);
|
||||
this.supportsCssColor4ColorFunction = this.supportsCssColor4ColorFunction.bind(
|
||||
this
|
||||
);
|
||||
|
||||
// A weakly held dummy HTMLDivElement to test CSS properties on the client.
|
||||
this._dummyElements = new WeakMap();
|
||||
|
@ -159,8 +180,10 @@ CssProperties.prototype = {
|
|||
* @return {Boolean}
|
||||
*/
|
||||
isInherited(property) {
|
||||
return (this.properties[property] && this.properties[property].isInherited) ||
|
||||
isCssVariable(property);
|
||||
return (
|
||||
(this.properties[property] && this.properties[property].isInherited) ||
|
||||
isCssVariable(property)
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -172,9 +195,11 @@ CssProperties.prototype = {
|
|||
*/
|
||||
supportsType(property, type) {
|
||||
const id = CSS_TYPES[type];
|
||||
return this.properties[property] &&
|
||||
return (
|
||||
this.properties[property] &&
|
||||
(this.properties[property].supports.includes(type) ||
|
||||
this.properties[property].supports.includes(id));
|
||||
this.properties[property].supports.includes(id))
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -249,8 +274,8 @@ const initCssProperties = async function(toolbox) {
|
|||
const db = await front.getCSSDatabase();
|
||||
|
||||
const cssProperties = new CssProperties(normalizeCssData(db));
|
||||
cachedCssProperties.set(client, {cssProperties, front});
|
||||
return {cssProperties, front};
|
||||
cachedCssProperties.set(client, { cssProperties, front });
|
||||
return { cssProperties, front };
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -261,9 +286,11 @@ const initCssProperties = async function(toolbox) {
|
|||
*/
|
||||
function getCssProperties(toolbox) {
|
||||
if (!cachedCssProperties.has(toolbox.target.client)) {
|
||||
throw new Error("The CSS database has not been initialized, please make " +
|
||||
"sure initCssDatabase was called once before for this " +
|
||||
"toolbox.");
|
||||
throw new Error(
|
||||
"The CSS database has not been initialized, please make " +
|
||||
"sure initCssDatabase was called once before for this " +
|
||||
"toolbox."
|
||||
);
|
||||
}
|
||||
return cachedCssProperties.get(toolbox.target.client).cssProperties;
|
||||
}
|
||||
|
@ -289,7 +316,7 @@ function normalizeCssData(db) {
|
|||
// If there is a `from` attributes, it means that it comes from RDP
|
||||
// and it is not the client CSS_PROPERTIES_DB object.
|
||||
// (prevent comparing to CSS_PROPERTIES_DB to avoid loading client database)
|
||||
if (typeof (db.from) == "string") {
|
||||
if (typeof db.from == "string") {
|
||||
// Firefox 49's getCSSDatabase() just returned the properties object, but
|
||||
// now it returns an object with multiple types of CSS information.
|
||||
if (!db.properties) {
|
||||
|
@ -301,7 +328,10 @@ function normalizeCssData(db) {
|
|||
const missingSubproperties = !db.properties.background.subproperties;
|
||||
const missingIsInherited = !db.properties.font.isInherited;
|
||||
|
||||
const missingSomething = missingSupports || missingValues || missingSubproperties ||
|
||||
const missingSomething =
|
||||
missingSupports ||
|
||||
missingValues ||
|
||||
missingSubproperties ||
|
||||
missingIsInherited;
|
||||
|
||||
if (missingSomething) {
|
||||
|
@ -313,11 +343,13 @@ function normalizeCssData(db) {
|
|||
|
||||
// Add "supports" information to the css properties if it's missing.
|
||||
if (missingSupports) {
|
||||
db.properties[name].supports = CSS_PROPERTIES_DB.properties[name].supports;
|
||||
db.properties[name].supports =
|
||||
CSS_PROPERTIES_DB.properties[name].supports;
|
||||
}
|
||||
// Add "values" information to the css properties if it's missing.
|
||||
if (missingValues) {
|
||||
db.properties[name].values = CSS_PROPERTIES_DB.properties[name].values;
|
||||
db.properties[name].values =
|
||||
CSS_PROPERTIES_DB.properties[name].values;
|
||||
}
|
||||
// Add "subproperties" information to the css properties if it's missing.
|
||||
if (missingSubproperties) {
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
const {deviceSpec} = require("devtools/shared/specs/device");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { Cu } = require("chrome");
|
||||
const { deviceSpec } = require("devtools/shared/specs/device");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const defer = require("devtools/shared/defer");
|
||||
|
||||
class DeviceFront extends FrontClassWithSpec(deviceSpec) {
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { emulationSpec } = require("devtools/shared/specs/emulation");
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { framerateSpec } = require("devtools/shared/specs/framerate");
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const flags = require("devtools/shared/flags");
|
||||
const {
|
||||
customHighlighterSpec,
|
||||
|
|
|
@ -7,8 +7,10 @@ const Telemetry = require("devtools/client/shared/telemetry");
|
|||
const telemetry = new Telemetry();
|
||||
const { NodePicker } = require("devtools/shared/fronts/inspector/node-picker");
|
||||
const TELEMETRY_EYEDROPPER_OPENED = "DEVTOOLS_EYEDROPPER_OPENED_COUNT";
|
||||
const TELEMETRY_EYEDROPPER_OPENED_MENU = "DEVTOOLS_MENU_EYEDROPPER_OPENED_COUNT";
|
||||
const SHOW_ALL_ANONYMOUS_CONTENT_PREF = "devtools.inspector.showAllAnonymousContent";
|
||||
const TELEMETRY_EYEDROPPER_OPENED_MENU =
|
||||
"DEVTOOLS_MENU_EYEDROPPER_OPENED_COUNT";
|
||||
const SHOW_ALL_ANONYMOUS_CONTENT_PREF =
|
||||
"devtools.inspector.showAllAnonymousContent";
|
||||
const SHOW_UA_SHADOW_ROOTS_PREF = "devtools.inspector.showUserAgentShadowRoots";
|
||||
|
||||
const {
|
||||
|
@ -23,12 +25,18 @@ const {
|
|||
|
||||
const Services = require("Services");
|
||||
const defer = require("devtools/shared/defer");
|
||||
loader.lazyRequireGetter(this, "nodeConstants",
|
||||
"devtools/shared/dom-node-constants");
|
||||
loader.lazyRequireGetter(this, "Selection",
|
||||
"devtools/client/framework/selection", true);
|
||||
loader.lazyRequireGetter(this, "flags",
|
||||
"devtools/shared/flags");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"nodeConstants",
|
||||
"devtools/shared/dom-node-constants"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"Selection",
|
||||
"devtools/client/framework/selection",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(this, "flags", "devtools/shared/flags");
|
||||
|
||||
/**
|
||||
* Client side of the DOM walker.
|
||||
|
@ -163,7 +171,9 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
const response = await this.getNodeActorFromObjectActor(grip.actor);
|
||||
const nodeFront = response ? response.node : null;
|
||||
if (!nodeFront) {
|
||||
throw new Error("The ValueGrip passed could not be translated to a NodeFront");
|
||||
throw new Error(
|
||||
"The ValueGrip passed could not be translated to a NodeFront"
|
||||
);
|
||||
}
|
||||
return nodeFront;
|
||||
}
|
||||
|
@ -197,8 +207,8 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
* @param {Object} options
|
||||
* - "reverse": search backwards
|
||||
*/
|
||||
async search(query, options = { }) {
|
||||
const searchData = this.searchData = this.searchData || { };
|
||||
async search(query, options = {}) {
|
||||
const searchData = (this.searchData = this.searchData || {});
|
||||
const result = await super.search(query, options);
|
||||
const nodeList = result.list;
|
||||
|
||||
|
@ -213,8 +223,9 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
}
|
||||
|
||||
// Move search result cursor and cycle if necessary.
|
||||
searchData.index = options.reverse ? searchData.index - 1 :
|
||||
searchData.index + 1;
|
||||
searchData.index = options.reverse
|
||||
? searchData.index - 1
|
||||
: searchData.index + 1;
|
||||
if (searchData.index >= nodeList.length) {
|
||||
searchData.index = 0;
|
||||
}
|
||||
|
@ -282,24 +293,30 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
}
|
||||
|
||||
if (!targetFront) {
|
||||
console.warn("Got a mutation for an unexpected actor: " + targetID +
|
||||
", please file a bug on bugzilla.mozilla.org!");
|
||||
console.warn(
|
||||
"Got a mutation for an unexpected actor: " +
|
||||
targetID +
|
||||
", please file a bug on bugzilla.mozilla.org!"
|
||||
);
|
||||
console.trace();
|
||||
continue;
|
||||
}
|
||||
|
||||
const emittedMutation = Object.assign(change, { target: targetFront });
|
||||
|
||||
if (change.type === "childList" ||
|
||||
change.type === "nativeAnonymousChildList") {
|
||||
if (
|
||||
change.type === "childList" ||
|
||||
change.type === "nativeAnonymousChildList"
|
||||
) {
|
||||
// Update the ownership tree according to the mutation record.
|
||||
const addedFronts = [];
|
||||
const removedFronts = [];
|
||||
for (const removed of change.removed) {
|
||||
const removedFront = this.get(removed);
|
||||
if (!removedFront) {
|
||||
console.error("Got a removal of an actor we didn't know about: " +
|
||||
removed);
|
||||
console.error(
|
||||
"Got a removal of an actor we didn't know about: " + removed
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Remove from the ownership tree
|
||||
|
@ -313,8 +330,11 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
for (const added of change.added) {
|
||||
const addedFront = this.get(added);
|
||||
if (!addedFront) {
|
||||
console.error("Got an addition of an actor we didn't know " +
|
||||
"about: " + added);
|
||||
console.error(
|
||||
"Got an addition of an actor we didn't know " +
|
||||
"about: " +
|
||||
added
|
||||
);
|
||||
continue;
|
||||
}
|
||||
addedFront.reparent(targetFront);
|
||||
|
@ -342,8 +362,10 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
// first.
|
||||
for (const child of targetFront.treeChildren()) {
|
||||
if (child.nodeType === nodeConstants.DOCUMENT_NODE) {
|
||||
console.warn("Got an unexpected frameLoad in the inspector, " +
|
||||
"please file a bug on bugzilla.mozilla.org!");
|
||||
console.warn(
|
||||
"Got an unexpected frameLoad in the inspector, " +
|
||||
"please file a bug on bugzilla.mozilla.org!"
|
||||
);
|
||||
console.trace();
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +384,8 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
} else if (change.type === "shadowRootAttached") {
|
||||
targetFront._form.isShadowHost = true;
|
||||
} else if (change.type === "customElementDefined") {
|
||||
targetFront._form.customElementLocation = change.customElementLocation;
|
||||
targetFront._form.customElementLocation =
|
||||
change.customElementLocation;
|
||||
} else if (change.type === "unretained") {
|
||||
// Retained orphans were force-released without the intervention of
|
||||
// client (probably a navigated frame).
|
||||
|
@ -377,13 +400,16 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
|
||||
// Update the inlineTextChild property of the target for a selected list of
|
||||
// mutation types.
|
||||
if (change.type === "inlineTextChild" ||
|
||||
change.type === "childList" ||
|
||||
change.type === "shadowRootAttached" ||
|
||||
change.type === "nativeAnonymousChildList") {
|
||||
if (
|
||||
change.type === "inlineTextChild" ||
|
||||
change.type === "childList" ||
|
||||
change.type === "shadowRootAttached" ||
|
||||
change.type === "nativeAnonymousChildList"
|
||||
) {
|
||||
if (change.inlineTextChild) {
|
||||
targetFront.inlineTextChild =
|
||||
types.getType("domnode").read(change.inlineTextChild, this);
|
||||
targetFront.inlineTextChild = types
|
||||
.getType("domnode")
|
||||
.read(change.inlineTextChild, this);
|
||||
} else {
|
||||
targetFront.inlineTextChild = undefined;
|
||||
}
|
||||
|
@ -411,7 +437,7 @@ class WalkerFront extends FrontClassWithSpec(walkerSpec) {
|
|||
*/
|
||||
onMutations() {
|
||||
// Fetch and process the mutations.
|
||||
this.getMutations({cleanup: this.autoCleanup}).catch(() => {});
|
||||
this.getMutations({ cleanup: this.autoCleanup }).catch(() => {});
|
||||
}
|
||||
|
||||
isLocal() {
|
||||
|
@ -448,20 +474,23 @@ class InspectorFront extends FrontClassWithSpec(inspectorSpec) {
|
|||
|
||||
// async initialization
|
||||
async initialize() {
|
||||
await Promise.all([
|
||||
this._getWalker(),
|
||||
this._getHighlighter(),
|
||||
]);
|
||||
await Promise.all([this._getWalker(), this._getHighlighter()]);
|
||||
|
||||
this.selection = new Selection(this.walker);
|
||||
this.nodePicker = new NodePicker(this.highlighter, this.walker, this.selection);
|
||||
this.nodePicker = new NodePicker(
|
||||
this.highlighter,
|
||||
this.walker,
|
||||
this.selection
|
||||
);
|
||||
}
|
||||
|
||||
async _getWalker() {
|
||||
const showAllAnonymousContent = Services.prefs.getBoolPref(
|
||||
SHOW_ALL_ANONYMOUS_CONTENT_PREF);
|
||||
SHOW_ALL_ANONYMOUS_CONTENT_PREF
|
||||
);
|
||||
const showUserAgentShadowRoots = Services.prefs.getBoolPref(
|
||||
SHOW_UA_SHADOW_ROOTS_PREF);
|
||||
SHOW_UA_SHADOW_ROOTS_PREF
|
||||
);
|
||||
this.walker = await this.getWalker({
|
||||
showAllAnonymousContent,
|
||||
showUserAgentShadowRoots,
|
||||
|
@ -502,8 +531,10 @@ class InspectorFront extends FrontClassWithSpec(inspectorSpec) {
|
|||
try {
|
||||
highlighter = await super.getHighlighterByType(typeName);
|
||||
} catch (_) {
|
||||
throw new Error("The target doesn't support " +
|
||||
`creating highlighters by types or ${typeName} is unknown`);
|
||||
throw new Error(
|
||||
"The target doesn't support " +
|
||||
`creating highlighters by types or ${typeName} is unknown`
|
||||
);
|
||||
}
|
||||
return highlighter;
|
||||
}
|
||||
|
@ -513,7 +544,7 @@ class InspectorFront extends FrontClassWithSpec(inspectorSpec) {
|
|||
}
|
||||
|
||||
async getOrCreateHighlighterByType(type) {
|
||||
let front = this._highlighters.get(type);
|
||||
let front = this._highlighters.get(type);
|
||||
if (!front) {
|
||||
front = await this.getHighlighterByType(type);
|
||||
this._highlighters.set(type, front);
|
||||
|
|
|
@ -109,8 +109,11 @@ RuleRewriter.prototype = {
|
|||
// Whether there are any newlines in the input text.
|
||||
this.hasNewLine = /[\r\n]/.test(this.inputString);
|
||||
// The declarations.
|
||||
this.declarations = parseNamedDeclarations(this.isCssPropertyKnown, this.inputString,
|
||||
true);
|
||||
this.declarations = parseNamedDeclarations(
|
||||
this.isCssPropertyKnown,
|
||||
this.inputString,
|
||||
true
|
||||
);
|
||||
this.decl = null;
|
||||
this.result = null;
|
||||
},
|
||||
|
@ -196,17 +199,19 @@ RuleRewriter.prototype = {
|
|||
|
||||
// Push a closing paren on the stack.
|
||||
const pushParen = (token, closer) => {
|
||||
result = result + text.substring(previousOffset, token.startOffset) +
|
||||
result =
|
||||
result +
|
||||
text.substring(previousOffset, token.startOffset) +
|
||||
text.substring(token.startOffset, token.endOffset);
|
||||
// We set the location of the paren in a funny way, to handle
|
||||
// the case where we've seen a function token, where the paren
|
||||
// appears at the end.
|
||||
parenStack.push({closer, offset: result.length - 1});
|
||||
parenStack.push({ closer, offset: result.length - 1 });
|
||||
previousOffset = token.endOffset;
|
||||
};
|
||||
|
||||
// Pop a closing paren from the stack.
|
||||
const popSomeParens = (closer) => {
|
||||
const popSomeParens = closer => {
|
||||
while (parenStack.length > 0) {
|
||||
const paren = parenStack.pop();
|
||||
|
||||
|
@ -216,7 +221,9 @@ RuleRewriter.prototype = {
|
|||
|
||||
// Found a non-matching closing paren, so quote it. Note that
|
||||
// these are processed in reverse order.
|
||||
result = result.substring(0, paren.offset) + "\\" +
|
||||
result =
|
||||
result.substring(0, paren.offset) +
|
||||
"\\" +
|
||||
result.substring(paren.offset);
|
||||
anySanitized = true;
|
||||
}
|
||||
|
@ -293,9 +300,11 @@ RuleRewriter.prototype = {
|
|||
* @return {Number} index of the first non-whitespace character, or -1
|
||||
*/
|
||||
skipWhitespaceBackward: function(string, index) {
|
||||
for (--index;
|
||||
index >= 0 && (string[index] === " " || string[index] === "\t");
|
||||
--index) {
|
||||
for (
|
||||
--index;
|
||||
index >= 0 && (string[index] === " " || string[index] === "\t");
|
||||
--index
|
||||
) {
|
||||
// Nothing.
|
||||
}
|
||||
return index;
|
||||
|
@ -309,9 +318,12 @@ RuleRewriter.prototype = {
|
|||
* function must check for that.
|
||||
*/
|
||||
maybeTerminateDecl: function(index) {
|
||||
if (index < 0 || index >= this.declarations.length
|
||||
// No need to rewrite declarations in comments.
|
||||
|| ("commentOffsets" in this.declarations[index])) {
|
||||
if (
|
||||
index < 0 ||
|
||||
index >= this.declarations.length ||
|
||||
// No need to rewrite declarations in comments.
|
||||
"commentOffsets" in this.declarations[index]
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -326,8 +338,8 @@ RuleRewriter.prototype = {
|
|||
if (termDecl.terminator) {
|
||||
// Insert the terminator just at the end of the declaration,
|
||||
// before any trailing whitespace.
|
||||
this.result = this.result.substring(0, endIndex) + termDecl.terminator +
|
||||
trailingText;
|
||||
this.result =
|
||||
this.result.substring(0, endIndex) + termDecl.terminator + trailingText;
|
||||
// In a couple of cases, we may have had to add something to
|
||||
// terminate the declaration, but the termination did not
|
||||
// actually affect the property's value -- and at this spot, we
|
||||
|
@ -404,16 +416,19 @@ RuleRewriter.prototype = {
|
|||
|
||||
// Insert the name and value separately, so we can report
|
||||
// sanitization changes properly.
|
||||
const commentNamePart =
|
||||
this.inputString.substring(decl.offsets[0],
|
||||
decl.colonOffsets[1]);
|
||||
const commentNamePart = this.inputString.substring(
|
||||
decl.offsets[0],
|
||||
decl.colonOffsets[1]
|
||||
);
|
||||
this.result += unescapeCSSComment(commentNamePart);
|
||||
|
||||
// When uncommenting, we must be sure to sanitize the text, to
|
||||
// avoid things like /* decl: }; */, which will be accepted as
|
||||
// a property but which would break the entire style sheet.
|
||||
let newText = this.inputString.substring(decl.colonOffsets[1],
|
||||
decl.offsets[1]);
|
||||
let newText = this.inputString.substring(
|
||||
decl.colonOffsets[1],
|
||||
decl.offsets[1]
|
||||
);
|
||||
newText = cssTrimRight(unescapeCSSComment(newText));
|
||||
this.result += this.sanitizeText(newText, index) + ";";
|
||||
|
||||
|
@ -427,15 +442,27 @@ RuleRewriter.prototype = {
|
|||
} else {
|
||||
// Disable it. Note that we use our special comment syntax
|
||||
// here.
|
||||
const declText = this.inputString.substring(decl.offsets[0],
|
||||
decl.offsets[1]);
|
||||
this.result += "/*" + COMMENT_PARSING_HEURISTIC_BYPASS_CHAR +
|
||||
" " + escapeCSSComment(declText) + " */";
|
||||
const declText = this.inputString.substring(
|
||||
decl.offsets[0],
|
||||
decl.offsets[1]
|
||||
);
|
||||
this.result +=
|
||||
"/*" +
|
||||
COMMENT_PARSING_HEURISTIC_BYPASS_CHAR +
|
||||
" " +
|
||||
escapeCSSComment(declText) +
|
||||
" */";
|
||||
}
|
||||
this.completeCopying(copyOffset);
|
||||
|
||||
if (isEnabled) {
|
||||
this.modifications.push({ type: "set", index, name, value: decl.value, priority });
|
||||
this.modifications.push({
|
||||
type: "set",
|
||||
index,
|
||||
name,
|
||||
value: decl.value,
|
||||
priority,
|
||||
});
|
||||
} else {
|
||||
this.modifications.push({ type: "disable", index, name });
|
||||
}
|
||||
|
@ -472,8 +499,10 @@ RuleRewriter.prototype = {
|
|||
let newIndentation = "";
|
||||
if (this.hasNewLine) {
|
||||
if (this.declarations.length > 0) {
|
||||
newIndentation = this.getIndentation(this.inputString,
|
||||
this.declarations[0].offsets[0]);
|
||||
newIndentation = this.getIndentation(
|
||||
this.inputString,
|
||||
this.declarations[0].offsets[0]
|
||||
);
|
||||
} else if (this.defaultIndentation) {
|
||||
newIndentation = this.defaultIndentation;
|
||||
} else {
|
||||
|
@ -489,8 +518,10 @@ RuleRewriter.prototype = {
|
|||
// is actually used.
|
||||
let savedWhitespace = "";
|
||||
if (this.hasNewLine) {
|
||||
const wsOffset = this.skipWhitespaceBackward(this.result,
|
||||
this.result.length);
|
||||
const wsOffset = this.skipWhitespaceBackward(
|
||||
this.result,
|
||||
this.result.length
|
||||
);
|
||||
if (this.result[wsOffset] === "\r" || this.result[wsOffset] === "\n") {
|
||||
savedWhitespace = this.result.substring(wsOffset + 1);
|
||||
this.result = this.result.substring(0, wsOffset + 1);
|
||||
|
@ -504,8 +535,12 @@ RuleRewriter.prototype = {
|
|||
newText += ";";
|
||||
|
||||
if (!enabled) {
|
||||
newText = "/*" + COMMENT_PARSING_HEURISTIC_BYPASS_CHAR + " " +
|
||||
escapeCSSComment(newText) + " */";
|
||||
newText =
|
||||
"/*" +
|
||||
COMMENT_PARSING_HEURISTIC_BYPASS_CHAR +
|
||||
" " +
|
||||
escapeCSSComment(newText) +
|
||||
" */";
|
||||
}
|
||||
|
||||
this.result += newIndentation + newText;
|
||||
|
@ -533,7 +568,13 @@ RuleRewriter.prototype = {
|
|||
* enabled, false if disabled
|
||||
*/
|
||||
createProperty: function(index, name, value, priority, enabled) {
|
||||
this.editPromise = this.internalCreateProperty(index, name, value, priority, enabled);
|
||||
this.editPromise = this.internalCreateProperty(
|
||||
index,
|
||||
name,
|
||||
value,
|
||||
priority,
|
||||
enabled
|
||||
);
|
||||
// Log the modification only if the created property is enabled.
|
||||
if (enabled) {
|
||||
this.modifications.push({ type: "set", index, name, value, priority });
|
||||
|
@ -564,9 +605,11 @@ RuleRewriter.prototype = {
|
|||
|
||||
// Note that this assumes that "set" never operates on disabled
|
||||
// properties.
|
||||
this.result += this.inputString.substring(this.decl.offsets[0],
|
||||
this.decl.colonOffsets[1]) +
|
||||
this.sanitizeText(value, index);
|
||||
this.result +=
|
||||
this.inputString.substring(
|
||||
this.decl.offsets[0],
|
||||
this.decl.colonOffsets[1]
|
||||
) + this.sanitizeText(value, index);
|
||||
|
||||
if (priority === "important") {
|
||||
this.result += " !important";
|
||||
|
@ -607,10 +650,15 @@ RuleRewriter.prototype = {
|
|||
// bother with this if we're looking at sources that already
|
||||
// have a newline somewhere.
|
||||
if (this.hasNewLine) {
|
||||
const nlOffset = this.skipWhitespaceBackward(this.result,
|
||||
this.decl.offsets[0]);
|
||||
if (nlOffset < 0 || this.result[nlOffset] === "\r" ||
|
||||
this.result[nlOffset] === "\n") {
|
||||
const nlOffset = this.skipWhitespaceBackward(
|
||||
this.result,
|
||||
this.decl.offsets[0]
|
||||
);
|
||||
if (
|
||||
nlOffset < 0 ||
|
||||
this.result[nlOffset] === "\r" ||
|
||||
this.result[nlOffset] === "\n"
|
||||
) {
|
||||
const trailingText = this.inputString.substring(copyOffset);
|
||||
const match = BLANK_LINE_RX.exec(trailingText);
|
||||
if (match) {
|
||||
|
@ -658,7 +706,7 @@ RuleRewriter.prototype = {
|
|||
* |text| is the rewritten text of the rule.
|
||||
*/
|
||||
getResult: function() {
|
||||
return {changed: this.changedDeclarations, text: this.result};
|
||||
return { changed: this.changedDeclarations, text: this.result };
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const {
|
||||
flexboxSpec,
|
||||
flexItemSpec,
|
||||
|
@ -132,8 +135,7 @@ class GridFront extends FrontClassWithSpec(gridSpec) {
|
|||
}
|
||||
}
|
||||
|
||||
class LayoutFront extends FrontClassWithSpec(layoutSpec) {
|
||||
}
|
||||
class LayoutFront extends FrontClassWithSpec(layoutSpec) {}
|
||||
|
||||
exports.FlexboxFront = FlexboxFront;
|
||||
registerFront(FlexboxFront);
|
||||
|
|
|
@ -4,12 +4,22 @@
|
|||
"use strict";
|
||||
|
||||
const { memorySpec } = require("devtools/shared/specs/memory");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyRequireGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
|
||||
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"HeapSnapshotFileUtils",
|
||||
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils"
|
||||
);
|
||||
|
||||
class MemoryFront extends FrontClassWithSpec(memorySpec) {
|
||||
constructor(client) {
|
||||
|
@ -42,8 +52,10 @@ class MemoryFront extends FrontClassWithSpec(memorySpec) {
|
|||
async saveHeapSnapshot(options = {}) {
|
||||
const snapshotId = await super.saveHeapSnapshot(options.boundaries);
|
||||
|
||||
if (!options.forceCopy &&
|
||||
(await HeapSnapshotFileUtils.haveHeapSnapshotTempFile(snapshotId))) {
|
||||
if (
|
||||
!options.forceCopy &&
|
||||
(await HeapSnapshotFileUtils.haveHeapSnapshotTempFile(snapshotId))
|
||||
) {
|
||||
return HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId);
|
||||
}
|
||||
|
||||
|
@ -72,8 +84,7 @@ class MemoryFront extends FrontClassWithSpec(memorySpec) {
|
|||
snapshotId,
|
||||
});
|
||||
|
||||
const outFilePath =
|
||||
HeapSnapshotFileUtils.getNewUniqueHeapSnapshotTempFilePath();
|
||||
const outFilePath = HeapSnapshotFileUtils.getNewUniqueHeapSnapshotTempFilePath();
|
||||
const outFile = new FileUtils.File(outFilePath);
|
||||
const outFileStream = FileUtils.openSafeFileOutputStream(outFile);
|
||||
|
||||
|
|
|
@ -9,16 +9,16 @@ const {
|
|||
registerFront,
|
||||
} = require("devtools/shared/protocol.js");
|
||||
|
||||
const {
|
||||
nodeSpec,
|
||||
nodeListSpec,
|
||||
} = require("devtools/shared/specs/node");
|
||||
const { nodeSpec, nodeListSpec } = require("devtools/shared/specs/node");
|
||||
|
||||
const promise = require("promise");
|
||||
const { SimpleStringFront } = require("devtools/shared/fronts/string");
|
||||
|
||||
loader.lazyRequireGetter(this, "nodeConstants",
|
||||
"devtools/shared/dom-node-constants");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"nodeConstants",
|
||||
"devtools/shared/dom-node-constants"
|
||||
);
|
||||
|
||||
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||
|
||||
|
@ -146,7 +146,9 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
// Get the owner actor for this actor (the walker), and find the
|
||||
// parent node of this actor from it, creating a standin node if
|
||||
// necessary.
|
||||
const parentNodeFront = ctx.marshallPool().ensureDOMNodeFront(form.parent);
|
||||
const parentNodeFront = ctx
|
||||
.marshallPool()
|
||||
.ensureDOMNodeFront(form.parent);
|
||||
this.reparent(parentNodeFront);
|
||||
}
|
||||
|
||||
|
@ -155,8 +157,9 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
}
|
||||
|
||||
if (form.inlineTextChild) {
|
||||
this.inlineTextChild =
|
||||
types.getType("domnode").read(form.inlineTextChild, ctx);
|
||||
this.inlineTextChild = types
|
||||
.getType("domnode")
|
||||
.read(form.inlineTextChild, ctx);
|
||||
} else {
|
||||
this.inlineTextChild = undefined;
|
||||
}
|
||||
|
@ -192,8 +195,10 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
let found = false;
|
||||
for (let i = 0; i < this.attributes.length; i++) {
|
||||
const attr = this.attributes[i];
|
||||
if (attr.name == change.attributeName &&
|
||||
attr.namespace == change.attributeNamespace) {
|
||||
if (
|
||||
attr.name == change.attributeName &&
|
||||
attr.namespace == change.attributeNamespace
|
||||
) {
|
||||
if (change.newValue !== null) {
|
||||
attr.value = change.newValue;
|
||||
} else {
|
||||
|
@ -239,16 +244,19 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
return this._form.nodeName;
|
||||
}
|
||||
get displayName() {
|
||||
const {displayName, nodeName} = this._form;
|
||||
const { displayName, nodeName } = this._form;
|
||||
|
||||
// Keep `nodeName.toLowerCase()` for backward compatibility
|
||||
return displayName || nodeName.toLowerCase();
|
||||
}
|
||||
get doctypeString() {
|
||||
return "<!DOCTYPE " + this._form.name +
|
||||
(this._form.publicId ? " PUBLIC \"" + this._form.publicId + "\"" : "") +
|
||||
(this._form.systemId ? " \"" + this._form.systemId + "\"" : "") +
|
||||
">";
|
||||
return (
|
||||
"<!DOCTYPE " +
|
||||
this._form.name +
|
||||
(this._form.publicId ? ' PUBLIC "' + this._form.publicId + '"' : "") +
|
||||
(this._form.systemId ? ' "' + this._form.systemId + '"' : "") +
|
||||
">"
|
||||
);
|
||||
}
|
||||
|
||||
get baseURI() {
|
||||
|
@ -279,8 +287,11 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
return this._form.isAfterPseudoElement;
|
||||
}
|
||||
get isPseudoElement() {
|
||||
return this.isBeforePseudoElement || this.isAfterPseudoElement ||
|
||||
this.isMarkerPseudoElement;
|
||||
return (
|
||||
this.isBeforePseudoElement ||
|
||||
this.isAfterPseudoElement ||
|
||||
this.isMarkerPseudoElement
|
||||
);
|
||||
}
|
||||
get isAnonymous() {
|
||||
return this._form.isAnonymous;
|
||||
|
@ -333,7 +344,7 @@ class NodeFront extends FrontClassWithSpec(nodeSpec) {
|
|||
}
|
||||
hasAttribute(name) {
|
||||
this._cacheAttributes();
|
||||
return (name in this._attrMap);
|
||||
return name in this._attrMap;
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { perfSpec } = require("devtools/shared/specs/perf");
|
||||
|
||||
class PerfFront extends FrontClassWithSpec(perfSpec) {
|
||||
|
|
|
@ -3,21 +3,38 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { performanceRecordingSpec } = require("devtools/shared/specs/performance-recording");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const {
|
||||
performanceRecordingSpec,
|
||||
} = require("devtools/shared/specs/performance-recording");
|
||||
|
||||
loader.lazyRequireGetter(this, "PerformanceIO",
|
||||
"devtools/client/performance/modules/io");
|
||||
loader.lazyRequireGetter(this, "PerformanceRecordingCommon",
|
||||
"devtools/shared/performance/recording-common", true);
|
||||
loader.lazyRequireGetter(this, "RecordingUtils",
|
||||
"devtools/shared/performance/recording-utils");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PerformanceIO",
|
||||
"devtools/client/performance/modules/io"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PerformanceRecordingCommon",
|
||||
"devtools/shared/performance/recording-common",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"RecordingUtils",
|
||||
"devtools/shared/performance/recording-utils"
|
||||
);
|
||||
|
||||
/**
|
||||
* This can be used on older Profiler implementations, but the methods cannot
|
||||
* be changed -- you must introduce a new method, and detect the server.
|
||||
*/
|
||||
class PerformanceRecordingFront extends FrontClassWithSpec(performanceRecordingSpec) {
|
||||
class PerformanceRecordingFront extends FrontClassWithSpec(
|
||||
performanceRecordingSpec
|
||||
) {
|
||||
form(form) {
|
||||
this.actorID = form.actor;
|
||||
this._form = form;
|
||||
|
@ -41,7 +58,7 @@ class PerformanceRecordingFront extends FrontClassWithSpec(performanceRecordingS
|
|||
// just finished. This is because GC/Compositing markers can come into the array out
|
||||
// of order with the other markers, leading to strange collapsing in waterfall view.
|
||||
if (this._completed && !this._markersSorted) {
|
||||
this._markers = this._markers.sort((a, b) => (a.start > b.start));
|
||||
this._markers = this._markers.sort((a, b) => a.start > b.start);
|
||||
this._markersSorted = true;
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +162,10 @@ class PerformanceRecordingFront extends FrontClassWithSpec(performanceRecordingS
|
|||
// PerformanceRecordingFront also needs to inherit from PerformanceRecordingCommon
|
||||
// but as ES classes don't support multiple inheritance, we are overriding the
|
||||
// prototype with PerformanceRecordingCommon methods.
|
||||
Object.defineProperties(PerformanceRecordingFront.prototype,
|
||||
Object.getOwnPropertyDescriptors(PerformanceRecordingCommon));
|
||||
Object.defineProperties(
|
||||
PerformanceRecordingFront.prototype,
|
||||
Object.getOwnPropertyDescriptors(PerformanceRecordingCommon)
|
||||
);
|
||||
|
||||
exports.PerformanceRecordingFront = PerformanceRecordingFront;
|
||||
registerFront(PerformanceRecordingFront);
|
||||
|
|
|
@ -4,14 +4,21 @@
|
|||
"use strict";
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { PerformanceRecordingFront } = require("devtools/shared/fronts/performance-recording");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const {
|
||||
PerformanceRecordingFront,
|
||||
} = require("devtools/shared/fronts/performance-recording");
|
||||
const { performanceSpec } = require("devtools/shared/specs/performance");
|
||||
|
||||
loader.lazyRequireGetter(this, "PerformanceIO",
|
||||
"devtools/client/performance/modules/io");
|
||||
loader.lazyRequireGetter(this, "getSystemInfo",
|
||||
"devtools/shared/system", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PerformanceIO",
|
||||
"devtools/client/performance/modules/io"
|
||||
);
|
||||
loader.lazyRequireGetter(this, "getSystemInfo", "devtools/shared/system", true);
|
||||
|
||||
class PerformanceFront extends FrontClassWithSpec(performanceSpec) {
|
||||
constructor(client) {
|
||||
|
@ -63,8 +70,10 @@ class PerformanceFront extends FrontClassWithSpec(performanceSpec) {
|
|||
|
||||
get traits() {
|
||||
if (!this._traits) {
|
||||
Cu.reportError("Cannot access traits of PerformanceFront before " +
|
||||
"calling `connect()`.");
|
||||
Cu.reportError(
|
||||
"Cannot access traits of PerformanceFront before " +
|
||||
"calling `connect()`."
|
||||
);
|
||||
}
|
||||
return this._traits;
|
||||
}
|
||||
|
@ -90,8 +99,8 @@ class PerformanceFront extends FrontClassWithSpec(performanceSpec) {
|
|||
generation: origGeneration,
|
||||
} = recording.getStartingBufferStatus();
|
||||
|
||||
const normalizedCurrent = (totalSize * (currentGeneration - origGeneration)) +
|
||||
currentPosition;
|
||||
const normalizedCurrent =
|
||||
totalSize * (currentGeneration - origGeneration) + currentPosition;
|
||||
const percent = (normalizedCurrent - origPosition) / totalSize;
|
||||
|
||||
// Clamp between 0 and 1; can get negative percentage values when a new
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {preferenceSpec} = require("devtools/shared/specs/preference");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { preferenceSpec } = require("devtools/shared/specs/preference");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class PreferenceFront extends FrontClassWithSpec(preferenceSpec) {
|
||||
constructor(client) {
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {reflowSpec} = require("devtools/shared/specs/reflow");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { reflowSpec } = require("devtools/shared/specs/reflow");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
/**
|
||||
* Usage example of the reflow front:
|
||||
|
|
|
@ -3,13 +3,26 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {Ci} = require("chrome");
|
||||
const {rootSpec} = require("devtools/shared/specs/root");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { Ci } = require("chrome");
|
||||
const { rootSpec } = require("devtools/shared/specs/root");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true);
|
||||
loader.lazyRequireGetter(this, "BrowsingContextTargetFront", "devtools/shared/fronts/targets/browsing-context", true);
|
||||
loader.lazyRequireGetter(this, "ContentProcessTargetFront", "devtools/shared/fronts/targets/content-process", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"BrowsingContextTargetFront",
|
||||
"devtools/shared/fronts/targets/browsing-context",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"ContentProcessTargetFront",
|
||||
"devtools/shared/fronts/targets/content-process",
|
||||
true
|
||||
);
|
||||
|
||||
class RootFront extends FrontClassWithSpec(rootSpec) {
|
||||
constructor(client, form) {
|
||||
|
@ -113,7 +126,9 @@ class RootFront extends FrontClassWithSpec(rootSpec) {
|
|||
};
|
||||
switch (front.type) {
|
||||
case Ci.nsIWorkerDebugger.TYPE_SERVICE:
|
||||
const registration = result.service.find(r => r.scope === front.scope);
|
||||
const registration = result.service.find(
|
||||
r => r.scope === front.scope
|
||||
);
|
||||
if (registration) {
|
||||
// XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't
|
||||
// have a scriptSpec, but its associated WorkerDebugger does.
|
||||
|
@ -210,9 +225,9 @@ class RootFront extends FrontClassWithSpec(rootSpec) {
|
|||
async getTab(filter) {
|
||||
const packet = {};
|
||||
if (filter) {
|
||||
if (typeof (filter.outerWindowID) == "number") {
|
||||
if (typeof filter.outerWindowID == "number") {
|
||||
packet.outerWindowID = filter.outerWindowID;
|
||||
} else if (typeof (filter.tabId) == "number") {
|
||||
} else if (typeof filter.tabId == "number") {
|
||||
packet.tabId = filter.tabId;
|
||||
} else if ("tab" in filter) {
|
||||
const browser = filter.tab.linkedBrowser;
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {screenshotSpec} = require("devtools/shared/specs/screenshot");
|
||||
const { screenshotSpec } = require("devtools/shared/specs/screenshot");
|
||||
const saveScreenshot = require("devtools/shared/screenshot/save");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class ScreenshotFront extends FrontClassWithSpec(screenshotSpec) {
|
||||
constructor(client) {
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
"use strict";
|
||||
|
||||
const { sourceSpec } = require("devtools/shared/specs/source");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { ArrayBufferFront } = require("devtools/shared/fronts/array-buffer");
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { childSpecs, storageSpec } = require("devtools/shared/specs/storage");
|
||||
|
||||
for (const childSpec of Object.values(childSpecs)) {
|
||||
|
|
|
@ -3,10 +3,16 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {DebuggerServer} = require("devtools/server/main");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
const promise = require("promise");
|
||||
const {longStringSpec, SimpleStringFront} = require("devtools/shared/specs/string");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
longStringSpec,
|
||||
SimpleStringFront,
|
||||
} = require("devtools/shared/specs/string");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class LongStringFront extends FrontClassWithSpec(longStringSpec) {
|
||||
destroy() {
|
||||
|
@ -24,13 +30,14 @@ class LongStringFront extends FrontClassWithSpec(longStringSpec) {
|
|||
|
||||
string() {
|
||||
if (!this.strPromise) {
|
||||
const promiseRest = (thusFar) => {
|
||||
const promiseRest = thusFar => {
|
||||
if (thusFar.length === this.length) {
|
||||
return promise.resolve(thusFar);
|
||||
}
|
||||
return this.substring(thusFar.length,
|
||||
thusFar.length + DebuggerServer.LONG_STRING_READ_LENGTH)
|
||||
.then((next) => promiseRest(thusFar + next));
|
||||
return this.substring(
|
||||
thusFar.length,
|
||||
thusFar.length + DebuggerServer.LONG_STRING_READ_LENGTH
|
||||
).then(next => promiseRest(thusFar + next));
|
||||
};
|
||||
|
||||
this.strPromise = promiseRest(this.initial);
|
||||
|
|
|
@ -13,7 +13,11 @@ const {
|
|||
} = require("devtools/shared/specs/styles");
|
||||
const promise = require("promise");
|
||||
|
||||
loader.lazyRequireGetter(this, "RuleRewriter", "devtools/shared/fronts/inspector/rule-rewriter");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"RuleRewriter",
|
||||
"devtools/shared/fronts/inspector/rule-rewriter"
|
||||
);
|
||||
|
||||
/**
|
||||
* PageStyleFront, the front object for the PageStyleActor
|
||||
|
@ -133,7 +137,7 @@ class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
|
|||
return this._form.cssText;
|
||||
}
|
||||
get authoredText() {
|
||||
return (typeof this._form.authoredText === "string")
|
||||
return typeof this._form.authoredText === "string"
|
||||
? this._form.authoredText
|
||||
: this._form.cssText;
|
||||
}
|
||||
|
@ -215,7 +219,8 @@ class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
|
|||
// Inline styles do not have any mediaText so we can return early.
|
||||
return promise.resolve(this.location);
|
||||
}
|
||||
return parentSheet.getOriginalLocation(this.line, this.column)
|
||||
return parentSheet
|
||||
.getOriginalLocation(this.line, this.column)
|
||||
.then(({ fromSourceMap, source, line, column }) => {
|
||||
const location = {
|
||||
href: source,
|
||||
|
@ -235,7 +240,11 @@ class StyleRuleFront extends FrontClassWithSpec(styleRuleSpec) {
|
|||
}
|
||||
|
||||
async modifySelector(node, value) {
|
||||
const response = await super.modifySelector(node, value, this.canSetRuleText);
|
||||
const response = await super.modifySelector(
|
||||
node,
|
||||
value,
|
||||
this.canSetRuleText
|
||||
);
|
||||
|
||||
if (response.ruleProps) {
|
||||
response.ruleProps = response.ruleProps.entries[0];
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const {
|
||||
mediaRuleSpec,
|
||||
styleSheetSpec,
|
||||
|
@ -11,10 +14,18 @@ const {
|
|||
} = require("devtools/shared/specs/stylesheets");
|
||||
const promise = require("promise");
|
||||
|
||||
loader.lazyRequireGetter(this, "getIndentationFromPrefs",
|
||||
"devtools/shared/indentation", true);
|
||||
loader.lazyRequireGetter(this, "getIndentationFromString",
|
||||
"devtools/shared/indentation", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"getIndentationFromPrefs",
|
||||
"devtools/shared/indentation",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"getIndentationFromString",
|
||||
"devtools/shared/indentation",
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Corresponding client-side front for a MediaRuleActor.
|
||||
|
@ -118,18 +129,18 @@ class StyleSheetFront extends FrontClassWithSpec(styleSheetSpec) {
|
|||
guessIndentation() {
|
||||
const prefIndent = getIndentationFromPrefs();
|
||||
if (prefIndent) {
|
||||
const {indentUnit, indentWithTabs} = prefIndent;
|
||||
const { indentUnit, indentWithTabs } = prefIndent;
|
||||
return promise.resolve(indentWithTabs ? "\t" : " ".repeat(indentUnit));
|
||||
}
|
||||
|
||||
return (async function() {
|
||||
return async function() {
|
||||
const longStr = await this.getText();
|
||||
const source = await longStr.string();
|
||||
|
||||
const {indentUnit, indentWithTabs} = getIndentationFromString(source);
|
||||
const { indentUnit, indentWithTabs } = getIndentationFromString(source);
|
||||
|
||||
return indentWithTabs ? "\t" : " ".repeat(indentUnit);
|
||||
}.bind(this))();
|
||||
}.bind(this)();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {addonTargetSpec} = require("devtools/shared/specs/targets/addon");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
loader.lazyRequireGetter(this, "BrowsingContextTargetFront", "devtools/shared/fronts/targets/browsing-context", true);
|
||||
const { addonTargetSpec } = require("devtools/shared/specs/targets/addon");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"BrowsingContextTargetFront",
|
||||
"devtools/shared/fronts/targets/browsing-context",
|
||||
true
|
||||
);
|
||||
|
||||
class AddonTargetFront extends FrontClassWithSpec(addonTargetSpec) {
|
||||
constructor(client) {
|
||||
|
@ -40,10 +48,12 @@ class AddonTargetFront extends FrontClassWithSpec(addonTargetSpec) {
|
|||
// irrelevant warning messages.
|
||||
return false;
|
||||
}
|
||||
return this.type == "extension" &&
|
||||
this.temporarilyInstalled &&
|
||||
!this.isWebExtension &&
|
||||
!this.isAPIExtension;
|
||||
return (
|
||||
this.type == "extension" &&
|
||||
this.temporarilyInstalled &&
|
||||
!this.isWebExtension &&
|
||||
!this.isAPIExtension
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,8 +66,10 @@ class AddonTargetFront extends FrontClassWithSpec(addonTargetSpec) {
|
|||
* the final target actor to use.
|
||||
*/
|
||||
async connect() {
|
||||
if (this.isWebExtension &&
|
||||
this.client.mainRoot.traits.webExtensionAddonConnect) {
|
||||
if (
|
||||
this.isWebExtension &&
|
||||
this.client.mainRoot.traits.webExtensionAddonConnect
|
||||
) {
|
||||
// The AddonTargetFront form is related to a WebExtensionActor instance,
|
||||
// which isn't a target actor on its own, it is an actor living in the parent
|
||||
// process with access to the addon metadata, it can control the addon (e.g.
|
||||
|
@ -66,7 +78,9 @@ class AddonTargetFront extends FrontClassWithSpec(addonTargetSpec) {
|
|||
// To retrieve the target actor instance, we call its "connect" method, (which
|
||||
// fetches the target actor targetForm from a WebExtensionTargetActor instance).
|
||||
const { form } = await super.connect();
|
||||
const front = new BrowsingContextTargetFront(this.client, { actor: form.actor });
|
||||
const front = new BrowsingContextTargetFront(this.client, {
|
||||
actor: form.actor,
|
||||
});
|
||||
front.form(form);
|
||||
this.manage(front);
|
||||
return front;
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {browsingContextTargetSpec} = require("devtools/shared/specs/targets/browsing-context");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
browsingContextTargetSpec,
|
||||
} = require("devtools/shared/specs/targets/browsing-context");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { TargetMixin } = require("./target-mixin");
|
||||
|
||||
class BrowsingContextTargetFront extends
|
||||
TargetMixin(FrontClassWithSpec(browsingContextTargetSpec)) {
|
||||
class BrowsingContextTargetFront extends TargetMixin(
|
||||
FrontClassWithSpec(browsingContextTargetSpec)
|
||||
) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
|
@ -127,7 +133,8 @@ class BrowsingContextTargetFront extends
|
|||
response = await super.detach();
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`Error while detaching the browsing context target front: ${e.message}`);
|
||||
`Error while detaching the browsing context target front: ${e.message}`
|
||||
);
|
||||
}
|
||||
|
||||
// Remove listeners set in attach
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {contentProcessTargetSpec} = require("devtools/shared/specs/targets/content-process");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
contentProcessTargetSpec,
|
||||
} = require("devtools/shared/specs/targets/content-process");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { TargetMixin } = require("./target-mixin");
|
||||
|
||||
class ContentProcessTargetFront extends
|
||||
TargetMixin(FrontClassWithSpec(contentProcessTargetSpec)) {
|
||||
class ContentProcessTargetFront extends TargetMixin(
|
||||
FrontClassWithSpec(contentProcessTargetSpec)
|
||||
) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
|
|
|
@ -8,9 +8,23 @@
|
|||
// This shouldn't happen, but Fronts should rather be part of client anyway.
|
||||
// Otherwise gDevTools is only used for local tabs and should propably only
|
||||
// used by a subclass, specific to local tabs.
|
||||
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
||||
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
|
||||
loader.lazyRequireGetter(this, "ThreadClient", "devtools/shared/client/deprecated-thread-client");
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"gDevTools",
|
||||
"devtools/client/framework/devtools",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"TargetFactory",
|
||||
"devtools/client/framework/target",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"ThreadClient",
|
||||
"devtools/shared/client/deprecated-thread-client"
|
||||
);
|
||||
loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true);
|
||||
|
||||
/**
|
||||
|
@ -107,7 +121,10 @@ function TargetMixin(parentClass) {
|
|||
* }
|
||||
*/
|
||||
async getActorDescription(actorName) {
|
||||
if (this._protocolDescription && this._protocolDescription.types[actorName]) {
|
||||
if (
|
||||
this._protocolDescription &&
|
||||
this._protocolDescription.types[actorName]
|
||||
) {
|
||||
return this._protocolDescription.types[actorName];
|
||||
}
|
||||
const description = await this.client.mainRoot.protocolDescription();
|
||||
|
@ -182,7 +199,11 @@ function TargetMixin(parentClass) {
|
|||
if (this._inspector && this._inspector.actorID) {
|
||||
return this._inspector;
|
||||
}
|
||||
this._inspector = await getFront(this.client, "inspector", this.targetForm);
|
||||
this._inspector = await getFront(
|
||||
this.client,
|
||||
"inspector",
|
||||
this.targetForm
|
||||
);
|
||||
this.emit("inspector", this._inspector);
|
||||
return this._inspector;
|
||||
}
|
||||
|
@ -202,7 +223,10 @@ function TargetMixin(parentClass) {
|
|||
async getFront(typeName) {
|
||||
let front = this.fronts.get(typeName);
|
||||
// the front might have been destroyed and no longer have an actor ID
|
||||
if ((front && front.actorID) || (front && typeof front.then === "function")) {
|
||||
if (
|
||||
(front && front.actorID) ||
|
||||
(front && typeof front.then === "function")
|
||||
) {
|
||||
return front;
|
||||
}
|
||||
front = getFront(this.client, typeName, this.targetForm);
|
||||
|
@ -402,7 +426,8 @@ function TargetMixin(parentClass) {
|
|||
async attachThread(options = {}) {
|
||||
if (!this._threadActor) {
|
||||
throw new Error(
|
||||
"TargetMixin sub class should set _threadActor before calling " + "attachThread"
|
||||
"TargetMixin sub class should set _threadActor before calling " +
|
||||
"attachThread"
|
||||
);
|
||||
}
|
||||
if (this.getTrait("hasThreadFront")) {
|
||||
|
@ -593,7 +618,9 @@ function TargetMixin(parentClass) {
|
|||
}
|
||||
|
||||
toString() {
|
||||
const id = this._tab ? this._tab : this.targetForm && this.targetForm.actor;
|
||||
const id = this._tab
|
||||
? this._tab
|
||||
: this.targetForm && this.targetForm.actor;
|
||||
return `Target:${id}`;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const {workerTargetSpec} = require("devtools/shared/specs/targets/worker");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const { workerTargetSpec } = require("devtools/shared/specs/targets/worker");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { TargetMixin } = require("./target-mixin");
|
||||
|
||||
class WorkerTargetFront extends
|
||||
TargetMixin(FrontClassWithSpec(workerTargetSpec)) {
|
||||
class WorkerTargetFront extends TargetMixin(
|
||||
FrontClassWithSpec(workerTargetSpec)
|
||||
) {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const LongStringClient = require("devtools/shared/client/long-string-client");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { webconsoleSpec } = require("devtools/shared/specs/webconsole");
|
||||
|
||||
/**
|
||||
|
@ -256,9 +259,12 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
onResponse(packet);
|
||||
this.pendingEvaluationResults.delete(packet.resultID);
|
||||
} else {
|
||||
DevToolsUtils.reportException("onEvaluationResult",
|
||||
DevToolsUtils.reportException(
|
||||
"onEvaluationResult",
|
||||
"No response handler for an evaluateJSAsync result (resultID: " +
|
||||
packet.resultID + ")");
|
||||
packet.resultID +
|
||||
")"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,8 +494,7 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
}
|
||||
this.off("evaluationResult", this.onEvaluationResult);
|
||||
this.off("serverNetworkEvent", this.onNetworkEvent);
|
||||
this._client.off("networkEventUpdate",
|
||||
this.onNetworkEventUpdate);
|
||||
this._client.off("networkEventUpdate", this.onNetworkEventUpdate);
|
||||
this._longStrings = null;
|
||||
this._client = null;
|
||||
this.pendingEvaluationResults.clear();
|
||||
|
@ -532,8 +537,10 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
|
||||
longStringClient.substring(initial.length, length, response => {
|
||||
if (response.error) {
|
||||
DevToolsUtils.reportException("getString",
|
||||
response.error + ": " + response.message);
|
||||
DevToolsUtils.reportException(
|
||||
"getString",
|
||||
response.error + ": " + response.message
|
||||
);
|
||||
reject(response);
|
||||
}
|
||||
resolve(initial + response.substring);
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
const { webSocketSpec } = require("devtools/shared/specs/websocket");
|
||||
|
||||
/**
|
||||
|
@ -58,7 +61,13 @@ class WebSocketFront extends FrontClassWithSpec(webSocketSpec) {
|
|||
* @param string extensions
|
||||
*/
|
||||
async _onWebSocketOpened(httpChannelId, effectiveURI, protocols, extensions) {
|
||||
this.emit("webSocketOpened", httpChannelId, effectiveURI, protocols, extensions);
|
||||
this.emit(
|
||||
"webSocketOpened",
|
||||
httpChannelId,
|
||||
effectiveURI,
|
||||
protocols,
|
||||
extensions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { pushSubscriptionSpec } =
|
||||
require("devtools/shared/specs/worker/push-subscription");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
pushSubscriptionSpec,
|
||||
} = require("devtools/shared/specs/worker/push-subscription");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class PushSubscriptionFront extends FrontClassWithSpec(pushSubscriptionSpec) {
|
||||
get endpoint() {
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { serviceWorkerRegistrationSpec } =
|
||||
require("devtools/shared/specs/worker/service-worker-registration");
|
||||
const { FrontClassWithSpec, registerFront, types } = require("devtools/shared/protocol");
|
||||
const {
|
||||
serviceWorkerRegistrationSpec,
|
||||
} = require("devtools/shared/specs/worker/service-worker-registration");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
types,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class ServiceWorkerRegistrationFront extends
|
||||
FrontClassWithSpec(serviceWorkerRegistrationSpec) {
|
||||
class ServiceWorkerRegistrationFront extends FrontClassWithSpec(
|
||||
serviceWorkerRegistrationSpec
|
||||
) {
|
||||
get active() {
|
||||
return this._form.active;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { serviceWorkerSpec } = require("devtools/shared/specs/worker/service-worker");
|
||||
const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
|
||||
const {
|
||||
serviceWorkerSpec,
|
||||
} = require("devtools/shared/specs/worker/service-worker");
|
||||
const {
|
||||
FrontClassWithSpec,
|
||||
registerFront,
|
||||
} = require("devtools/shared/protocol");
|
||||
|
||||
class ServiceWorkerFront extends FrontClassWithSpec(serviceWorkerSpec) {
|
||||
get fetch() {
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
"use strict";
|
||||
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const { generateUUID } =
|
||||
Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
|
||||
const { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(
|
||||
Ci.nsIUUIDGenerator
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns a new `uuid`.
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { flatten } = require("resource://devtools/shared/ThreadSafeDevToolsUtils.js");
|
||||
const {
|
||||
flatten,
|
||||
} = require("resource://devtools/shared/ThreadSafeDevToolsUtils.js");
|
||||
|
||||
/** * Visitor ****************************************************************/
|
||||
|
||||
|
@ -11,7 +13,7 @@ const { flatten } = require("resource://devtools/shared/ThreadSafeDevToolsUtils.
|
|||
* A Visitor visits each node and edge of a census report tree as the census
|
||||
* report is being traversed by `walk`.
|
||||
*/
|
||||
function Visitor() { }
|
||||
function Visitor() {}
|
||||
exports.Visitor = Visitor;
|
||||
|
||||
/**
|
||||
|
@ -27,7 +29,7 @@ exports.Visitor = Visitor;
|
|||
* The edge leading to this sub-report. The edge is null if (but not iff!
|
||||
* eg, null allocation stack edges) we are entering the root report.
|
||||
*/
|
||||
Visitor.prototype.enter = function(breakdown, report, edge) { };
|
||||
Visitor.prototype.enter = function(breakdown, report, edge) {};
|
||||
|
||||
/**
|
||||
* The `exit` method is called when traversal of a sub-report has finished.
|
||||
|
@ -42,7 +44,7 @@ Visitor.prototype.enter = function(breakdown, report, edge) { };
|
|||
* The edge leading to this sub-report. The edge is null if (but not iff!
|
||||
* eg, null allocation stack edges) we are entering the root report.
|
||||
*/
|
||||
Visitor.prototype.exit = function(breakdown, report, edge) { };
|
||||
Visitor.prototype.exit = function(breakdown, report, edge) {};
|
||||
|
||||
/**
|
||||
* The `count` method is called when leaf nodes (reports whose breakdown is
|
||||
|
@ -58,7 +60,7 @@ Visitor.prototype.exit = function(breakdown, report, edge) { };
|
|||
* The edge leading to this count report. The edge is null if we are
|
||||
* entering the root report.
|
||||
*/
|
||||
Visitor.prototype.count = function(breakdown, report, edge) { };
|
||||
Visitor.prototype.count = function(breakdown, report, edge) {};
|
||||
|
||||
/** * getReportEdges *********************************************************/
|
||||
|
||||
|
@ -150,8 +152,11 @@ function recursiveWalk(breakdown, edge, report, visitor) {
|
|||
visitor.exit(breakdown, report, edge);
|
||||
} else {
|
||||
visitor.enter(breakdown, report, edge);
|
||||
for (const { edge: ed, referent, breakdown: subBreakdown }
|
||||
of getReportEdges(breakdown, report)) {
|
||||
for (const {
|
||||
edge: ed,
|
||||
referent,
|
||||
breakdown: subBreakdown,
|
||||
} of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(subBreakdown, ed, referent, visitor);
|
||||
}
|
||||
visitor.exit(breakdown, report, edge);
|
||||
|
@ -323,8 +328,8 @@ DiffVisitor.prototype.count = function(breakdown, report, edge) {
|
|||
}
|
||||
};
|
||||
|
||||
const basisTotalBytes = exports.basisTotalBytes = Symbol("basisTotalBytes");
|
||||
const basisTotalCount = exports.basisTotalCount = Symbol("basisTotalCount");
|
||||
const basisTotalBytes = (exports.basisTotalBytes = Symbol("basisTotalBytes"));
|
||||
const basisTotalCount = (exports.basisTotalCount = Symbol("basisTotalCount"));
|
||||
|
||||
/**
|
||||
* Get the resulting report of the difference between the traversed census
|
||||
|
@ -488,8 +493,10 @@ exports.getReportLeaves = function(indices, breakdown, report) {
|
|||
exports.getCensusIndividuals = function(indices, countBreakdown, snapshot) {
|
||||
const bucketBreakdown = exports.countToBucketBreakdown(countBreakdown);
|
||||
const bucketReport = snapshot.takeCensus({ breakdown: bucketBreakdown });
|
||||
const buckets = exports.getReportLeaves(indices,
|
||||
bucketBreakdown,
|
||||
bucketReport);
|
||||
const buckets = exports.getReportLeaves(
|
||||
indices,
|
||||
bucketBreakdown,
|
||||
bucketReport
|
||||
);
|
||||
return flatten(buckets);
|
||||
};
|
||||
|
|
|
@ -3,9 +3,16 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { immutableUpdate } = require("resource://devtools/shared/ThreadSafeDevToolsUtils.js");
|
||||
const { Visitor, walk } = require("resource://devtools/shared/heapsnapshot/CensusUtils.js");
|
||||
const { deduplicatePaths } = require("resource://devtools/shared/heapsnapshot/shortest-paths");
|
||||
const {
|
||||
immutableUpdate,
|
||||
} = require("resource://devtools/shared/ThreadSafeDevToolsUtils.js");
|
||||
const {
|
||||
Visitor,
|
||||
walk,
|
||||
} = require("resource://devtools/shared/heapsnapshot/CensusUtils.js");
|
||||
const {
|
||||
deduplicatePaths,
|
||||
} = require("resource://devtools/shared/heapsnapshot/shortest-paths");
|
||||
|
||||
const DEFAULT_MAX_DEPTH = 4;
|
||||
const DEFAULT_MAX_SIBLINGS = 15;
|
||||
|
@ -163,9 +170,11 @@ LabelAndShallowSizeVisitor.prototype.shallowSize = function() {
|
|||
* - {Number} shallowSize
|
||||
* - {Object} label
|
||||
*/
|
||||
DominatorTreeNode.getLabelAndShallowSize = function(nodeId,
|
||||
snapshot,
|
||||
breakdown) {
|
||||
DominatorTreeNode.getLabelAndShallowSize = function(
|
||||
nodeId,
|
||||
snapshot,
|
||||
breakdown
|
||||
) {
|
||||
const description = snapshot.describeNode(breakdown, nodeId);
|
||||
|
||||
const visitor = new LabelAndShallowSizeVisitor();
|
||||
|
@ -194,16 +203,26 @@ DominatorTreeNode.getLabelAndShallowSize = function(nodeId,
|
|||
*
|
||||
* @returns {DominatorTreeNode}
|
||||
*/
|
||||
DominatorTreeNode.partialTraversal = function(dominatorTree,
|
||||
snapshot,
|
||||
breakdown,
|
||||
maxDepth = DEFAULT_MAX_DEPTH,
|
||||
maxSiblings = DEFAULT_MAX_SIBLINGS) {
|
||||
DominatorTreeNode.partialTraversal = function(
|
||||
dominatorTree,
|
||||
snapshot,
|
||||
breakdown,
|
||||
maxDepth = DEFAULT_MAX_DEPTH,
|
||||
maxSiblings = DEFAULT_MAX_SIBLINGS
|
||||
) {
|
||||
function dfs(nodeId, depth) {
|
||||
const { label, shallowSize } =
|
||||
DominatorTreeNode.getLabelAndShallowSize(nodeId, snapshot, breakdown);
|
||||
const { label, shallowSize } = DominatorTreeNode.getLabelAndShallowSize(
|
||||
nodeId,
|
||||
snapshot,
|
||||
breakdown
|
||||
);
|
||||
const retainedSize = dominatorTree.getRetainedSize(nodeId);
|
||||
const node = new DominatorTreeNode(nodeId, label, shallowSize, retainedSize);
|
||||
const node = new DominatorTreeNode(
|
||||
nodeId,
|
||||
label,
|
||||
shallowSize,
|
||||
retainedSize
|
||||
);
|
||||
const childNodeIds = dominatorTree.getImmediatelyDominated(nodeId);
|
||||
|
||||
const newDepth = depth + 1;
|
||||
|
@ -237,7 +256,12 @@ DominatorTreeNode.partialTraversal = function(dominatorTree,
|
|||
*
|
||||
* @returns {DominatorTreeNode}
|
||||
*/
|
||||
DominatorTreeNode.insert = function(nodeTree, path, newChildren, moreChildrenAvailable) {
|
||||
DominatorTreeNode.insert = function(
|
||||
nodeTree,
|
||||
path,
|
||||
newChildren,
|
||||
moreChildrenAvailable
|
||||
) {
|
||||
function insert(tree, i) {
|
||||
if (tree.nodeId !== path[i]) {
|
||||
return tree;
|
||||
|
@ -252,8 +276,8 @@ DominatorTreeNode.insert = function(nodeTree, path, newChildren, moreChildrenAva
|
|||
|
||||
return tree.children
|
||||
? immutableUpdate(tree, {
|
||||
children: tree.children.map(c => insert(c, i + 1)),
|
||||
})
|
||||
children: tree.children.map(c => insert(c, i + 1)),
|
||||
})
|
||||
: tree;
|
||||
}
|
||||
|
||||
|
@ -306,11 +330,13 @@ DominatorTreeNode.getNodeByIdAlongPath = function(id, tree, path) {
|
|||
* @param {Array<DominatorTreeNode>} treeNodes
|
||||
* @param {Number} maxNumPaths
|
||||
*/
|
||||
DominatorTreeNode.attachShortestPaths = function(snapshot,
|
||||
breakdown,
|
||||
start,
|
||||
treeNodes,
|
||||
maxNumPaths = DEFAULT_MAX_NUM_PATHS) {
|
||||
DominatorTreeNode.attachShortestPaths = function(
|
||||
snapshot,
|
||||
breakdown,
|
||||
start,
|
||||
treeNodes,
|
||||
maxNumPaths = DEFAULT_MAX_NUM_PATHS
|
||||
) {
|
||||
const idToTreeNode = new Map();
|
||||
const targets = [];
|
||||
for (const node of treeNodes) {
|
||||
|
@ -319,15 +345,20 @@ DominatorTreeNode.attachShortestPaths = function(snapshot,
|
|||
targets.push(id);
|
||||
}
|
||||
|
||||
const shortestPaths = snapshot.computeShortestPaths(start,
|
||||
targets,
|
||||
maxNumPaths);
|
||||
const shortestPaths = snapshot.computeShortestPaths(
|
||||
start,
|
||||
targets,
|
||||
maxNumPaths
|
||||
);
|
||||
|
||||
for (const [target, paths] of shortestPaths) {
|
||||
const deduped = deduplicatePaths(target, paths);
|
||||
deduped.nodes = deduped.nodes.map(id => {
|
||||
const { label } =
|
||||
DominatorTreeNode.getLabelAndShallowSize(id, snapshot, breakdown);
|
||||
const { label } = DominatorTreeNode.getLabelAndShallowSize(
|
||||
id,
|
||||
snapshot,
|
||||
breakdown
|
||||
);
|
||||
return { id, label };
|
||||
});
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ var workerCounter = 0;
|
|||
* HeapAnalysesClient owns the worker, and terminating the worker is done by
|
||||
* terminating the client (see the `destroy` method).
|
||||
*/
|
||||
const HeapAnalysesClient = module.exports = function() {
|
||||
const HeapAnalysesClient = (module.exports = function() {
|
||||
this._worker = new DevToolsWorker(WORKER_URL, {
|
||||
name: `HeapAnalyses-${workerCounter++}`,
|
||||
verbose: DevToolsUtils.dumpv.wantVerbose,
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Destroy the worker, causing it to release its resources (such as heap
|
||||
|
@ -114,9 +114,11 @@ HeapAnalysesClient.prototype.getCreationTime = function(snapshotFilePath) {
|
|||
* The result of calling CensusUtils.createParentMap on the generated
|
||||
* report. Only exists if asTreeNode or asInvertedTreeNode are set.
|
||||
*/
|
||||
HeapAnalysesClient.prototype.takeCensus = function(snapshotFilePath,
|
||||
censusOptions,
|
||||
requestOptions = {}) {
|
||||
HeapAnalysesClient.prototype.takeCensus = function(
|
||||
snapshotFilePath,
|
||||
censusOptions,
|
||||
requestOptions = {}
|
||||
) {
|
||||
return this._worker.performTask("takeCensus", {
|
||||
snapshotFilePath,
|
||||
censusOptions,
|
||||
|
@ -190,10 +192,12 @@ HeapAnalysesClient.prototype.getCensusIndividuals = function(opts) {
|
|||
* The result of calling CensusUtils.createParentMap on the generated
|
||||
* delta. Only exists if asTreeNode or asInvertedTreeNode are set.
|
||||
*/
|
||||
HeapAnalysesClient.prototype.takeCensusDiff = function(firstSnapshotFilePath,
|
||||
secondSnapshotFilePath,
|
||||
censusOptions,
|
||||
requestOptions = {}) {
|
||||
HeapAnalysesClient.prototype.takeCensusDiff = function(
|
||||
firstSnapshotFilePath,
|
||||
secondSnapshotFilePath,
|
||||
censusOptions,
|
||||
requestOptions = {}
|
||||
) {
|
||||
return this._worker.performTask("takeCensusDiff", {
|
||||
firstSnapshotFilePath,
|
||||
secondSnapshotFilePath,
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
importScripts("resource://gre/modules/workers/require.js");
|
||||
importScripts("resource://devtools/shared/worker/helper.js");
|
||||
const { censusReportToCensusTreeNode } = require("resource://devtools/shared/heapsnapshot/census-tree-node.js");
|
||||
const {
|
||||
censusReportToCensusTreeNode,
|
||||
} = require("resource://devtools/shared/heapsnapshot/census-tree-node.js");
|
||||
const DominatorTreeNode = require("resource://devtools/shared/heapsnapshot/DominatorTreeNode.js");
|
||||
const CensusUtils = require("resource://devtools/shared/heapsnapshot/CensusUtils.js");
|
||||
|
||||
|
@ -46,8 +48,7 @@ const dominatorTreeSnapshots = [];
|
|||
* @see HeapAnalysesClient.prototype.readHeapSnapshot
|
||||
*/
|
||||
workerHelper.createTask(self, "readHeapSnapshot", ({ snapshotFilePath }) => {
|
||||
snapshots[snapshotFilePath] =
|
||||
ChromeUtils.readHeapSnapshot(snapshotFilePath);
|
||||
snapshots[snapshotFilePath] = ChromeUtils.readHeapSnapshot(snapshotFilePath);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -72,26 +73,33 @@ workerHelper.createTask(self, "deleteHeapSnapshot", ({ snapshotFilePath }) => {
|
|||
/**
|
||||
* @see HeapAnalysesClient.prototype.takeCensus
|
||||
*/
|
||||
workerHelper.createTask(self, "takeCensus", (
|
||||
{ snapshotFilePath, censusOptions, requestOptions }) => {
|
||||
if (!snapshots[snapshotFilePath]) {
|
||||
throw new Error(`No known heap snapshot for '${snapshotFilePath}'`);
|
||||
}
|
||||
|
||||
let report = snapshots[snapshotFilePath].takeCensus(censusOptions);
|
||||
let parentMap;
|
||||
|
||||
if (requestOptions.asTreeNode || requestOptions.asInvertedTreeNode) {
|
||||
const opts = { filter: requestOptions.filter || null };
|
||||
if (requestOptions.asInvertedTreeNode) {
|
||||
opts.invert = true;
|
||||
workerHelper.createTask(
|
||||
self,
|
||||
"takeCensus",
|
||||
({ snapshotFilePath, censusOptions, requestOptions }) => {
|
||||
if (!snapshots[snapshotFilePath]) {
|
||||
throw new Error(`No known heap snapshot for '${snapshotFilePath}'`);
|
||||
}
|
||||
report = censusReportToCensusTreeNode(censusOptions.breakdown, report, opts);
|
||||
parentMap = CensusUtils.createParentMap(report);
|
||||
}
|
||||
|
||||
return { report, parentMap };
|
||||
});
|
||||
let report = snapshots[snapshotFilePath].takeCensus(censusOptions);
|
||||
let parentMap;
|
||||
|
||||
if (requestOptions.asTreeNode || requestOptions.asInvertedTreeNode) {
|
||||
const opts = { filter: requestOptions.filter || null };
|
||||
if (requestOptions.asInvertedTreeNode) {
|
||||
opts.invert = true;
|
||||
}
|
||||
report = censusReportToCensusTreeNode(
|
||||
censusOptions.breakdown,
|
||||
report,
|
||||
opts
|
||||
);
|
||||
parentMap = CensusUtils.createParentMap(report);
|
||||
}
|
||||
|
||||
return { report, parentMap };
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @see HeapAnalysesClient.prototype.getCensusIndividuals
|
||||
|
@ -109,29 +117,42 @@ workerHelper.createTask(self, "getCensusIndividuals", request => {
|
|||
const dominatorTree = dominatorTrees[dominatorTreeId];
|
||||
if (!dominatorTree) {
|
||||
throw new Error(
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`);
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`
|
||||
);
|
||||
}
|
||||
|
||||
const snapshot = dominatorTreeSnapshots[dominatorTreeId];
|
||||
const nodeIds = CensusUtils.getCensusIndividuals(indices, censusBreakdown, snapshot);
|
||||
const nodeIds = CensusUtils.getCensusIndividuals(
|
||||
indices,
|
||||
censusBreakdown,
|
||||
snapshot
|
||||
);
|
||||
|
||||
const nodes = nodeIds
|
||||
.sort((a, b) => dominatorTree.getRetainedSize(b) - dominatorTree.getRetainedSize(a))
|
||||
.sort(
|
||||
(a, b) =>
|
||||
dominatorTree.getRetainedSize(b) - dominatorTree.getRetainedSize(a)
|
||||
)
|
||||
.slice(0, maxIndividuals)
|
||||
.map(id => {
|
||||
const { label, shallowSize } =
|
||||
DominatorTreeNode.getLabelAndShallowSize(id, snapshot, labelBreakdown);
|
||||
const { label, shallowSize } = DominatorTreeNode.getLabelAndShallowSize(
|
||||
id,
|
||||
snapshot,
|
||||
labelBreakdown
|
||||
);
|
||||
const retainedSize = dominatorTree.getRetainedSize(id);
|
||||
const node = new DominatorTreeNode(id, label, shallowSize, retainedSize);
|
||||
node.moreChildrenAvailable = false;
|
||||
return node;
|
||||
});
|
||||
|
||||
DominatorTreeNode.attachShortestPaths(snapshot,
|
||||
labelBreakdown,
|
||||
dominatorTree.root,
|
||||
nodes,
|
||||
maxRetainingPaths);
|
||||
DominatorTreeNode.attachShortestPaths(
|
||||
snapshot,
|
||||
labelBreakdown,
|
||||
dominatorTree.root,
|
||||
nodes,
|
||||
maxRetainingPaths
|
||||
);
|
||||
|
||||
return { nodes };
|
||||
});
|
||||
|
@ -211,17 +232,20 @@ workerHelper.createTask(self, "getDominatorTree", request => {
|
|||
|
||||
if (!(dominatorTreeId >= 0 && dominatorTreeId < dominatorTrees.length)) {
|
||||
throw new Error(
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`);
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`
|
||||
);
|
||||
}
|
||||
|
||||
const dominatorTree = dominatorTrees[dominatorTreeId];
|
||||
const snapshot = dominatorTreeSnapshots[dominatorTreeId];
|
||||
|
||||
const tree = DominatorTreeNode.partialTraversal(dominatorTree,
|
||||
snapshot,
|
||||
breakdown,
|
||||
maxDepth,
|
||||
maxSiblings);
|
||||
const tree = DominatorTreeNode.partialTraversal(
|
||||
dominatorTree,
|
||||
snapshot,
|
||||
breakdown,
|
||||
maxDepth,
|
||||
maxSiblings
|
||||
);
|
||||
|
||||
const nodes = [];
|
||||
(function getNodes(node) {
|
||||
|
@ -231,13 +255,15 @@ workerHelper.createTask(self, "getDominatorTree", request => {
|
|||
getNodes(node.children[i]);
|
||||
}
|
||||
}
|
||||
}(tree));
|
||||
})(tree);
|
||||
|
||||
DominatorTreeNode.attachShortestPaths(snapshot,
|
||||
breakdown,
|
||||
dominatorTree.root,
|
||||
nodes,
|
||||
maxRetainingPaths);
|
||||
DominatorTreeNode.attachShortestPaths(
|
||||
snapshot,
|
||||
breakdown,
|
||||
dominatorTree.root,
|
||||
nodes,
|
||||
maxRetainingPaths
|
||||
);
|
||||
|
||||
return tree;
|
||||
});
|
||||
|
@ -257,7 +283,8 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
|
|||
|
||||
if (!(dominatorTreeId >= 0 && dominatorTreeId < dominatorTrees.length)) {
|
||||
throw new Error(
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`);
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`
|
||||
);
|
||||
}
|
||||
|
||||
const dominatorTree = dominatorTrees[dominatorTreeId];
|
||||
|
@ -272,19 +299,21 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
|
|||
const count = maxCount || DEFAULT_MAX_COUNT;
|
||||
const end = start + count;
|
||||
|
||||
const nodes = childIds
|
||||
.slice(start, end)
|
||||
.map(id => {
|
||||
const { label, shallowSize } =
|
||||
DominatorTreeNode.getLabelAndShallowSize(id, snapshot, breakdown);
|
||||
const retainedSize = dominatorTree.getRetainedSize(id);
|
||||
const node = new DominatorTreeNode(id, label, shallowSize, retainedSize);
|
||||
node.parentId = nodeId;
|
||||
// DominatorTree.getImmediatelyDominated will always return non-null here
|
||||
// because we got the id directly from the dominator tree.
|
||||
node.moreChildrenAvailable = dominatorTree.getImmediatelyDominated(id).length > 0;
|
||||
return node;
|
||||
});
|
||||
const nodes = childIds.slice(start, end).map(id => {
|
||||
const { label, shallowSize } = DominatorTreeNode.getLabelAndShallowSize(
|
||||
id,
|
||||
snapshot,
|
||||
breakdown
|
||||
);
|
||||
const retainedSize = dominatorTree.getRetainedSize(id);
|
||||
const node = new DominatorTreeNode(id, label, shallowSize, retainedSize);
|
||||
node.parentId = nodeId;
|
||||
// DominatorTree.getImmediatelyDominated will always return non-null here
|
||||
// because we got the id directly from the dominator tree.
|
||||
node.moreChildrenAvailable =
|
||||
dominatorTree.getImmediatelyDominated(id).length > 0;
|
||||
return node;
|
||||
});
|
||||
|
||||
const path = [];
|
||||
let id = nodeId;
|
||||
|
@ -296,11 +325,13 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
|
|||
|
||||
const moreChildrenAvailable = childIds.length > end;
|
||||
|
||||
DominatorTreeNode.attachShortestPaths(snapshot,
|
||||
breakdown,
|
||||
dominatorTree.root,
|
||||
nodes,
|
||||
maxRetainingPaths);
|
||||
DominatorTreeNode.attachShortestPaths(
|
||||
snapshot,
|
||||
breakdown,
|
||||
dominatorTree.root,
|
||||
nodes,
|
||||
maxRetainingPaths
|
||||
);
|
||||
|
||||
return { nodes, moreChildrenAvailable, path };
|
||||
});
|
||||
|
|
|
@ -23,8 +23,12 @@
|
|||
"use strict";
|
||||
|
||||
const { Ci } = require("chrome");
|
||||
loader.lazyRequireGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(this, "OS", "resource://gre/modules/osfile.jsm", true);
|
||||
|
||||
function getHeapSnapshotFileTemplate() {
|
||||
|
@ -78,6 +82,5 @@ exports.haveHeapSnapshotTempFile = function(snapshotId) {
|
|||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return OS.File.stat(path).then(() => true,
|
||||
() => false);
|
||||
return OS.File.stat(path).then(() => true, () => false);
|
||||
};
|
||||
|
|
|
@ -75,7 +75,9 @@ CensusTreeNodeCacheValue.prototype = null;
|
|||
*/
|
||||
CensusTreeNodeCache.hashFrame = function(frame) {
|
||||
// eslint-disable-next-line max-len
|
||||
return `FRAME,${frame.functionDisplayName},${frame.source},${frame.line},${frame.column},${frame.asyncCause}`;
|
||||
return `FRAME,${frame.functionDisplayName},${frame.source},${frame.line},${
|
||||
frame.column
|
||||
},${frame.asyncCause}`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -318,9 +320,11 @@ function values(cache) {
|
|||
}
|
||||
|
||||
function isNonEmpty(node) {
|
||||
return (node.children !== undefined && node.children.length)
|
||||
|| node.bytes !== 0
|
||||
|| node.count !== 0;
|
||||
return (
|
||||
(node.children !== undefined && node.children.length) ||
|
||||
node.bytes !== 0 ||
|
||||
node.count !== 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -388,7 +392,9 @@ CensusTreeNodeVisitor.prototype.count = function(breakdown, report, edge) {
|
|||
*/
|
||||
CensusTreeNodeVisitor.prototype.root = function() {
|
||||
if (!this._root) {
|
||||
throw new Error("Attempt to get the root before walking the census report!");
|
||||
throw new Error(
|
||||
"Attempt to get the root before walking the census report!"
|
||||
);
|
||||
}
|
||||
|
||||
if (this._nodeStack.length) {
|
||||
|
@ -468,10 +474,12 @@ CensusTreeNode.prototype = null;
|
|||
* A number suitable for using with Array.prototype.sort.
|
||||
*/
|
||||
function compareByTotal(node1, node2) {
|
||||
return Math.abs(node2.totalBytes) - Math.abs(node1.totalBytes)
|
||||
|| Math.abs(node2.totalCount) - Math.abs(node1.totalCount)
|
||||
|| Math.abs(node2.bytes) - Math.abs(node1.bytes)
|
||||
|| Math.abs(node2.count) - Math.abs(node1.count);
|
||||
return (
|
||||
Math.abs(node2.totalBytes) - Math.abs(node1.totalBytes) ||
|
||||
Math.abs(node2.totalCount) - Math.abs(node1.totalCount) ||
|
||||
Math.abs(node2.bytes) - Math.abs(node1.bytes) ||
|
||||
Math.abs(node2.count) - Math.abs(node1.count)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -485,10 +493,12 @@ function compareByTotal(node1, node2) {
|
|||
* A number suitable for using with Array.prototype.sort.
|
||||
*/
|
||||
function compareBySelf(node1, node2) {
|
||||
return Math.abs(node2.bytes) - Math.abs(node1.bytes)
|
||||
|| Math.abs(node2.count) - Math.abs(node1.count)
|
||||
|| Math.abs(node2.totalBytes) - Math.abs(node1.totalBytes)
|
||||
|| Math.abs(node2.totalCount) - Math.abs(node1.totalCount);
|
||||
return (
|
||||
Math.abs(node2.bytes) - Math.abs(node1.bytes) ||
|
||||
Math.abs(node2.count) - Math.abs(node1.count) ||
|
||||
Math.abs(node2.totalBytes) - Math.abs(node1.totalBytes) ||
|
||||
Math.abs(node2.totalCount) - Math.abs(node1.totalCount)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -515,8 +525,10 @@ function insertOrMergeNode(parentCacheValue, node) {
|
|||
// When inverting, it is possible that multiple leaves in the census report
|
||||
// get merged into a single CensusTreeNode node. When this occurs, switch
|
||||
// from a single index to a set of indices.
|
||||
if (val.node.reportLeafIndex !== undefined &&
|
||||
val.node.reportLeafIndex !== node.reportLeafIndex) {
|
||||
if (
|
||||
val.node.reportLeafIndex !== undefined &&
|
||||
val.node.reportLeafIndex !== node.reportLeafIndex
|
||||
) {
|
||||
if (typeof val.node.reportLeafIndex === "number") {
|
||||
const oldIndex = val.node.reportLeafIndex;
|
||||
val.node.reportLeafIndex = new Set();
|
||||
|
@ -582,7 +594,7 @@ function invert(tree) {
|
|||
}
|
||||
|
||||
path.pop();
|
||||
}(tree));
|
||||
})(tree);
|
||||
|
||||
// Ensure that the root node always has the totals.
|
||||
inverted.node.totalBytes = tree.totalBytes;
|
||||
|
@ -665,9 +677,11 @@ function makeFilterPredicate(filterString) {
|
|||
}
|
||||
|
||||
if (isSavedFrame(node.name)) {
|
||||
return node.name.source.includes(filterString)
|
||||
|| (node.name.functionDisplayName || "").includes(filterString)
|
||||
|| (node.name.asyncCause || "").includes(filterString);
|
||||
return (
|
||||
node.name.source.includes(filterString) ||
|
||||
(node.name.functionDisplayName || "").includes(filterString) ||
|
||||
(node.name.asyncCause || "").includes(filterString)
|
||||
);
|
||||
}
|
||||
|
||||
return String(node.name).includes(filterString);
|
||||
|
@ -704,11 +718,14 @@ function makeFilterPredicate(filterString) {
|
|||
*
|
||||
* @returns {CensusTreeNode}
|
||||
*/
|
||||
exports.censusReportToCensusTreeNode = function(breakdown, report,
|
||||
options = {
|
||||
invert: false,
|
||||
filter: null,
|
||||
}) {
|
||||
exports.censusReportToCensusTreeNode = function(
|
||||
breakdown,
|
||||
report,
|
||||
options = {
|
||||
invert: false,
|
||||
filter: null,
|
||||
}
|
||||
) {
|
||||
// Reset the counter so that turning the same census report into a
|
||||
// CensusTreeNode tree repeatedly is idempotent.
|
||||
censusTreeNodeIdCounter = 0;
|
||||
|
@ -743,7 +760,7 @@ exports.censusReportToCensusTreeNode = function(breakdown, report,
|
|||
ensureSorted(node.children[i]);
|
||||
}
|
||||
}
|
||||
}(result));
|
||||
})(result);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
|
|
@ -38,10 +38,12 @@ this.Census = (function() {
|
|||
if (typeof subject === "object") {
|
||||
dumpn(name);
|
||||
for (const prop in subject) {
|
||||
count = walk(subject[prop],
|
||||
name + "[" + uneval(prop) + "]",
|
||||
walker.enter(prop),
|
||||
count);
|
||||
count = walk(
|
||||
subject[prop],
|
||||
name + "[" + uneval(prop) + "]",
|
||||
walker.enter(prop),
|
||||
count
|
||||
);
|
||||
}
|
||||
walker.done();
|
||||
} else {
|
||||
|
@ -72,11 +74,15 @@ this.Census = (function() {
|
|||
};
|
||||
|
||||
function expectedObject() {
|
||||
throw new Error("Census mismatch: subject has leaf where basis has nested object");
|
||||
throw new Error(
|
||||
"Census mismatch: subject has leaf where basis has nested object"
|
||||
);
|
||||
}
|
||||
|
||||
function expectedLeaf() {
|
||||
throw new Error("Census mismatch: subject has nested object where basis has leaf");
|
||||
throw new Error(
|
||||
"Census mismatch: subject has nested object where basis has leaf"
|
||||
);
|
||||
}
|
||||
|
||||
// Return a function that, given a 'basis' census, returns a census walker that
|
||||
|
@ -92,7 +98,7 @@ this.Census = (function() {
|
|||
// - extra(prop): Called when the subject has a property named |prop|, but the
|
||||
// basis has no such property. This should return a walker that can check
|
||||
// the subject's value.
|
||||
function makeBasisChecker({compare, missing, extra}) {
|
||||
function makeBasisChecker({ compare, missing, extra }) {
|
||||
return function makeWalker(basis) {
|
||||
if (typeof basis === "object") {
|
||||
const unvisited = new Set(Object.getOwnPropertyNames(basis));
|
||||
|
@ -120,12 +126,15 @@ this.Census = (function() {
|
|||
}
|
||||
|
||||
function missingProp(prop) {
|
||||
throw new Error("Census mismatch: subject lacks property present in basis: " + prop);
|
||||
throw new Error(
|
||||
"Census mismatch: subject lacks property present in basis: " + prop
|
||||
);
|
||||
}
|
||||
|
||||
function extraProp(prop) {
|
||||
throw new Error("Census mismatch: subject has property not present in basis: "
|
||||
+ prop);
|
||||
throw new Error(
|
||||
"Census mismatch: subject has property not present in basis: " + prop
|
||||
);
|
||||
}
|
||||
|
||||
// Return a walker that checks that the subject census has counts all equal to
|
||||
|
@ -173,4 +182,4 @@ this.Census = (function() {
|
|||
};
|
||||
|
||||
return Census;
|
||||
}());
|
||||
})();
|
||||
|
|
|
@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = ["Match"];
|
|||
|
||||
this.Match = (function() {
|
||||
function Pattern(template) {
|
||||
// act like a constructor even as a function
|
||||
// act like a constructor even as a function
|
||||
if (!(this instanceof Pattern)) {
|
||||
return new Pattern(template);
|
||||
}
|
||||
|
@ -77,15 +77,17 @@ this.Match = (function() {
|
|||
};
|
||||
|
||||
function isAtom(x) {
|
||||
return (typeof x === "number") ||
|
||||
(typeof x === "string") ||
|
||||
(typeof x === "boolean") ||
|
||||
(x === null) ||
|
||||
(typeof x === "object" && x instanceof RegExp);
|
||||
return (
|
||||
typeof x === "number" ||
|
||||
typeof x === "string" ||
|
||||
typeof x === "boolean" ||
|
||||
x === null ||
|
||||
(typeof x === "object" && x instanceof RegExp)
|
||||
);
|
||||
}
|
||||
|
||||
function isObject(x) {
|
||||
return (x !== null) && (typeof x === "object");
|
||||
return x !== null && typeof x === "object";
|
||||
}
|
||||
|
||||
function isFunction(x) {
|
||||
|
@ -93,12 +95,12 @@ this.Match = (function() {
|
|||
}
|
||||
|
||||
function isArrayLike(x) {
|
||||
return isObject(x) && ("length" in x);
|
||||
return isObject(x) && "length" in x;
|
||||
}
|
||||
|
||||
function matchAtom(act, exp) {
|
||||
if ((typeof exp) === "number" && isNaN(exp)) {
|
||||
if ((typeof act) !== "number" || !isNaN(act)) {
|
||||
if (typeof exp === "number" && isNaN(exp)) {
|
||||
if (typeof act !== "number" || !isNaN(act)) {
|
||||
throw new MatchError("expected NaN, got: " + quote(act));
|
||||
}
|
||||
return true;
|
||||
|
@ -121,7 +123,9 @@ this.Match = (function() {
|
|||
switch (typeof exp) {
|
||||
case "string":
|
||||
if (act !== exp) {
|
||||
throw new MatchError("expected " + quote(exp) + ", got " + quote(act));
|
||||
throw new MatchError(
|
||||
"expected " + quote(exp) + ", got " + quote(act)
|
||||
);
|
||||
}
|
||||
return true;
|
||||
case "boolean":
|
||||
|
@ -142,8 +146,9 @@ this.Match = (function() {
|
|||
|
||||
for (const key in exp) {
|
||||
if (!(key in act)) {
|
||||
throw new MatchError("expected property " + quote(key)
|
||||
+ " not found in " + quote(act));
|
||||
throw new MatchError(
|
||||
"expected property " + quote(key) + " not found in " + quote(act)
|
||||
);
|
||||
}
|
||||
match(act[key], exp[key]);
|
||||
}
|
||||
|
@ -157,8 +162,9 @@ this.Match = (function() {
|
|||
}
|
||||
|
||||
if (act !== exp) {
|
||||
throw new MatchError("expected function: " + exp +
|
||||
"\nbut got different function: " + act);
|
||||
throw new MatchError(
|
||||
"expected function: " + exp + "\nbut got different function: " + act
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,15 +175,17 @@ this.Match = (function() {
|
|||
|
||||
const length = exp.length;
|
||||
if (act.length !== exp.length) {
|
||||
throw new MatchError("expected array-like object of length "
|
||||
+ length + ", got " + quote(act));
|
||||
throw new MatchError(
|
||||
"expected array-like object of length " + length + ", got " + quote(act)
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (i in exp) {
|
||||
if (!(i in act)) {
|
||||
throw new MatchError("expected array property " + i + " not found in "
|
||||
+ quote(act));
|
||||
throw new MatchError(
|
||||
"expected array property " + i + " not found in " + quote(act)
|
||||
);
|
||||
}
|
||||
match(act[i], exp[i]);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,10 @@ self.onmessage = e => {
|
|||
}
|
||||
ok(threw, "Constructor shouldn't be usable");
|
||||
} catch (ex) {
|
||||
ok(false, "Unexpected error inside worker:\n" + ex.toString() + "\n" + ex.stack);
|
||||
ok(
|
||||
false,
|
||||
"Unexpected error inside worker:\n" + ex.toString() + "\n" + ex.stack
|
||||
);
|
||||
} finally {
|
||||
done();
|
||||
}
|
||||
|
@ -31,7 +34,7 @@ self.onmessage = e => {
|
|||
|
||||
// Proxy assertions to the main thread.
|
||||
function ok(val, msg) {
|
||||
console.log("ok(" + !!val + ", \"" + msg + "\")");
|
||||
console.log("ok(" + !!val + ', "' + msg + '")');
|
||||
self.postMessage({
|
||||
type: "assertion",
|
||||
passed: !!val,
|
||||
|
|
|
@ -14,17 +14,21 @@ var CC = Components.Constructor;
|
|||
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
||||
const { Match } = ChromeUtils.import("resource://test/Match.jsm");
|
||||
const { Census } = ChromeUtils.import("resource://test/Census.jsm");
|
||||
const { addDebuggerToGlobal } =
|
||||
ChromeUtils.import("resource://gre/modules/jsdebugger.jsm");
|
||||
const { addDebuggerToGlobal } = ChromeUtils.import(
|
||||
"resource://gre/modules/jsdebugger.jsm"
|
||||
);
|
||||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const HeapAnalysesClient =
|
||||
require("devtools/shared/heapsnapshot/HeapAnalysesClient");
|
||||
const HeapAnalysesClient = require("devtools/shared/heapsnapshot/HeapAnalysesClient");
|
||||
const Services = require("Services");
|
||||
const { censusReportToCensusTreeNode } = require("devtools/shared/heapsnapshot/census-tree-node");
|
||||
const {
|
||||
censusReportToCensusTreeNode,
|
||||
} = require("devtools/shared/heapsnapshot/census-tree-node");
|
||||
const CensusUtils = require("devtools/shared/heapsnapshot/CensusUtils");
|
||||
const DominatorTreeNode = require("devtools/shared/heapsnapshot/DominatorTreeNode");
|
||||
const { deduplicatePaths } = require("devtools/shared/heapsnapshot/shortest-paths");
|
||||
const {
|
||||
deduplicatePaths,
|
||||
} = require("devtools/shared/heapsnapshot/shortest-paths");
|
||||
const { LabelAndShallowSizeVisitor } = DominatorTreeNode;
|
||||
|
||||
// Always log packets when running tests. runxpcshelltests.py will throw
|
||||
|
@ -38,8 +42,9 @@ if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT) {
|
|||
});
|
||||
}
|
||||
|
||||
const SYSTEM_PRINCIPAL = Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(Ci.nsIPrincipal);
|
||||
const SYSTEM_PRINCIPAL = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
|
||||
function dumpn(msg) {
|
||||
dump("HEAPSNAPSHOT-TEST: " + msg + "\n");
|
||||
|
@ -83,7 +88,7 @@ function assertThrows(f, val, msg) {
|
|||
try {
|
||||
f();
|
||||
} catch (exc) {
|
||||
if ((exc === val) && (val !== 0 || 1 / exc === 1 / val)) {
|
||||
if (exc === val && (val !== 0 || 1 / exc === 1 / val)) {
|
||||
return;
|
||||
} else if (exc instanceof Error && exc.message === val) {
|
||||
return;
|
||||
|
@ -91,7 +96,8 @@ function assertThrows(f, val, msg) {
|
|||
fullmsg = "Assertion failed: expected exception " + val + ", got " + exc;
|
||||
}
|
||||
if (fullmsg === undefined) {
|
||||
fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown";
|
||||
fullmsg =
|
||||
"Assertion failed: expected exception " + val + ", no exception thrown";
|
||||
}
|
||||
if (msg !== undefined) {
|
||||
fullmsg += " - " + msg;
|
||||
|
@ -103,12 +109,15 @@ function assertThrows(f, val, msg) {
|
|||
* Returns the full path of the file with the specified name in a
|
||||
* platform-independent and URL-like form.
|
||||
*/
|
||||
function getFilePath(name, allowMissing = false, usePlatformPathSeparator = false) {
|
||||
function getFilePath(
|
||||
name,
|
||||
allowMissing = false,
|
||||
usePlatformPathSeparator = false
|
||||
) {
|
||||
const file = do_get_file(name, allowMissing);
|
||||
let path = Services.io.newFileURI(file).spec;
|
||||
let filePrePath = "file://";
|
||||
if ("nsILocalFileWin" in Ci &&
|
||||
file instanceof Ci.nsILocalFileWin) {
|
||||
if ("nsILocalFileWin" in Ci && file instanceof Ci.nsILocalFileWin) {
|
||||
filePrePath += "/";
|
||||
}
|
||||
|
||||
|
@ -131,7 +140,10 @@ function saveNewHeapSnapshot(opts = { runtime: true }) {
|
|||
function readHeapSnapshot(filePath) {
|
||||
const snapshot = ChromeUtils.readHeapSnapshot(filePath);
|
||||
ok(snapshot, "Should have read a heap snapshot back from " + filePath);
|
||||
ok(snapshot instanceof HeapSnapshot, "snapshot should be an instance of HeapSnapshot");
|
||||
ok(
|
||||
snapshot instanceof HeapSnapshot,
|
||||
"snapshot should be an instance of HeapSnapshot"
|
||||
);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
|
@ -159,8 +171,11 @@ function saveHeapSnapshotAndTakeCensus(dbg = null, censusOptions = undefined) {
|
|||
const filePath = saveNewHeapSnapshot(snapshotOptions);
|
||||
const snapshot = readHeapSnapshot(filePath);
|
||||
|
||||
equal(typeof snapshot.takeCensus, "function",
|
||||
"snapshot should have a takeCensus method");
|
||||
equal(
|
||||
typeof snapshot.takeCensus,
|
||||
"function",
|
||||
"snapshot should have a takeCensus method"
|
||||
);
|
||||
|
||||
return snapshot.takeCensus(censusOptions);
|
||||
}
|
||||
|
@ -180,13 +195,19 @@ function saveHeapSnapshotAndComputeDominatorTree(dbg = null) {
|
|||
const filePath = saveNewHeapSnapshot(snapshotOptions);
|
||||
const snapshot = readHeapSnapshot(filePath);
|
||||
|
||||
equal(typeof snapshot.computeDominatorTree, "function",
|
||||
"snapshot should have a `computeDominatorTree` method");
|
||||
equal(
|
||||
typeof snapshot.computeDominatorTree,
|
||||
"function",
|
||||
"snapshot should have a `computeDominatorTree` method"
|
||||
);
|
||||
|
||||
const dominatorTree = snapshot.computeDominatorTree();
|
||||
|
||||
ok(dominatorTree, "Should be able to compute a dominator tree");
|
||||
ok(dominatorTree instanceof DominatorTree, "Should be an instance of DominatorTree");
|
||||
ok(
|
||||
dominatorTree instanceof DominatorTree,
|
||||
"Should be an instance of DominatorTree"
|
||||
);
|
||||
|
||||
return dominatorTree;
|
||||
}
|
||||
|
@ -197,7 +218,10 @@ function isSavedFrame(obj) {
|
|||
|
||||
function savedFrameReplacer(key, val) {
|
||||
if (isSavedFrame(val)) {
|
||||
return `<SavedFrame '${val.toString().split(/\n/g).shift()}'>`;
|
||||
return `<SavedFrame '${val
|
||||
.toString()
|
||||
.split(/\n/g)
|
||||
.shift()}'>`;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -243,50 +267,78 @@ function assertStructurallyEquivalent(actual, expected, path = "root") {
|
|||
if (actual && typeof actual === "object") {
|
||||
const actualProtoString = Object.prototype.toString.call(actual);
|
||||
const expectedProtoString = Object.prototype.toString.call(expected);
|
||||
equal(actualProtoString, expectedProtoString,
|
||||
`${path}: Object.prototype.toString.call() should be the same`);
|
||||
equal(
|
||||
actualProtoString,
|
||||
expectedProtoString,
|
||||
`${path}: Object.prototype.toString.call() should be the same`
|
||||
);
|
||||
|
||||
if (actualProtoString === "[object Map]") {
|
||||
const expectedKeys = new Set([...expected.keys()]);
|
||||
|
||||
for (const key of actual.keys()) {
|
||||
ok(expectedKeys.has(key),
|
||||
`${path}: every key in actual is expected: ${String(key).slice(0, 10)}`);
|
||||
ok(
|
||||
expectedKeys.has(key),
|
||||
`${path}: every key in actual is expected: ${String(key).slice(
|
||||
0,
|
||||
10
|
||||
)}`
|
||||
);
|
||||
expectedKeys.delete(key);
|
||||
|
||||
assertStructurallyEquivalent(actual.get(key), expected.get(key),
|
||||
path + ".get(" + String(key).slice(0, 20) + ")");
|
||||
assertStructurallyEquivalent(
|
||||
actual.get(key),
|
||||
expected.get(key),
|
||||
path + ".get(" + String(key).slice(0, 20) + ")"
|
||||
);
|
||||
}
|
||||
|
||||
equal(expectedKeys.size, 0,
|
||||
equal(
|
||||
expectedKeys.size,
|
||||
0,
|
||||
`${path}: every key in expected should also exist in actual,\
|
||||
did not see ${[...expectedKeys]}`);
|
||||
did not see ${[...expectedKeys]}`
|
||||
);
|
||||
} else if (actualProtoString === "[object Set]") {
|
||||
const expectedItems = new Set([...expected]);
|
||||
|
||||
for (const item of actual) {
|
||||
ok(expectedItems.has(item),
|
||||
`${path}: every set item in actual should exist in expected: ${item}`);
|
||||
ok(
|
||||
expectedItems.has(item),
|
||||
`${path}: every set item in actual should exist in expected: ${item}`
|
||||
);
|
||||
expectedItems.delete(item);
|
||||
}
|
||||
|
||||
equal(expectedItems.size, 0,
|
||||
equal(
|
||||
expectedItems.size,
|
||||
0,
|
||||
`${path}: every set item in expected should also exist in actual,\
|
||||
did not see ${[...expectedItems]}`);
|
||||
did not see ${[...expectedItems]}`
|
||||
);
|
||||
} else {
|
||||
const expectedKeys = new Set(Object.keys(expected));
|
||||
|
||||
for (const key of Object.keys(actual)) {
|
||||
ok(expectedKeys.has(key),
|
||||
`${path}: every key in actual should exist in expected: ${key}`);
|
||||
ok(
|
||||
expectedKeys.has(key),
|
||||
`${path}: every key in actual should exist in expected: ${key}`
|
||||
);
|
||||
expectedKeys.delete(key);
|
||||
|
||||
assertStructurallyEquivalent(actual[key], expected[key], path + "." + key);
|
||||
assertStructurallyEquivalent(
|
||||
actual[key],
|
||||
expected[key],
|
||||
path + "." + key
|
||||
);
|
||||
}
|
||||
|
||||
equal(expectedKeys.size, 0,
|
||||
equal(
|
||||
expectedKeys.size,
|
||||
0,
|
||||
`${path}: every key in expected should also exist in actual,\
|
||||
did not see ${[...expectedKeys]}`);
|
||||
did not see ${[...expectedKeys]}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
equal(actual, expected, `${path}: primitives should be equal`);
|
||||
|
@ -331,8 +383,12 @@ function assertDiff(breakdown, first, second, expected) {
|
|||
* @param {Number} expectedShallowSize
|
||||
* @param {Object} expectedLabel
|
||||
*/
|
||||
function assertLabelAndShallowSize(breakdown, givenDescription,
|
||||
expectedShallowSize, expectedLabel) {
|
||||
function assertLabelAndShallowSize(
|
||||
breakdown,
|
||||
givenDescription,
|
||||
expectedShallowSize,
|
||||
expectedLabel
|
||||
) {
|
||||
dumpn("Computing label and shallow size from node description:");
|
||||
dumpn("Breakdown: " + JSON.stringify(breakdown, null, 4));
|
||||
dumpn("Given description: " + JSON.stringify(givenDescription, null, 4));
|
||||
|
@ -342,7 +398,11 @@ function assertLabelAndShallowSize(breakdown, givenDescription,
|
|||
|
||||
dumpn("Expected shallow size: " + expectedShallowSize);
|
||||
dumpn("Actual shallow size: " + visitor.shallowSize());
|
||||
equal(visitor.shallowSize(), expectedShallowSize, "Shallow size should be correct");
|
||||
equal(
|
||||
visitor.shallowSize(),
|
||||
expectedShallowSize,
|
||||
"Shallow size should be correct"
|
||||
);
|
||||
|
||||
dumpn("Expected label: " + JSON.stringify(expectedLabel, null, 4));
|
||||
dumpn("Actual label: " + JSON.stringify(visitor.label(), null, 4));
|
||||
|
@ -364,15 +424,21 @@ let TEST_NODE_ID_COUNTER = 0;
|
|||
function makeTestDominatorTreeNode(opts, children) {
|
||||
const nodeId = TEST_NODE_ID_COUNTER++;
|
||||
|
||||
const node = Object.assign({
|
||||
nodeId,
|
||||
label: undefined,
|
||||
shallowSize: 1,
|
||||
retainedSize: (children || []).reduce((size, c) => size + c.retainedSize, 1),
|
||||
parentId: undefined,
|
||||
children,
|
||||
moreChildrenAvailable: true,
|
||||
}, opts);
|
||||
const node = Object.assign(
|
||||
{
|
||||
nodeId,
|
||||
label: undefined,
|
||||
shallowSize: 1,
|
||||
retainedSize: (children || []).reduce(
|
||||
(size, c) => size + c.retainedSize,
|
||||
1
|
||||
),
|
||||
parentId: undefined,
|
||||
children,
|
||||
moreChildrenAvailable: true,
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
||||
if (children && children.length) {
|
||||
children.map(c => (c.parentId = node.nodeId));
|
||||
|
@ -386,21 +452,36 @@ function makeTestDominatorTreeNode(opts, children) {
|
|||
* `path` from the root to the node the `newChildren` should be inserted
|
||||
* beneath. Assert that the resulting tree matches `expected`.
|
||||
*/
|
||||
function assertDominatorTreeNodeInsertion(tree, path, newChildren,
|
||||
moreChildrenAvailable, expected) {
|
||||
function assertDominatorTreeNodeInsertion(
|
||||
tree,
|
||||
path,
|
||||
newChildren,
|
||||
moreChildrenAvailable,
|
||||
expected
|
||||
) {
|
||||
dumpn("Inserting new children into a dominator tree:");
|
||||
dumpn("Dominator tree: " + JSON.stringify(tree, null, 2));
|
||||
dumpn("Path: " + JSON.stringify(path, null, 2));
|
||||
dumpn("New children: " + JSON.stringify(newChildren, null, 2));
|
||||
dumpn("Expected resulting tree: " + JSON.stringify(expected, null, 2));
|
||||
|
||||
const actual = DominatorTreeNode.insert(tree, path, newChildren, moreChildrenAvailable);
|
||||
const actual = DominatorTreeNode.insert(
|
||||
tree,
|
||||
path,
|
||||
newChildren,
|
||||
moreChildrenAvailable
|
||||
);
|
||||
dumpn("Actual resulting tree: " + JSON.stringify(actual, null, 2));
|
||||
|
||||
assertStructurallyEquivalent(actual, expected);
|
||||
}
|
||||
|
||||
function assertDeduplicatedPaths({ target, paths, expectedNodes, expectedEdges }) {
|
||||
function assertDeduplicatedPaths({
|
||||
target,
|
||||
paths,
|
||||
expectedNodes,
|
||||
expectedEdges,
|
||||
}) {
|
||||
dumpn("Deduplicating paths:");
|
||||
dumpn("target = " + target);
|
||||
dumpn("paths = " + JSON.stringify(paths, null, 2));
|
||||
|
@ -412,16 +493,21 @@ function assertDeduplicatedPaths({ target, paths, expectedNodes, expectedEdges }
|
|||
dumpn("Actual nodes = " + nodes);
|
||||
dumpn("Actual edges = " + JSON.stringify(edges, null, 2));
|
||||
|
||||
equal(nodes.length, expectedNodes.length,
|
||||
"actual number of nodes is equal to the expected number of nodes");
|
||||
equal(
|
||||
nodes.length,
|
||||
expectedNodes.length,
|
||||
"actual number of nodes is equal to the expected number of nodes"
|
||||
);
|
||||
|
||||
equal(edges.length, expectedEdges.length,
|
||||
"actual number of edges is equal to the expected number of edges");
|
||||
equal(
|
||||
edges.length,
|
||||
expectedEdges.length,
|
||||
"actual number of edges is equal to the expected number of edges"
|
||||
);
|
||||
|
||||
const expectedNodeSet = new Set(expectedNodes);
|
||||
const nodeSet = new Set(nodes);
|
||||
ok(nodeSet.size === nodes.length,
|
||||
"each returned node should be unique");
|
||||
ok(nodeSet.size === nodes.length, "each returned node should be unique");
|
||||
|
||||
for (const node of nodes) {
|
||||
ok(expectedNodeSet.has(node), `the ${node} node was expected`);
|
||||
|
@ -430,15 +516,20 @@ function assertDeduplicatedPaths({ target, paths, expectedNodes, expectedEdges }
|
|||
for (const expectedEdge of expectedEdges) {
|
||||
let count = 0;
|
||||
for (const edge of edges) {
|
||||
if (edge.from === expectedEdge.from &&
|
||||
edge.to === expectedEdge.to &&
|
||||
edge.name === expectedEdge.name) {
|
||||
if (
|
||||
edge.from === expectedEdge.from &&
|
||||
edge.to === expectedEdge.to &&
|
||||
edge.name === expectedEdge.name
|
||||
) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
equal(count, 1,
|
||||
"should have exactly one matching edge for the expected edge = "
|
||||
+ JSON.stringify(expectedEdge));
|
||||
equal(
|
||||
count,
|
||||
1,
|
||||
"should have exactly one matching edge for the expected edge = " +
|
||||
JSON.stringify(expectedEdge)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,19 +8,23 @@ console.log("Initializing worker.");
|
|||
self.onmessage = ex => {
|
||||
console.log("Starting test.");
|
||||
try {
|
||||
ok(ChromeUtils,
|
||||
"Should have access to ChromeUtils in a worker.");
|
||||
ok(HeapSnapshot,
|
||||
"Should have access to HeapSnapshot in a worker.");
|
||||
ok(ChromeUtils, "Should have access to ChromeUtils in a worker.");
|
||||
ok(HeapSnapshot, "Should have access to HeapSnapshot in a worker.");
|
||||
|
||||
const filePath = ChromeUtils.saveHeapSnapshot({ globals: [this] });
|
||||
ok(true, "Should be able to save a snapshot.");
|
||||
|
||||
const snapshot = ChromeUtils.readHeapSnapshot(filePath);
|
||||
ok(snapshot, "Should be able to read a heap snapshot");
|
||||
ok(snapshot instanceof HeapSnapshot, "Should be an instanceof HeapSnapshot");
|
||||
ok(
|
||||
snapshot instanceof HeapSnapshot,
|
||||
"Should be an instanceof HeapSnapshot"
|
||||
);
|
||||
} catch (e) {
|
||||
ok(false, "Unexpected error inside worker:\n" + e.toString() + "\n" + e.stack);
|
||||
ok(
|
||||
false,
|
||||
"Unexpected error inside worker:\n" + e.toString() + "\n" + e.stack
|
||||
);
|
||||
} finally {
|
||||
done();
|
||||
}
|
||||
|
@ -28,7 +32,7 @@ self.onmessage = ex => {
|
|||
|
||||
// Proxy assertions to the main thread.
|
||||
function ok(val, msg) {
|
||||
console.log("ok(" + !!val + ", \"" + msg + "\")");
|
||||
console.log("ok(" + !!val + ', "' + msg + '")');
|
||||
self.postMessage({
|
||||
type: "assertion",
|
||||
passed: !!val,
|
||||
|
|
|
@ -40,10 +40,7 @@ const description = {
|
|||
domNode: {},
|
||||
};
|
||||
|
||||
const expected = [
|
||||
"objects",
|
||||
"Function",
|
||||
];
|
||||
const expected = ["objects", "Function"];
|
||||
|
||||
const shallowSize = 32;
|
||||
|
||||
|
|
|
@ -39,10 +39,7 @@ const description = {
|
|||
domNode: {},
|
||||
};
|
||||
|
||||
const expected = [
|
||||
"objects",
|
||||
"other",
|
||||
];
|
||||
const expected = ["objects", "other"];
|
||||
|
||||
const shallowSize = 10;
|
||||
|
||||
|
|
|
@ -34,17 +34,14 @@ const description = {
|
|||
other: { count: 0, bytes: 0 },
|
||||
},
|
||||
strings: {
|
||||
"JSString": { count: 1, bytes: 42 },
|
||||
JSString: { count: 1, bytes: 42 },
|
||||
},
|
||||
scripts: {},
|
||||
other: {},
|
||||
domNode: {},
|
||||
};
|
||||
|
||||
const expected = [
|
||||
"strings",
|
||||
"JSString",
|
||||
];
|
||||
const expected = ["strings", "JSString"];
|
||||
|
||||
const shallowSize = 42;
|
||||
|
||||
|
|
|
@ -46,11 +46,7 @@ const description = {
|
|||
domNode: {},
|
||||
};
|
||||
|
||||
const expected = [
|
||||
"objects",
|
||||
"Array",
|
||||
stack,
|
||||
];
|
||||
const expected = ["objects", "Array", stack];
|
||||
|
||||
const shallowSize = 512;
|
||||
|
||||
|
|
|
@ -10,21 +10,25 @@ const maxNumPaths = 2;
|
|||
|
||||
// Mock data mapping node id to shortest paths to that node id.
|
||||
const shortestPaths = new Map([
|
||||
[1000, [
|
||||
[pathEntry(1100, "a"), pathEntry(1200, "b")],
|
||||
[pathEntry(1100, "c"), pathEntry(1300, "d")],
|
||||
]],
|
||||
[2000, [
|
||||
[pathEntry(2100, "e"), pathEntry(2200, "f"), pathEntry(2300, "g")],
|
||||
]],
|
||||
[3000, [
|
||||
[pathEntry(3100, "h")],
|
||||
[pathEntry(3100, "i")],
|
||||
[pathEntry(3100, "j")],
|
||||
[pathEntry(3200, "k")],
|
||||
[pathEntry(3300, "l")],
|
||||
[pathEntry(3400, "m")],
|
||||
]],
|
||||
[
|
||||
1000,
|
||||
[
|
||||
[pathEntry(1100, "a"), pathEntry(1200, "b")],
|
||||
[pathEntry(1100, "c"), pathEntry(1300, "d")],
|
||||
],
|
||||
],
|
||||
[2000, [[pathEntry(2100, "e"), pathEntry(2200, "f"), pathEntry(2300, "g")]]],
|
||||
[
|
||||
3000,
|
||||
[
|
||||
[pathEntry(3100, "h")],
|
||||
[pathEntry(3100, "i")],
|
||||
[pathEntry(3100, "j")],
|
||||
[pathEntry(3200, "k")],
|
||||
[pathEntry(3300, "l")],
|
||||
[pathEntry(3400, "m")],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
const actual = [
|
||||
|
@ -101,11 +105,13 @@ const mockSnapshot = {
|
|||
equal(start, startNodeId);
|
||||
equal(max, maxNumPaths);
|
||||
|
||||
return new Map(nodeIds.map(nodeId => {
|
||||
const paths = shortestPaths.get(nodeId);
|
||||
ok(paths, "Expected computeShortestPaths call for node id = " + nodeId);
|
||||
return [nodeId, paths];
|
||||
}));
|
||||
return new Map(
|
||||
nodeIds.map(nodeId => {
|
||||
const paths = shortestPaths.get(nodeId);
|
||||
ok(paths, "Expected computeShortestPaths call for node id = " + nodeId);
|
||||
return [nodeId, paths];
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
describeNode: (bd, nodeId) => {
|
||||
|
@ -120,11 +126,13 @@ const mockSnapshot = {
|
|||
};
|
||||
|
||||
function run_test() {
|
||||
DominatorTreeNode.attachShortestPaths(mockSnapshot,
|
||||
breakdown,
|
||||
startNodeId,
|
||||
actual,
|
||||
maxNumPaths);
|
||||
DominatorTreeNode.attachShortestPaths(
|
||||
mockSnapshot,
|
||||
breakdown,
|
||||
startNodeId,
|
||||
actual,
|
||||
maxNumPaths
|
||||
);
|
||||
|
||||
dumpn("Expected = " + JSON.stringify(expected, null, 2));
|
||||
dumpn("Actual = " + JSON.stringify(actual, null, 2));
|
||||
|
|
|
@ -34,12 +34,16 @@ function run_test() {
|
|||
equal(actual, expected, `We should have got the node with id = ${id}`);
|
||||
}
|
||||
|
||||
equal(null,
|
||||
DominatorTreeNode.getNodeByIdAlongPath(999999999999, tree, path),
|
||||
"null is returned for nodes that are not even in the tree");
|
||||
equal(
|
||||
null,
|
||||
DominatorTreeNode.getNodeByIdAlongPath(999999999999, tree, path),
|
||||
"null is returned for nodes that are not even in the tree"
|
||||
);
|
||||
|
||||
const lastNodeId = tree.children[tree.children.length - 1].nodeId;
|
||||
equal(null,
|
||||
DominatorTreeNode.getNodeByIdAlongPath(lastNodeId, tree, path),
|
||||
"null is returned for nodes that are not along the path");
|
||||
equal(
|
||||
null,
|
||||
DominatorTreeNode.getNodeByIdAlongPath(lastNodeId, tree, path),
|
||||
"null is returned for nodes that are not along the path"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -109,6 +109,11 @@ const expected = {
|
|||
};
|
||||
|
||||
function run_test() {
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren,
|
||||
moreChildrenAvailable, expected);
|
||||
assertDominatorTreeNodeInsertion(
|
||||
tree,
|
||||
path,
|
||||
newChildren,
|
||||
moreChildrenAvailable,
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче