Skip to content

feat: add type attribute to @JavaScript for runtime ES modules#24239

Open
Artur- wants to merge 3 commits intomainfrom
javascript-type-module-attribute
Open

feat: add type attribute to @JavaScript for runtime ES modules#24239
Artur- wants to merge 3 commits intomainfrom
javascript-type-module-attribute

Conversation

@Artur-
Copy link
Copy Markdown
Member

@Artur- Artur- commented May 1, 2026

Lets a @javascript annotation render as a <script type="module"> tag instead of a classic <script>, so hand-authored or CDN-hosted ESmodules can be loaded at runtime through annotations without going through Vite. For build-time bundled ES modules @jsmodule remains the right tool.

The new @JavaScript.Type enum has values SCRIPT (default, current behavior) and MODULE. The annotation gains a type() attribute that selects between them.

To make @javascript the unified entry point on the programmatic side as well, this commit also:

  • adds a new Page.addJavaScript(String url, LoadMode loadMode, JavaScript.Type type) overload that handles both classic <script> and <script type="module"> tags, with full LoadMode support for both;
  • delegates the existing addJavaScript(String, LoadMode) and addJavaScript(String) overloads to the new method with
    Type.SCRIPT;
  • deprecates Page.addJsModule(String) — recommend addJavaScript(url, loadMode, Type.MODULE) instead. The deprecated method keeps working for backwards compatibility.

UIInternals.addExternalDependencies routes both @javascript runtime values and external @jsmodule values through the new addJavaScript overload. @javascript values pass js.loadMode() and js.type() straight through, so type=MODULE supports LAZY and INLINE load modes just like type=SCRIPT.

FrontendClassVisitor.JSAnnotationVisitor reads the type enum via a new visitEnum override and skips MODULE-typed values from the bundle imports collection. The type attribute does not exist on @jsmodule, so visitEnum is a no-op for it.

Existing @javascript usages keep their behavior: bare relative values default to type=SCRIPT and continue to bundle (legacy interpretation), external URLs continue to render as runtime <script> tags.

@github-actions github-actions Bot added the +0.1.0 label May 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 1, 2026

Test Results

 1 405 files  ±0   1 405 suites  ±0   1h 21m 6s ⏱️ -45s
10 137 tests +1  10 067 ✅ +1  70 💤 ±0  0 ❌ ±0 
10 612 runs  +1  10 533 ✅ +1  79 💤 ±0  0 ❌ ±0 

Results for commit 9bd36c2. ± Comparison against base commit 28e1cc9.

♻️ This comment has been updated with latest results.

Lets a @javascript annotation render as a <script type="module"> tag
instead of a classic <script>, so hand-authored or CDN-hosted ES
modules can be loaded at runtime through annotations without going
through Vite. For build-time bundled ES modules @jsmodule remains the
right tool.

The new @JavaScript.Type enum has values SCRIPT (default, current
behavior) and MODULE. The annotation gains a type() attribute that
selects between them.

To make @javascript the unified entry point on the programmatic side
as well, this commit also:
- adds a new Page.addJavaScript(String url, LoadMode loadMode,
  JavaScript.Type type) overload that handles both classic <script>
  and <script type="module"> tags, with full LoadMode support for
  both;
- delegates the existing addJavaScript(String, LoadMode) and
  addJavaScript(String) overloads to the new method with
  Type.SCRIPT;
- deprecates Page.addJsModule(String) — recommend
  addJavaScript(url, loadMode, Type.MODULE) instead. The deprecated
  method keeps working for backwards compatibility.

UIInternals.addExternalDependencies routes both @javascript runtime
values and external @jsmodule values through the new addJavaScript
overload. @javascript values pass js.loadMode() and js.type()
straight through, so type=MODULE supports LAZY and INLINE load modes
just like type=SCRIPT.

FrontendClassVisitor.JSAnnotationVisitor reads the type enum via a
new visitEnum override and skips MODULE-typed values from the bundle
imports collection. The type attribute does not exist on @jsmodule,
so visitEnum is a no-op for it.

Existing @javascript usages keep their behavior: bare relative values
default to type=SCRIPT and continue to bundle (legacy interpretation),
external URLs continue to render as runtime <script> tags.
@Artur- Artur- force-pushed the javascript-type-module-attribute branch from 3dbfcf3 to f9e8620 Compare May 4, 2026 07:19
@Artur- Artur- marked this pull request as ready for review May 4, 2026 07:19
@mshabarov mshabarov requested a review from platosha May 4, 2026 11:38
@Artur-
Copy link
Copy Markdown
Member Author

Artur- commented May 8, 2026

@copilot resolve the merge conflicts in this pull request

…e-attribute

# Conflicts:
#	flow-server/src/main/java/com/vaadin/flow/component/internal/UIInternals.java

Co-authored-by: Artur- <260340+Artur-@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 8, 2026

@copilot resolve the merge conflicts in this pull request

Done — I merged the latest main into this branch and resolved the conflict in UIInternals. The fix is in commit 9bd36c2.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • maven.vaadin.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/flow/flow org.codehaus.plexus.classworlds.launcher.Launcher -pl flow-server,flow-build-tools -Dtest=JavaScriptBootstrapUITest,FrontendDependenciesTest test -DskipITs (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/flow/flow org.codehaus.plexus.classworlds.launcher.Launcher -pl flow-server -Dtest=JavaScriptBootstrapUITest,UIRouterStateSignalTest test -DskipITs (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of Artur- May 8, 2026 12:32
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 8, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants