Revise "cx"/context "threadcx"/thread context assertion in the debugger
Categories
(DevTools :: Debugger, task)
Tracking
(firefox117 fixed)
Tracking | Status | |
---|---|---|
firefox117 | --- | fixed |
People
(Reporter: ochameau, Assigned: ochameau)
References
(Depends on 1 open bug)
Details
Attachments
(21 files, 8 obsolete files)
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review |
The debugger codebase inconsistently use assertions against either a "context" (cx
) or a "thread context" (threadcx
):
These assertions are going to break bug 1806796.
These assertions explicitely prevents some actions from completing after NAVIGATE action is fired. This will break all these actions which will be fired for unload breakpoint as the breakpoint related to the previous context and the new one has been notified via NAVIGATE.
It means that we have to revise these assertions. Instead, we should make them become target/thread based. An async action should bailout if the related target/thread has been removed. But we should ignore navigation, as we may have meaningful actions going across navigation, typically anything around unload event.
We should probably find an API where the action declares its related target/thread,
and the middleware would automatically check if the target/thread is still valid before completing more async actions.
Assignee | ||
Comment 1•2 years ago
|
||
Which is the case. The thread state resource is always emited with a related top frame actor.
Also clarify where does pausedInfo comes from.
Assignee | ||
Comment 2•2 years ago
|
||
Assignee | ||
Comment 3•2 years ago
|
||
Assignee | ||
Comment 4•2 years ago
|
||
The current "thread context" is too loose. These actions are specific to a given frame.
If we step to another frame, or select another frame in the call stack, we can cancel these async actions.
Comment 5•1 years ago
|
||
Comment on attachment 9333112 [details]
Bug 1822310 - [devtools] Assume that pause always comes with a frame attribute.
Revision D177784 was moved to bug 1839192. Setting attachment 9333112 [details] to obsolete.
Assignee | ||
Comment 6•1 years ago
|
||
Stop storing context for expression actions as it sounds fine
trying to update the expression to whatever is the latest selected thread/frame.
That, instead of throwing if the current thread/frame is different from the one
original set when rendering the React component.
This is slightly more complex than fetch scopes actions
as expression aren't only evaluated on paused frames, but also against the global
scope of the target.
Removing a few jest test as they are testing more mocks than actual code
and poorly replicate correct state regarding selected thread/frame.
Updated•1 years ago
|
Assignee | ||
Comment 7•1 year ago
|
||
This action records the expanded path expanded in the scope panel.
While these paths are saved across pause/resume via lastExpandedScopes,
this action saves the data into expandedScopes which is specific to each paused/step location.
Also simplify scope selectors by passing only the frame object.
The frame object already has a reference to the related thread,
and the sourceId
can be fetched late instead of being passed in all these functions.
Assignee | ||
Comment 8•1 year ago
|
||
This isn't super useful. Instead we could verify in the reducer if the frame exists
and assert in the action that the frame was selected.
While doing this, fix the Frame component and stop passing new arrow function to <div>.
This force re-renderings.
Assignee | ||
Comment 9•1 year ago
|
||
The current "thread context" is too loose. These actions are specific to the currently selected frame.
If we step to another frame, or select another frame in the call stack, or select another thread, we can cancel these async actions.
But instead of using the "context" pattern, only identify the "selectedFrame" attribute passed
and ensure it is still relevant.
Also correctly await for async actions from selectFrame.
Assignee | ||
Comment 10•1 year ago
|
||
This is slightly more complex than "scopes" actions.
Expressions aren't only evaluated on paused frames,
but also against the global scope of the target.
So that we have to accept having a null selectedFrame
.
The main special case here is that the action will either have selectedFrame or thread attribute set.
Removing a few jest test as they are testing more mocks than actual code
and poorly replicate correct state regarding selected thread/frame.
Assignee | ||
Comment 11•1 year ago
|
||
This action records the expanded paths in the scope panel.
While these paths are saved across pause/resume via lastExpandedScopes,
this particular action saves the data into expandedScopes
which is specific to each paused/step location.
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Assignee | ||
Comment 12•1 year ago
|
||
Focus on actions involving SET_BREAKPOINT and all its nested callsites.
Assignee | ||
Comment 13•1 year ago
|
||
Focus on actions involving REMOVE_BREAKPOINT
Assignee | ||
Comment 14•1 year ago
|
||
Assignee | ||
Comment 15•1 year ago
|
||
Focus on actions involving ADD_BREAKPOINT.
While doing this, simplify loadSourceText,loadGeneratedSourceText,loadOriginalSourceText to pass source/sourceActor directly instead of a dictionary argument.
Also migrate LOAD_GENERATED_SOURCE_TEXT/LOAD_ORIGINAL_SOURCE_TEXT to assert source/sourceActor instead of using cx.
To do that, also start asserting "sourceActor" attributes of actions.
This removes the last usage of context for breakpoint related action
and we can remove lots of nested usage of context which were solely related to these actions...
Assignee | ||
Comment 16•1 year ago
|
||
Assignee | ||
Comment 17•1 year ago
|
||
Assignee | ||
Comment 18•1 year ago
|
||
Assignee | ||
Comment 19•1 year ago
|
||
Assignee | ||
Comment 20•1 year ago
|
||
Step and resume actions (command action) are acting on the currently selected thread,
so that there is no need to pass a context. These actions could also query the selectors
to guess what is the currently selected thread.
Comment 21•1 year ago
|
||
Comment on attachment 9342534 [details]
Bug 1822310 - [devtools] Remove leftover "cx" variable from preview actions.
Revision D182873 was moved to bug 1841967. Setting attachment 9342534 [details] to obsolete.
Comment 22•1 year ago
|
||
Comment on attachment 9342535 [details]
Bug 1822310 - [devtools] Align breakOnNext and continueToHere with step and resume actions.
Revision D182874 was moved to bug 1841967. Setting attachment 9342535 [details] to obsolete.
Assignee | ||
Comment 23•1 year ago
|
||
This is similar to D182874 and breakOnNext.
Assignee | ||
Comment 24•1 year ago
|
||
Removing some jest test not able to set correct location objects.
The mocks are lacking sourceActor attributes.
Assignee | ||
Comment 25•1 year ago
|
||
Assignee | ||
Comment 26•1 year ago
|
||
Here we should simply ensure that the frame
is still valid.
Compared to selectedFrame
we only want to check if the frame exists
and not that it is the currently selected one.
Rename frame to topFrame in PAUSED in order to avoid triggerring this assertion.
That other action is the action populating the first frame.
Assignee | ||
Comment 27•1 year ago
|
||
This action is a bit tricky. Ideally we would assert against the frame object,
but as this cause the server to resume execution, we would immediately
switch to a new pause location and frames would change.
It is probably easier to avoid trying to cancel this action.
When it executes, it first checks if frame's thread is paused,
then it also validates the frame argument.
Assignee | ||
Comment 28•1 year ago
|
||
Assignee | ||
Comment 29•1 year ago
|
||
As we declare a related generated source actor, we can ensure it is still valid in the reducer.
The source actors are being removed on thread removal.
For ADD_SOURCES, it is harder to find a good assertion.
The current context assertion is useless as we fetch the "cx" just before dispatching the ADD_SOURCES action...
Anyway, this action is emitted synchronously from onResourceAvailable so that should be reliable.
The only check we could do would be to ensure that the thread which emitted these SOURCE resources
is still registered in the reducer, but that's a bit complex as wight be notified about sources
related to many threads (via ResourceCommand throttling).
Assignee | ||
Comment 30•1 year ago
|
||
This one is the last and has lots of nested dependencies.
Assignee | ||
Comment 31•1 year ago
|
||
The resume helper should wait correctly for any async work.
If not, it should be fixed instead.
Assignee | ||
Updated•1 year ago
|
Comment 32•1 year ago
|
||
Comment 33•1 year ago
|
||
Backed out for causing dt failures on browser_dbg-windowless-service-workers-reload.js.
[task 2023-07-12T21:38:29.955Z] 21:38:29 INFO - TEST-PASS | devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers-reload.js | a new breakpoint was created -
[task 2023-07-12T21:38:29.956Z] 21:38:29 INFO - Invoking in tab: fetchFromWorker()
[task 2023-07-12T21:38:29.956Z] 21:38:29 INFO - Waiting for the debugger to pause
[task 2023-07-12T21:38:29.957Z] 21:38:29 INFO - Waiting for state change: paused
[task 2023-07-12T21:38:29.957Z] 21:38:29 INFO - Finished waiting for state change: paused
[task 2023-07-12T21:38:29.957Z] 21:38:29 INFO - Waiting for state change: fetched frames
[task 2023-07-12T21:38:29.958Z] 21:38:29 INFO - Buffered messages finished
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - TEST-UNEXPECTED-FAIL | devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers-reload.js | Uncaught exception in test bound - at resource://devtools/client/debugger/src/selectors/pause.js:154 - TypeError: can't access property "filter", frames is null
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - Stack trace:
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - getCurrentThreadFrames<@resource://devtools/client/debugger/src/selectors/pause.js:154:3
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - createSelectorCreator/createSelector/memoizedResultFunc<@resource://devtools/client/shared/vendor/reselect.js:218:27
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - memoized@resource://devtools/client/shared/vendor/reselect.js:129:22
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - createSelectorCreator/createSelector/selector<@resource://devtools/client/shared/vendor/reselect.js:232:42
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - memoized@resource://devtools/client/shared/vendor/reselect.js:129:22
[task 2023-07-12T21:38:29.961Z] 21:38:29 INFO - bindSelectors/</bound[selector]@resource://devtools/client/debugger/src/utils/dbg.js:34:59
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - waitForState/<@chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js:78:18
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - waitForState@chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js:76:10
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - waitForPaused@chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js:563:9
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - async*@chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers-reload.js:26:9
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - async*handleTask@chrome://mochikit/content/browser-test.js:1131:26
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - _runTaskBasedTest@chrome://mochikit/content/browser-test.js:1203:18
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - Tester_execTest@chrome://mochikit/content/browser-test.js:1345:14
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - nextTest/<@chrome://mochikit/content/browser-test.js:1120:14
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - SimpleTest.waitForFocus/<@chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:1056:13
[task 2023-07-12T21:38:29.962Z] 21:38:29 INFO - Leaving test bound
[task 2023-07-12T21:38:30.174Z] 21:38:30 INFO - Removing tab.
[task 2023-07-12T21:38:30.180Z] 21:38:30 INFO - Waiting for event: 'TabClose' on [object XULElement].
[task 2023-07-12T21:38:30.185Z] 21:38:30 INFO - Got event: 'TabClose' on [object XULElement].
[task 2023-07-12T21:38:30.194Z] 21:38:30 INFO - Tab removed and finished closing
[task 2023-07-12T21:38:30.203Z] 21:38:30 INFO - GECKO(7056) | JavaScript error: , line 0: NotFoundError: No such JSWindowActor 'DevToolsFrame'
[task 2023-07-12T21:38:30.216Z] 21:38:30 INFO - Console message: [JavaScript Error: "NotFoundError: No such JSWindowActor 'DevToolsFrame'"]
[task 2023-07-12T21:38:30.217Z] 21:38:30 INFO - GECKO(7056) | JavaScript error: resource://devtools/shared/protocol/Front.js, line 106: Error: Connection closed, pending request to server0.conn0.content-process51/workerDescriptor6/thread1, type frames failed
[task 2023-07-12T21:38:30.218Z] 21:38:30 INFO - GECKO(7056) | Request stack:
[task 2023-07-12T21:38:30.218Z] 21:38:30 INFO - GECKO(7056) | request@resource://devtools/shared/protocol/Front.js:300:14
[task 2023-07-12T21:38:30.218Z] 21:38:30 INFO - GECKO(7056) | generateRequestMethods/</frontProto[name]@resource://devtools/shared/protocol/Front/FrontClassWithSpec.js:47:19
[task 2023-07-12T21:38:30.218Z] 21:38:30 INFO - GECKO(7056) | getFrames@resource://devtools/client/fronts/thread.js:82:18
[task 2023-07-12T21:38:30.222Z] 21:38:30 INFO - GECKO(7056) | getFrames@resource://devtools/client/debugger/src/client/firefox/commands.js:366:38
[task 2023-07-12T21:38:30.223Z] 21:38:30 INFO - GECKO(7056) | fetchFrames/<@resource://devtools/client/debugger/src/actions/pause/fetchFrames.js:24:29
[task 2023-07-12T21:38:30.223Z] 21:38:30 INFO - GECKO(7056) | thunk/</</<@resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29:45
[task 2023-07-12T21:38:30.223Z] 21:38:30 INFO - GECKO(7056) | dispatch@resource://devtools/client/shared/vendor/redux.js:681:28
[task 2023-07-12T21:38:30.223Z] 21:38:30 INFO - GECKO(7056) | paused/<@resource://devtools/client/debugger/src/actions/pause/paused.js:62:11
[task 2023-07-12T21:38:30.224Z] 21:38:30 INFO - GECKO(7056) | thunk/</</<@resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29:45
[task 2023-07-12T21:38:30.225Z] 21:38:30 INFO - GECKO(7056) | bindActionCreator/<@resource://devtools/client/shared/vendor/redux.js:520:12
[task 2023-07-12T21:38:30.225Z] 21:38:30 INFO - GECKO(7056) | onThreadStateAvailable@resource://devtools/client/debugger/src/client/firefox.js:183:21
[task 2023-07-12T21:38:30.225Z] 21:38:30 INFO - GECKO(7056) | async*_notifyWatchers@resource://devtools/shared/commands/resource/resource-command.js:871:24
[task 2023-07-12T21:38:30.225Z] 21:38:30 INFO - GECKO(7056) | later@resource://devtools/shared/throttle.js:33:19
[task 2023-07-12T21:38:30.225Z] 21:38:30 INFO - GECKO(7056) | notify@resource://gre/modules/Timer.sys.mjs:49:17
[task 2023-07-12T21:38:30.225Z] 21:38:30 INFO - TEST-PASS | devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers-reload.js | The main process DevToolsServer has no pending connection when the test ends -
[task 2023-07-12T21:38:30.228Z] 21:38:30 INFO - Console message: [JavaScript Error: "Failed to load . A ServiceWorker intercepted the request and encountered an unexpected error." {file: "https://example.com/browser/devtools/client/debugger/test/mochitest/examples/service-worker.sjs" line: 14}]
[task 2023-07-12T21:38:30.230Z] 21:38:30 INFO - Console message: [JavaScript Error: "Error: Connection closed, pending request to server0.conn0.content-process51/workerDescriptor6/thread1, type frames failed
[task 2023-07-12T21:38:30.230Z] 21:38:30 INFO -
[task 2023-07-12T21:38:30.230Z] 21:38:30 INFO - Request stack:
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - request@resource://devtools/shared/protocol/Front.js:300:14
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - generateRequestMethods/</frontProto[name]@resource://devtools/shared/protocol/Front/FrontClassWithSpec.js:47:19
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - getFrames@resource://devtools/client/fronts/thread.js:82:18
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - getFrames@resource://devtools/client/debugger/src/client/firefox/commands.js:366:38
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - fetchFrames/<@resource://devtools/client/debugger/src/actions/pause/fetchFrames.js:24:29
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - thunk/</</<@resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29:45
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - dispatch@resource://devtools/client/shared/vendor/redux.js:681:28
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - paused/<@resource://devtools/client/debugger/src/actions/pause/paused.js:62:11
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - thunk/</</<@resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29:45
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - bindActionCreator/<@resource://devtools/client/shared/vendor/redux.js:520:12
[task 2023-07-12T21:38:30.231Z] 21:38:30 INFO - onThreadStateAvailable@resource://devtools/client/debugger/src/client/firefox.js:183:21
[task 2023-07-12T21:38:30.232Z] 21:38:30 INFO - async*_notifyWatchers@resource://devtools/shared/commands/resource/resource-command.js:871:24
[task 2023-07-12T21:38:30.232Z] 21:38:30 INFO - later@resource://devtools/shared/throttle.js:33:19
[task 2023-07-12T21:38:30.232Z] 21:38:30 INFO - notify@resource://gre/modules/Timer.sys.mjs:49:17
[task 2023-07-12T21:38:30.232Z] 21:38:30 INFO - " {file: "resource://devtools/shared/protocol/Front.js" line: 106}]
[task 2023-07-12T21:38:30.233Z] 21:38:30 INFO - GECKO(7056) | [Parent 2988, IPC I/O Parent] WARNING: DuplicateHandle failed for handle 0 in TransferHandles: file /builds/worker/checkouts/gecko/ipc/chromium/src/chrome/common/ipc_channel_win.cc:621
[task 2023-07-12T21:38:30.234Z] 21:38:30 INFO - GECKO(7056) | [GPU 10032, IPC I/O Child] WARNING: pipe error: 232: file /builds/worker/checkouts/gecko/ipc/chromium/src/chrome/common/ipc_channel_win.cc:443
[task 2023-07-12T21:38:30.582Z] 21:38:30 INFO - GECKO(7056) | MEMORY STAT | vsize 2113220MB | vsizeMaxContiguous 65089987MB | residentFast 723MB | heapAllocated 302MB
[task 2023-07-12T21:38:30.585Z] 21:38:30 INFO - TEST-OK | devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers-reload.js | took 2662ms
[task 2023-07-12T21:38:30.596Z] 21:38:30 INFO - checking window state
[task 2023-07-12T21:38:30.604Z] 21:38:30 INFO - TEST-START | devtools/client/debugger/test/mochitest/browser_dbg-windowless-service-workers.js
Assignee | ||
Comment 34•1 year ago
|
||
Seems to be fixed in the latest revision:
https://treeherder.mozilla.org/jobs?repo=try&selectedTaskRun=INIwPSArSG2ebnp8D0cTdw.0&revision=a89c7d4c022aed77eb60f4eca7730203565e4d24
Comment 35•1 year ago
|
||
Assignee | ||
Comment 36•1 year ago
|
||
Comment 37•1 year ago
|
||
Backed out for damp failure on custom.js
Backout link: https://hg.mozilla.org/integration/autoland/rev/5f6e606c18953417de5f8ac1e0acc13cab5df516
Log link: https://treeherder.mozilla.org/logviewer?job_id=422573179&repo=autoland&lineNumber=1695
Comment 38•1 year ago
|
||
Comment 39•1 year ago
|
||
Comment 40•1 year ago
|
||
Backout merged to central: https://hg.mozilla.org/mozilla-central/rev/5f6e606c1895
Comment 41•1 year ago
|
||
bugherder |
Comment 42•1 year ago
|
||
Comment 43•1 year ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/d11c3ae486aa
https://hg.mozilla.org/mozilla-central/rev/86e174bda89a
https://hg.mozilla.org/mozilla-central/rev/0f7f67b13792
https://hg.mozilla.org/mozilla-central/rev/167395be46a1
https://hg.mozilla.org/mozilla-central/rev/d936f00c8296
https://hg.mozilla.org/mozilla-central/rev/5f6276ae93a4
https://hg.mozilla.org/mozilla-central/rev/2471a29a9e41
https://hg.mozilla.org/mozilla-central/rev/822b87c44e29
https://hg.mozilla.org/mozilla-central/rev/68c047de6103
https://hg.mozilla.org/mozilla-central/rev/c2b5ed240be2
https://hg.mozilla.org/mozilla-central/rev/2c2ee353412f
https://hg.mozilla.org/mozilla-central/rev/47208ffa2647
https://hg.mozilla.org/mozilla-central/rev/cfc433febf5b
https://hg.mozilla.org/mozilla-central/rev/1733a94650da
https://hg.mozilla.org/mozilla-central/rev/a668cdc3e6ea
https://hg.mozilla.org/mozilla-central/rev/038e656bb933
Assignee | ||
Updated•1 year ago
|
Comment 44•1 year ago
|
||
== Change summary for alert #39032 (as of Sun, 16 Jul 2023 16:39:57 GMT) ==
Improvements:
Ratio | Test | Platform | Options | Absolute values (old vs new) |
---|---|---|---|---|
33% | reload-debugger:parent-process objects-with-stacks | linux1804-64-qr | 20.77 -> 14.00 |
For up to date results, see: https://treeherder.mozilla.org/perfherder/alerts?id=39032
Comment 45•1 year ago
|
||
Can this bug be closed? It looks like all the patches landed in Firefox 117.
Assignee | ||
Comment 46•1 year ago
|
||
Oh yes, good catch!
I forgot to close it when removing the leave-info.
Updated•1 year ago
|
Comment 47•1 year ago
|
||
Comment on attachment 9333114 [details]
Bug 1822310 - [devtools] Add tests to cover breakpoints on unload.
Revision D177786 was moved to bug 1806796. Setting attachment 9333114 [details] to obsolete.
Description
•