-
Notifications
You must be signed in to change notification settings - Fork 758
[WIP] Stop waiting for sourcemap sources #4709
[WIP] Stop waiting for sourcemap sources #4709
Conversation
i mentioned it in the issue but i will mention it here as well: removing awaits can be a bit dangerous here, especially in regards to loadSourceText. maybe what we should do is create a queuing system for loadSourceText, so that we can call it without worry. ie) if the same file is being loaded twice, and we are in the process of loading it, wait for the promise with the given source id to load. might look something like this const queue ={};
//...
export function loadSourceText(...) {
// ...
if (source.text) {
return source.text;
}
const queuedRequest = queue[source.id];
if (queuedRequest) {
return queuedRequest;
}
queue[source.id] = ( ... // promise) in the promise resolution we should delete the queued item. |
thanks for the suggestion! I'll try to implement that. I will close the PR as I don't think we'll go with anything remotely similar to this. Interesting (and scary ? :) ) to see that no test failed. |
Opening so we can iterate here. |
i took a look and i think the concern is w/ load source text, which is easy to check for... pending bps, might trigger more loads or simultaneous syncs, but that should be safe. gathering some docs on profiling redux so you can see the sequence of actions diff --git a/src/actions/sources.js b/src/actions/sources.js
index 79df46b..c9e2b5e 100644
--- a/src/actions/sources.js
+++ b/src/actions/sources.js
@@ -133,9 +133,9 @@ function loadSourceMap(generatedSource) {
dispatch({ type: "ADD_SOURCES", sources: originalSources });
- await dispatch(loadSourceText(generatedSource));
+ dispatch(loadSourceText(generatedSource));
originalSources.forEach(async source => {
- await checkSelectedSource(getState(), dispatch, source);
+ checkSelectedSource(getState(), dispatch, source);
checkPendingBreakpoints(getState(), dispatch, source.id);
});
};
diff --git a/src/actions/sources/loadSourceText.js b/src/actions/sources/loadSourceText.js
index ad87ea2..81c63e3 100644
--- a/src/actions/sources/loadSourceText.js
+++ b/src/actions/sources/loadSourceText.js
@@ -11,6 +11,8 @@ import { setSource } from "../../workers/parser";
import type { Source } from "../../types";
import type { ThunkArgs } from "../types";
+import { isLoaded, isLoading } from "../../utils/source";
+
async function loadSource(source: Source, { sourceMaps, client }) {
if (sourceMaps.isOriginalId(source.id)) {
return await sourceMaps.getOriginalSourceText(source);
@@ -32,7 +34,7 @@ async function loadSource(source: Source, { sourceMaps, client }) {
export function loadSourceText(source: Source) {
return async ({ dispatch, getState, client, sourceMaps }: ThunkArgs) => {
// Fetch the source text only once.
- if (source.text) {
+ if (isLoading(source) || isLoaded(source)) {
return Promise.resolve(source);
}
diff --git a/src/utils/source.js b/src/utils/source.js
index f1e2e37..8439da1 100644
--- a/src/utils/source.js
+++ b/src/utils/source.js
@@ -263,6 +263,10 @@ function isLoaded(source: Source) {
return source.loadedState === "loaded";
}
+function isLoading(source: Source) {
+ return source.loadedState === "loading";
+}
+
export {
isJavaScript,
isPretty,
@@ -276,5 +280,6 @@ export {
getSourcePath,
getSourceLineCount,
getMode,
- isLoaded
+ isLoaded,
+ isLoading
}; |
3b65ea0
to
c47e09f
Compare
I pushed a small version w/ queuing, which is a good short term solution. The benefit of this approach is that it makes the simple case of loading a source map as fast as possible. In the situation where there is a breakpoint in an original file, we will need both sources (original, generated) to be loaded. We can add these checks where we need them in We probably could go a couple step further and remove similar diff --git a/src/actions/sources.js b/src/actions/sources.js
index af77b3d..fc7f319 100644
--- a/src/actions/sources.js
+++ b/src/actions/sources.js
dispatch({ type: "ADD_SOURCE", source });
if (prefs.clientSourceMapsEnabled) {
- await dispatch(loadSourceMap(source));
+ dispatch(loadSourceMap(source));
}
- await checkSelectedSource(getState(), dispatch, source);
- await checkPendingBreakpoints(getState(), dispatch, source.id);
+ checkSelectedSource(getState(), dispatch, source);
+ checkPendingBreakpoints(getState(), dispatch, source.id);
};
}
@@ -102,7 +103,7 @@ export function newSources(sources: Source[]) {
);
for (const source of filteredSources) {
- await dispatch(newSource(source));
+ dispatch(newSource(source));
}
};
} A good next step would be to make sure the mochitests and jest tests still pass. When they do, we can make sure we have the appropriate coverage. Fortunately, this is mostly coverage for pending breakpoints which we do test quite a bit already in both jest |
left a writeup in the original issue |
And adds some extra super powers for source maps.
The intuition for this algorithm came from Chrome Canary's timeline, which shows significant gaps between addSources calls... while in theory updating the store should be cheap, in practice it is something we definitely want to minimize. Also, putting all the rules in newSources feels good because we continue to make this algorithm more sophisticated. |
I updated this PR to include some pretty significant refactoring for the sources actions: the actions got the
Next Steps:
|
d1c63b5
to
357edca
Compare
some parts of this have been broken out already, and it is too large of a change to merge in. What else can we break out so that this pr can be closed? |
closing this as all of the work has been moved to separate PRs except for the refactor, which i'll re-open. |
Not ready for review, just want to trigger CI and see if I broke the world with this.
Attempts to fix #4654 and #4705