Add windowless workers UI #7525
Add windowless workers UI #7525
Conversation
src/reducers/pause.js
Outdated
function update( | ||
state: PauseState = createPauseState(), | ||
allState: AllPauseState = createAllPauseState(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think i'd prefer keeping this state
as that is a convention we use in other places
src/reducers/pause.js
Outdated
): AllPauseState { | ||
// Actions need to specify any thread they are operating on. These helpers | ||
// manage updating the pause state for that thread. | ||
const state = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps we can call this getThreadState
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a minor thing, but maybe it's possible to only assert the thread action in the update function, this way we can use an expression.
getThreadState => allState.threads[action.thread] || createInitialPauseState()
const threads = { ...allState.threads }; | ||
threads[action.thread] = newState; | ||
return { ...allState, threads }; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bit simpler
const updateThreadState = threadState => {
if (!action.thread) {
throw new Error(`Missing thread in action ${action.type}`);
}
return {
...state,
threads: {
...state.threads,
[action.thread]: threadState
}
};
};
const { item, depth } = this.props; | ||
|
||
const name = | ||
depth == 0 ? item.name.substr(item.name.indexOf(":") + 1) : item.name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unmangling the addition of the thread to the URL information which was made in src/utils/sources-tree/addToTree.js
@@ -54,12 +58,14 @@ export function createSource( | |||
isBlackBoxed: false, | |||
loadedState: "unloaded" | |||
}; | |||
clientCommands.registerSource(createdSource); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fortunately i think we will simplify this pretty soon
src/client/firefox/commands.js
Outdated
actor, | ||
url: workerClients[actor].url, | ||
// Ci.nsIWorkerDebugger.TYPE_DEDICATED | ||
type: 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it might be nice to have a createWorker
method.
src/client/firefox/commands.js
Outdated
} | ||
|
||
workerClients = newWorkerClients; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be nice to move this to its own util because it will likely be extracted later anyways ...
0b351e9
to
2c1e50a
Compare
src/reducers/pause.js
Outdated
currentThread: string, | ||
debuggeeUrl: string, | ||
canRewind: boolean, | ||
threads: Object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we type this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, it looks like this can be { [string]: PauseState }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep - seems right
src/reducers/pause.js
Outdated
threads: Object | ||
}; | ||
|
||
export const createAllPauseState = (): PauseState => ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
createPauseState
src/reducers/pause.js
Outdated
return { | ||
...state, | ||
currentThread: actor | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return {...state, currentThread: action.thread }
src/reducers/pause.js
Outdated
generated | ||
} | ||
}; | ||
|
||
return updateThreadState(newState); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updateThreadState({
...threadState(),
frameScopes: {
...threadState().frameScopes,
generated
}
})
src/reducers/pause.js
Outdated
original, | ||
mappings | ||
} | ||
}; | ||
|
||
return updateThreadState(newState); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think i prefer passing newState directly into updateThreadState
as i did before
src/reducers/pause.js
Outdated
} | ||
|
||
case "BREAK_ON_NEXT": | ||
return { ...state, isWaitingOnBreak: true }; | ||
return updateThreadState({ ...threadState(), isWaitingOnBreak: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// Workaround for threads resuming before the initial connection. | ||
if (!action.thread && !state.currentThread) { | ||
return state; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yikes
src/reducers/pause.js
Outdated
...state, | ||
case "EVALUATE_EXPRESSION": { | ||
const newState = { | ||
...threadState(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it feels like we still have a lot of boilerplate
this feels better
return updateThreadState({
...threadState(),
command: action.status === "start" ? "expression" : null
});
... but i wonder if we could do a bit more
updateThreadState({
command: action.status === "start" ? "expression" : null
});
this means will always compute the threadState inside of update
const updateThreadState = threadState => {
if (!action.thread) {
throw new Error(`Missing thread in action ${action.type}`);
}
return {
...state,
threads: {
...state.threads,
[action.thread]: { ...threadState(), ...threadState }
}
};
};
src/reducers/pause.js
Outdated
const getPauseState = state => state.pause; | ||
function getCurrentPauseState(state: OuterState): ThreadPauseState { | ||
return ( | ||
state.pause.threads[state.pause.currentThread] || createInitialPauseState() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this? createInitialPauseState()
maybe we create this state when we see the new worker?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be removed but we would need to make sure that the pause state includes entries for all threads. Right now they are lazily initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think it would be nice to do that, maybe by observing connect and SET_WORKERS.
The pushes above fix the following issues:
|
0349e0a
to
49e298c
Compare
…ndowless-workers pref.
49e298c
to
e82c4f7
Compare
My guess is that we just need to tweak the panel
|
AFAICT these failures (well, the first failure at least) is a problem with the new workers.js file: Error: Module I don't know where it came up with firefox/workers/index.js from, as the new file is firefox/workers.js. I had to update my m-c to add workers.js to the moz.build, and after that the browser_browser_toolbox_debugger.js test passes with the other changes that have been made here. |
78e8b00
to
d9abb97
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late review, but I have a few comments about the code related to targets and thread client.
const supportsListWorkers = await checkServerSupportsListWorkers({ | ||
tabTarget, | ||
debuggerClient | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to get rid of that method as we only support up to current release version, which is now 64.
The following code is going to warn when connecting to an old device.
!supportsListWorkers | ||
) { | ||
return newWorkerClients; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
threadClient._parent
is equivalent to tabTarget.activeTab
.
While tabTarget is a Target class instance, its activeTab
property refer to the target front.
While tabTarget will always be a Target class instance, activeTab will be a front specific to which target the toolbox is connected to.
If a regular web toolbox, it will be a BrowsingContextTargetFront,
if a worker window toolbox, it will be a WorkerTargetFront,
if a web extension, it will be a WebExtensionTargetFront and so on.
It would be clear if here and elsewhere, you were using tabTarget.activeTab
rather than threadClient._parent
. Everywhere where you have access to tabTarget in the scope, otherwise, if you only have the threadClient, that's ok, we may try to followup on that.
A much better check here would be to whitelist by target kind, rather than doing this duck typing.
We know which are the target kinds that supports workers.
All browsing context inherited ones as well as content process.
So here we could replace this check by:
if (!tabTarget.isBrowsingContext && !tabTarget.isContentProcess) {
return newWorkerClients;
}
Note that I'm actively working on https://bugzilla.mozilla.org/show_bug.cgi?id=1465635 which aims to merge tabTarget and its activeTab attribute. So that it will be easier to use and think about this type of code.
const [, consoleClient] = await debuggerClient.attachConsole( | ||
workerTargetFront.targetForm.consoleActor, | ||
[] | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I have a patch in flight to stop doing that. Stop duplicating console client instances like that.
https://phabricator.services.mozilla.com/D14278
So here, please fetch the console client like this:
const consoleClient = target.activeConsole;
activeConsole will be defined if you called target.attach(). You do this a few lines before this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I just tried in the browser, and workerTargetFront.activeConsole is undefined at this point.
newWorkerClients[workerThread.actor] = workerClients[workerThread.actor]; | ||
} else { | ||
addThreadEventListeners(workerThread); | ||
workerThread.url = workerTargetFront.url; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks quite hacky to put url
on ThreadClient right here.
Is that really necessary? Can't we use the url
attribute we set in newWorkerClients
dictionary? If not, a comment would be helpful here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, we are supposed to be using the url attribute in newWorkerClients instead of this hack. I'll create a PR to fix this.
Fixes bug 1241958
Summary of Changes
Add windowless worker UI which is used when the devtools.debugger.features.windowless-workers is set (defaults to off).
Test Plan
Tests still need to be added. Since workers don't work in the standalone debugger.html, it seemed better to add new mochitests after this lands.