fable-compiler / Fable

F# to JavaScript, TypeScript, Python, Rust and Dart Compiler
http://fable.io/
MIT License
2.93k stars 301 forks source link

Web components sample is broken with Fable3 #2327

Closed OnurGumus closed 3 years ago

OnurGumus commented 3 years ago

Hello, Earlier I have seen observed, https://fable.io/repl/ was pointing to Fable2 and https://fable.io/repl3/ was pointing Fable3. Now I am observing https://fable.io/repl/ is also pointing to Fable3. As you would remember I have made blog post about a sample web component:

https://onurgumus.github.io/2020/11/25/Fable-Web-Components.html

I am seeing 2 issues with Fable3 repl. At line 96 I import entire bulma as a string, but with Repl3 this causes

Failed to compile Assemblies couldn't be loaded. Some firewalls prevent download of binary files, please check.

because of that line. You can see the sample here: sample

Second issue is more compiler related. Basically I am extending a class with global attribute, in the sample HtmlElement class which is in another module.

But Fable3 generates

export class ModalWindow_ModalWindow extends WebComponent_HTMLElement

Since HTMLElement is global class it complains WebComponent_HTMLElement not found. This was also working fine with Fable2. I would expect Fable not to include the module names when the class is a global one.

OnurGumus commented 3 years ago

A more isolated case for the second problem:


open Fable.Core

module Bar =
    [<Global>]
    type HTMLElement() = class end

open Bar
    type ModalWindow()  =
        inherit HTMLElement()

And generated output

import { class_type } from "fable-library/Reflection.js";

export class ModalWindow extends Bar_HTMLElement {
    constructor() {
        super();
    }
}

export function ModalWindow$reflection() {
    return class_type("Test.ModalWindow", void 0, ModalWindow, class_type("Test.Bar.HTMLElement"));
}

export function ModalWindow_$ctor() {
    return new ModalWindow();
}
alfonsogarciacaro commented 3 years ago

Thanks @OnurGumus! The first issue only happens in the REPL right? Looking at the browser console, it seems this is a stack overflow error. It goes away when replacing the bulma styles with an empty string. I'm assuming there's a tail-call optimization in the parser that's not working properly in the repl.

About the second issue, it should be fixed with Fable 3.0.5, can you please try? Also, for cases similar to yours where you need to declare a class that needs to be used from JS I've added the AttachMembers attribute (included in Fable.Core 3.2.2). This will attach all members, including static, to the type as in a "standard" JS declaration. So:

[<AttachMembers>]
type MinStack() =
    let inner = createMinStack()
    member _.push(a) = push(inner, a)
    member _.pop() = pop(inner)
    member _.top() = top(inner)
    member _.getMin() = getMin(inner)

Becomes:

  export class MinStack{
    constructor(){
      this.inner = createMinStack()
    }
    push(a){ push(this.inner, a) }
    pop(){ pop(this.inner) }
    top(){ return top(this.inner) }
    getMin(){ return getMin(this.inner) }
  }
ncave commented 3 years ago

@alfonsogarciacaro For me the first issue only happens on Firefox, works fine on Chrome.

alfonsogarciacaro commented 3 years ago

Thanks for checking @ncave! Interesting, I do see the error in Chrome. Maybe you have some different settings (a bigger call stack limit for V8 in Chrome) or a more powerful machine than mine :)

image

We could try to run this with a non-minified version of the REPL to get a better stack trace. By the way, there are other errors reported for the REPL like #2316, so maybe there's an issue in Fable self-compilation that we haven't managed to spot.

alfonsogarciacaro commented 3 years ago

I will try to do it myself, but just to let you know this is how you can run a non-minified version of the REPL.

  1. In this repo, run: dotnet fsi build.fsx compiler-js --no-minify
  2. In the repl repo (pun unintended), run: LOCAL_PKG=1 ./fake.sh build -t WatchApp

The second point assumes Fable is in a sibling folder, but you can check where METADATA_LIB and STANDALONE_DIST are defined in the repl build.fsx and change that.

ncave commented 3 years ago

@alfonsogarciacaro I already tried with a non-minified version of fable-compiler-js (Node.js v14), it Works Fine On My Machine ™.

I wonder if down-transpiling to ES5 before minification will help the Firefox performance.

OnurGumus commented 3 years ago

I confirm the second case is fixed with 3.0.5.

I wonder if I can keep my blog post demo online. Is it possible if we could have Repl for Fable2 alive somewhere? (I think it's a good idea since a lot of people still relies on Fable2). Otherwise we need to update Repl to 3.0.5 and find a solution or workaround to above problem.

alfonsogarciacaro commented 3 years ago

Ok, I will do both :) Update repl to 3.0.5 and put back repl2 in fable.io/repl2

OnurGumus commented 3 years ago

Hello, @alfonsogarciacaro is repl2 up somewhere?

alfonsogarciacaro commented 3 years ago

Sorry @OnurGumus, forgot about this! 😅 You should be able to find repl2 in https://fable.io/repl2/ now. Please clear the cache if you have issues.

@ncave One benefit of having the two repls up is we can easily make performance comparisons. I'm actually not seeing a big difference in the Raytracer, it was already slower in Firefox for Fable 2.

OnurGumus commented 3 years ago

Thanks. Closing the issue as I have nothing else to ask.