Skip to content

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

Open
Artur- wants to merge 1 commit into
mainfrom
javascript-type-module-attribute
Open

feat: add type attribute to @JavaScript for runtime ES modules#24239
Artur- wants to merge 1 commit into
mainfrom
javascript-type-module-attribute

Conversation

@Artur-

@Artur- Artur- commented May 1, 2026

Copy link
Copy Markdown
Member

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

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown

Test Results

 1 449 files  ±0   1 449 suites  ±0   1h 23m 57s ⏱️ +16s
10 228 tests +1  10 160 ✅ +1  68 💤 ±0  0 ❌ ±0 
10 700 runs  +1  10 631 ✅ +1  69 💤 ±0  0 ❌ ±0 

Results for commit 23c5685. ± Comparison against base commit d76411c.

♻️ This comment has been updated with latest results.

@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-

Artur- commented May 8, 2026

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented May 8, 2026

Copy link
Copy Markdown
Contributor

@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

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 92e8c6a to 23c5685 Compare June 13, 2026 17:16
@sonarqubecloud

Copy link
Copy Markdown

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