Bug 1711463 - [devtools] Update EvaluationContextSelector items on DOCUMENT_EVENT resources. r=jdescottes.

This patch adds a `refreshTargets` action that is called from the toolbox when
a dom-interactive DOCUMENT_EVENT is received.
This action will only update a new state property, `lastTargetRefresh`, with the
current timestamp, so the `EvaluationContextSelector` component will re-render;
as the target information are directly retrieved from the target fronts, any
changes in the title/url will be shown in the component.

Differential Revision: https://phabricator.services.mozilla.com/D115205
This commit is contained in:
Nicolas Chevobbe 2021-05-19 16:58:07 +00:00
Родитель f8b1226395
Коммит 1f638b9e06
5 изменённых файлов: 57 добавлений и 12 удалений

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

@ -21,8 +21,13 @@ function selectTarget(targetActorID) {
}; };
} }
function refreshTargets() {
return { type: "REFRESH_TARGETS" };
}
module.exports = { module.exports = {
registerTarget, registerTarget,
unregisterTarget, unregisterTarget,
selectTarget, selectTarget,
refreshTargets,
}; };

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

@ -8,6 +8,10 @@ const initialReducerState = {
targets: [], targets: [],
// The selected targetFront instance // The selected targetFront instance
selected: null, selected: null,
// timestamp of the last time a target was updated (i.e. url/title was updated).
// This is used by the EvaluationContextSelector component to re-render the list of
// targets when the list itself did not change (no addition/removal)
lastTargetRefresh: Date.now(),
}; };
exports.reducer = targetsReducer; exports.reducer = targetsReducer;
@ -40,6 +44,15 @@ function targetsReducer(state = initialReducerState, action) {
}; };
} }
case "REFRESH_TARGETS": {
// The data _in_ targetFront was updated, so we only need to mutate the state,
// while keeping the same values.
return {
...state,
lastTargetRefresh: Date.now(),
};
}
case "UNREGISTER_TARGET": { case "UNREGISTER_TARGET": {
const targets = state.targets.filter( const targets = state.targets.filter(
target => target !== action.targetFront target => target !== action.targetFront
@ -56,12 +69,18 @@ function targetsReducer(state = initialReducerState, action) {
return state; return state;
} }
exports.getToolboxTargets = getToolboxTargets;
function getToolboxTargets(state) { function getToolboxTargets(state) {
return state.targets.targets; return state.targets.targets;
} }
exports.getSelectedTarget = getSelectedTarget;
function getSelectedTarget(state) { function getSelectedTarget(state) {
return state.targets.selected; return state.targets.selected;
} }
function getLastTargetRefresh(state) {
return state.targets.lastTargetRefresh;
}
exports.getToolboxTargets = getToolboxTargets;
exports.getSelectedTarget = getSelectedTarget;
exports.getLastTargetRefresh = getLastTargetRefresh;

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

@ -62,8 +62,9 @@ loader.lazyRequireGetter(
loader.lazyRequireGetter( loader.lazyRequireGetter(
this, this,
[ [
"registerWalkerListeners", "refreshTargets",
"registerTarget", "registerTarget",
"registerWalkerListeners",
"selectTarget", "selectTarget",
"unregisterTarget", "unregisterTarget",
], ],
@ -4319,7 +4320,6 @@ Toolbox.prototype = {
if ( if (
resource.resourceType === this.resourceCommand.TYPES.DOCUMENT_EVENT && resource.resourceType === this.resourceCommand.TYPES.DOCUMENT_EVENT &&
resource?.targetFront.isTopLevel &&
!resource.isFrameSwitching && !resource.isFrameSwitching &&
// `url` is set on the targetFront when we receive dom-loading, and `title` when // `url` is set on the targetFront when we receive dom-loading, and `title` when
// `dom-interactive` is received. Here we're only updating the window title in // `dom-interactive` is received. Here we're only updating the window title in
@ -4330,9 +4330,14 @@ Toolbox.prototype = {
// the host title a bit in order for the event listener in targetCommand to be // the host title a bit in order for the event listener in targetCommand to be
// executed. // executed.
setTimeout(() => { setTimeout(() => {
this._refreshHostTitle(); // Update the EvaluationContext selector so url/title of targets can be updated
this.store.dispatch(refreshTargets());
if (resource.targetFront.isTopLevel) {
this._refreshHostTitle();
this._setDebugTargetData();
}
}, 0); }, 0);
this._setDebugTargetData();
} }
} }

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

@ -48,6 +48,7 @@ class EvaluationContextSelector extends Component {
updateInstantEvaluationResultForCurrentExpression: updateInstantEvaluationResultForCurrentExpression:
PropTypes.func.isRequired, PropTypes.func.isRequired,
selectedTarget: PropTypes.object, selectedTarget: PropTypes.object,
lastTargetRefresh: PropTypes.number,
targets: PropTypes.array, targets: PropTypes.array,
webConsoleUI: PropTypes.object.isRequired, webConsoleUI: PropTypes.object.isRequired,
}; };
@ -57,9 +58,15 @@ class EvaluationContextSelector extends Component {
if (this.props.selectedTarget !== nextProps.selectedTarget) { if (this.props.selectedTarget !== nextProps.selectedTarget) {
return true; return true;
} }
if (this.props.lastTargetRefresh !== nextProps.lastTargetRefresh) {
return true;
}
if (this.props.targets.length !== nextProps.targets.length) { if (this.props.targets.length !== nextProps.targets.length) {
return true; return true;
} }
for (let i = 0; i < nextProps.targets.length; i++) { for (let i = 0; i < nextProps.targets.length; i++) {
const target = this.props.targets[i]; const target = this.props.targets[i];
const nextTarget = nextProps.targets[i]; const nextTarget = nextProps.targets[i];
@ -206,6 +213,7 @@ const toolboxConnected = connect(
state => ({ state => ({
targets: targetSelectors.getToolboxTargets(state), targets: targetSelectors.getToolboxTargets(state),
selectedTarget: targetSelectors.getSelectedTarget(state), selectedTarget: targetSelectors.getSelectedTarget(state),
lastTargetRefresh: targetSelectors.getLastTargetRefresh(state),
}), }),
dispatch => ({ dispatch => ({
selectTarget: actorID => dispatch(frameworkActions.selectTarget(actorID)), selectTarget: actorID => dispatch(frameworkActions.selectTarget(actorID)),

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

@ -62,12 +62,20 @@ add_task(async function() {
}); });
// Wait until the new iframe is rendered in the context selector. // Wait until the new iframe is rendered in the context selector.
await waitFor(() => getContextSelectorItems(hud).length === 4); await waitFor(() => {
const items = getContextSelectorItems(hud);
return (
items.length === 4 &&
items.some(el =>
el
.querySelector(".label")
?.textContent.includes("iframe-2|test1.example.org")
)
);
});
const expectedSecondIframeItem = { const expectedSecondIframeItem = {
// The title is set in a script, but we don't update the context selector entry (it label: `iframe-2|test1.example.org`,
// should be "iframe-2|test1.example.org:80").
label: `http://test1.example.org/${IFRAME_PATH}?id=iframe-2`,
tooltip: `http://test1.example.org/${IFRAME_PATH}?id=iframe-2`, tooltip: `http://test1.example.org/${IFRAME_PATH}?id=iframe-2`,
}; };
@ -78,11 +86,11 @@ add_task(async function() {
}, },
expectedSeparatorItem, expectedSeparatorItem,
{ {
...expectedSecondIframeItem, ...expectedFirstIframeItem,
checked: false, checked: false,
}, },
{ {
...expectedFirstIframeItem, ...expectedSecondIframeItem,
checked: false, checked: false,
}, },
]); ]);