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

Multiple functions in my Javascript file #124

Closed
fallais opened this issue Feb 20, 2020 · 12 comments
Closed

Multiple functions in my Javascript file #124

fallais opened this issue Feb 20, 2020 · 12 comments
Labels

Comments

@fallais
Copy link

fallais commented Feb 20, 2020

Hello, I come from Otto world and I want to migrate to this library because of very bad performance issues. I am using it for a normalisation pipeline.

I used to put 4 or 5 functions into a JS file, and then call one of them into my Golang code.

Example (here I call the function Exlcude) :

// Run
returnRaw, err := vm.Run(`Exclude(` + string(incidentJSON) + `);`)
if err != nil {
	return false, fmt.Errorf("Error while running the JS code : %s", err)
}

How can I do this with your lib please ? Thanks a lot ! :)

@dop251
Copy link
Owner

dop251 commented Feb 20, 2020

Hi @fallais,

Assuming that you have run the code that defines the Exclude function, you can do the following:

exclude, _ := goja.AssertFunction(vm.Get("Exclude"))

returnRaw, err := exclude(nil, vm.ToValue(string(incidentJSON))
// note, res will be a goja.Value, if you need a native Go value you need to export it:
v := returnRaw.Export()

Hope this helps.

@fallais
Copy link
Author

fallais commented Feb 25, 2020

Thanks a lot !
But it is not working, it is not finding the function..

Here is the code, it should find it..

// Exclude returns true if the incident is excluded. Otherwise it must return false.
var Exclude = function(incident){
   ...
}

@fallais
Copy link
Author

fallais commented Feb 25, 2020

I do not set the script file anywhere.. that is the issue I guess.. ^^

        // Create the VM
	vm := goja.New()

	// Set the variables
	vm.Set("customer", customer)
	vm.Set("incident", incidentJSON)

	// Run
	excludeFunc, ok := goja.AssertFunction(vm.Get("Exclude"))
	if !ok {
		return false, fmt.Errorf("Error while asserting the function [Exclude]: %s", err)
	}
	returnRaw, err := excludeFunc(nil, vm.ToValue(string(incidentJSON)))
	if err != nil {
		return false, fmt.Errorf("Error while executing the function [Exclude]: %s", err)
	}

	excluded := returnRaw.ToBoolean()

PS : do I really need to marshall into JSON ? Does the lib do it automatically when passing struct into the VM ?

@dop251
Copy link
Owner

dop251 commented Feb 25, 2020

I can't see you are running anything that could define the Exclude function. Do you expect it to appear in the vm by magic? :)

@fallais
Copy link
Author

fallais commented Feb 25, 2020

Yes, I realized it... But I do not understand the logic here. I have to get a Callable in order to run the function I defined in the source file. But to get it, I need to run it into the VM. But I can't run it because is has no parameter..

So, if I understand correctly, I ned to run it one first time for "nothing" ?

@dop251
Copy link
Owner

dop251 commented Feb 25, 2020

You don't run the function, you run the code that defines the function.

@fallais
Copy link
Author

fallais commented Feb 25, 2020

Something like this ?

// Marshal incident as JSON object
	incidentJSON, err := json.Marshal(incident)
	if err != nil {
		return false, fmt.Errorf("Error while marshalling the incident : %s", err)
	}

	// Create the VM
	vm := goja.New()

	// Set the variables
	vm.Set("customer", customer)
	vm.Set("incident", incidentJSON)

	// Run the script
	_, err = vm.RunString(norm.script)
	if err != nil {
		return false, fmt.Errorf("Error while running the JS code: %s", err)
	}

	// Run
	excludeFunc, ok := goja.AssertFunction(vm.Get("Exclude"))
	if !ok {
		return false, fmt.Errorf("Error while asserting the function [Exclude]: %s", err)
	}
	returnRaw, err := excludeFunc(nil, vm.ToValue(string(incidentJSON)))
	if err != nil {
		return false, fmt.Errorf("Error while executing the function [Exclude]: %s", err)
	}

	excluded := returnRaw.ToBoolean()

@dop251
Copy link
Owner

dop251 commented Feb 25, 2020

Something like this:

vm := goja.New()
_, err = vm.RunString("function Exclude(incident) { ... your code here ... }")
if err != nil {
	return false, fmt.Errorf("Error while running the JS code: %s", err)
}

// Run
excludeFunc, ok := goja.AssertFunction(vm.Get("Exclude"))
if !ok {
	return false, fmt.Errorf("Error while asserting the function [Exclude]: %s", err)
}
returnRaw, err := excludeFunc(nil, vm.ToValue(string(incidentJSON)))
if err != nil {
	return false, fmt.Errorf("Error while executing the function [Exclude]: %s", err)
}

excluded := returnRaw.ToBoolean()

I'm not sure about the role of the customer variable and whether you need to set it as a global variable, rather than passing it as a parameter.

As for serialising into JSON, you can pass a Go variable directly (like vm.ToValue(incident)), however bear in mind that it will wrap it into a js "host" object so it will not behave exactly as a native JS value. If you don't need to modify it inside your javascript function it should be ok.

@fallais
Copy link
Author

fallais commented Feb 25, 2020

Perfect thanks :)

@fallais
Copy link
Author

fallais commented Feb 25, 2020

Well, I have errors with the indexOf : TypeError: Cannot read property 'indexOf' of undefined at

But the description field does exists, so the indexOf should work.. It may be because of the host object type ?

@fallais
Copy link
Author

fallais commented Feb 25, 2020

If I use JSON.parse() inside the JS function to parse the object, it seems to be working. But I need to marshal it of course. If I do not marshal it and do not use the JSON.parse(), not working.

@dop251
Copy link
Owner

dop251 commented Feb 25, 2020

I can't really help you without seeing a full test case, sorry.

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

No branches or pull requests

2 participants