Bug 1499289 - Bug 1513244 - Extract fetchAutocompleteProperties from JsTerm into a Redux action; r=Honza.

The functions needed to build the autocomplete request are moved
to the serviceContainer so it can be called from everywhere in
the code, and not only from the JsTerm.

Differential Revision: https://phabricator.services.mozilla.com/D12939

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Chevobbe 2018-12-13 14:37:20 +00:00
Родитель 48b47d05cd
Коммит a587b43474
6 изменённых файлов: 84 добавлений и 114 удалений

Просмотреть файл

@ -14,26 +14,21 @@ const {
/**
* Update the data used for the autocomplete popup in the console input (JsTerm).
*
* @param {Object} Object of the following shape:
* - {String} inputValue: the expression to complete.
* - {Int} cursor: The position of the cursor in the inputValue.
* - {WebConsoleClient} client: The webconsole client.
* - {String} frameActorId: The id of the frame we want to autocomplete in.
* - {Boolean} force: True to force a call to the server (as opposed to retrieve
* from the cache).
* - {String} selectedNodeActor: Actor id of the selected node in the inspector.
* @param {Boolean} force: True to force a call to the server (as opposed to retrieve
* from the cache).
*/
function autocompleteUpdate({
inputValue,
cursor,
client,
frameActorId,
force,
selectedNodeActor,
}) {
return ({dispatch, getState}) => {
const {cache} = getState().autocomplete;
function autocompleteUpdate(force) {
return ({dispatch, getState, services}) => {
if (services.inputHasSelection()) {
return dispatch(autocompleteClear());
}
const inputValue = services.getInputValue();
const frameActorId = services.getFrameActor();
const cursor = services.getInputCursor();
const state = getState().autocomplete;
const { cache } = state;
if (!force && (
!inputValue ||
/^[a-zA-Z0-9_$]/.test(inputValue.substring(cursor))
@ -56,8 +51,7 @@ function autocompleteUpdate({
return dispatch(autocompleteDataFetch({
input,
frameActorId,
client,
selectedNodeActor,
client: services.getWebConsoleClient(),
}));
};
}
@ -96,15 +90,14 @@ function generateRequestId() {
* - {String} input: the expression that we want to complete.
* - {String} frameActorId: The id of the frame we want to autocomplete in.
* - {WebConsoleClient} client: The webconsole client.
* - {String} selectedNodeActor: Actor id of the selected node in the inspector.
*/
function autocompleteDataFetch({
input,
frameActorId,
client,
selectedNodeActor,
}) {
return ({dispatch}) => {
return ({dispatch, services}) => {
const selectedNodeActor = services.getSelectedNodeActor();
const id = generateRequestId();
dispatch({type: AUTOCOMPLETE_PENDING_REQUEST, id});
client.autocomplete(input, undefined, frameActorId, selectedNodeActor).then(res => {

Просмотреть файл

@ -102,8 +102,6 @@ class JSTerm extends Component {
this.onContextMenu = this.onContextMenu.bind(this);
this.imperativeUpdate = this.imperativeUpdate.bind(this);
this.SELECTED_FRAME = -1;
/**
* Last input value.
* @type string
@ -350,7 +348,7 @@ class JSTerm extends Component {
"Ctrl-Space": () => {
if (!this.autocompletePopup.isOpen) {
this.fetchAutocompletionProperties(true);
this.props.autocompleteUpdate(true);
return null;
}
@ -578,7 +576,6 @@ class JSTerm extends Component {
executeString = mappedExpressionRes ? mappedExpressionRes.expression : executeString;
const options = {
frame: this.SELECTED_FRAME,
selectedNodeActor,
mapped: mappedExpressionRes ? mappedExpressionRes.mapped : null,
};
@ -602,12 +599,6 @@ class JSTerm extends Component {
* the evaluation. The Debugger.Object of the OA will be bound to
* |_self| during evaluation, such that it's usable in the string you
* execute.
* - frame: tells the stackframe depth to evaluate the string in. If
* the jsdebugger is paused, you can pick the stackframe to be used for
* evaluation. Use |this.SELECTED_FRAME| to always pick th;
* user-selected stackframe.
* If you do not provide a |frame| the string will be evaluated in the
* global content window.
* - selectedNodeActor: tells the NodeActor ID of the current selection
* in the Inspector, if such a selection exists. This is used by
* helper functions that can evaluate on the current selection.
@ -624,13 +615,8 @@ class JSTerm extends Component {
"lines": str.split(/\n/).length,
});
let frameActor = null;
if ("frame" in options) {
frameActor = this.getFrameActor(options.frame);
}
return this.webConsoleClient.evaluateJSAsync(str, null, {
frameActor,
frameActor: this.props.serviceContainer.getFrameActor(options.frame),
...options,
});
}
@ -650,30 +636,6 @@ class JSTerm extends Component {
null, evalOptions);
}
/**
* Retrieve the FrameActor ID given a frame depth.
*
* @param number frame
* Frame depth.
* @return string|null
* The FrameActor ID for the given frame depth.
*/
getFrameActor(frame) {
const state = this.hud.owner.getDebuggerFrames();
if (!state) {
return null;
}
let grip;
if (frame == this.SELECTED_FRAME) {
grip = state.frames[state.selected];
} else {
grip = state.frames[frame];
}
return grip ? grip.actor : null;
}
/**
* Updates the size of the input field (command line) to fit its contents.
*
@ -786,7 +748,7 @@ class JSTerm extends Component {
const value = this.getInputValue();
if (this.lastInputValue !== value) {
this.resizeInput();
this.fetchAutocompletionProperties();
this.props.autocompleteUpdate();
this.lastInputValue = value;
}
}
@ -873,7 +835,7 @@ class JSTerm extends Component {
if (event.key === " " && !this.autocompletePopup.isOpen) {
// Open the autocompletion popup on Ctrl-Space (if it wasn't displayed).
this.fetchAutocompletionProperties(true);
this.props.autocompleteUpdate(true);
event.preventDefault();
}
@ -1126,47 +1088,6 @@ class JSTerm extends Component {
node.selectionStart == 0 && !multiline;
}
/**
* Retrieves properties maching the current input for the selected frame, either from
* the server or from a cache if possible.
* Will bail-out if there's some text selection in the input.
*
* @param {Boolean} force: True to not perform any check before trying to show the
* autocompletion popup. Defaults to false.
* @fires autocomplete-updated
* @returns void
*/
async fetchAutocompletionProperties(force = false) {
const inputValue = this.getInputValue();
const frameActorId = this.getFrameActor(this.SELECTED_FRAME);
const cursor = this.getSelectionStart();
const {editor, inputNode} = this;
if (
(inputNode && inputNode.selectionStart != inputNode.selectionEnd) ||
(editor && editor.getSelection())
) {
this.clearCompletion();
this.emit("autocomplete-updated");
return;
}
let selectedNodeActor = null;
const inspectorSelection = this.hud.owner.getInspectorSelection();
if (inspectorSelection && inspectorSelection.nodeFront) {
selectedNodeActor = inspectorSelection.nodeFront.actorID;
}
this.props.autocompleteUpdate({
inputValue,
cursor,
frameActorId,
force,
client: this.webConsoleClient,
selectedNodeActor,
});
}
/**
* Takes the data returned by the server and update the autocomplete popup state (i.e.
* its visibility and items).
@ -1321,6 +1242,7 @@ class JSTerm extends Component {
this.autocompletePopup.hidePopup();
}
}
this.emit("autocomplete-updated");
}
/**
@ -1636,14 +1558,11 @@ function mapStateToProps(state) {
function mapDispatchToProps(dispatch) {
return {
appendToHistory: (expr) => dispatch(historyActions.appendToHistory(expr)),
clearHistory: () => dispatch(historyActions.clearHistory()),
updateHistoryPosition: (direction, expression) =>
dispatch(historyActions.updateHistoryPosition(direction, expression)),
autocompleteUpdate: options => dispatch(
autocompleteActions.autocompleteUpdate(options)
),
autocompleteUpdate: force => dispatch(autocompleteActions.autocompleteUpdate(force)),
autocompleteBailOut: () => dispatch(autocompleteActions.autocompleteBailOut()),
};
}

Просмотреть файл

@ -76,8 +76,19 @@ function configureStore(hud, options = {}) {
};
// Prepare middleware.
const services = (options.services || {});
const middleware = applyMiddleware(
thunk.bind(null, {prefsService, client: (options.services || {})}),
thunk.bind(null, {
prefsService,
services,
// Needed for the ObjectInspector
client: {
createObjectClient: services.createObjectClient,
createLongStringClient: services.createLongStringClient,
releaseActor: services.releaseActor,
},
}),
historyPersistence,
eventTelemetry.bind(null, options.telemetry, options.sessionId),
);

Просмотреть файл

@ -108,6 +108,53 @@ WebConsoleOutputWrapper.prototype = {
return debuggerClient.release(actor);
},
getWebConsoleClient: () => {
return hud.webConsoleClient;
},
/**
* Retrieve the FrameActor ID given a frame depth, or the selected one if no
* frame depth given.
*
* @param {Number} frame: optional frame depth.
* @return {String|null}: The FrameActor ID for the given frame depth (or the
* selected frame if it exists).
*/
getFrameActor: (frame = null) => {
const state = this.owner.getDebuggerFrames();
if (!state) {
return null;
}
const grip = Number.isInteger(frame)
? state.frames[frame]
: state.frames[state.selected];
return grip ? grip.actor : null;
},
inputHasSelection: () => {
const {editor, inputNode} = hud.jsterm || {};
return editor
? !!editor.getSelection()
: (inputNode && inputNode.selectionStart !== inputNode.selectionEnd);
},
getInputValue: () => {
return hud.jsterm && hud.jsterm.getInputValue();
},
getInputCursor: () => {
return hud.jsterm && hud.jsterm.getSelectionStart();
},
getSelectedNodeActor: () => {
const inspectorSelection = this.owner.getInspectorSelection();
if (inspectorSelection && inspectorSelection.nodeFront) {
return inspectorSelection.nodeFront.actorID;
}
return null;
},
};
// Set `openContextMenu` this way so, `serviceContainer` variable

Просмотреть файл

@ -69,8 +69,8 @@ function hideAutocompletePopup(jsterm) {
function setJsTermValueForCompletion(jsterm, value) {
// setInputValue does not trigger the autocompletion;
// we need to call `fetchAutocompletionProperties` in order to display the popup.
// we need to call the `autocompleteUpdate` action in order to display the popup.
jsterm.setInputValue(value);
jsterm.fetchAutocompletionProperties();
jsterm.props.autocompleteUpdate();
}

Просмотреть файл

@ -44,7 +44,7 @@ module.exports = async function() {
const onPopupOpened = jsterm.autocompletePopup.once("popup-opened");
jsterm.insertStringAtCursor(char);
// We need to trigger autocompletion update to show the popup.
jsterm.fetchAutocompletionProperties();
jsterm.props.autocompleteUpdate();
await onPopupOpened;
}