/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/* global Temporal, TrustedHTML, TrustedScript, TrustedScriptURL */
if (obj.displayName) {
grip.displayName = obj.displayName.substr(0, 500);
}
if (obj.parameterNames) {
grip.parameterNames = obj.parameterNames;
}
// Check if the developer has added a de-facto standard displayName // property for us to use.
let userDisplayName; try {
userDisplayName = obj.getOwnPropertyDescriptor("displayName");
} catch (e) { // The above can throw "permission denied" errors when the debuggee // does not subsume the function's compartment.
}
if (obj.script) { // NOTE: Debugger.Script.prototype.startColumn is 1-based. // Convert to 0-based, while keeping the wasm's column (1) as is. // (bug 1863878) const columnBase = obj.script.format === "wasm" ? 0 : 1;
grip.location = {
url: obj.script.url,
line: obj.script.startLine,
column: obj.script.startColumn - columnBase,
};
}
returntrue;
},
],
RegExp: [ function(objectActor, grip, depth) {
let str; if (isWorker) { // For some reason, the following incantation on the worker thread returns "/undefined/undefined" // str = RegExp.prototype.toString.call(objectActor.obj.unsafeDereference()); // // The following method will throw in case of method being overloaded by the page, // and a more generic previewer will render the object. try {
str = DevToolsUtils.callPropertyOnObject(objectActor.obj, "toString");
} catch(e) { // Ensure displaying something in case of error. // Otherwise this would render an object with an empty label
grip.displayString = "RegExp with overloaded toString";
}
} else { const { RegExp } = objectActor.targetActor.targetGlobal;
str = RegExp.prototype.toString.call(objectActor.safeRawObj);
}
Date: [ function(objectActor, grip, depth) {
let time; if (isWorker) { // Also, targetGlobal is an opaque wrapper, from which we can't access its Date object, // so fallback to the privileged one // // In worker objectActor.safeRawObj is considered unsafe and is null, // so retrieve the objectActor.rawObj object directly from Debugger.Object.unsafeDereference
time = Date.prototype.getTime.call(objectActor.rawObj);
} else { const { Date } = objectActor.targetActor.targetGlobal;
time = Date.prototype.getTime.call(objectActor.safeRawObj);
} if (typeof time != "number") { returnfalse;
}
TrustedHTML: [ function(objectActor, grip, depth) { const text = TrustedHTML.prototype.toString.call( // In worker objectActor.safeRawObj is considered unsafe and is null
objectActor.safeRawObj || objectActor.rawObj
);
TrustedScript: [ function(objectActor, grip, depth) { const text = TrustedScript.prototype.toString.call( // In worker objectActor.safeRawObj is considered unsafe and is null
objectActor.safeRawObj || objectActor.rawObj
);
TrustedScriptURL: [ function(objectActor, grip, depth) { const url = TrustedScriptURL.prototype.toString.call( // In worker objectActor.safeRawObj is considered unsafe and is null
objectActor.safeRawObj || objectActor.rawObj
);
for (let i = 0; i < length; ++i) { if (rawObj && !isWorker) { // Array Xrays filter out various possibly-unsafe properties (like // functions, and claim that the value is undefined instead. This // is generally the right thing for privileged code accessing untrusted // objects, but quite confusing for Object previews. So we manually // override this protection by waiving Xrays on the array, and re-applying // Xrays on any indexed value props that we pull off of it. const desc = Object.getOwnPropertyDescriptor(Cu.waiveXrays(rawObj), i); if (desc && !desc.get && !desc.set) {
let value = Cu.unwaiveXrays(desc.value);
value = ObjectUtils.makeDebuggeeValueIfNeeded(obj, value);
items.push(objectActor.createValueGrip(value, depth));
} elseif (!desc) {
items.push(null);
} else { const item = {}; if (desc.get) {
let getter = Cu.unwaiveXrays(desc.get);
getter = ObjectUtils.makeDebuggeeValueIfNeeded(obj, getter);
item.get = objectActor.createValueGrip(getter, depth);
} if (desc.set) {
let setter = Cu.unwaiveXrays(desc.set);
setter = ObjectUtils.makeDebuggeeValueIfNeeded(obj, setter);
item.set = objectActor.createValueGrip(setter, depth);
}
items.push(item);
}
} elseif (rawObj && !obj.getOwnPropertyDescriptor(i)) {
items.push(null);
} else { // Workers do not have access to Cu. const value = DevToolsUtils.getProperty(obj, i);
items.push(objectActor.createValueGrip(value, depth));
}
if (items.length == OBJECT_PREVIEW_MAX_ITEMS) { break;
}
}
Proxy: [ function(objectActor, grip, depth) { // Only preview top-level proxies, avoiding recursion. Otherwise, since both the // target and handler can also be proxies, we could get an exponential behavior. if (depth > 1) { returntrue;
}
const { obj } = objectActor;
// The `isProxy` getter of the debuggee object only detects proxies without // security wrappers. If false, the target and handler are not available. const hasTargetAndHandler = obj.isProxy;
let length,
i = 0;
let specialStringBehavior = objectActor.className === "String"; if (specialStringBehavior) {
length = DevToolsUtils.getProperty(obj, "length"); if (typeof length != "number") {
specialStringBehavior = false;
}
}
for (const name of names) { if (specialStringBehavior && /^[0-9]+$/.test(name)) { const num = parseInt(name, 10); if (num.toString() === name && num >= 0 && num < length) { continue;
}
}
if (++i == OBJECT_PREVIEW_MAX_ITEMS) { break;
}
}
}
if (i === OBJECT_PREVIEW_MAX_ITEMS) { returntrue;
}
const safeGetterValues = objectActor._findSafeGetterValues(
Object.keys(preview.ownProperties),
depth,
OBJECT_PREVIEW_MAX_ITEMS - i
); if (Object.keys(safeGetterValues).length) {
preview.safeGetterValues = safeGetterValues;
}
returntrue;
}
// Preview functions that do not rely on the object class.
previewers.Object = [ function TypedArray(objectActor, grip, depth) { const { obj, className } = objectActor; if (!ObjectUtils.isTypedArray(obj)) { returnfalse;
}
for (let i = 0; i < previewLength; i++) { const desc = obj.getOwnPropertyDescriptor(i); if (!desc) { break;
}
// We need to create grips for items of BigInt arrays. Other typed arrays are fine // as they hold serializable primitives (Numbers) const item = isBigIntArray
? ObjectUtils.createBigIntValueGrip(desc.value)
: desc.value;
grip.preview.items.push(item);
}
returntrue;
},
function Error(objectActor, grip, depth) { if (!ERROR_CLASSNAMES.has(objectActor.className)) { returnfalse;
}
// The name and/or message could be getters, and even if it's unsafe, // we do want to show it to the user, unless the error is muted // (See Bug 1710694). const invokeUnsafeGetters = allowSideEffect && !obj.isMutedError;
let url; if (isWindow && safeRawObj.location) { try {
url = safeRawObj.location.href;
} catch(e) { // This can happen when we have a cross-process window. // In such case, let's retrieve the url from the iframe. // For window.top from a remote iframe, there's no way we can't retrieve the URL, // so return a label that help user know what's going on.
url = safeRawObj.browsingContext?.embedderElement?.src || "Restricted";
}
} elseif (safeRawObj.href) {
url = safeRawObj.href;
} else { returnfalse;
}
for (
let i = 0;
i < safeRawObj.length && items.length < OBJECT_PREVIEW_MAX_ITEMS;
i++
) { const value = ObjectUtils.makeDebuggeeValueIfNeeded(objectActor.obj, safeRawObj[i]);
items.push(objectActor.createValueGrip(value, depth));
}
if (depth < 2) {
preview.childNodes = []; for (const node of safeRawObj.childNodes) { const actor = objectActor.createValueGrip(obj.makeDebuggeeValue(node), depth);
preview.childNodes.push(actor); if (preview.childNodes.length == OBJECT_PREVIEW_MAX_ITEMS) { break;
}
}
}
} elseif (Element.isInstance(safeRawObj)) { // For HTML elements (in an HTML document, at least), the nodeName is an // uppercased version of the actual element name. Check for HTML // elements, that is elements in the HTML namespace, and lowercase the // nodeName in that case. if (safeRawObj.namespaceURI == "http://www.w3.org/1999/xhtml") {
preview.nodeName = preview.nodeName.toLowerCase();
}
// Add preview for DOM element attributes.
preview.attributes = {};
preview.attributesLength = safeRawObj.attributes.length; for (const attr of safeRawObj.attributes) {
preview.attributes[attr.nodeName] = objectActor.createValueGrip(attr.value, depth);
}
// Custom elements may have private properties. Ensure that we provide // enough information for ObjectInspector to know it should check for // them. const privatePropertiesSymbols = ObjectUtils.getSafePrivatePropertiesSymbols(
obj
); if (privatePropertiesSymbols.length) {
preview.privatePropertiesLength = privatePropertiesSymbols.length;
}
} elseif (className == "Attr") {
preview.value = objectActor.createValueGrip(safeRawObj.value, depth);
} elseif (
className == "Text" ||
className == "CDATASection" ||
className == "Comment"
) {
preview.textContent = objectActor.createValueGrip(safeRawObj.textContent, depth);
}
returntrue;
},
function DOMEvent(objectActor, grip, depth) { const { safeRawObj } = objectActor; if (!safeRawObj || !Event.isInstance(safeRawObj) || isWorker) { returnfalse;
}
// Add event-specific properties. for (const prop of props) {
let value = safeRawObj[prop]; if (ObjectUtils.isObjectOrFunction(value)) { // Skip properties pointing to objects. if (depth > 1) { continue;
}
value = obj.makeDebuggeeValue(value);
}
preview.properties[prop] = objectActor.createValueGrip(value, depth);
}
// Add any properties we find on the event object. if (!props.length) {
let i = 0; for (const prop in safeRawObj) {
let value = safeRawObj[prop]; if (
prop == "target" ||
prop == "type" ||
value === null || typeof value == "function"
) { continue;
} if (value && typeof value == "object") { if (depth > 1) { continue;
}
value = obj.makeDebuggeeValue(value);
}
preview.properties[prop] = objectActor.createValueGrip(value, depth); if (++i == OBJECT_PREVIEW_MAX_ITEMS) { break;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.