Fable: window / Option inconvenience

Created on 8 Mar 2018  路  9Comments  路  Source: fable-compiler/Fable

Description

This line:

let window = Browser.window

meant to eliminate repeating Browser.window get translated to var window = window which leaves us with local variable window set to undefined (I believe due to hoisting this assignment reference itself not a global window).

This line:

open Fable.Import.Browser

overrides (annoyingly) Option type, as there is actually Fable.Import.Browser.Option, so:

open Fable.Import.Browser
Some 7 |> Option.iter ignore

is a compilation error.

Repro code

open Fable.Import
let window = Browser.window
window.addEventListener_load (fun _ -> box ())
Some 7 |> Option.iter ignore

fails on runtime with (addEventListener is not a member of undefined).
NOTE: this code is valid if F# but window is a special name. It hits by surprise though. You cannot have a local variable called window and use Browser.window in the same scope.

open Fable.Import.Browser
window.addEventListener_load (fun _ -> box ())
Some 7 |> Option.iter ignore

does not compile.

Actual results

Runtime or compile time error.

Expected results

Both cases working fine :-)

Related information

  • Fable version (dotnet fable --version): 1.3.8
  • Operating system: Win10

Most helpful comment

Because I have CDO (it's a OCD, but alphabetically).
I found it polishing some code for presentation to make it more readable and fluent (subjective I know).
I had a button and a canvas so I wanted a window (not a Browser.window). So I've added open Fable.Import.Browser but all my Option.xxx stopped compiling at this point.

All 9 comments

Does this work? In that case, we can just add window to the list of JS keywords so Fable mangles it (actually it's already there but with the first letter in upper case):

open Fable.Import
let window = Browser.window
window.addEventListener_load (fun _ -> box ())
Some 7 |> Option.iter ignore

No. This part:

open Fable.Import
let window = Browser.window
window.addEventListener_load (fun _ -> box ())

gets translated to:

var window = window;
window.addEventListener("load", function (_arg1) {
  return null;
});

and fails to addEventListener as window is undefined.
var window = window causes window to be local not global and hoisted so it exists event before it's own declaration, so how javascript understands it is:

var window;
window = window;

This probably explains it better.

Anyway, yes: it should a mangled name (I guess global also deserves it then).

I ran into this today as well with let console = Fable.Import.JS.console.

I have a naive question, why do you create alias like that ?

I agree it's a bug and should be address just trying to understand the motivation :)

Because I have CDO (it's a OCD, but alphabetically).
I found it polishing some code for presentation to make it more readable and fluent (subjective I know).
I had a button and a canvas so I wanted a window (not a Browser.window). So I've added open Fable.Import.Browser but all my Option.xxx stopped compiling at this point.

I guess it's because opening Fable.Import.Browser shadows F# Option but it's painful to type Browser.window all the time.

I personally like to alias the module with a letter like module B = Fable.Import.Browser so you can do B.window and have autocompletion, but I know it's not everybody's cup of tea :)

Thanks for the explanation and I understand them :)

Can I ask for document and global? :-)

@MiloszKrajewski Sure! Can you please send a PR?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

forki picture forki  路  3Comments

funlambda picture funlambda  路  4Comments

MangelMaxime picture MangelMaxime  路  3Comments

SirUppyPancakes picture SirUppyPancakes  路  3Comments

et1975 picture et1975  路  3Comments