Flow: The @JavaScript annotation should explain that it's included in a module scope

Created on 8 May 2020  路  8Comments  路  Source: vaadin/flow

In general, the following forum topic poses an interesting question:

https://vaadin.com/forum/thread/18116726/javascript-function-defined-in-jsfile-used-by-javascript-annotation-is-n

The question is: why does not @JavaScript() annotation run given javascript file in a global scope, but in a module scope? I think it's really important to document this straight in the @JavaScript annotation javadoc, since Java developers are usually not JavaScript developers.

- Vaadin / Flow version: 14.1.27
High Major bug documentation

All 8 comments

The documentation page at https://vaadin.com/docs/v14/flow/importing-dependencies/tutorial-importing.html even mentions that, quoting

use @JavaScript for importing plain .js files.

However, I have a @JavaScript annotation loading the following script:

function test(val){
    alert('Hi'+val);
}

I am not able to call that function simply via

UI.getCurrent().getPage().executeJs("test('User')");

So it just doesn't feel that @JavaScript imports plain .js files, or maybe I'm missing something.

The workaround is to use the following script:

window.test = function test(val){
    alert('Hi'+val);
}

Quoting Leif:

The confusion here is that @JavaScript pointing to a "local" file is included into the application bundle and thus loaded as a module, whereas @JavaScript pointing to a "remote" file is loaded on-the-fly as a regular script tag (i.e. no modules and no forced strict mode). This is a compromise that was done in an attempt to help with backwards compatibility, but it's starting to look like we didn't find a good balance.

Based on insights from the confusion caused by the current double role of @JavaScript, my suggestion today would be to deprecate @JavaScript and introducing a new annotation for explicitly loading something as a standalone file regardless of whether the URL is relative or absolute.

I tried a workaround: to load the script from src/main/webapp using the context:// URL however that did not work: https://github.com/vaadin/flow/issues/8290

Based on insights from the confusion caused by the current double role of @javascript, my suggestion today would be to deprecate @javascript and introducing a new annotation for explicitly loading something as a standalone file regardless of whether the URL is relative or absolute.

I'm not sure if it would help more to be able to configure the @JavaScript to be exported to global scope with an annotation, where the default would though be something weird as local files are module scope and external files global, so I guess that could be called "mixed" or something and the alternative would be "global".

However this ticket is about fixing the documentation and and adding a new annotation or modifying the existing one would be considered as a new feature.

What would be needed (as a separate ticket) is a way of explicitly choosing whether a local script file should be included in the bundle or loaded as a standalone <script> (i.e. no module scoping, no strict mode). The current approach that chooses based on the structure of the string defined for the annotation is very confusing, and even making workarounds difficult because of https://github.com/vaadin/flow/issues/8290.

Trying to work around this issue by calling Page.addJavaScript("./src/test.js") doesn't work: https://github.com/vaadin/flow/issues/8320

Luckily, placing the file into src/main/webapp/js/test.js and calling Page.addJavaScript("context://js/test.js") works :+1:

Was this page helpful?
0 / 5 - 0 ratings