wails icon indicating copy to clipboard operation
wails copied to clipboard

[V2] Execute JavaScript in the frontend from go

Open KiddoV opened this issue 2 years ago • 18 comments

  1. Is there any way that I can call the JavaScript functions in Go?
  2. How do I pass my JQuery objects to the backend, to use its functions?
  3. Is there a way to make all Go functions private instead of global? I fear that user can get to the browser console and call any Go functions.

KiddoV avatar Jan 26 '22 13:01 KiddoV

  1. Events is the only way
  2. Events
  3. How would this work?

leaanthony avatar Jan 26 '22 20:01 leaanthony

@leaanthony Thanks for the reply. Can you be more specific on the Events? Is there a Go package for the Events that I don't know? Number 3 is just a curiosity. I don't think there is a way to do that. :)

KiddoV avatar Jan 26 '22 20:01 KiddoV

https://wails.io/docs/reference/runtime/events

Emit an event from Go with any data you want to pass, in JS have a listener for the event and call whatever method from there with the passed data

leaanthony avatar Jan 26 '22 20:01 leaanthony

@leaanthony Can you provide some example code? This is a little bit confusing for newbie. For example I have this in JS:

instance = $("#some-id").terminal();
//Call in JS
instance.echo("Hello there!");

If I want to pass that instance to GO side and call .echo() from it, how can I do that?

KiddoV avatar Jan 26 '22 20:01 KiddoV

You can't pass JS instance methods to Go. You can do something like this though:

Backend:

func echo(text string) {
    runtime.EventsEmit("terminal-echo", text)
}

Frontend:

runtime.EventsOn("terminal-echo", instance.echo);

leaanthony avatar Jan 26 '22 21:01 leaanthony

So I have to make one listener for every JS instance method?

KiddoV avatar Jan 26 '22 21:01 KiddoV

So I have to make one listener for every JS instance method?

You don't need to set a listener for each JS method, just set one and distribute it according to the passed parameters.

misitebao avatar Jan 27 '22 04:01 misitebao

Yeah that's another way

leaanthony avatar Jan 27 '22 07:01 leaanthony

@misitebao thank you both! I think I got it now.

KiddoV avatar Jan 27 '22 11:01 KiddoV

Looking for a way to actually call JS functions from go, I was wondering the design decision to do not expose ExecJS?

The core idea here is to keep the FE implementation, as much as possible, the same no matter where it runs (pure web or as desktop app or PWA). Having the ability to call the FE app API from go allows a clean, loosely bounded way to interact (f.e. logout user, etc).

It is clear that all of that could be achieved using events however it couples both sides a tat bit too much then. Thoughts?

pierrejoye avatar Jun 02 '22 15:06 pierrejoye

It's not an unreasonable request. One caveat is that there would be no way of knowing if the call fails as there would be no return value. Thoughts @stffabi ?

leaanthony avatar Jun 02 '22 22:06 leaanthony

I do not know (yet) about other platform, however on windows WebView2, it can return values using ExecuteScriptAsync

pierrejoye avatar Jun 03 '22 10:06 pierrejoye

Yeah I would also say that's a good extension to wails. I just briefly taken a look into the apis and it should be possible to get the returning value on all platforms. Maybe we need some trampoline functions to properly returning errors for exceptions.

Maybe we should also take a look into supporting async js methods that can execute a callback to finish the call on the go side?

stffabi avatar Jun 05 '22 19:06 stffabi

Sounds good to me! This has to be the last last feature for v2 right 😉😉😉

leaanthony avatar Jun 06 '22 10:06 leaanthony

Yeah, or maybe v2.1?

stffabi avatar Jun 06 '22 20:06 stffabi

Nice addition!!! So I don't need to make events in the front-end anymore?

window.runtime.EventsOn("EventName", function(...args) {...});

KiddoV avatar Jun 07 '22 12:06 KiddoV

@leaanthony Does this means it would be possible to run arbitrary JS code in a sandboxed environment?

sidwebworks avatar Jun 25 '22 01:06 sidwebworks

Hopefully!

leaanthony avatar Jun 25 '22 05:06 leaanthony

WindowExecJS has been exposed with #1927 and merged.

Currently it is fire and forget, without the possibility to get return values.

stffabi avatar Oct 05 '22 06:10 stffabi

Does WindowExecJS only execute JS in global or window scope?. It seems like I can only call console.log and alert(), but not my global functions.

export function myFunc() {
    console.log("Func called!")
}

Edit: NVM, I should define the function like this to work:

(<any>window).testFunc = (msg: string) => {
    console.log(msg);
}
//or...
(window as any).testFunc = (msg: string) => {
    console.log(msg);
}

KiddoV avatar Dec 21 '22 14:12 KiddoV

Does WindowExecJS only execute JS in global or window scope?. It seems like I can only call console.log and alert(), but not my global functions.

export function myFunc() {
    console.log("Func called!")
}

Edit: NVM, I should define the function like this to work:

(<any>window).testFunc = (msg: string) => {
    console.log(msg);
}
//or...
(window as any).testFunc = (msg: string) => {
    console.log(msg);
}

Hello. I am confused. Can you give me one complete example, call to javascript?

AlexJujushvili avatar Feb 12 '23 23:02 AlexJujushvili

Capture Hello. I am confused. Can you give me one complete example, call to javascript?

AlexJujushvili avatar Feb 12 '23 23:02 AlexJujushvili

Your code shown above is the other way around. The WindowExecJS is for calling JavaScript function or execute JS code directly from Golang without creating any wrapper functions.

For example, in JavaScript/ TypeScript you have a GLOBBAL function:

//JS
window.testFunc = (msg) => {
    console.log(msg);
}
//TS
(<any>window).testFunc = (msg: string) => {
    console.log(msg);
}

Then you can call this function directly from Golang using the new method called WindowExecJS

runtime.WindowExecJS(`
window.testFunc(“Hello from Golang”);
`)
//expecting console displays a message 

KiddoV avatar Feb 13 '23 03:02 KiddoV

Capture

Thank you very much !!! :)

AlexJujushvili avatar Feb 13 '23 17:02 AlexJujushvili

How to get the result from WindowExecJS which the function return some content。In other words,how to get some content when click hot keys 。 For example, save the content which from frontend to local file

RandyWei avatar Feb 14 '23 02:02 RandyWei

Currently it is fire and forget, without the possibility to get return values.

Currently does not support return value from frontend.

KiddoV avatar Feb 14 '23 04:02 KiddoV

Thks

RandyWei avatar Feb 14 '23 05:02 RandyWei

Currently it is fire and forget, without the possibility to get return values.

Currently does not support return value from frontend.

And never can. Limitation of executing JS. The best thing you can do is do an event.On with a random number, pass in that number to the call and get the call to emit an event back with the result

leaanthony avatar Feb 14 '23 09:02 leaanthony