ciscoheat / mithril-hx

Haxe externs for Mithril (JS MVC framework)
181 stars 12 forks source link

Broken in Haxe 4.2? #37

Closed hamaluik closed 3 years ago

hamaluik commented 3 years ago

I wish I could figure this out myself, but unfortunately I'm not making any traction. The Either abstract seems to be broken in Haxe 4.2?

Using Haxe 4.2 and running haxe client.hxml you get:

➜ haxe client.hxml
example/DashboardComponent.hx:81: characters 18-27 : DashboardComponent should be mithril._M.Either<mithril.Component, mithril.RouteResolver<Dynamic>>
example/DashboardComponent.hx:81: characters 18-27 : ... For function argument 'routes'

This replicates what I'm seeing in my projects as well, whenever I try to use a route.

Minimal example showing the issue:

package;

import mithril.M;
import js.Browser;

class TestPage implements Mithril {
    public function new() {}

    public function view(vnode: Vnode<TestPage>): Vnodes {
        return m('p', 'Hello');
    }
}

class Main {
    static function main() {
        var testPage = TestPage();

        M.route.route(Browser.document.body, '/', {
            '/': testPage,
        });
    }
}

I believe I've traced this to the abstract Either definition, but I can't figure out how to fix it yet (other than just defining Either as Dynamic and calling it a day).

ciscoheat commented 3 years ago

Hi, this was/is a very strange, intermittent error. I managed to make it work through this process:

  1. Moved the routes to a var (still got the error after this)
  2. Added $type around the var just to see what was going on
  3. Got a compiler failure message with stack dump
  4. Removed $type
  5. Suddenly it started to work, and after that I've been unable to reproduce the issue.

Testing with your example, moving the routes to a var makes it work without going through the above hoops. Can you confirm?

class Main {
    static function main() {
        var testPage = new TestPage();
        var routes = {
            '/': testPage,
        };

        M.route.route(Browser.document.body, '/', routes);
    }
}
hamaluik commented 3 years ago

Hmm, that fixed the routes, thanks! Now I'm running into a problem using static lifecycle methods instead of instantiated components, i.e.:

package;

import mithril.M;
import js.Browser;

class Component implements Mithril {
    public static function view(vnode: Vnode<Component>): Vnodes {
        return m('p', 'component');
    }
}

class TestPage implements Mithril {
    public static function view(vnode: Vnode<TestPage>): Vnodes {
        return [
            m('p', 'testpage'),
            m(Component),
        ];
    }
}

class Main {
    static function main() {
        var routes = {
            '/': TestPage,
        };
        M.route.route(Browser.document.body, '/', routes);
    }
}

Gives me:

➜ haxe build.hxml 
src/Main.hx:16: characters 13-25 : Could not find a suitable overload, reasons follow
src/Main.hx:16: characters 13-25 : Overload resolution failed for (selector : mithril._M.Either<String, mithril.Component>, attributes : Dynamic, children : Dynamic) -> mithril.Vnodes
src/Main.hx:16: characters 15-24 : Class<Component> should be mithril._M.Either<String, mithril.Component>
src/Main.hx:16: characters 15-24 : ... For function argument 'selector'
src/Main.hx:16: characters 13-25 : Overload resolution failed for (selector : mithril.Mithril) -> mithril.Vnodes
src/Main.hx:16: characters 15-24 : Class<Component> should be mithril.Mithril
src/Main.hx:16: characters 15-24 : ... For function argument 'selector'
src/Main.hx:16: characters 13-25 : End of overload failure reasons

I feel like I ran into this before, but I don't remember what the fix was :(

Not insurmountable, I can just change all the components in my code into instantiated objects rather than static classes, but I wish I knew why that stopped working :/

ciscoheat commented 3 years ago

The route method wants a Component, not a Class<Component>, which is what you're passing to it when referencing to the class directly. It must be instantiated, which is also essential in ModuleBuilder.hx that uses some code injection with this.

hamaluik commented 3 years ago

The route method is fine, it's the m() method that is causing me grief now.. it used to work fine with Haxe 4.1 though :/

I guess I was just abusing something without realizing.