microsoft / ClearScript

A library for adding scripting to .NET applications. Supports V8 (Windows, Linux, macOS) and JScript/VBScript (Windows).
https://microsoft.github.io/ClearScript/
MIT License
1.76k stars 148 forks source link

Methods from Derived Classes Not Bound in ClearScript #607

Open herki18 opened 1 day ago

herki18 commented 1 day ago

I may have misunderstood how binding works in ClearScript, but I'm encountering an issue where methods from derived classes are not accessible. We have a method createElement that returns an object of type IElement. However, the actual object being returned is an instance of a derived class, HtmlDivElement, which inherits from IElement. The problem is that ClearScript only binds methods and properties from IElement and its ancestors. This results in methods specific to HtmlDivElement being inaccessible from JavaScript.

Example:

public interface IElement
{
    void SetAttribute(string name, string value);
    string GetAttribute(string name);
}

public class HtmlDivElement : IElement
{
    public void SetAttribute(string name, string value) 
    {
        // Set attribute logic
    }

    public string GetAttribute(string name) 
    {
        // Get attribute logic
        return string.Empty;
    }

    public void SetDivSpecificMethod() 
    {
        // Method specific to HtmlDivElement
    }
}

JavaScript Example:

var div = document.createElement("div");
div.setAttribute("id", "myDiv");

// This fails because methods specific to HtmlDivElement are not bound
div.setDivSpecificMethod(); // Error: setDivSpecificMethod is not a function

Question:
How can I ensure that ClearScript binds methods from the derived class (HtmlDivElement) so that they are accessible in JavaScript? Is there a way to expose these methods while keeping the inheritance structure intact?

ClearScriptLib commented 1 day ago

Hi @herki18,

The behavior you're seeing is by design. It's an effect of a ClearScript feature called type restriction, which enhances the ability of script languages to consume strongly typed .NET APIs.

// This fails because methods specific to HtmlDivElement are not bound div.setDivSpecificMethod(); // Error: setDivSpecificMethod is not a function

That's right. The variable div is effectively of type IElement. If this were C# code, you couldn't call SetDivSpecificMethod without casting, and the same applies to JavaScript.

Type restriction is important for .NET member binding. Suppose you wanted to pass div to a .NET method overloaded as follows:

void DoSomething(IElement element);
void DoSomething(HtmlDivElement element);

Without type restriction, the first overload would be inaccessible, and that's just the tip of the iceberg. .NET APIs often rely heavily on precise type tracking for correct member binding, ambiguity resolution, type inferencing, generic type and method instantiation, etc. ClearScript aims not only to make such APIs usable from script code but also to make them behave as .NET developers would expect.

That said, ClearScript does give hosts some control over type restriction:

Good luck!