New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Qt 6.5: Start hint: "Unknown error while getting elements" #7662
Comments
This is a Qt 6.5 regression, see #7624 - but probably good to have a separate issue for this anyways. |
From there:
(note: |
Thanks, I'll try it. |
The branch isn't meant for public use, and currently only contains CI debugging (and |
I think we are just missing a complete reproduction setup. I suspect it is yet another weird lifecycle issue. @rien333's reproducer was pretty good but sometimes the hinting just keeps working after that, even in the same browser instance (and then it breaks again). |
And… I was using Qt5.15. I thought the name was self-explanatory. |
Not quite - both Qt 5 and 6 are supported in the master branch (and thus also in that branch). Qt 5 support will only be dropped at some later date. |
I haven't found a root cause yet, but I think I've found a minimal enough reproducer that we could put it in some c++ for upstream. It seems to be something to do with navigating away from a page with an iframe? (Maybe navigating to a page on the same domain? Need to test that. And I assume it needs to be a cross domain iframe.) Have these two pages: index.html: <body>
<h1>index.html</h1>
<a href="other.html">other.html</a>
<iframe src='https://example.com/'>
</iframe>
</body> other.html <body>
<h1>other.html</h1>
<a href="index.html">index.html</a>
</body> Now start a web server in the folder they are in (eg You can try this on 6.4 too and hints should keep working like usual, so it seems a clear regression. Other places I saw this in the wild:
|
New observation: when hinting breaks, caret mode also breaks. I've seen this happen a couple of times, and it happens consistently on my google reproducer (which, btw, I still haven't seen fail?). Duplicating the tab makes caret mode + hinting work again. Caret mode behaves pretty oddly in this buggy state. For one, the text of the "modeline" changes to "CARET MODE" (like normal), but the color of the modeline doesn't change at all. Also, pressing v (to toggle caret selection mode) gives the error "error toggling caret selection". Moreover, pressing y to yank a selection shows the message "nothing to yank". |
Note that a 100% reproducer for me seems to be amazon:
|
Upstream bug report here: https://bugreports.qt.io/browse/QTBUG-113109 We may be able to mitigate some cases of this (not all of them, but it looks like the search engine case "change query param on page with iframe") by injecting the global JS at multiple injection points, currently they are injected at DocumentCreation only and those scripts are affected worse. (I feel like injecting stuff twice is a workaround we've used elsewhere?) |
Looks like there is an upstream fix now: Fix user script management when subframes are present (Ibda66f55) · Gerrit Code Review From the issue:
And indeed this quick hack seems to fix things: diff --git i/qutebrowser/browser/webengine/webenginetab.py w/qutebrowser/browser/webengine/webenginetab.py
index 6f0ea82f3..57efb515b 100644
--- i/qutebrowser/browser/webengine/webenginetab.py
+++ w/qutebrowser/browser/webengine/webenginetab.py
@@ -1058,11 +1058,11 @@ def _inject_js(self, name, js_code, *,
script.setWorldId(world)
script.setRunsOnSubFrames(subframes)
script.setName(f'_qute_{name}')
- self._widget.page().scripts().insert(script)
+ self._widget.page().profile().scripts().insert(script)
def _remove_js(self, name):
"""Remove an early QWebEngineScript."""
- scripts = self._widget.page().scripts()
+ scripts = self._widget.page().profile().scripts()
if machinery.IS_QT6:
for script in scripts.find(f'_qute_{name}'):
scripts.remove(script)
@@ -1109,7 +1109,7 @@ def _inject_all_greasemonkey_scripts(self):
self._inject_greasemonkey_scripts(scripts)
def _remove_all_greasemonkey_scripts(self):
- page_scripts = self._widget.page().scripts()
+ page_scripts = self._widget.page().profile().scripts()
for script in page_scripts.toList():
if script.name().startswith("GM-"):
log.greasemonkey.debug('Removing script: {}'
@@ -1131,7 +1131,7 @@ def _inject_greasemonkey_scripts(self, scripts):
# make sure we replace existing scripts, not just add new ones.
# While, taking care not to remove any other scripts that might
# have been added elsewhere, like the one for stylesheets.
- page_scripts = self._widget.page().scripts()
+ page_scripts = self._widget.page().profile().scripts()
self._remove_all_greasemonkey_scripts()
seen_names = set()
But that's indeed quite the hack - it should probably come with a wrapper function only doing that on Qt 6.5.0, and it probably needs some logic to not inject scripts multiple times. It's also unclear to me if there is any other logic which would break if the scripts are shared between all pages. On the other hand, I suppose we could do this properly and move the scripts to something per-profile instead of per-tab entirely? I don't know, I don't see a reason off-hand why we'd need them to be per-tab at the moment. @toofar what's your take on this? I'll probably be busy this/next week, so can you take it from here? Would be happy to do a quick review somewhere between things. |
I agree. They are global scripts that we want everywhere. Registering them with the profiles (when we create the profiles, not in the page lifecycle hooks!) and letting Qt take care of inserting them into all the pages sounds like a good idea. I don't remember if there is a reason why we are doing it per-page, presumably it is a hangover from the pre-qtwebenginescript jseval-like insertion method (which we would still need to use for webkit).
I won't have any time to look at this until the weekend (and I think getting a release ready is more important than this tbh). If no-one has had a look at it by then I'll try to see how much work moving them up to the profiles is. But seeing as this is going to be fixed with 6.5.1 (how often do point releases come out?) if it looks like a reasonable amount of work I would lean toward the injecting them twice hack so I can get back to release stuff, as I think that would be much less work. If anyone is building webengine themselves currently the upstream fix is working great! |
QtWebEngine 6.5.1 is planned for May 10th, so only about 2 weeks away. Once the fix is merged upstream, I also plan to ask the Archlinux maintainer to add it to their QtWebEngine package, which I suppose should cover most people. |
I added the fix to Gentoo's qtwebengine and just here to +1 that it's indeed working fine 👍 |
Qt had a regression relating to injecting scripts in 6.5. This only applied to QWebEngineScripts in a page's collection, ones in a profile's collection where fine. Since QWebEngineScripts learnt about greasemonkey compatible metadata (a few years ago now) Qt manages when scripts are injected and into what sites. So from that point of view all we have to do is make sure scripts are registered with Qt when a profile is initialised and then forget about them. So moving up to the profile level fits that lifecycle better. This is an initial, low effort, attempt at moving script registrations to be up in the profile. Here's what I've done: * move everything around QWebEngineScript out of webenginetab up to webenginesettings * injecting greasemonkey scripts * injecting site specific quirks (the site specific part is actually managed by greasemonkey metadata) * injecting global JS that is used on every page like hint, caret and stylesheet utility code * move JS_WORLD_MAP up to qtutils alongside MAX_WORLD_ID * this now introduces backend specific code into this module * move greasemonkey initialisation to be earlier so the singleton manager exists when webenginesettings are initialized * I haven't looked at what dependancies the grasemonkey module has, if this causes issue we could split the greasemonkey initialization up (part one: create singleton, part two: read all scripts + fire reloaded signal) * the profile level stylesheet is still overriden in the tab when a) a search is started or ended, to show/hide the scroll bar b) when the user stylesheets setting changes, so you don't have to reload the page Moving everything up off of an object, in webenginetab, up to module level function in webenginesettings meant removing a bunch of references to "self" and using functools.partial to retain references to profiles for signals. Subclassing QWebEngineProfile would probably help make that stuff a little more robust, and would help us move towards having an arbitrary number of profiles. But the only downside I can think of right now is that signal connections wont get cleaned up when profiles are deleted because they aren't connected to bound methods. But we aren't currently deleting profiles (apart from at shutdown). I left a couple of comments in around possible improvements. The interface for the change_filter decorator surprised me a bit. `_inject_greasemonkey_scripts()` might be able to be made smaller by re-using the script factory. Or moving the world validation out. Regarding the original regression in 6.5, regarding all the global scripts like stylesheet, hint, caret etc. That issue can also be worked around by injecting them twice (at document created and deferred). They all have guards in the code so should be idempotent. That doesn't help greasemonkey scripts though which are also affected. I haven't tried running the tests :) ref: #7662
Qt had a regression relating to injecting scripts in 6.5. This only applied to QWebEngineScripts in a page's collection, ones in a profile's collection where fine. Since QWebEngineScripts learnt about greasemonkey compatible metadata (a few years ago now) Qt manages when scripts are injected and into what sites. So from that point of view all we have to do is make sure scripts are registered with Qt when a profile is initialised and then forget about them. So moving up to the profile level fits that lifecycle better. This is an initial, low effort, attempt at moving script registrations to be up in the profile. Here's what I've done: * move everything around QWebEngineScript out of webenginetab up to webenginesettings * injecting greasemonkey scripts * injecting site specific quirks (the site specific part is actually managed by greasemonkey metadata) * injecting global JS that is used on every page like hint, caret and stylesheet utility code * move JS_WORLD_MAP up to qtutils alongside MAX_WORLD_ID * this now introduces backend specific code into this module * move greasemonkey initialisation to be earlier so the singleton manager exists when webenginesettings are initialized * I haven't looked at what dependancies the grasemonkey module has, if this causes issue we could split the greasemonkey initialization up (part one: create singleton, part two: read all scripts + fire reloaded signal) * the profile level stylesheet is still overriden in the tab when a) a search is started or ended, to show/hide the scroll bar b) when the user stylesheets setting changes, so you don't have to reload the page Moving everything up off of an object, in webenginetab, up to module level function in webenginesettings meant removing a bunch of references to "self" and using functools.partial to retain references to profiles for signals. Subclassing QWebEngineProfile would probably help make that stuff a little more robust, and would help us move towards having an arbitrary number of profiles. But the only downside I can think of right now is that signal connections wont get cleaned up when profiles are deleted because they aren't connected to bound methods. But we aren't currently deleting profiles (apart from at shutdown). I left a couple of comments in around possible improvements. The interface for the change_filter decorator surprised me a bit. `_inject_greasemonkey_scripts()` might be able to be made smaller by re-using the script factory. Or moving the world validation out. Regarding the original regression in 6.5, regarding all the global scripts like stylesheet, hint, caret etc. That issue can also be worked around by injecting them twice (at document created and deferred). They all have guards in the code so should be idempotent. That doesn't help greasemonkey scripts though which are also affected. I haven't tried running the tests :) ref: #7662
I asked the arch maintainers to look at incorporating the upstream fix: https://bugs.archlinux.org/task/78426. (also: really happy that arch is making progress in moving from flyspray to gitlab 😌) Edit: won't happen, but I guess webengine 6.5.1 is only a few days away. |
Updated plan 24.5.2023: Coming soon! |
Qt had a regression relating to injecting scripts in 6.5. This only applied to QWebEngineScripts in a page's collection, ones in a profile's collection where fine. Since QWebEngineScripts learnt about greasemonkey compatible metadata (a few years ago now) Qt manages when scripts are injected and into what sites. So from that point of view all we have to do is make sure scripts are registered with Qt when a profile is initialised and then forget about them. So moving up to the profile level fits that lifecycle better. This is an initial, low effort, attempt at moving script registrations to be up in the profile. Here's what I've done: * move everything around QWebEngineScript out of webenginetab up to webenginesettings * injecting greasemonkey scripts * injecting site specific quirks (the site specific part is actually managed by greasemonkey metadata) * injecting global JS that is used on every page like hint, caret and stylesheet utility code * move JS_WORLD_MAP up to qtutils alongside MAX_WORLD_ID * this now introduces backend specific code into this module * move greasemonkey initialisation to be earlier so the singleton manager exists when webenginesettings are initialized * I haven't looked at what dependancies the grasemonkey module has, if this causes issue we could split the greasemonkey initialization up (part one: create singleton, part two: read all scripts + fire reloaded signal) * the profile level stylesheet is still overriden in the tab when a) a search is started or ended, to show/hide the scroll bar b) when the user stylesheets setting changes, so you don't have to reload the page Moving everything up off of an object, in webenginetab, up to module level function in webenginesettings meant removing a bunch of references to "self" and using functools.partial to retain references to profiles for signals. Subclassing QWebEngineProfile would probably help make that stuff a little more robust, and would help us move towards having an arbitrary number of profiles. But the only downside I can think of right now is that signal connections wont get cleaned up when profiles are deleted because they aren't connected to bound methods. But we aren't currently deleting profiles (apart from at shutdown). I left a couple of comments in around possible improvements. The interface for the change_filter decorator surprised me a bit. `_inject_greasemonkey_scripts()` might be able to be made smaller by re-using the script factory. Or moving the world validation out. Regarding the original regression in 6.5, regarding all the global scripts like stylesheet, hint, caret etc. That issue can also be worked around by injecting them twice (at document created and deferred). They all have guards in the code so should be idempotent. That doesn't help greasemonkey scripts though which are also affected. I haven't tried running the tests :) ref: #7662
This comment was marked as off-topic.
This comment was marked as off-topic.
I get pretty frequent crashes on 6.5.1, btw. If someone happens to land on a consistent reproducer, let me know. |
I still have not met any "full" crash, just some JS messages in random places just like the one I posted in my previous comment. |
@rien333 Could it be related to pinch zooming? I had someone in IRC report something around that. Can you maybe get a stacktrace? If you're on Archlinux, it should show up in |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
@OmeletWithoutEgg @rien333 Thanks! Split off iinto #7732. |
Version info:
Does the bug happen if you start with
--temp-basedir
?:Yes
Description
Since 2-3 days, I often have some pages where hints doesn't work and return the following message
Unknown error while getting elements
. Most of the time it's on a search result from duckduckgo, by I'm pretty sure I experienced the same issue with other sites (Outlook on o365 did that I think).How to reproduce
I use
qutebrowser-qt6-git
from AUR on ArchLinux, running insway
(not XWayland).Since today, I'm able to reproduce every time with
$ qutebrowser -Td
, then:open hello world
. Once on the ddg results, pressing f returns the error message.Stacktrace
Before pressing Enter and after the error:There are already some issues about it, but most of them are closed and the other seem to use specific QT settings (#5569, #6277), while I don't (except maybe running under Wayland). So… sorry if it is still a duplicate.
The text was updated successfully, but these errors were encountered: