Open techygrrrl opened 1 month ago
I'm not really interested in hijacking browser navigation, but the extension does need a way to import scripts.
The most likely option to be implemented would be to load the currently selected text into the editor via the context menu.
What about importing from a URL?
What about importing from a URL?
The current UI design needs to be modified to support importing from URLs. I do not plan to provide a single-page dashboard, so I have to find a way to use the limited space of the popup window. Perhaps the easiest way is to change all text buttons to icon buttons to free up space.
Now that I think about it, importing from a URL is already technically possible using the @update-url
tag. However, it currently seems to be broken.
To test it, I created a new script with the following content:
// ==UserScript==
// @name Google Translate Auto Languages
// @update-url https://update.greasyfork.org/scripts/378166/Google%20Translate%20Auto%20Languages.user.js
// @match *://translate.google.com/*
// ==UserScript==
When clicking the update button from the editor, nothing happens. Same goes for the "Update All Scripts" button from the popup.
I think it's because of the way applyPropertyDecorators
is being used here which in turn is causing this
to be undefined
here at runtime.
@examosa Just updated the code, should fix it. In the latest version, invalid scripts can be downloaded and saved. The extension lacks a good way to tell the user that the script is invalid.
I was still unable to update from the URL with the latest changes; I got it working locally by making the following change:
diff --git a/src/background/index.ts b/src/background/index.ts
index 1c5a576..8ba406d 100644
--- a/src/background/index.ts
+++ b/src/background/index.ts
@@ -90,14 +90,7 @@ createServer<IBackgroundAPI>(
applyPropertyDecorators(
api
, Object.keys(api) as Array<keyof IBackgroundAPI>
- , (fn: (...args: unknown[]) => unknown) => {
- return async function (this: typeof api, ...args: unknown[]): Promise<unknown> {
- // 等待初始化/迁移执行完毕
- await launched
-
- return await Reflect.apply(fn, this, args)
- }
- }
+ , (fn: (...args: unknown[]) => unknown) => (...args: unknown[]) => launched.then(fn.bind(api, ...args))
) as ImplementationOf<IBackgroundAPI>
)
I may be too tired, but they should be equivalent code.
The only difference is that the first code uses this
and the second code directly passes in the api
object.
Did you modify other parts of the code?
As originally written, the code is using a this
parameter which only carries type information; the actual value of this
still winds up as undefined
at runtime because the async function
is defined inside an arrow function where this
is lexically bound. So each fn
of api
either has to be explicitly bound to api
when invoked, or already bound to api
before using applyPropertyDecorators
e.g. with bind
from your extra-proxy
lib.
A smaller change to the same effect:
diff --git a/src/background/index.ts b/src/background/index.ts
index 1c5a576..39800a9 100644
--- a/src/background/index.ts
+++ b/src/background/index.ts
@@ -91,11 +91,11 @@ createServer<IBackgroundAPI>(
api
, Object.keys(api) as Array<keyof IBackgroundAPI>
, (fn: (...args: unknown[]) => unknown) => {
- return async function (this: typeof api, ...args: unknown[]): Promise<unknown> {
+ return async function (...args: unknown[]): Promise<unknown> {
// 等待初始化/迁移执行完毕
await launched
- return await Reflect.apply(fn, this, args)
+ return await Reflect.apply(fn, api, args) // fn.apply(api, args) would also work
}
}
) as ImplementationOf<IBackgroundAPI>
It might also be a good idea to update applyPropertyDecorators
to forward the this
binding of value
if it's a function; it could either pass obj
as a second argument to propertyDecorator
or invoke it using Function.prototype.call
.
@examosa Sadly, you are wrong. applyPropertyDecorators
was actually designed with tests specifically for this use case, which you can find here: https://github.com/BlackGlory/extra-proxy/blob/master/__tests__/decorator.spec.ts, and the this
in this code doesn't work the way you think, I don't want to give a JavaScript lecture here.
The real question is why the code that works in my browser doesn't work in yours.
Ah, you're right! I must have forgotten to reload the extension after rebuilding the first time 😅
@examosa
Although eternity uses a Meta similar to Greasemonkey, it does not fully support Greasemonkey's script Meta
Thanks to @BlackGlory for open source. vanilla-pudding borrows the idea and Code of eternity
. You are welcome to try it.
First you need to create a new script, paste Meta in the editor, and save it(CTRL + S)
Refresh the editor page and you will find that the plugin is automatically converted into a compliant Meta
Yes. Next, we need to click Update, and the plugin will update the script content according to the @update-url
address. Refresh the editor page to see the updated source code.
I tested your script and it works fine on the Google Translate page ~
Other user script runners have the ability to auto-load a user script into the extension when visiting a
*.user.js
URL.Would it be possible to add this feature to this extension?
Right now when I try to do this, I see this error, which is the same error I see when the extension is disabled.