Taritsyn / JavaScriptEngineSwitcher

JavaScript Engine Switcher determines unified interface for access to the basic features of popular JavaScript engines. This library allows you to quickly and easily switch to using of another JavaScript engine.
Apache License 2.0
439 stars 49 forks source link

Extend JavaScript library with global functions #78

Closed CzaiStefanB closed 4 years ago

CzaiStefanB commented 4 years ago

First let me thank you for that really nice library.

I have one qustion. Is it possible to extend the JavaScript library with global functions (IActiveScript::AddNamedItem with dwFlags set to SCRIPTITEM_GLOBALMEMBERS). I can imagine something like IJsEngine.EmbedHostType(string itemName, Type type, ScriptItem.GlobalMembers) or IJsEngine.EmbedHostObject(string itemName, object value, ScriptItem.GlobalMembers). I did not find a way to do that or did I overlook something?

Thanks!

Taritsyn commented 4 years ago

Hello!

You can give an example of code that requires this functionality.

CzaiStefanB commented 4 years ago

I know, I can also solve that for example by adding a .NET type and use the static methods and properties of it. Anyway I'm thinking about a more function based environment for the user, who should create the scripts later in our software. So an example script code could be "bool result = GetModuleResult("Module1");" instead of "bool result = [StaticClassName].GetModuleResult("Module1");" If the first approach is not possible, I will do it with the static class.

Taritsyn commented 4 years ago

I think that in the context of this library this cannot be done.

The main principle of the JavaScript Engine Switcher is as follows:

JavaScript Engine Switcher determines unified interface for access to the basic features of popular JavaScript engines (…). This library allows you to quickly and easily switch to using of another JavaScript engine.

CzaiStefanB commented 4 years ago

Do you think the global functions contradict the mentioned principle? I think it would be an extension to the existing functionality. At the moment you can embed a host type (with IJsEngine:EmbedHostType) and use the static methods/properties of that type by calling [HostType].[StaticMethodOrProperty]. What is wrong with the approach to map all static methods of the host type to global functions to call them in the script like existing global functions (for example eval(), isNaN(), ...)? (Okay, one reason could be that global functions are evil, but for scripting I would find them rather advantageous.) I'm not very familiar with the scripting engine stuff, but as far as I know in the past a script engine was implementing the IActiveScript interface. The IActiveScript:AddNamedItem method is having a parameter dwFlags which can have the value SCRIPTITEM_GLOBALMEMBERS. The description says in that case the script engine is exposing the members of the object as global variables and methods.

https://docs.microsoft.com/de-de/scripting/winscript/reference/iactivescript-addnameditem

Perhaps newer script engines like Chakra doesn't support that function any longer so you will not be able to add that to the common interface. In that case I will go with the EmbedHostType approach.

Taritsyn commented 4 years ago

Perhaps newer script engines like Chakra doesn't support that function any longer so you will not be able to add that to the common interface. In that case I will go with the EmbedHostType approach.

This approach is not supported by all other engines.

Already now you can use the following approach:

using (IJsEngine engine = JsEngineSwitcher.Current.CreateDefaultEngine())
{
    var getModuleResult = (Func<string, string>)StaticClassName.GetModuleResult;

    engine.EmbedHostObject("GetModuleResult", getModuleResult);
    string result = engine.Evaluate<string>("GetModuleResult('Module1')");

    Console.WriteLine(result);
}
CzaiStefanB commented 4 years ago

I was not aware that this possibility exists. I will use that approach. Thank you for your help.

Taritsyn commented 4 years ago

This is not even a JavaScript Engine Switcher feature, but a. NET feature. We just convert the method call to a delegate.