зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1448287 - Fix devtools.dump.emit when using new event emitter r=jdescottes
components.stack is not always available, throw new Error() to obtain a stack instead. MozReview-Commit-ID: BZq7zLKgA9H --HG-- extra : rebase_source : 03878a50b4aa419830533f024c27c2df64f97265
This commit is contained in:
Родитель
95b2b21737
Коммит
e876bc8d02
|
@ -18,18 +18,22 @@ function callFunctionWithAsyncStack(callee, stack, id) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a description of the Nth caller, suitable for logging.
|
||||
* Return the Nth path from the stack excluding substr.
|
||||
*
|
||||
* @param {Number} n the caller to describe
|
||||
* @return {String} a description of the nth caller.
|
||||
* @param {Number}
|
||||
* n the Nth path from the stack to describe.
|
||||
* @param {String} substr
|
||||
* A segment of the path that should be excluded.
|
||||
*/
|
||||
function describeNthCaller(n) {
|
||||
function getNthPathExcluding(n, substr) {
|
||||
if (isWorker) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let stack = new Error().stack.split("\n");
|
||||
// Add one here to skip this function.
|
||||
stack = stack.filter(line => {
|
||||
return line && !line.includes(substr);
|
||||
});
|
||||
return stack[n + 1];
|
||||
}
|
||||
|
||||
|
@ -45,5 +49,5 @@ function getStack() {
|
|||
}
|
||||
|
||||
exports.callFunctionWithAsyncStack = callFunctionWithAsyncStack;
|
||||
exports.describeNthCaller = describeNthCaller;
|
||||
exports.getNthPathExcluding = getNthPathExcluding;
|
||||
exports.getStack = getStack;
|
||||
|
|
|
@ -11,11 +11,11 @@ const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {}
|
|||
const {
|
||||
callFunctionWithAsyncStack,
|
||||
getStack,
|
||||
describeNthCaller
|
||||
getNthPathExcluding
|
||||
} = require("devtools/client/shared/webpack/shims/platform-stack-stub");
|
||||
|
||||
function f3() {
|
||||
return describeNthCaller(2);
|
||||
return getNthPathExcluding(2);
|
||||
}
|
||||
|
||||
function f2() {
|
||||
|
|
|
@ -262,7 +262,7 @@ const isEventHandler = (listener) =>
|
|||
listener && handler in listener && typeof listener[handler] === "function";
|
||||
|
||||
const Services = require("Services");
|
||||
const { describeNthCaller } = require("devtools/shared/platform/stack");
|
||||
const { getNthPathExcluding } = require("devtools/shared/platform/stack");
|
||||
let loggingEnabled = false;
|
||||
|
||||
if (!isWorker) {
|
||||
|
@ -275,20 +275,80 @@ if (!isWorker) {
|
|||
}
|
||||
|
||||
function serialize(target) {
|
||||
let out = String(target);
|
||||
const MAXLEN = 60;
|
||||
|
||||
// Undefined
|
||||
if (typeof target === "undefined") {
|
||||
return "undefined";
|
||||
}
|
||||
|
||||
if (target === null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Number / String
|
||||
if (typeof target === "string" ||
|
||||
typeof target === "number") {
|
||||
return truncate(target, MAXLEN);
|
||||
}
|
||||
|
||||
// HTML Node
|
||||
if (target.nodeName) {
|
||||
let out = target.nodeName;
|
||||
|
||||
if (target && target.nodeName) {
|
||||
out += " (" + target.nodeName;
|
||||
if (target.id) {
|
||||
out += "#" + target.id;
|
||||
}
|
||||
if (target.className) {
|
||||
out += "." + target.className;
|
||||
}
|
||||
out += ")";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
// Array
|
||||
if (Array.isArray(target)) {
|
||||
return truncate(target.toSource(), MAXLEN);
|
||||
}
|
||||
|
||||
// Function
|
||||
if (typeof target === "function") {
|
||||
return `function ${target.name ? target.name : "anonymous"}()`;
|
||||
}
|
||||
|
||||
// Window
|
||||
if (target.constructor &&
|
||||
target.constructor.name &&
|
||||
target.constructor.name === "Window") {
|
||||
return `window (${target.location.origin})`;
|
||||
}
|
||||
|
||||
// Object
|
||||
if (typeof target === "object") {
|
||||
let out = "{";
|
||||
|
||||
let entries = Object.entries(target);
|
||||
for (let i = 0; i < Math.min(10, entries.length); i++) {
|
||||
let [name, value] = entries[i];
|
||||
|
||||
if (i > 0) {
|
||||
out += ", ";
|
||||
}
|
||||
|
||||
out += `${name}: ${truncate(value, MAXLEN)}`;
|
||||
}
|
||||
|
||||
return out + "}";
|
||||
}
|
||||
|
||||
// Other
|
||||
return truncate(target.toSource(), MAXLEN);
|
||||
}
|
||||
|
||||
function truncate(value, maxLen) {
|
||||
// We don't use value.toString() because it can throw.
|
||||
let str = String(value);
|
||||
return str.length > maxLen ? str.substring(0, maxLen) + "..." : str;
|
||||
}
|
||||
|
||||
function logEvent(type, args) {
|
||||
|
@ -297,15 +357,20 @@ function logEvent(type, args) {
|
|||
}
|
||||
|
||||
let argsOut = "";
|
||||
let description = describeNthCaller(2);
|
||||
|
||||
// We need this try / catch to prevent any dead object errors.
|
||||
try {
|
||||
argsOut = args.map(serialize).join(", ");
|
||||
argsOut = `${args.map(serialize).join(", ")}`;
|
||||
} catch (e) {
|
||||
// Object is dead so the toolbox is most likely shutting down,
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
dump(`EMITTING: emit(${type}${argsOut}) from ${description}\n`);
|
||||
const path = getNthPathExcluding(0, "devtools/shared/event-emitter.js");
|
||||
|
||||
if (args.length > 0) {
|
||||
dump(`EMITTING: emit(${type}, ${argsOut}) from ${path}\n`);
|
||||
} else {
|
||||
dump(`EMITTING: emit(${type}) from ${path}\n`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
const Services = require("Services");
|
||||
const defer = require("devtools/shared/defer");
|
||||
const { describeNthCaller } = require("devtools/shared/platform/stack");
|
||||
const { getNthPathExcluding } = require("devtools/shared/platform/stack");
|
||||
let loggingEnabled = false;
|
||||
|
||||
if (!isWorker) {
|
||||
|
@ -150,7 +150,7 @@ EventEmitter.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
let description = describeNthCaller(2);
|
||||
let description = getNthPathExcluding(0, "devtools/shared/old-event-emitter.js");
|
||||
|
||||
let argOut = "(";
|
||||
if (args.length === 1) {
|
||||
|
|
|
@ -10,31 +10,36 @@
|
|||
const { Cu, components } = require("chrome");
|
||||
|
||||
/**
|
||||
* Return a description of the Nth caller, suitable for logging.
|
||||
* Return the Nth path from the stack excluding substr.
|
||||
*
|
||||
* @param {Number} n the caller to describe
|
||||
* @return {String} a description of the nth caller.
|
||||
* @param {Number}
|
||||
* n the Nth path from the stack to describe.
|
||||
* @param {String} substr
|
||||
* A segment of the path that should be excluded.
|
||||
*/
|
||||
function describeNthCaller(n) {
|
||||
if (isWorker) {
|
||||
return "";
|
||||
function getNthPathExcluding(n, substr) {
|
||||
let stack = components.stack.formattedStack.split("\n");
|
||||
|
||||
// Remove this method from the stack
|
||||
stack = stack.splice(1);
|
||||
|
||||
stack = stack.map(line => {
|
||||
if (line.includes(" -> ")) {
|
||||
return line.split(" -> ")[1];
|
||||
}
|
||||
return line;
|
||||
});
|
||||
|
||||
if (substr) {
|
||||
stack = stack.filter(line => {
|
||||
return line && !line.includes(substr);
|
||||
});
|
||||
}
|
||||
|
||||
let caller = components.stack;
|
||||
// Do one extra iteration to skip this function.
|
||||
while (n >= 0) {
|
||||
--n;
|
||||
caller = caller.caller;
|
||||
if (!stack[n]) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
let func = caller.name;
|
||||
let file = caller.filename;
|
||||
if (file.includes(" -> ")) {
|
||||
file = caller.filename.split(/ -> /)[1];
|
||||
}
|
||||
let path = file + ":" + caller.lineNumber;
|
||||
|
||||
return func + "() -> " + path;
|
||||
return (stack[n] || "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,5 +62,5 @@ function callFunctionWithAsyncStack(callee, stack, id) {
|
|||
}
|
||||
|
||||
exports.callFunctionWithAsyncStack = callFunctionWithAsyncStack;
|
||||
exports.describeNthCaller = describeNthCaller;
|
||||
exports.getNthPathExcluding = getNthPathExcluding;
|
||||
exports.getStack = getStack;
|
||||
|
|
Загрузка…
Ссылка в новой задаче