Skip to content
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

Provide script author migration documentation #2559

Closed
arantius opened this issue Sep 13, 2017 · 16 comments
Closed

Provide script author migration documentation #2559

arantius opened this issue Sep 13, 2017 · 16 comments
Milestone

Comments

@arantius
Copy link
Collaborator

We're switching to an async/promise API system. Provide some documentation/examples for script authors to use. See e.g.

https://github.com/mozilla/webextension-polyfill

The "Or, using an async function:" section especially. If we work just a bit, we can show how things can be done in a manner that's nearly as easy to code with.

@arantius arantius added this to the 4.0 milestone Sep 13, 2017
arantius added a commit to arantius/greasemonkey that referenced this issue Sep 20, 2017
This allows await usage at the top level.

Refs greasemonkey#2559
@mnghsn
Copy link

mnghsn commented Sep 25, 2017

Since user script codes are actually wrapped in a async function, Providing a polyfill using @require don't work if the user script has await at the top level.

Maybe a polyfill like:

async function main (GM) {
  // UserScript code goes here...
  await GM.setValue('foobar', 123)
  let value = await GM.getValue('foobar') // -> 123
}

typeof GM === 'object' ? main(GM) : main({
  info: GM_info,
  getValue: function (key, def) {
    return Promise.resolve(GM_getValue(key, def))
  },
  setValue: function (key, value) {
    return Promise.resolve(GM_setValue(key, value))
  }
})

@fdellwing
Copy link

You need to make sure, that you wrap you whole code in an async function. Otherwise it will not work in legacy GM!

(async () => {

if (typeof GM === "undefined") {
	GM = new Object();
	GM.info = GM_info;
	GM.listValues = function() {
		return Promise.resolve(GM_listValues.apply(null, arguments));
	};
	GM.getValue = function() {
		return Promise.resolve(GM_getValue.apply(null, arguments));
	};
	GM.setValue = function() {
		return Promise.resolve(GM_setValue.apply(null, arguments));
	};
	GM.deleteValue = function() {
		return Promise.resolve(GM_deleteValue.apply(null, arguments));
	};
	GM.xmlhttpRequest = function() {
		return Promise.resolve(GM_xmlhttpRequest.apply(null, arguments));
	};
}

console.log(GM.info);
console.log(await GM.listValues());
})();

@fdellwing
Copy link

I just made my biggest script (about 5000 lines) backward compatibel with GM3 and can say: It is not nice.

The script uses a lot of functions and only some of them are using the GM API. So this functions have to be async. But if the calling function relies on the work of the called function, you need to await that function too, so you need to async the calling function...and so on.

Best would to be, to rewrite the whole script and just make it async as a whole. But this would be a pain in the ass...

@arantius
Copy link
Collaborator Author

A) I've started the polyfill script, if you'd like a preview:
https://arantius.com/misc/greasemonkey/imports/greasemonkey4-polyfill.js

B) Make sure to include in documentation case changes: GM_xmlhttpRequest becomes GM.xmlHttpRequest; GM_getResourceURL becomes GM.getResourceUrl; maybe others.

@fdellwing
Copy link

Will test the polyfill, but it only saves about ~30 lines of code. The bigger problem is to make an syncron script run with asyncron parts ^^

@fdellwing
Copy link

Polyfill does work, but:

a) GM.info is a function, but needs to be an array/object
b) I, personally, think it would be better, to reverse the polyfill: So you need to call GM.listValues() instead of GM_listValues(). It shows, that the script is ready for GM4.

@eight04
Copy link

eight04 commented Sep 27, 2017

@arantius I saw that GM_registerMenuCommand is replaced with HTML5 context menu. Is there any plan to add it in GM 4.x? I can't find the tracking issue.

I haven't test it, but it might be a good idea to not overwrite existing APIs

function GM_addStyle(...) {...}
// v.s.
if (!this.GM_addStyle) {
	this.GM_addStyle = function(...) {...};
}

@roger21
Copy link

roger21 commented Oct 7, 2017

is openInTab also excluded from gm4 ???

same as #2559 (comment) b) i would prefer to code in GM4 style as for now and for ever instead of sticking to the old API style

and same as #2559 (comment) i actually don't understand how that would work with gm4

and a bogus in the second comment in the file, there are 2 gm4, one should be "gm before 4" or something

@arantius
Copy link
Collaborator Author

I, personally, think it would be better, to reverse the polyfill: So you need to call GM.listValues() instead of GM_listValues().

I'm not sure what you mean, that (call new style APIs) is already the intended model. What the polyfill does is make new style API calls work in old-API script managers.

I saw that GM_registerMenuCommand is replaced with HTML5 context menu. Is there any plan to add it in GM 4.x?

No. Greasemonkey's policy has been (for a long time) not to implement "user space" features. Any script can do this, or @require something like this polyfill which does it. Greasemonkey doesn't need to build nor support this feature to enable scripts to use it. The point here is just to do what the polyfill does: make it easier to update scripts to be compatible with both old and new versions of Greasemonkey.

@eight04
Copy link

eight04 commented Oct 18, 2017

No. Greasemonkey's policy has been (for a long time) not to implement "user space" features. Any script can do this, or @require something like this polyfill which does it. Greasemonkey doesn't need to build nor support this feature to enable scripts to use it. The point here is just to do what the polyfill does: make it easier to update scripts to be compatible with both old and new versions of Greasemonkey.

I meant if GM4 will also provide an API to execute script commands from the UI of userscript manager like old GM_registerMenuCommand, not asking whether there will be a HTML5 contextmenu API in GM. GM_registerMenuCommand is often used to launch script configuration dialog, which shouldn't be polyfilled as a HTML5 contextmenu IMHO.

BTW, I have created a library to work with HTML contextmenu just few months ago, which would reuse contextmenu property on the page if it is already set:
https://github.com/eight04/GM_context

@arantius
Copy link
Collaborator Author

GM_registerMenuCommand is often used to launch script configuration dialog, which shouldn't be polyfilled as a HTML5 contextmenu IMHO

Why not?

@arantius
Copy link
Collaborator Author

There's more work to do, especially updating the wiki, but the blog post is enough progress for now ...

@eight04
Copy link

eight04 commented Oct 25, 2017

Why not?

  1. The command on the contextmenu should be:

    • An action which works on specified context (element). For example, when some text is selected, "Copy" command, which is an action to work with the selection, is shown.
    • A shortcut to execute specified command for convenience.

    A "My userscript setting" command doesn't fall into both categories. It does not depend on the context, also there is no need to use a shortcut for configuration.

  2. It is not reliable. It may be blocked/replaced by page scripts.

@trlkly
Copy link

trlkly commented Oct 25, 2017

I agree with the conceptual level difficultires. I do not have any extensions anymore that use the context menu for settings. It would get pretty busy pretty quickly if they did, since I run a lot of extensions.

But the main reason I see is that Chrome has removed the HTML5 context menu from the spec, which means it's probably going to be removed from Firefox, too. I didn't even know it existed, seeing as I've not seen any site use it. Apps just spin their own, blocking the real context menu (which is a huge, huge annoyance in most cases. That removes functionality.)

Also, a question: will there be any way to inject at document start? Or is that now asyncronous too? Injection at document-start is the main reason I still treat Greasemonkey as my primary development engine (even though Chrome is my main browser now). I hate pop-in.

@arantius
Copy link
Collaborator Author

Also, a question: will there be any way to inject at document start?

#2526

@fdellwing
Copy link

I pushed my first FF57 userscript with downward compatibility to upstream today.

It was quite some work to get everything to run, but I think I got it.

You might want to take a look at it: http://wod.zerosgaming.de/scripts/mm_skills/mm_skills_0_23.user.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants