/* 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/. */
/** * Update the data used for the autocomplete popup in the console input (JsTerm). * * @param {Boolean} force: True to force a call to the server (as opposed to retrieve * from the cache). * @param {Array<String>} getterPath: Array representing the getter access (i.e. * `a.b.c.d.` is described as ['a', 'b', 'c', 'd'] ). * @param {Array<String>} expressionVars: Array of the variables defined in the expression.
*/ function autocompleteUpdate(force, getterPath, expressionVars) { return async ({ dispatch, getState, webConsoleUI, hud }) => { if (hud.inputHasSelection()) { return dispatch(autocompleteClear());
}
/** * Combine or replace authorizedEvaluations with the newly authorized getter path, if any. * @param {Array<Array<String>>} authorizedEvaluations Existing authorized evaluations (may * be updated in place) * @param {Array<String>} getterPath The new getter path * @param {{[String]: String}} mappedVars Map of original to generated variable names. * @returns {Array<Array<String>>} The updated authorized evaluations (the original array,
* if it was updated in place) */ function updateAuthorizedEvaluations(
authorizedEvaluations,
getterPath,
mappedVars
) { if (!Array.isArray(authorizedEvaluations) || !authorizedEvaluations.length) {
authorizedEvaluations = [];
}
if (Array.isArray(getterPath) && getterPath.length) { // We need to check for any previous authorizations. For example, here if getterPath // is ["a", "b", "c", "d"], we want to see if there was any other path that was // authorized in a previous request. For that, we only add the previous // authorizations if the last auth is contained in getterPath. (for the example, we // would keep if it is [["a", "b"]], not if [["b"]] nor [["f", "g"]]) const last = authorizedEvaluations[authorizedEvaluations.length - 1];
const isMappedVariable =
generatedPath && getterPath.length === generatedPath.length; const concat = !last || last.every((x, index) => x === getterPath[index]); if (isMappedVariable) { // If the path consists only of an original variable, add all the prefixes of its // mapping. For example, for myVar => a.b.c, authorize a, a.b, and a.b.c. This // ensures we'll only show a prompt for myVar once even if a.b and a.b.c are both // unsafe getters.
authorizedEvaluations = generatedPath.map((_, i) =>
generatedPath.slice(0, i + 1)
);
} elseif (concat) {
authorizedEvaluations.push(getterPath);
} else {
authorizedEvaluations = [getterPath];
}
} return authorizedEvaluations;
}
/** * Apply source mapping to the autocomplete input. * @param {String} rawInput The input to map. * @param {{[String]: String}} mappedVars Map of original to generated variable names. * @param {WebConsole} hud A reference to the webconsole hud. * @returns {String} The source-mapped expression to autocomplete.
*/
async function getMappedInput(rawInput, mappedVars, hud) { if (!mappedVars || !Object.keys(mappedVars).length) { return { input: rawInput, originalExpression: undefined };
}
// If we're autocompleting a variable name, pass it through unchanged so that we // show original variable names rather than generated ones. // For example, if we have the mapping `myVariable` => `x`, show variables starting // with myVariable rather than x. if (!isPropertyAccess && !isElementAccess) { return { input: lastStatement, originalExpression };
}
let generated =
(await hud.getMappedExpression(originalExpression))?.expression ??
originalExpression; // Strip off the semicolon if the expression was converted to a statement const trailingSemicolon = /;\s*$/; if (
trailingSemicolon.test(generated) &&
!trailingSemicolon.test(originalExpression)
) {
generated = generated.slice(0, generated.lastIndexOf(";"));
}
/** * Called when the autocompletion data should be cleared.
*/ function autocompleteClear() { return {
type: AUTOCOMPLETE_CLEAR,
};
}
/** * Called when the autocompletion data should be retrieved from the cache (i.e. * client-side). * * @param {String} input: The input used to filter the cached data.
*/ function autoCompleteDataRetrieveFromCache(input) { return {
type: AUTOCOMPLETE_RETRIEVE_FROM_CACHE,
input,
};
}
let currentRequestId = 0; function generateRequestId() { return currentRequestId++;
}
/** * Action that fetch autocompletion data from the server. * * @param {Object} Object of the following shape: * - {String} input: the expression that we want to complete. * - {String} frameActorId: The id of the frame we want to autocomplete in. * - {Boolean} force: true if the user forced an autocompletion (with Ctrl+Space). * - {Array} authorizedEvaluations: Array of the properties access which can be * executed by the engine. * Example: [["x", "myGetter"], ["x", "myGetter", "y", "glitter"]] * to retrieve properties of `x.myGetter.` and `x.myGetter.y.glitter`.
*/ function autocompleteDataFetch({
input,
frameActorId,
force,
authorizedEvaluations,
allVars,
mappedVars,
originalExpression,
}) { return async ({ dispatch, commands, webConsoleUI, hud }) => { // Retrieve the right WebConsole front that relates either to (by order of priority): // - the currently selected target in the context selector // (contextSelectedTargetFront), // - the currently selected Node in the inspector (selectedNodeActor), // - the currently selected frame in the debugger (when paused) (frameActor), // - the currently selected target in the iframe dropdown // (selectedTargetFront from the TargetCommand) const selectedNodeActorId = webConsoleUI.getSelectedNodeActorID();
let targetFront = commands.targetCommand.selectedTargetFront; // Note that getSelectedTargetFront will return null if we default to the top level target. const contextSelectorTargetFront = getSelectedTarget(
hud.commands.targetCommand.store.getState()
); const selectedActorId = selectedNodeActorId || frameActorId; if (contextSelectorTargetFront) {
targetFront = contextSelectorTargetFront;
} elseif (selectedActorId) { const selectedFront = commands.client.getFrontByID(selectedActorId); if (selectedFront) {
targetFront = selectedFront.targetFront;
}
}
/** * Replace generated variable names in an unsafe getter path with their original * counterparts. * @param {Array<String>} getterPath Array of properties leading up to and including the * unsafe getter. * @param {String} originalExpression The expression that was evaluated, before mapping. * @param {{[String]: String}} mappedVars Map of original to generated variable names. * @returns {Array<String>} An updated getter path containing original variables.
*/ function unmapGetterPath(getterPath, originalExpression, mappedVars) { // We know that the original expression is a sequence of property accesses, that only // the first part can be a mapped variable, and that the getter path must start with // its generated path or be a prefix of it.
// Suppose we have the expression `foo.bar`, which maps to `a.b.c.bar`. // Get the first part of the expression ("foo") const originalVariable = /^[^.[?]*/s.exec(originalExpression)[0].trim(); const generatedVariable = mappedVars[originalVariable]; if (generatedVariable) { // Get number of properties in "a.b.c" const generatedVariableParts = generatedVariable.split("."); // Replace ["a", "b", "c"] with "foo" in the getter path. // Note that this will also work if the getter path ends inside of the mapped // variable, like ["a", "b"]. return [
originalVariable,
...getterPath.slice(generatedVariableParts.length),
];
} return getterPath;
}
/** * Called when we receive the autocompletion data from the server. * * @param {Object} Object of the following shape: * - {Integer} id: The autocompletion request id. This will be used in the reducer * to check that we update the state with the last request results. * - {String} input: the expression that we want to complete. * - {String} frameActorId: The id of the frame we want to autocomplete in. * - {Boolean} force: true if the user forced an autocompletion (with Ctrl+Space). * - {Object} data: The actual data returned from the server. * - {Array} authorizedEvaluations: Array of the properties access which can be * executed by the engine. * Example: [["x", "myGetter"], ["x", "myGetter", "y", "glitter"]] * to retrieve properties of `x.myGetter.` and `x.myGetter.y.glitter`.
*/ function autocompleteDataReceive({
id,
input,
frameActorId,
force,
data,
authorizedEvaluations,
}) { return {
type: AUTOCOMPLETE_DATA_RECEIVE,
id,
input,
force,
frameActorId,
data,
authorizedEvaluations,
};
}
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.