/* 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/. */
function waiveXrays(obj) { return isWorker ? obj : Cu.waiveXrays(obj);
}
function unwaiveXrays(obj) { return isWorker ? obj : Cu.unwaiveXrays(obj);
}
/** * Helper function to create a grip from a Map/Set entry
*/ function gripFromEntry(objectActor, entry, depth) {
entry = unwaiveXrays(entry); return objectActor.createValueGrip(
ObjectUtils.makeDebuggeeValueIfNeeded(objectActor.obj, entry),
depth
);
}
function enumObjectProperties(objectActor, options, depth) {
let names = []; try {
names = objectActor.obj.getOwnPropertyNames();
} catch (ex) { // Calling getOwnPropertyNames() on some wrapped native prototypes is not // allowed: "cannot modify properties of a WrappedNative". See bug 952093.
}
if (options.ignoreNonIndexedProperties || options.ignoreIndexedProperties) { const length = DevToolsUtils.getProperty(objectActor.obj, "length");
let sliceIndex;
if (!isLengthTrustworthy) { // The length property may not reflect what the object looks like, let's find // where indexed properties end.
if (!ObjectUtils.isArrayIndex(names[0])) { // If the first item is not a number, this means there is no indexed properties // in this object.
sliceIndex = 0;
} else {
sliceIndex = names.length; while (sliceIndex > 0) { if (ObjectUtils.isArrayIndex(names[sliceIndex - 1])) { break;
}
sliceIndex--;
}
}
} else {
sliceIndex = length;
}
// It appears that getOwnPropertyNames always returns indexed properties // first, so we can safely slice `names` for/against indexed properties. // We do such clever operation to optimize very large array inspection. if (options.ignoreIndexedProperties) { // Keep items after `sliceIndex` index
names = names.slice(sliceIndex);
} elseif (options.ignoreNonIndexedProperties) { // Keep `sliceIndex` first items
names.length = sliceIndex;
}
}
const safeGetterValues = objectActor._findSafeGetterValues(names, depth); const safeGetterNames = Object.keys(safeGetterValues); // Merge the safe getter values into the existing properties list. for (const name of safeGetterNames) { if (!names.includes(name)) {
names.push(name);
}
}
if (options.query) {
let { query } = options;
query = query.toLowerCase();
names = names.filter(name => { // Filter on attribute names if (name.toLowerCase().includes(query)) { returntrue;
} // and then on attribute values
let desc; try {
desc = objectActor.obj.getOwnPropertyDescriptor(name);
} catch (e) { // Calling getOwnPropertyDescriptor on wrapped native prototypes is not // allowed (bug 560072).
} if (desc?.value && String(desc.value).includes(query)) { returntrue;
} returnfalse;
});
}
if (options.sort) {
names.sort();
}
return {
size: names.length,
propertyName(index) { return names[index];
},
propertyDescription(index) { const name = names[index];
let desc = propertyDescriptor(objectActor, name, depth); if (!desc) {
desc = safeGetterValues[name];
} elseif (name in safeGetterValues) { // Merge the safe getter values into the existing properties list. const { getterValue, getterPrototypeLevel } = safeGetterValues[name];
desc.getterValue = getterValue;
desc.getterPrototypeLevel = getterPrototypeLevel;
} return desc;
},
};
}
function getMapEntries(objectActor) { const { obj, rawObj } = objectActor; // Iterating over a Map via .entries goes through various intermediate // objects - an Iterator object, then a 2-element Array object, then the // actual values we care about. We don't have Xrays to Iterator objects, // so we get Opaque wrappers for them. And even though we have Xrays to // Arrays, the semantics often deny access to the entires based on the // nature of the values. So we need waive Xrays for the iterator object // and the tupes, and then re-apply them on the underlying values until // we fix bug 1023984. // // Even then though, we might want to continue waiving Xrays here for the // same reason we do so for Arrays above - this filtering behavior is likely // to be more confusing than beneficial in the case of Object previews. const iterator = obj.makeDebuggeeValue(
waiveXrays(Map.prototype.keys.call(rawObj))
); return [...DevToolsUtils.makeDebuggeeIterator(iterator)].map(k => { const key = waiveXrays(ObjectUtils.unwrapDebuggeeValue(k)); const value = Map.prototype.get.call(rawObj, key); return [key, value];
});
}
function enumMapEntries(objectActor, depth) { const entries = getMapEntries(objectActor);
function enumStorageEntries(objectActor, depth) { // Iterating over local / sessionStorage entries goes through various // intermediate objects - an Iterator object, then a 2-element Array object, // then the actual values we care about. We don't have Xrays to Iterator // objects, so we get Opaque wrappers for them. const { rawObj } = objectActor; const keys = []; for (let i = 0; i < rawObj.length; i++) {
keys.push(rawObj.key(i));
} return {
[Symbol.iterator]: function*() { for (const key of keys) { const value = rawObj.getItem(key);
yield [key, value].map(val => gripFromEntry(objectActor, val, depth));
}
},
size: keys.length,
propertyName(index) { return index;
},
propertyDescription(index) { const key = keys[index]; const val = rawObj.getItem(key); return {
enumerable: true,
value: {
type: "storageEntry",
preview: {
key: gripFromEntry(objectActor, key, depth),
value: gripFromEntry(objectActor, val, depth),
},
},
};
},
};
}
function enumURLSearchParamsEntries(objectActor, depth) { const entries = [...waiveXrays(URLSearchParams.prototype.entries.call(objectActor.rawObj))];
return {
[Symbol.iterator]: function*() { for (const [key, value] of entries) {
yield [key, value];
}
},
size: entries.length,
propertyName(index) { // UrlSearchParams entries can have the same key multiple times (e.g. `?a=1&a=2`), // so let's return the index as a name to be able to display them properly in the client. return index;
},
propertyDescription(index) { const [key, value] = entries[index];
function enumMidiInputMapEntries(objectActor, depth) { // We need to waive `rawObj` as we can't get the iterator from the Xray for MapLike (See Bug 1173651). // We also need to waive Xrays on the result of the call to `entries` as we don't have // Xrays to Iterator objects (see Bug 1023984) const entries = Array.from(
waiveXrays(MIDIInputMap.prototype.entries.call(waiveXrays(objectActor.rawObj)))
);
function enumMidiOutputMapEntries(objectActor, depth) { // We need to waive `rawObj` as we can't get the iterator from the Xray for MapLike (See Bug 1173651). // We also need to waive Xrays on the result of the call to `entries` as we don't have // Xrays to Iterator objects (see Bug 1023984) const entries = Array.from(
waiveXrays(MIDIOutputMap.prototype.entries.call(waiveXrays(objectActor.rawObj)))
);
function getWeakMapEntries(rawObj) { // We currently lack XrayWrappers for WeakMap, so when we iterate over // the values, the temporary iterator objects get created in the target // compartment. However, we _do_ have Xrays to Object now, so we end up // Xraying those temporary objects, and filtering access to |it.value| // based on whether or not it's Xrayable and/or callable, which breaks // the for/of iteration. // // This code is designed to handle untrusted objects, so we can safely // waive Xrays on the iterable, and relying on the Debugger machinery to // make sure we handle the resulting objects carefully. const keys = waiveXrays(ChromeUtils.nondeterministicGetWeakMapKeys(rawObj));
function getSetValues(objectActor) { // We currently lack XrayWrappers for Set, so when we iterate over // the values, the temporary iterator objects get created in the target // compartment. However, we _do_ have Xrays to Object now, so we end up // Xraying those temporary objects, and filtering access to |it.value| // based on whether or not it's Xrayable and/or callable, which breaks // the for/of iteration. // // This code is designed to handle untrusted objects, so we can safely // waive Xrays on the iterable, and relying on the Debugger machinery to // make sure we handle the resulting objects carefully. const iterator = objectActor.obj.makeDebuggeeValue(
waiveXrays(Set.prototype.values.call(objectActor.rawObj))
); return [...DevToolsUtils.makeDebuggeeIterator(iterator)];
}
function getWeakSetEntries(rawObj) { // We currently lack XrayWrappers for WeakSet, so when we iterate over // the values, the temporary iterator objects get created in the target // compartment. However, we _do_ have Xrays to Object now, so we end up // Xraying those temporary objects, and filtering access to |it.value| // based on whether or not it's Xrayable and/or callable, which breaks // the for/of iteration. // // This code is designed to handle untrusted objects, so we can safely // waive Xrays on the iterable, and relying on the Debugger machinery to // make sure we handle the resulting objects carefully. return waiveXrays(ChromeUtils.nondeterministicGetWeakSetKeys(rawObj));
}
function enumWeakSetEntries(objectActor, depth) { const keys = getWeakSetEntries(objectActor.rawObj);
function enumCustomStateSetEntries(objectActor, depth) {
let { rawObj } = objectActor; // We need to waive `rawObj` as we can't get the iterator from the Xray for SetLike (See Bug 1173651). // We also need to waive Xrays on the result of the call to `values` as we don't have // Xrays to Iterator objects (see Bug 1023984) const values = Array.from(
waiveXrays(CustomStateSet.prototype.values.call(waiveXrays(rawObj)))
);
/** * Returns true if the parameter can be stored as a 32-bit unsigned integer. * If so, it will be suitable for use as the length of an array object. * * @param num Number * The number to test. * @return Boolean
*/ function isUint32(num) { return num >>> 0 === num;
}
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 ist noch experimentell.