Pages that constantly call `eval`/`new Function` can bring the devtools parent-process UI to its knees
Categories
(DevTools :: Debugger, defect, P3)
Tracking
(firefox79 fixed)
Tracking | Status | |
---|---|---|
firefox79 | --- | fixed |
People
(Reporter: raphael.mozilla, Assigned: jlast)
References
(Blocks 2 open bugs)
Details
Attachments
(2 files)
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0
Steps to reproduce:
I opened oui.sncf (in a small window trigger the mobile version of the layout) in Firefox nightly.
I searched for a train, and then clicked on one of the results, as per the video.
Then, I right-clicked on the arrow to close the result and chose "Inspect element"
On the parent of the element, there is an event. I clicked on the button to open the event handler in the debugger tab.
On the current stable version of Firefox, opening oui.sncf and then opening the debugger tab suffices.
Actual results:
The developer tools became slugging, the CPU and memory usage spikes, the whole browser eventually becomes sluggish, even freezes until the developer tools are closed.
The situation is way worse on current stable Firefox version.
Expected results:
Everything should remain smooth.
Comment 1•5 years ago
|
||
Bugbug thinks this bug should belong to this component, but please revert this change in case of error.
Reporter | ||
Comment 2•5 years ago
|
||
Yes, sure. Sorry about that.
Comment 3•5 years ago
|
||
Alright, this sounded like a potentially bad issue so I did some digging into this to try to sort things out a bit.
I connected to Firefox and dumped a stack trace a few times and almost every time I get something along the lines of:
#0 7ffee4a2fc90 I resource://devtools/client/debugger/src/utils/resource/base-query.js:64 (2576efc85c90 @ 9)
#1 7ffee4a2fc90 I resource://devtools/client/debugger/src/utils/resource/base-query.js:82 (2576efc85e20 @ 116)
#2 7ffee4a2fc90 I resource://devtools/client/debugger/src/utils/resource/base-query.js:66 (2576efc85ce0 @ 29)
#3 7ffee4a2fc90 I resource://devtools/client/debugger/src/utils/resource/base-query.js:31 (2576efc85ba0 @ 24)
#4 7ffee4a2fcf0 I self-hosted:251 (2395af89e600 @ 295)
#5 7ffee4a2fdc0 b resource://devtools/client/debugger/src/utils/resource/base-query.js:31 (2576efc85b50 @ 76)
#6 7ffee4a2fe30 I resource://devtools/client/debugger/src/utils/resource/query-cache.js:84 (2576efc8b2e0 @ 349)
#7 7ffee4a2fef0 b resource://devtools/client/debugger/src/reducers/sources.js:673 (2576efc91830 @ 237)
#8 7ffee4a2ff40 I resource://devtools/client/shared/vendor/reselect.js:99 (2576efc79fb0 @ 95)
#9 7ffee4a30ab0 I resource://devtools/client/shared/vendor/reselect.js:49 (2576efc79d80 @ 57)
#10 7ffee4a30b00 I resource://devtools/client/shared/vendor/reselect.js:99 (2576efc79fb0 @ 95)
#11 7ffee4a31670 I resource://devtools/client/shared/vendor/reselect.js:49 (2576efc79d80 @ 57)
#12 7ffee4a31740 b resource://devtools/client/debugger/src/components/PrimaryPanes/SourcesTree.js:298 (bd8e61e9c0 @ 78)
#13 7ffee4a317c0 I resource://devtools/client/shared/vendor/react-redux.js:1776 (2576efc43dd0 @ 38)
#14 7ffee4a317c0 I resource://devtools/client/shared/vendor/react-redux.js:1937 (2576efc46600 @ 16)
#15 7ffee4a31810 I resource://devtools/client/shared/vendor/react-redux.js:1954 (2576efc46650 @ 162)
#16 7ffee4a31870 I resource://devtools/client/shared/vendor/react-redux.js:1959 (2576efc466a0 @ 27)
#17 7ffee4a318d0 I resource://devtools/client/shared/vendor/react-redux.js:1233 (2576efc431f0 @ 29)
#18 7ffee4a31910 I resource://devtools/client/shared/vendor/react-redux.js:1406 (2576efc436a0 @ 31)
#19 7ffee4a31950 I self-hosted:873 (fc81c5f4c40 @ 398)
#20 7ffee4a319b0 I resource://devtools/client/shared/vendor/react-redux.js:1159 (2576efc38fb0 @ 62)
#21 7ffee4a319b0 I resource://devtools/client/shared/vendor/react-redux.js:1198 (2576efc48bf0 @ 22)
#22 7ffee4a319f0 I self-hosted:873 (fc81c5f4c40 @ 398)
#23 7ffee4a31a30 I resource://devtools/client/shared/vendor/react-redux.js:1409 (2576efc436a0 @ 71)
#24 7ffee4a31a70 I self-hosted:873 (fc81c5f4c40 @ 398)
#25 7ffee4a31ad0 I resource://devtools/client/shared/vendor/react-redux.js:1159 (2576efc38fb0 @ 62)
#26 7ffee4a31ad0 I resource://devtools/client/shared/vendor/react-redux.js:1198 (2576efc48bf0 @ 22)
#27 7ffee4a31b10 I self-hosted:873 (fc81c5f4c40 @ 398)
#28 7ffee4a31b50 I resource://devtools/client/shared/vendor/react-redux.js:1409 (2576efc436a0 @ 71)
#29 7ffee4a31b90 I self-hosted:873 (fc81c5f4c40 @ 398)
#30 7ffee4a31c50 b resource://devtools/client/shared/vendor/redux.js:265 (2576efc4c0b0 @ 283)
#31 7ffee4a31d10 b resource://devtools/client/debugger/src/actions/utils/middleware/wait-service.js:71 (bd8e6e9150 @ 72)
#32 7ffee4a31dd0 b resource://devtools/client/debugger/src/actions/utils/middleware/promise.js:46 (bd8e6e2e20 @ 43)
#33 7ffee4a31e80 b resource://devtools/client/debugger/src/actions/utils/middleware/context.js:35 (bd8e6e2ba0 @ 55)
#34 7ffee4a31f30 b resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29 (bd8e6e2a10 @ 114)
#35 7ffee4a31ff0 b resource://devtools/client/shared/vendor/redux.js:520 (2576efc4c5b0 @ 41)
#36 7ffee4a320a0 b resource://devtools/client/debugger/src/components/PrimaryPanes/SourcesTree.js:95 (bd8e61e560 @ 21)
#37 7ffee4a32190 b resource://devtools/client/debugger/src/components/shared/ManagedTree.js:64 (bd8e60c290 @ 819)
#38 7ffee4a32260 b resource://devtools/client/debugger/src/components/shared/ManagedTree.js:129 (bd8e60c560 @ 19)
#39 7ffee4a322d0 I resource://devtools/client/debugger/dist/vendors.js:738 (fc81c5bdba0 @ 274)
#40 7ffee4a323b0 b resource://devtools/client/debugger/dist/vendors.js:757 (fc81c5bdb50 @ 313)
#41 7ffee4a323f0 I self-hosted:873 (fc81c5f4c40 @ 398)
#42 7ffee4a324a0 b resource://devtools/client/debugger/dist/vendors.js:700 (fc81c5bdab0 @ 17)
#43 7ffee4a32510 I resource://devtools/client/shared/vendor/react-dom.js:8303 (2395af87ca60 @ 72)
#44 7ffee4a325d0 I resource://devtools/client/shared/vendor/react-dom.js:8482 (2395af87cb50 @ 453)
#45 7ffee4a32660 I resource://devtools/client/shared/vendor/react-dom.js:10599 (2395af884970 @ 314)
#46 7ffee4a32700 I resource://devtools/client/shared/vendor/react-dom.js:11419 (2395af884e70 @ 1528)
#47 7ffee4a32760 I resource://devtools/client/shared/vendor/react-dom.js:14702 (2395af8897e0 @ 204)
#48 7ffee4a327a0 I resource://devtools/client/shared/vendor/react-dom.js:14720 (2395af889830 @ 48)
#49 7ffee4a32900 b resource://devtools/client/shared/vendor/react-dom.js:14803 (2395af889880 @ 601)
#50 7ffee4a329e0 b resource://devtools/client/shared/vendor/react-dom.js:15655 (2395af88c3d0 @ 217)
#51 7ffee4a32ac0 b resource://devtools/client/shared/vendor/react-dom.js:15567 (2395af88c2e0 @ 400)
#52 7ffee4a32b80 b resource://devtools/client/shared/vendor/react-dom.js:15541 (2395af88c290 @ 12)
#53 7ffee4a32c20 b resource://devtools/client/shared/vendor/react-dom.js:15410 (2395af88c100 @ 144)
#54 7ffee4a32cf0 b resource://devtools/client/shared/vendor/react-dom.js:15224 (2395af889ce0 @ 233)
#55 7ffee4a32dd0 b resource://devtools/client/shared/vendor/react-dom.js:8192 (2395af8955b0 @ 184)
#56 7ffee4a32ec0 b resource://devtools/client/shared/vendor/react.js:328 (2395af89e0b0 @ 132)
#57 7ffee4a32f10 I resource://devtools/client/shared/vendor/react-redux.js:1412 (2576efc436a0 @ 120)
#58 7ffee4a32f50 I self-hosted:873 (fc81c5f4c40 @ 398)
#59 7ffee4a32fb0 I resource://devtools/client/shared/vendor/react-redux.js:1159 (2576efc38fb0 @ 62)
#60 7ffee4a32fb0 I resource://devtools/client/shared/vendor/react-redux.js:1198 (2576efc48bf0 @ 22)
#61 7ffee4a32ff0 I self-hosted:873 (fc81c5f4c40 @ 398)
#62 7ffee4a33030 I resource://devtools/client/shared/vendor/react-redux.js:1409 (2576efc436a0 @ 71)
#63 7ffee4a33070 I self-hosted:873 (fc81c5f4c40 @ 398)
#64 7ffee4a330d0 I resource://devtools/client/shared/vendor/react-redux.js:1159 (2576efc38fb0 @ 62)
#65 7ffee4a330d0 I resource://devtools/client/shared/vendor/react-redux.js:1198 (2576efc48bf0 @ 22)
#66 7ffee4a33110 I self-hosted:873 (fc81c5f4c40 @ 398)
#67 7ffee4a33150 I resource://devtools/client/shared/vendor/react-redux.js:1409 (2576efc436a0 @ 71)
#68 7ffee4a33190 I self-hosted:873 (fc81c5f4c40 @ 398)
#69 7ffee4a33250 b resource://devtools/client/shared/vendor/redux.js:265 (2576efc4c0b0 @ 283)
#70 7ffee4a33310 b resource://devtools/client/debugger/src/actions/utils/middleware/wait-service.js:71 (bd8e6e9150 @ 72)
#71 7ffee4a333d0 b resource://devtools/client/debugger/src/actions/utils/middleware/promise.js:46 (bd8e6e2e20 @ 43)
#72 7ffee4a33480 b resource://devtools/client/debugger/src/actions/utils/middleware/context.js:35 (bd8e6e2ba0 @ 55)
#73 7ffee4a33530 b resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29 (bd8e6e2a10 @ 114)
#74 7ffee4a335f0 b resource://devtools/client/shared/vendor/redux.js:681 (2576efc4cab0 @ 24)
#75 7ffee4a336b0 b resource://devtools/client/debugger/src/actions/sources/newSources.js:400 (2576efce5060 @ 67)
#76 7ffee4a33760 b resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29 (bd8e6e2a10 @ 92)
#77 7ffee4a33820 b resource://devtools/client/shared/vendor/redux.js:681 (2576efc4cab0 @ 24)
#78 7ffee4a338d0 b resource://devtools/client/debugger/src/actions/sources/newSources.js:362 (2576efce1e70 @ 1078)
#79 7ffee4a33980 b resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29 (bd8e6e2a10 @ 92)
#80 7ffee4a33a40 b resource://devtools/client/shared/vendor/redux.js:681 (2576efc4cab0 @ 24)
#81 7ffee4a33af0 b resource://devtools/client/debugger/src/actions/sources/newSources.js:234 (2576efce1bf0 @ 421)
#82 7ffee4a33ba0 b resource://devtools/client/debugger/src/actions/utils/middleware/thunk.js:29 (bd8e6e2a10 @ 92)
#83 7ffee4a33c60 b resource://devtools/client/shared/vendor/redux.js:520 (2576efc4c5b0 @ 41)
#84 7ffee4a33d20 b resource://devtools/client/debugger/src/utils/source-queue.js:20 (2395af89ece0 @ 64)
#85 7ffee4a34d00 b resource://devtools/client/shared/vendor/lodash.js:10333 (1dcd73625330 @ 65)
#86 7ffee4a34db0 b resource://devtools/client/shared/vendor/lodash.js:10343 (1dcd73625380 @ 58)
#87 7ffee4a34e80 b resource://devtools/client/shared/vendor/lodash.js:10410 (1dcd736255b0 @ 120)
#88 7ffee4a34f20 b resource://devtools/client/debugger/src/utils/source-queue.js:31 (2395af89ed80 @ 29)
#89 7ffee4a34fe0 b resource://devtools/client/debugger/src/client/firefox/events.js:135 (bd8e6e9600 @ 76)
#90 7ffee4a35030 I self-hosted:919 (fc81c5e8c40 @ 417)
#91 7ffee4a35840 b resource://devtools/shared/event-emitter.js:226 (63261824f10 @ 727)
#92 7ffee4a35910 b resource://devtools/shared/event-emitter.js:172 (63261824e70 @ 134)
#93 7ffee4a359e0 b resource://devtools/shared/event-emitter.js:324 (632618201f0 @ 126)
#94 7ffee4a35ac0 b resource://devtools/shared/protocol/Front.js:294 (4b23295e510 @ 603)
#95 7ffee4a35b90 b resource://devtools/shared/client/devtools-client.js:495 (4b232997510 @ 287)
#96 7ffee4a35c40 b resource://devtools/shared/transport/local-transport.js:68 (4b232997e70 @ 132)
#97 7ffee4a36c30 b resource://devtools/shared/ThreadSafeDevToolsUtils.js:111 (4b2329cc880 @ 42)
#98 7ffee4a37c20 b resource://devtools/shared/ThreadSafeDevToolsUtils.js:111 (4b2329cc880 @ 42)
Digging into that further, it isn't actually that we are slow rendering the sidebar, the issue is that we are constantly getting newSource
notifications and therefore resource://devtools/client/debugger/src/actions/sources/newSources.js
is constantly triggering updates that require us to regenerate the list of files for the source tree.
If you edit the TabSources.js file to inspect all the new sources, it appears that this page makes super aggressive use of new Function
/eval
to execute logic on the page, and every time it does so, the DevTools are notified and the UI tries to decide if any new files need to be shown in the list of sidebar files. Since evaled files don't show up in the sidebar, there aren't any re-renders happening AFAIK, but we have to constantly query the redux store to decide if there is anything new.
I'm sure there's an long discussion that we could have here about optimizing the client and server to handle constant eval
calls.
In the short term, I'd recommend that this site explore alternatives to constant creation of new functions. The script https://en.oui.sncf/abtasty/ww/WW.js contains a payload with tons and tons of strings that get evaluated somewhere. Search for if(window.customerLib.customer) {
for an example. It appears that many of these strings are re-evaled over and over, so one option might be for this site to cache the functions instead of re-evaling the string each time the function runs. Is that something that could be explored Raphaël?
Reporter | ||
Comment 4•5 years ago
|
||
Hello Logan,
Thanks for the investigation. Unfortunately, I am not involved with the development of this website. I develop Oui Light, a Firefox extension to debloat oui.sncf :-)
Comment 5•5 years ago
|
||
Ahh well then, nevermind!
I just verified and it looks like injecting
Function = (function(Function){
const cache = new Map();
return function(...args){
const key = JSON.stringify(args);
let value = cache.get(key);
if (!value) {
value = new Function(...args);
cache.set(key, value);
}
return value;
};
})(Function);
via the Console tool before switching to Debugger tool allows the debugger to load successfully on that page, since that prevents the page from constantly recreating functions with the same arguments. Hard to say if that would cause issues though, I suppose it depends on whether the object identity of any of the evaled values is important to the functionality of the page.
Comment 6•5 years ago
|
||
The priority flag is not set for this bug.
:jlast, could you have a look please?
For more information, please visit auto_nag documentation.
Updated•5 years ago
|
Comment 7•5 years ago
|
||
Logan, given how bad the impact of this is; I wonder if it can affect developers that depend on new Function
/eval
as it was a common pattern in the past with frameworks like Angular. If it has wider reach, it might be worth to elevate it to P2. WDYT?
Comment 8•5 years ago
|
||
The issue here is specifically that new Function
/eval
is called constantly. Any framework would generally keep those calls to an absolute minimum by running them once up front and then using the returned function to call the logic multiple times, or else is at least executing a string that is static and eval
s the same string every time and can therefore cached by SpiderMonkey.
I'd personally expect the conditions required to trigger this to be pretty uncommon. That said, it's certainly a frustrating issue, so it probably would make sense to try to get to sooner rather than later.
Comment 9•5 years ago
|
||
Because this bug's Severity has not been changed from the default since it was filed, and it's Priority is P3
(Backlog,) indicating it has been triaged, the bug's Severity is being updated to S3
(normal.)
Assignee | ||
Comment 10•4 years ago
|
||
Updated•4 years ago
|
Comment 11•4 years ago
|
||
Comment 12•4 years ago
|
||
bugherder |
Description
•