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
[FireMonkey] GM_getValue/GM_setValue should be synchronous #98
Comments
The values are saved to extension storage and the storage operation, like most other operations, are asynchronous. There isn't any way to access storage synchronously. It is the same case for GM4 where these operations are asynchronous. GM3 had synchronous operations but that was in legacy Firefox. Such operations are all asynchronous in FF57+. Any script that is written for or need to run on Firefox 57+ needs to be updated for that.
|
@erosman Sorry, I meant that GM3's I believe the way Violentmonkey does it is that it caches the settings to the content script, allowing it to return the value directly without a promise, without needing to send a message to the background script. If you don't plan on implementing this yet (considering that this might require restructuring the code), would it be possible to remove support for |
I will look through the Violentmonkey but I doubt it. The storage areas available to extensions are limited eg. local/sync/IndexedDB It does not mater if a script users GM.getValue or GM_getValue. As long as Firefox is 57+, the operation is async, One of the cornerstones of Quantum Firefox was to make all sync operations async so that they wont halt other operations while executing. The only sync storage areas available as WebAPI (both page and extension) are localStorage & sessionStorage. As content script is saved in storage then "caches the settings to the content script" is the storage unless it wants to keep them as temporary variables in RAM which is not feasible. |
Yes, that's why Violentmonkey has to cache the userscript settings on the content script in order to allow GM_getValue to be synchronous (it returns the cached value, instead of querying browser.storage) Here is the related code: https://github.com/violentmonkey/violentmonkey/blob/49dfdd02bbb4d27b0c55e30048d49babb702d0be/src/injected/web/index.js#L223 https://github.com/violentmonkey/violentmonkey/blob/49dfdd02bbb4d27b0c55e30048d49babb702d0be/src/injected/web/index.js#L369 This checks for store.values, which is populated at start, and when the values change (through a storage listener).
Unfortunately it does, because the
Sorry, I didn't explain it properly. The content script has a variable ( Thanks for looking into this! |
I see ... That is violentmonkey way of keeping all values in RAM. There are many problems with that. Using sync/await is easy and it behaves like sync. It will also work with GM3 & GM4 and other managers. It will also work on Firefox 52.+
|
No, it sets it to the storage immediately after: https://github.com/violentmonkey/violentmonkey/blob/49dfdd02bbb4d27b0c55e30048d49babb702d0be/src/injected/web/index.js#L252 (https://github.com/violentmonkey/violentmonkey/blob/49dfdd02bbb4d27b0c55e30048d49babb702d0be/src/injected/web/index.js#L381). The RAM is just a cache mirror of the storage in order to allow the synchronous behavior to work. Whenever the value changes either way, it mirrors it back (if the storage is updated, it's mirrored to the cache, if the cache is updated, it's mirrored to the storage).
Yes, it's a rather hacky workaround, but legacy scripts (that use
That's the other issue, the userscript needs to work for older browsers without async support (and I am aware of a number of users that regularly use it with legacy browsers). If you want, I can try to implement this in your addon and send you a patch. I understand that this might take a while to implement, due to the storage mirroring :) |
I am able to write the code.. however... that misses the point completely. Minimum Firefox version to use FireMonkey is 65.0 There is no point in trying to make FireMonkey compatible for something that was written for any Firefox older than 65.0 (especially something as old as before FF52) |
That's fine, but could you then remove support for Any legacy userscript using Currently there's no way I can work around this issue on my end, as adding To summarize:
One thing that might be good to note though, is that there are many userscripts that people still actively use (such as MPIV: https://greasyfork.org/en/scripts/404-mouseover-popup-image-viewer, probably one of the more popular userscripts), that require the legacy APIs to work according to spec in order to work properly (e.g. settings). I hope this doesn't come across harshly, I appreciate your time looking into this :) |
FireMonkey is NOT a clone of other script managers. It has many features that other script mangers don't. Others also have features that are not supported in FireMonkey. FireMonkey is a NEW script & CSS manger. All the necessary information is in the included help. Adding a simple It is easy enough to make scripts run on multiple script managers. I have 100s of script that can run on all script mangers. There are many differences between current script managers, some of which are listed in the Help, e.g. the default Detecting FireMonkey is also easy. AFAIK other script manger dont support GM_fetch so
You can also check this way, since FireMonkey is the only one supporting both at the same time: In your script, I noticed a check is performed for each GM function. That way the script will run on any browser and any script manger that supports
FireMonkey For old browser support, a |
Fair enough, and that's great! Many other userscript handlers have been stagnating adding new features, which really is a shame, especially for a few features that would be very useful for many userscripts. I hope you can keep on adding new features as needed! :) However, I would again personally argue that where they offer the same API, they should at least function somewhat similarly. FireMonkey's
Most that I have tried partially work under FireMonkey, but are unable to read their settings (due to this issue). For some, settings aren't too important, but for others, settings are rather crucial to the base functionality (including mine).
Thank you!! I'll use That being said, if you do not plan on either removing the function, or fixing it to work according to the spec, would you at least consider at least partially implementing Even just supporting
As I wrote earlier, the reason I didn't do this is because of performance. The quicker the page can load, the more bandwidth is saved when redirecting images. Using
Sorry, I misworded that. I meant that most other userscript handlers return the value of the setting directly, while FireMonkey maps the function to On a sidenote, I'm really sorry if this has taken a more hostile tone, that was absolutely not my intention when opening this issue. |
Currently FireMonkey implements GM_getValue as a map to GM.getValue, which prevents the value from being found. Github issue for this: erosman/support#98
Sure and I will add them if there is a popular demand and it is feasible. FireMonkey is still in its early days.
true... but then how does
TBH, I never found it useful personally HOWEVER, it is very easy to add the feature. Let me think about it and since someone else also ask for it, maybe I will add it. |
It works the other way around :) It creates a new function:
Thank you for considering! This will help greatly to provide proper support for FireMonkey with the userscript :) I don't care much about the reflection properties (finding the version/name of your own script), but knowing which userscript handler is running it (as well as the version, in case a quirk only appears in one version but not another) is super helpful for working around quirks like these to provide a good experience for as many users as possible :) So even if you just add support for those two variables ( |
OK.. I added I will update once something is sorted. |
BTW.. in your code you first check If you change the order, then you wont need extra code to check In fact, I would check it once and cache it at the start of script .e.g.
|
@erosman Thank you, but as I wrote earlier, the reason I didn't do this is because of performance. The quicker the page can load, the more bandwidth is saved when redirecting images. Using GM.getValue by default is noticeably slower in other userscript managers (since asynchronous code is delayed for an undefined amount of time). |
That should not be a factor here since except FireMonkey, others dont support BOTH so it is either this or that so there is no choice. Also since the script is injected at Anyway.. that was just a suggestion. |
v1.16 uploaded with GM.info/GM_info support .. but read the Help |
@erosman Thank you! |
I'm not sure why this is marked as "done", the root issue (GM_getValue/GM_setValue working as GM.getValue/GM.setValue, which is incorrect) still remains... |
You requested Let's see if there is a popular demand for what you requested about |
synch GM_getValue I have been thinking about it. The way API works is that:
scriptAPI & user-script are injected automatically into the relevant page and have content scope. In order for the user-script to have synchronous access to the stored data, the data must be available in content scope with means in scriptAPI or user-script itself. Any interaction with background script will be an async interaction anyway so caching it in the background script would mean async access. That would mean injecting the actual storage value as a JS into the page e.g.: I can write the code to make it possible but that would add some extra processing (read/write/update to cache as well as actual storage). There are GM_setValue/GM_getValue/GM_deleteValue/GM_listValues which used to by synch. TBH, synch did not mean immediately even in GM3. The data still require read/write from/to file and that took time. The main difference was that the running code would not progress further until the process was completed. Bearing in mind that There is also the fact that FireMonkey is not clone of other script managers and there are other differences as well which would mean not all user-scripts can run on FireMonkey without some adjustment. |
It's completely fine if you don't implement it (and I completely understand your reasons), but then if so, please don't expose As I wrote earlier, I personally believe there are two options here: 1: Implement GM_get/setValue to conform to spec (make them synchronous). GM3 scripts will work properly, regardless of whether they implement a GM4 fallback or not. The current solution (GM_get/setValue working in a completely different way than the spec) breaks both GM3 scripts that don't implement a GM4 fallback, and GM3 scripts that implement a GM4 fallback. In other words, there is absolutely no advantage to doing it this way.
I understand that, but removing GM_get/setValue (if you don't want to implement it) will allow more userscripts to run out of the box. The current solution (having GM_get/setValue work contrary to spec) breaks every userscript that uses GM_get/setValue. |
I am going to write the synch code and see how it works out ... let's see |
So far, I have made ALL these synch (both GM.* & GM_*)
I thought it would be simpler to make both type the same. async/await will work nonetheless. I have to test them out though. |
I am going to see if it is possible to implement a quasi-synchronous |
It is done and I am testing... for v1.45 const value = GM_getValue(key, default); // sync
const value = await GM.getValue(key, default); // async Promise
const keys = GM_listValues(); // sync
const keys = await GM.listValues(); // async Promise |
v1.45 uploaded |
FireMonkey v1.45 has added support for the synchronous storage APIs [1], but it's currently buggy [1] erosman/support#98
Actually, the sync |
I have not found a method to pass the script storage to the script before it is inserted in order to make it available synchronously to the script. Script storage data is in extension storage and getting it is asynchronous. My previous attempt (v1.45-1.46) failed and caused problems. If anyone has a suggestion, I can work on it. |
Sorry if I'm misunderstanding the issue, but how about having a sort of Edit: Ah, if you're instead referring to the |
Yes.. GM
In FireMonkey using the dedicated API, those variables are set at script register time. Typically, that is when browser is started and/or when script is enabled. After registering a script, the extension doesn't do anything else with the script and all is handled by Firefox. That is how the dedicated userScript API works and since the process is handled by Firefox (not manually by the extension), it is more efficient. Therefore, while it is possible to add script storage data to the script, the data would be old (e.g. at the time of browser start) and can not be updated. Other user script mangers manually inject script into the tab. That would mean:
Besides the overheads of doing above, it also takes time to process. For example, the After injecting a script and its storage data, then any further update to its storage data will still be asynchronous since there is no way to pass the new data to the script synchronously. In the failed attempted (v1.45-1.46) I tried to inject the script storage into the script as script is injected. However that failed since the process was still async and the script that sets or gets values immediately (as opposing to later after a timer or after an event listener) would run before the data is received. One script manager also uses
Background script in my extensions always cache the storage data for sync & fast retrieval anyway. The problem is passing it the script. As mentioned above, it is only possible at register time. Any attempt to pass it to the scripts later would require an async process. |
Got it, sorry I'm not familiar with the userscript API, I wasn't aware that was the case. Perhaps then a ticket could be opened? E.g. adding an |
I have already discussed it with Mozilla engineers multiple times. There is no interest to create any sync operation as it will affect the browser performance (sync means browser has to halt other operations while async means it is queued for the next available cycle). In fact, user-script developers are sticking to the old sync code. VM|TM (but not GM) have kept the compatibility at a cost of performance to keep the user-script developers happy. The delay is there as far as running the script is concerned. The quasi-sync get the storage data (delay here) and make it available to the script but after that the script can get the data without delay. The manual insertion of the user-script creates additional delay on top of that. The async method runs the script without delay but there is delay when getting storage data. Both have a delay. In fact running the script without delay works better for most script, especially those that do not use script storage immediately on loading. Furthermore, the delays is often 2 milliseconds. so Comparison
ℹ️ In brief ...
|
I can't see it mentioned in the documentation, but it does support both. |
I couldn't see it in their documentation and it is not open source any more.
|
GM_getValue & GM_listValues (v2.0)Partial compatibility has been implemented. Please note:
The async |
v2.0 released |
v2.43 uploaded Added experimental sync storage compatibility |
Just checked this and it doesn't appear to be working for Environment
Test// ==UserScript==
// @name FireMonkey Sync Storage Test
// @version 0.0.1
// @namespace firemonkey-test
// @include *
// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_setValue
// ==/UserScript==
const KEY = 'test'
const VALUE = 42
const stored = Object.fromEntries(GM_listValues().map(key => [key, GM_getValue(key)]))
console.log('stored:', stored)
if (GM_getValue(KEY)) {
GM_deleteValue(KEY)
console.log(`deleted ${KEY}:`, GM_getValue(KEY) === undefined)
} else {
GM_setValue(KEY, VALUE)
console.log(`set ${KEY}:`, GM_getValue(KEY) === VALUE)
}
console.log('test:', GM_getValue(KEY)) Expected Output
Actual Output
|
I will check it. It might be related to (and fixed via) the issue #491 |
I checked and it is related to issue listed above and should be fixed in v2.57 |
GM_getValue/GM_setValue are synchronous:
Looking at the source code (scriptAPI.js), it appears
GM_setValue
is just mapped directly toGM.setValue
:I'm not sure if GM_setValue needs to be changed, but
GM_getValue
returning a promise prevents some userscripts (including mine) from properly working. I'm guessingGM_listValues
should also be synchronous.Thank you for doing this by the way, it's great to have more options :)
The text was updated successfully, but these errors were encountered: