Fable icon indicating copy to clipboard operation
Fable copied to clipboard

CLIEvent and Object expressions

Open dbrattli opened this issue 3 years ago • 6 comments

Description

The CLIEvent property seems to be missing from object expressions.

Repro code

open System

type InterfaceWithCLIEvent<'t> =
    [<CLIEvent>]
    abstract Event : IEvent<System.Action<obj,'t>,'t>


let event = Event<Action<obj, bool>,bool>()
let ifaceWIthEvent =
    { new InterfaceWithCLIEvent<_> with
        [<CLIEvent>]
        member __.Event = event.Publish }

Expected and actual results

In JavaScript this compiles to:

import Event$ from "fable-library/Event.js";

export const event = new Event$();

export const ifaceWIthEvent = {
    add_Event(handler) {
        event.Publish.AddHandler(handler);
    },
    remove_Event(handler_1) {
        event.Publish.RemoveHandler(handler_1);
    },
};

So the Event property is gone. I came across this issue since Python uses interfaces and I get the error: Can't instantiate abstract class ObjectExpr0 with abstract method Event

Interface looks like this:

class InterfaceWithCLIEvent_1(Protocol, Generic[_T]):
    @abstractmethod
    def add_event(self, __arg0: Any) -> None:
        ...

    @property
    @abstractmethod
    def Event(self) -> IEvent_2[Any, _T]:
        ...

    @abstractmethod
    def remove_event(self, __arg0: Any) -> None:
        ...

So the Event is part of the interface, but not part of the implementation. If you implement a class using the interface, then the property will be available.

Related information

  • Fable version: repl4
  • Operating system

dbrattli avatar Aug 03 '22 12:08 dbrattli

Thanks for reporting @dbrattli! I need to have a look. Actually I never wanted to add Events to Fable, because I like Observables much better (current support has been mostly done by Krzystof and ncave) so I don't remember all the fitting parts 😅

alfonsogarciacaro avatar Aug 08 '22 00:08 alfonsogarciacaro

Yes, the only reference I can find is: https://github.com/fable-compiler/Fable/blob/main/src/fcs-fable/src/Compiler/Checking/CheckExpressions.fs#L2745 Is that where this things happen?

dbrattli avatar Aug 08 '22 06:08 dbrattli

Hmm, that's the "trimmed down FCS" created by @ncave that we use to self-compile Fable.Standalone. But Fable.Cli doesn't use fable-fcs but a custom build also from ncave's FCS fork (service_slim branch). If we need to generate some code for object expressions implementing Events I assume we have to do it either here (for Fable AST) or here (for Babel/JS AST).

alfonsogarciacaro avatar Aug 08 '22 07:08 alfonsogarciacaro

The problem is that the main property seem to have been removed, so it's not that easy to know that you have to re-add it just by looking for the _remove and _add methods. Anyways, consider this low-priority. I'm not using it for anything, just porting more tests to Python.

dbrattli avatar Aug 08 '22 07:08 dbrattli

@dbrattli I'm no expert, but it looks like this is how F# compiler (FCS) works for [<CLIEvent>] properties. In any case, it is not something that Fable is doing or changing.

Can you perhaps just not output (in the interface) any property with [<CLIEvent>] attribute, instead of trying to re-add the property in the object expression? (Technically that should be done for all languages that emit interfaces, so in Rust too).

ncave avatar Aug 08 '22 11:08 ncave

@dbrattli @alfonsogarciacaro Looks like Dart also generates interfaces, so it has to be fixed there too (to not output [<CLIEvent>] properties in the interface).

ncave avatar Aug 08 '22 16:08 ncave