зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1534847 - Part 2: Invalidate the loadSourceText cache on navigation. r=jlast
Summary: If users navigate while source text is loading, we need to ignore existing cached promises because they may resolve and then not actually set the resulting source, because the source was deleted from the source list. We want to explicitly use a new cache entry if we have navigated. Reviewers: jlast Bug #: 1534847 Differential Revision: https://phabricator.services.mozilla.com/D23452
This commit is contained in:
Родитель
cefa9c5b9c
Коммит
d1e54f1409
|
@ -5,7 +5,7 @@
|
|||
// @flow
|
||||
|
||||
import { PROMISE } from "../utils/middleware/promise";
|
||||
import { getSource } from "../../selectors";
|
||||
import { getSource, getSourcesEpoch } from "../../selectors";
|
||||
import { setBreakpointPositions } from "../breakpoints";
|
||||
|
||||
import * as parser from "../../workers/parser";
|
||||
|
@ -44,6 +44,7 @@ async function loadSource(state, source: Source, { sourceMaps, client }) {
|
|||
|
||||
async function loadSourceTextPromise(
|
||||
source: Source,
|
||||
epoch: number,
|
||||
{ dispatch, getState, client, sourceMaps }: ThunkArgs
|
||||
): Promise<?Source> {
|
||||
if (isLoaded(source)) {
|
||||
|
@ -53,6 +54,7 @@ async function loadSourceTextPromise(
|
|||
await dispatch({
|
||||
type: "LOAD_SOURCE_TEXT",
|
||||
sourceId: source.id,
|
||||
epoch,
|
||||
[PROMISE]: loadSource(getState(), source, { sourceMaps, client })
|
||||
});
|
||||
|
||||
|
@ -82,12 +84,14 @@ export function loadSourceText(inputSource: ?Source) {
|
|||
// below in a way that Flow is happy with.
|
||||
const source = inputSource;
|
||||
|
||||
const id = source.id;
|
||||
const epoch = getSourcesEpoch(thunkArgs.getState());
|
||||
|
||||
const id = `${epoch}:${source.id}`;
|
||||
let promise = requests.get(id);
|
||||
if (!promise) {
|
||||
promise = (async () => {
|
||||
try {
|
||||
return await loadSourceTextPromise(source, thunkArgs);
|
||||
return await loadSourceTextPromise(source, epoch, thunkArgs);
|
||||
} catch (e) {
|
||||
// TODO: This swallows errors for now. Ideally we would get rid of
|
||||
// this once we have a better handle on our async state management.
|
||||
|
|
|
@ -10,7 +10,8 @@ import type { PromiseAction } from "../utils/middleware/promise";
|
|||
export type LoadSourceAction = PromiseAction<
|
||||
{|
|
||||
+type: "LOAD_SOURCE_TEXT",
|
||||
+sourceId: string
|
||||
+sourceId: string,
|
||||
+epoch: number
|
||||
|},
|
||||
Source
|
||||
>;
|
||||
|
|
|
@ -36,6 +36,8 @@ type DisplayedSources = { [ThreadId]: { [SourceId]: boolean } };
|
|||
type GetDisplayedSourcesSelector = OuterState => { [ThreadId]: SourcesMap };
|
||||
|
||||
export type SourcesState = {
|
||||
epoch: number,
|
||||
|
||||
// All known sources.
|
||||
sources: SourcesMap,
|
||||
|
||||
|
@ -63,6 +65,7 @@ const emptySources = {
|
|||
export function initialSourcesState(): SourcesState {
|
||||
return {
|
||||
...emptySources,
|
||||
epoch: 1,
|
||||
selectedLocation: undefined,
|
||||
pendingSelectedLocation: prefs.pendingSelectedLocation,
|
||||
projectDirectoryRoot: prefs.projectDirectoryRoot,
|
||||
|
@ -164,7 +167,10 @@ function update(
|
|||
return updateProjectDirectoryRoot(state, action.url);
|
||||
|
||||
case "NAVIGATE":
|
||||
return initialSourcesState();
|
||||
return {
|
||||
...initialSourcesState(),
|
||||
epoch: state.epoch + 1
|
||||
};
|
||||
|
||||
case "SET_FOCUSED_SOURCE_ITEM":
|
||||
return { ...state, focusedItem: action.item };
|
||||
|
@ -296,10 +302,19 @@ function updateProjectDirectoryRoot(state: SourcesState, root: string) {
|
|||
* Update a source's loaded state fields
|
||||
* i.e. loadedState, text, error
|
||||
*/
|
||||
function updateLoadedState(state, action: LoadSourceAction): SourcesState {
|
||||
function updateLoadedState(
|
||||
state: SourcesState,
|
||||
action: LoadSourceAction
|
||||
): SourcesState {
|
||||
const { sourceId } = action;
|
||||
let source;
|
||||
|
||||
// If there was a nativation between the time the action was started and
|
||||
// completed, we don't want to update the store.
|
||||
if (action.epoch !== state.epoch) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.status === "start") {
|
||||
source = { id: sourceId, loadedState: "loading" };
|
||||
} else if (action.status === "error") {
|
||||
|
@ -522,6 +537,10 @@ export function getSources(state: OuterState) {
|
|||
return state.sources.sources;
|
||||
}
|
||||
|
||||
export function getSourcesEpoch(state: OuterState) {
|
||||
return state.sources.epoch;
|
||||
}
|
||||
|
||||
export function getUrls(state: OuterState) {
|
||||
return state.sources.urls;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче