Closed MattMinke closed 5 years ago
Hello, Matt!
It would be nice to be able to send host objects as arguments to CallFunction.
Unfortunately, it is impossible to implement in the JavaScript Engine Switcher from a technical point of view, because most JavaScript engines do not support this feature.
In principle, you can pass objects as strings by using JSON serialization. As an example, see LessCompiler
class from the Bundle Transformer.
In addition, you can try to use JsRT API directly - https://www.smashingmagazine.com/2016/09/building-hybrid-apps-with-chakracore/
Hello, Matt!!
I would like that solution too! You could use just a wrapper function to do so, and use the javacript engine json parser.
---- test.js ----
var func = function (p) {
return "Hello World " + p.Name + "!";
}
---- TestController.cs ----
// into some action method
JsEngineSwitcher engineSwitcher = JsEngineSwitcher.Instance;
engineSwitcher.EngineFactories.Add(new ChakraCoreJsEngineFactory());
engineSwitcher.DefaultEngineName = "ChakraCoreJsEngine";
// usage
IJsEngine engine = JsEngineSwitcher.Instance.CreateDefaultEngine();
// evaluate my file
engine.Evaluate<string>(System.IO.File.ReadAllText(HttpContext.Server.MapPath("~/Scripts/test.js")));
// create a wrapper function to the target one
engine.Evaluate<string>(@"var funcWrapper = function(str) {
// target 'func' function
return func(JSON.parse(str));
};");
// execute the wrapper function
var res = engine.CallFunction<string>("funcWrapper", new JavaScriptSerializer().Serialize(new Person { Name = "Joe"}));
// res will be: "Hello World Joe!"
In this case you could create an extension method to encapsulate the creation of a generic parsing javascript function.
Something like this:
public static class JsEngineExtension
{
public static T CallFunction<T, O>(this IJsEngine engine, string name, O obj)
{
engine.Evaluate<string>(@"var wrapper = function(callback, data){
// no window object here... there is some way to prevent eval usage?
return eval(callback)(JSON.parse(data));
};");
return engine.CallFunction<T>("wrapper", name, new JavaScriptSerializer().Serialize(obj));
}
}
// execution now is like this: var res = engine.CallFunction<string, Person>("func", new Person { Name = "Joe"});
@Taritsyn - in order to use the JsRT APIs, you should expose the underlying type so we can write custom type conversions. However, the underlying type is internal and is not exposed. So there is no way to cast the returned value or create a value of type JsValue
(in the case of ChakraCore) to pass into the function as arguments.
Can you please provide a sample of how you think we could use JsRT APIs to convert the function arguments and return values to the underlying type using the JavaScriptEngineSwitcher
library?
Hello, Charles!
I know the ChakraCore engine supports this feature, but not all other JS engines support it. I want to remind for what purpose the JavaScript Engine Switcher library was created:
JavaScript Engine Switcher determines unified interface for access to the basic features of popular JavaScript engines (MSIE JavaScript Engine for .Net, Microsoft ClearScript.V8, Jurassic, Jint, ChakraCore and VroomJs). This library allows you to quickly and easily switch to using of another JavaScript engine.
it's threadsafe if can pass object as parameter, if use EmbedHostType, the Precompiled script can't run in multithread
@coader Give a specific example.
It would be nice to be able to send host objects as arguments to CallFunction. So for example I would like to be able to do something like this:
Currently it is possible for a HostObject to be returned as a result of CallFunction.