mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-20 03:13:09 +09:00
283 lines
8.1 KiB
JavaScript
283 lines
8.1 KiB
JavaScript
|
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|||
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|||
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|||
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|||
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|||
|
|
|
|||
|
|
"use strict";
|
|||
|
|
|
|||
|
|
const WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
|
|||
|
|
const STRINGS_URI = "devtools/client/locales/webconsole.properties";
|
|||
|
|
const l10n = new WebConsoleUtils.L10n(STRINGS_URI);
|
|||
|
|
|
|||
|
|
const {
|
|||
|
|
MESSAGE_SOURCE,
|
|||
|
|
MESSAGE_TYPE,
|
|||
|
|
MESSAGE_LEVEL,
|
|||
|
|
} = require("../constants");
|
|||
|
|
const {
|
|||
|
|
ConsoleMessage,
|
|||
|
|
NetworkEventMessage,
|
|||
|
|
} = require("../types");
|
|||
|
|
|
|||
|
|
function prepareMessage(packet, idGenerator) {
|
|||
|
|
// This packet is already in the expected packet structure. Simply return.
|
|||
|
|
if (!packet.source) {
|
|||
|
|
packet = transformPacket(packet);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (packet.allowRepeating) {
|
|||
|
|
packet = packet.set("repeatId", getRepeatId(packet));
|
|||
|
|
}
|
|||
|
|
return packet.set("id", idGenerator.getNextId());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Transforms a packet from Firefox RDP structure to Chrome RDP structure.
|
|||
|
|
*/
|
|||
|
|
function transformPacket(packet) {
|
|||
|
|
if (packet._type) {
|
|||
|
|
packet = convertCachedPacket(packet);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch (packet.type) {
|
|||
|
|
case "consoleAPICall": {
|
|||
|
|
let { message } = packet;
|
|||
|
|
|
|||
|
|
let parameters = message.arguments;
|
|||
|
|
let type = message.level;
|
|||
|
|
let level = getLevelFromType(type);
|
|||
|
|
let messageText = null;
|
|||
|
|
const timer = message.timer;
|
|||
|
|
|
|||
|
|
// Special per-type conversion.
|
|||
|
|
switch (type) {
|
|||
|
|
case "clear":
|
|||
|
|
// We show a message to users when calls console.clear() is called.
|
|||
|
|
parameters = [l10n.getStr("consoleCleared")];
|
|||
|
|
break;
|
|||
|
|
case "count":
|
|||
|
|
// Chrome RDP doesn't have a special type for count.
|
|||
|
|
type = MESSAGE_TYPE.LOG;
|
|||
|
|
let {counter} = message;
|
|||
|
|
let label = counter.label ? counter.label : l10n.getStr("noCounterLabel");
|
|||
|
|
messageText = `${label}: ${counter.count}`;
|
|||
|
|
parameters = null;
|
|||
|
|
break;
|
|||
|
|
case "time":
|
|||
|
|
// We don't show anything for console.time calls to match Chrome's behaviour.
|
|||
|
|
parameters = null;
|
|||
|
|
type = MESSAGE_TYPE.NULL_MESSAGE;
|
|||
|
|
break;
|
|||
|
|
case "timeEnd":
|
|||
|
|
parameters = null;
|
|||
|
|
if (timer) {
|
|||
|
|
// We show the duration to users when calls console.timeEnd() is called,
|
|||
|
|
// if corresponding console.time() was called before.
|
|||
|
|
let duration = Math.round(timer.duration * 100) / 100;
|
|||
|
|
messageText = l10n.getFormatStr("timeEnd", [timer.name, duration]);
|
|||
|
|
} else {
|
|||
|
|
// If the `timer` property does not exists, we don't output anything.
|
|||
|
|
type = MESSAGE_TYPE.NULL_MESSAGE;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case "table":
|
|||
|
|
const supportedClasses = [
|
|||
|
|
"Array", "Object", "Map", "Set", "WeakMap", "WeakSet"];
|
|||
|
|
if (
|
|||
|
|
!Array.isArray(parameters) ||
|
|||
|
|
parameters.length === 0 ||
|
|||
|
|
!supportedClasses.includes(parameters[0].class)
|
|||
|
|
) {
|
|||
|
|
// If the class of the first parameter is not supported,
|
|||
|
|
// we handle the call as a simple console.log
|
|||
|
|
type = "log";
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case "group":
|
|||
|
|
type = MESSAGE_TYPE.START_GROUP;
|
|||
|
|
parameters = null;
|
|||
|
|
messageText = message.groupName || l10n.getStr("noGroupLabel");
|
|||
|
|
break;
|
|||
|
|
case "groupCollapsed":
|
|||
|
|
type = MESSAGE_TYPE.START_GROUP_COLLAPSED;
|
|||
|
|
parameters = null;
|
|||
|
|
messageText = message.groupName || l10n.getStr("noGroupLabel");
|
|||
|
|
break;
|
|||
|
|
case "groupEnd":
|
|||
|
|
type = MESSAGE_TYPE.END_GROUP;
|
|||
|
|
parameters = null;
|
|||
|
|
break;
|
|||
|
|
case "dirxml":
|
|||
|
|
// Handle console.dirxml calls as simple console.log
|
|||
|
|
type = "log";
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const frame = message.filename ? {
|
|||
|
|
source: message.filename,
|
|||
|
|
line: message.lineNumber,
|
|||
|
|
column: message.columnNumber,
|
|||
|
|
} : null;
|
|||
|
|
|
|||
|
|
return new ConsoleMessage({
|
|||
|
|
source: MESSAGE_SOURCE.CONSOLE_API,
|
|||
|
|
type,
|
|||
|
|
level,
|
|||
|
|
parameters,
|
|||
|
|
messageText,
|
|||
|
|
stacktrace: message.stacktrace ? message.stacktrace : null,
|
|||
|
|
frame,
|
|||
|
|
userProvidedStyles: message.styles,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case "navigationMessage": {
|
|||
|
|
let { message } = packet;
|
|||
|
|
return new ConsoleMessage({
|
|||
|
|
source: MESSAGE_SOURCE.CONSOLE_API,
|
|||
|
|
type: MESSAGE_TYPE.LOG,
|
|||
|
|
level: MESSAGE_LEVEL.LOG,
|
|||
|
|
messageText: "Navigated to " + message.url,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case "pageError": {
|
|||
|
|
let { pageError } = packet;
|
|||
|
|
let level = MESSAGE_LEVEL.ERROR;
|
|||
|
|
if (pageError.warning || pageError.strict) {
|
|||
|
|
level = MESSAGE_LEVEL.WARN;
|
|||
|
|
} else if (pageError.info) {
|
|||
|
|
level = MESSAGE_LEVEL.INFO;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const frame = pageError.sourceName ? {
|
|||
|
|
source: pageError.sourceName,
|
|||
|
|
line: pageError.lineNumber,
|
|||
|
|
column: pageError.columnNumber
|
|||
|
|
} : null;
|
|||
|
|
|
|||
|
|
return new ConsoleMessage({
|
|||
|
|
source: MESSAGE_SOURCE.JAVASCRIPT,
|
|||
|
|
type: MESSAGE_TYPE.LOG,
|
|||
|
|
level,
|
|||
|
|
messageText: pageError.errorMessage,
|
|||
|
|
stacktrace: pageError.stacktrace ? pageError.stacktrace : null,
|
|||
|
|
frame,
|
|||
|
|
exceptionDocURL: pageError.exceptionDocURL,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case "networkEvent": {
|
|||
|
|
let { networkEvent } = packet;
|
|||
|
|
|
|||
|
|
return new NetworkEventMessage({
|
|||
|
|
actor: networkEvent.actor,
|
|||
|
|
isXHR: networkEvent.isXHR,
|
|||
|
|
request: networkEvent.request,
|
|||
|
|
response: networkEvent.response,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
case "evaluationResult":
|
|||
|
|
default: {
|
|||
|
|
let {
|
|||
|
|
exceptionMessage: messageText,
|
|||
|
|
exceptionDocURL,
|
|||
|
|
frame,
|
|||
|
|
result: parameters
|
|||
|
|
} = packet;
|
|||
|
|
|
|||
|
|
const level = messageText ? MESSAGE_LEVEL.ERROR : MESSAGE_LEVEL.LOG;
|
|||
|
|
return new ConsoleMessage({
|
|||
|
|
source: MESSAGE_SOURCE.JAVASCRIPT,
|
|||
|
|
type: MESSAGE_TYPE.RESULT,
|
|||
|
|
level,
|
|||
|
|
messageText,
|
|||
|
|
parameters,
|
|||
|
|
exceptionDocURL,
|
|||
|
|
frame,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Helpers
|
|||
|
|
function getRepeatId(message) {
|
|||
|
|
message = message.toJS();
|
|||
|
|
delete message.repeat;
|
|||
|
|
return JSON.stringify(message);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function convertCachedPacket(packet) {
|
|||
|
|
// The devtools server provides cached message packets in a different shape, so we
|
|||
|
|
// transform them here.
|
|||
|
|
let convertPacket = {};
|
|||
|
|
if (packet._type === "ConsoleAPI") {
|
|||
|
|
convertPacket.message = packet;
|
|||
|
|
convertPacket.type = "consoleAPICall";
|
|||
|
|
} else if (packet._type === "PageError") {
|
|||
|
|
convertPacket.pageError = packet;
|
|||
|
|
convertPacket.type = "pageError";
|
|||
|
|
} else if ("_navPayload" in packet) {
|
|||
|
|
convertPacket.type = "navigationMessage";
|
|||
|
|
convertPacket.message = packet;
|
|||
|
|
} else if (packet._type === "NetworkEvent") {
|
|||
|
|
convertPacket.networkEvent = packet;
|
|||
|
|
convertPacket.type = "networkEvent";
|
|||
|
|
} else {
|
|||
|
|
throw new Error("Unexpected packet type");
|
|||
|
|
}
|
|||
|
|
return convertPacket;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Maps a Firefox RDP type to its corresponding level.
|
|||
|
|
*/
|
|||
|
|
function getLevelFromType(type) {
|
|||
|
|
const levels = {
|
|||
|
|
LEVEL_ERROR: "error",
|
|||
|
|
LEVEL_WARNING: "warn",
|
|||
|
|
LEVEL_INFO: "info",
|
|||
|
|
LEVEL_LOG: "log",
|
|||
|
|
LEVEL_DEBUG: "debug",
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// A mapping from the console API log event levels to the Web Console levels.
|
|||
|
|
const levelMap = {
|
|||
|
|
error: levels.LEVEL_ERROR,
|
|||
|
|
exception: levels.LEVEL_ERROR,
|
|||
|
|
assert: levels.LEVEL_ERROR,
|
|||
|
|
warn: levels.LEVEL_WARNING,
|
|||
|
|
info: levels.LEVEL_INFO,
|
|||
|
|
log: levels.LEVEL_LOG,
|
|||
|
|
clear: levels.LEVEL_LOG,
|
|||
|
|
trace: levels.LEVEL_LOG,
|
|||
|
|
table: levels.LEVEL_LOG,
|
|||
|
|
debug: levels.LEVEL_LOG,
|
|||
|
|
dir: levels.LEVEL_LOG,
|
|||
|
|
dirxml: levels.LEVEL_LOG,
|
|||
|
|
group: levels.LEVEL_LOG,
|
|||
|
|
groupCollapsed: levels.LEVEL_LOG,
|
|||
|
|
groupEnd: levels.LEVEL_LOG,
|
|||
|
|
time: levels.LEVEL_LOG,
|
|||
|
|
timeEnd: levels.LEVEL_LOG,
|
|||
|
|
count: levels.LEVEL_DEBUG,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return levelMap[type] || MESSAGE_TYPE.LOG;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function isGroupType(type) {
|
|||
|
|
return [
|
|||
|
|
MESSAGE_TYPE.START_GROUP,
|
|||
|
|
MESSAGE_TYPE.START_GROUP_COLLAPSED
|
|||
|
|
].includes(type);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exports.prepareMessage = prepareMessage;
|
|||
|
|
// Export for use in testing.
|
|||
|
|
exports.getRepeatId = getRepeatId;
|
|||
|
|
|
|||
|
|
exports.l10n = l10n;
|
|||
|
|
exports.isGroupType = isGroupType;
|