Skip to content

JavaScript port: emit a bundle that is ready to deploy as-is#5466

Merged
shai-almog merged 7 commits into
masterfrom
fix/js-port-prune-demo-assets
Jul 25, 2026
Merged

JavaScript port: emit a bundle that is ready to deploy as-is#5466
shai-almog merged 7 commits into
masterfrom
fix/js-port-prune-demo-assets

Conversation

@shai-almog

@shai-almog shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #5465 / #5457.

Since #5457, JavaScriptPort.jar carries webapp/ so off-repo builds can find port.js, and the translator copies that webapp into every app it builds. That made the port's public web root the de facto payload of every JavaScript app — and it turned out to contain the port test app's own fixtures, a video-capture stack no app asked for, developer diagnostics, and the app jar's Maven descriptors.

This PR makes the JavaScript build emit a tree you can deploy as-is: nothing in it is there by accident, and the zip unpacks straight into a web root.

Rebuilding a real app (the BuildCloud console) against it: 16 MB → 9.0 MB, with no change to what the app can do.


1. Native themes now actually work when you opt in

HTML5Implementation.resolveNativeThemeResource() picks a theme at runtime from the browser user agent plus the ios.themeMode / and.themeMode / nativeTheme / javascript.native.theme hints. The bundle only ever shipped three of the six themes it can resolve, so opting into modern silently fell back to the legacy theme instead of applying — the file simply wasn't there.

All six now ship, staged straight from Themes/ — the single source of truth kept in sync from the CSS sources by native-themes-sync.yml — the same way maven/ios folds iOSModernTheme.res into nativeios.jar and maven/javase copies the whole set onto its classpath. The webapp's own copies are excluded because they drift: its iPhoneTheme.res already differs from the one in Themes/.

Defaults are unchanged: with no theme hint the port still lands on android_holo_light.res for an Android user agent and iOS7Theme.res everywhere else, so existing screenshot baselines stay comparable.

2. Demo fixtures stay in the source tree

file size
leather.res 2.0 MB
theme.res (the port test app's own) 1.4 MB
chrome.res 760 KB
video.mp4 651 KB
Handlee-Regular.ttf 38 KB
tzone_theme.res 84 KB
Page.html, test.json ~1.4 KB combined

None is referenced by any class in the port or in CodenameOne core — I checked every name with fixed-string searches across Ports/JavaScriptPort/src/main/java and CodenameOne/src; zero hits. (Handlee-Regular.ttf appears only inside a Javadoc example in Font.java. The single mention of tzone_theme.res in the port is inside a comment — no resolution path yields it.)

assets/theme.res is worth calling out separately: real apps ship their own theme.res at the bundle root, and getResourceAsStream() deliberately prefers the root for theme.res / CN1Resource.res, so the webapp copy was never read (confirmed against a running app — the root one is fetched, this one never is) while keeping a shadowing hazard alive.

They are excluded from the jar and stay in the source tree, so in-repo builds and the javascript-screenshots suite still see them.

3. The media stack is opt-in, as its own error message always claimed

VideoJS.init() is called by HTML5Implementation.captureVideo() behind a try/catch that logs:

VideoJS is not loaded, using default captureVideo behaviour. Add the javascript.includeVideoJS build hint…

…but nothing on the build side ever implemented that hint, so every app paid 944 KB of video.js + RecordRTC whether or not it captured video. The hint is now honoured (javascript.includeVideoJS=true to bundle them).

samplerate.min.js (488 KB) is unconditional dead weight and is always dropped: nothing loads it by path. js/fontmetrics.js only probes for an already-defined Samplerate global ("use libsamplerate if it is available"), and no script tag, ScriptTool call or bridge ever defines one.

Reachability analysis can't gate either of these — HTML5Implementation references the media classes itself — which is why it's a build hint.

4. Developer diagnostics are behind a flag

vm_protocol.md and jso-bridge-dispatch-ids.txt were written into the app's public web root on every build.

Both are now written only under -Dparparvm.js.diagnostics=1 (or =true). JavascriptTargetIntegrationTest sets it, so the test that inspects them still does.

5. Maven descriptors no longer leak into the web root

The translator copies every non-class file out of the app jar, which included META-INF/maven/**/pom.xml, pom.properties and META-INF/MANIFEST.MF — publishing the app's group/artifact/version and its build metadata at a fetchable URL.

The filter is path-aware: it only skips these names when they sit under a META-INF directory, so an app resource that happens to be called pom.xml is still copied.

⚠️ 6. Compatibility change: the zip is now flat

The output zip no longer contains a top-level <MainClass>-js/ wrapper directory. Entries sit at the root, so unzip -d /var/www/app produces a working web root instead of one directory containing it.

This is the point of the PR — the previous layout forced every consumer to unwrap the bundle before serving it — but it will break deployment tooling that expects the wrapper, e.g. unzip … && cp -R <MainClass>-js/. dest/. The fix is to drop the wrapper hop. Flagging it for the release notes.

Also: force the jar to be recreated

Ant's <jar> treats an existing archive as up to date when it is newer than every input file. The include/exclude list lives in the POM, not in the inputs, so on an incremental build a change to it is silently ignored and a stale jar ships. This cost a full debugging cycle: the exclusions above appeared to do nothing until I noticed the inner jar was hours old. The task deletes the jar first now.

Verification

  • Jar inspected directly: 0 demo fixtures, all 6 native themes present.
  • A real app rebuilt against it (the BuildCloud console): 16 MB → 9.0 MB, renders with icons, theme and material icon font intact, all APIs 200, browser console clean.
  • Bundle contents cross-checked against a request log captured from the running console, so "unused" means observed unused, not assumed.

🤖 Generated with Claude Code

JavaScriptPort.jar carries webapp/ so off-repo builds can find port.js, and
the translator copies webapp/assets into every app it builds. That meant
~3.6MB of the port test app's own fixtures -- leather.res (2.1MB),
chrome.res (778KB), video.mp4 (666KB), Handlee-Regular.ttf, Page.html,
test.json -- landed in every JavaScript app's public web root. None of them
is referenced by any class in the port or in CodenameOne core.

Exclude them from the jar. They stay in the source tree, so in-repo builds
and the javascript-screenshots suite still see them. The system themes
HTML5Implementation.getNativeTheme() resolves (iOS7Theme.res,
iPhoneTheme.res, iOSModernTheme.res, android_holo_light.res,
tzone_theme.res) and CN1Resource.res are kept.

Also delete the jar before rebuilding it: Ant's jar task treats an existing
archive as up to date when it is newer than every input file, so on an
incremental build a change to this include/exclude list is silently ignored
and a stale jar ships. That cost a full debugging cycle here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 11:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces the default output size of JavaScript builds by preventing the JavaScript port’s demo/test fixture assets from being bundled into JavaScriptPort.jar, which the translator then propagates into every JavaScript app’s public web root. It also makes the jar packaging step robust for incremental builds by forcing the jar to be recreated when include/exclude rules change.

Changes:

  • Delete the previously-built JavaScriptPort.jar before running Ant’s <jar> task to avoid stale archives on incremental builds.
  • Exclude large demo/test fixture files (e.g., leather.res, chrome.res, video.mp4) from the webapp/assets content that gets embedded into JavaScriptPort.jar.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread maven/parparvm/pom.xml Outdated
Comment on lines +239 to +242
The system themes assets/ must keep are the ones
HTML5Implementation.getNativeTheme() resolves:
iOS7Theme.res, iPhoneTheme.res, iOSModernTheme.res,
android_holo_light.res and tzone_theme.res. -->

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, and already fixed — that comment was rewritten a few commits ago. It now names installNativeTheme() (for what the bundle must contain) and resolveNativeThemeResource() (for what picks between them at runtime). No getNativeTheme() left in the tree.

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [HTML preview] [Download]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 1 findings (Normal: 1)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

assets/theme.res is the port test app's theme (1.4MB). Real apps ship their
own theme.res at the bundle root and getResourceAsStream() deliberately
prefers the root copy for theme.res / CN1Resource.res, so this one is never
read -- confirmed against a running app, whose request log shows the root
theme.res fetched and this one never touched. Shipping it also kept a
shadowing hazard alive for no benefit.

assets/tzone_theme.res is returned by no code path: getNativeTheme() only
ever yields iOS7Theme / iPhoneTheme / iOSModernTheme / android_holo_light /
AndroidMaterialTheme / androidTheme. The single mention of tzone_theme in
the port is inside a comment, which is exactly why it survived the first
pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

maven/parparvm/pom.xml:242

  • The comment listing the “system themes assets/ must keep” includes tzone_theme.res, but the JS port’s theme selection doesn’t return that resource. In Ports/JavaScriptPort/.../HTML5Implementation.java, resolveNativeThemeResource() returns only iOS7/iPhone/iOSModern/AndroidMaterial/android_holo_light/androidTheme (see ~4092-4147), so this list is misleading and contradicts the later exclusion of assets/tzone_theme.res. Update the comment to reflect the actual set of themes that may be loaded.
                                             The system themes assets/ must keep are the ones
                                             HTML5Implementation.getNativeTheme() resolves:
                                             iOS7Theme.res, iPhoneTheme.res, iOSModernTheme.res,
                                             android_holo_light.res and tzone_theme.res. -->

maven/parparvm/pom.xml:261

  • This exclusion rationale refers to getNativeTheme(), but there is no getNativeTheme() in the JavaScript port; theme selection is performed by HTML5Implementation.resolveNativeThemeResource() (called from installNativeTheme()). Updating this comment will avoid confusion when someone tries to audit which themes must remain bundled.
                                        <!-- No code path returns tzone_theme.res: getNativeTheme()
                                             only ever yields iOS7Theme / iPhoneTheme /
                                             iOSModernTheme / android_holo_light /
                                             AndroidMaterialTheme / androidTheme. The one mention of
                                             tzone_theme in the port is inside a comment. -->

I had described iOS7Theme/iPhoneTheme/android_holo_light as "the themes
getNativeTheme() resolves" and listed iOSModernTheme among them. That
misread installNativeTheme(): the JS port defaults to the LEGACY pair
(android_holo_light on an Android user agent, iOS7Theme elsewhere) so
existing screenshot baselines stay comparable, and the modern themes are
opt-in via ios.themeMode / and.themeMode / nativeTheme /
javascript.native.theme. The modern .res files live in Themes/ and are
staged per target, not from webapp/assets.

No functional change: the same files are excluded and the same ones kept.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 11:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

maven/parparvm/pom.xml:243

  • PR description says the bundle keeps tzone_theme.res and theme.res, but this POM change explicitly excludes both (assets/theme.res and assets/tzone_theme.res). Either the description/kept list is outdated, or these excludes are too aggressive. Please align the PR description and/or the inline comment here so it’s clear which themes/resources are intentionally retained vs excluded (and why).
                                             Kept: the native themes installNativeTheme() can open
                                             from the bundle. The JS port defaults to the LEGACY
                                             pair (android_holo_light.res on an Android user agent,
                                             iOS7Theme.res elsewhere) so existing screenshot
                                             baselines stay comparable; iPhoneTheme.res is the

HTML5Implementation.resolveNativeThemeResource() can return six themes --
iOS7Theme, iPhoneTheme, iOSModernTheme, androidTheme, android_holo_light,
AndroidMaterialTheme -- but the bundle only carried three of them, so
setting ios.themeMode / and.themeMode / nativeTheme /
javascript.native.theme to anything modern (or to legacy on Android) hit
the catch in installNativeTheme() and silently fell back to the legacy
theme. The modern themes postdate the old TeaVM port; the ParparVM port
never grew the wiring the other targets have.

The build cannot pick one of the six: resolveNativeThemeResource() decides
at RUNTIME from the browser user agent, so "modern" means iOSModernTheme
in an iOS-like browser and AndroidMaterialTheme everywhere else. Ship the
whole set instead.

Take them from Themes/, the single source of truth kept in sync from the
CSS sources by native-themes-sync.yml, the same way maven/ios folds
iOSModernTheme.res into nativeios.jar and maven/javase copies the set onto
its classpath -- rather than from the port's own copies under
webapp/assets, which drift: the webapp's iPhoneTheme.res was already a
stale version of the Themes/ one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 12:11
@shai-almog shai-almog changed the title Keep the JavaScript port's demo fixtures out of every app's bundle JavaScript port: wire the native themes from Themes/, drop unused demo fixtures Jul 25, 2026
@shai-almog

Copy link
Copy Markdown
Collaborator Author

Scope grew after review feedback — this now fixes a real bug, not just bloat.

The modern native themes were never wired up on the JavaScript port. They postdate the old TeaVM port, and the ParparVM port never grew the staging the other targets have. HTML5Implementation.resolveNativeThemeResource() can return six themes, but the bundle shipped three, so setting ios.themeMode / and.themeMode / nativeTheme / javascript.native.theme to anything modern — or to legacy on Android, which needs androidTheme.res — hit the catch in installNativeTheme() and silently fell back to the legacy theme.

Note the build cannot stage just the one an app needs: resolveNativeThemeResource() decides at runtime from the browser user agent, so modern resolves to iOSModernTheme.res in an iOS-like browser and AndroidMaterialTheme.res everywhere else. The whole set has to be present.

They now come from Themes/ — the single source of truth synced by native-themes-sync.yml — mirroring maven/ios folding iOSModernTheme.res into nativeios.jar and maven/javase copying the set onto its classpath. That also fixes a second problem: the port's own copies under webapp/assets/ drift, and iPhoneTheme.res there was already stale relative to Themes/.

Net size: the six themes add ~780KB versus the three stale copies, and removing the demo fixtures takes ~3.6MB off, so a JavaScript bundle still ends up substantially smaller than before.

I also closed #5468, which I had filed claiming the modern path was broken by default. That was wrong — legacy is the intended default, to keep screenshot baselines comparable. The real defect is the one fixed here: the opt-in never worked.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

maven/parparvm/pom.xml:263

  • This change excludes assets/tzone_theme.res from the shipped JavaScriptPort.jar, but (a) the PR description says it is kept, and (b) apps can still explicitly request it via Display property javascript.native.theme. With this exclusion, that explicit selection will now fall back to the legacy theme at runtime.
                                        <!-- No theme-resolution path yields tzone_theme.res; the one
                                             mention of it in the port is inside a comment. -->
                                        <exclude name="assets/tzone_theme.res"/>

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 151 screenshots: 151 matched.

Native Android coverage

  • 📊 Line coverage: 8.37% (7322/87435 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.26% (38206/462263), branch 3.02% (1310/43428), complexity 3.29% (1571/47783), method 4.94% (1275/25820), class 10.04% (349/3475)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/551 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 8.37% (7322/87435 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.26% (38206/462263), branch 3.02% (1310/43428), complexity 3.29% (1571/47783), method 4.94% (1275/25820), class 10.04% (349/3475)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/551 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 229ms / native 124ms = 1.8x speedup
SIMD float-mul (64K x300) java 129ms / native 79ms = 1.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 71.000 ms
Base64 CN1 decode 65.000 ms
Base64 native encode 398.000 ms
Base64 encode ratio (CN1/native) 0.178x (82.2% faster)
Base64 native decode 301.000 ms
Base64 decode ratio (CN1/native) 0.216x (78.4% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 144 screenshots: 144 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 149 screenshots: 149 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 326 seconds

Build and Run Timing

Metric Duration
Simulator Boot 61000 ms
Simulator Boot (Run) 1000 ms
App Install 15000 ms
App Launch 2000 ms
Test Execution 797000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 77ms / native 4ms = 19.2x speedup
SIMD float-mul (64K x300) java 322ms / native 3ms = 107.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 241.000 ms
Base64 CN1 decode 189.000 ms
Base64 native encode 369.000 ms
Base64 encode ratio (CN1/native) 0.653x (34.7% faster)
Base64 native decode 513.000 ms
Base64 decode ratio (CN1/native) 0.368x (63.2% faster)
Base64 SIMD encode 66.000 ms
Base64 encode ratio (SIMD/CN1) 0.274x (72.6% faster)
Base64 SIMD decode 117.000 ms
Base64 decode ratio (SIMD/CN1) 0.619x (38.1% faster)
Base64 encode ratio (SIMD/native) 0.179x (82.1% faster)
Base64 decode ratio (SIMD/native) 0.228x (77.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 8.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.250x (75.0% faster)
Image applyMask (SIMD off) 42.000 ms
Image applyMask (SIMD on) 36.000 ms
Image applyMask ratio (SIMD on/off) 0.857x (14.3% faster)
Image modifyAlpha (SIMD off) 43.000 ms
Image modifyAlpha (SIMD on) 73.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.698x (69.8% slower)
Image modifyAlpha removeColor (SIMD off) 48.000 ms
Image modifyAlpha removeColor (SIMD on) 72.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.500x (50.0% slower)

The bundle is meant to be unpacked straight into a web root, but two things
made every consumer post-process it first.

Zip the dist FLAT. zipDirectory() was passed the dist directory's own name as
the zip root, so everything landed under "<MainClass>-js/" and had to be
flattened before it could be served. The old cloud/TeaVM bundle was flat, so
this also lets one deployment script handle both.

Stop copying build descriptors into the bundle. ByteCodeTranslator copies
every non-class input file into the output by basename, so a Maven-built app
leaks META-INF/maven/**/pom.xml -- dependency list and all -- plus
pom.properties and MANIFEST.MF. Harmless for the iOS target, where the output
is a source tree; for the JavaScript target that output IS a public document
root. None of them is an application resource.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 12:47
@shai-almog

Copy link
Copy Markdown
Collaborator Author

Two more build-side fixes, prompted by the fair question of why a consumer should have to post-process the bundle at all. The JavaScript build is supposed to hand back something deployable as-is, and it wasn't.

1. The zip is now flat. zipDirectory() was passed the dist directory's own name as the zip root, so everything landed under <MainClass>-js/ and every consumer had to flatten it before serving. The old cloud/TeaVM bundle was flat, so this also means one deployment script can handle both.

2. Build descriptors no longer leak into the bundle. ByteCodeTranslator copies every non-class input file into the output by basename, so a Maven-built app's META-INF/maven/**/pom.xml — dependency list and all — plus pom.properties and MANIFEST.MF ended up in the bundle root. That is harmless for the iOS target, where the output is a source tree, but for JavaScript the output is a public document root. None of them is an application resource.

Both were being worked around downstream; that workaround is now deleted.

Two things I deliberately did not change, since they look intentional and you'd know better:

  • vm_protocol.md and jso-bridge-dispatch-ids.txt are still emitted into the dist. JavascriptTargetIntegrationTest asserts the former ("Translator should emit the VM protocol contract artifact"), so it is a deliberate contract artifact; nothing reads the latter. They are developer artifacts on a public web root, so they arguably belong beside the dist rather than inside it — but that is test-encoded intent, not mine to flip.
  • The media stack (js/videojs/, js/samplerate.min.js, ~1.4MB) ships unconditionally. Only the Media/Capture APIs use it. The translator already computes reachability for the RTA pass, so it could include it only when those classes survive culling — that would drop another 1.4MB from most bundles. Happy to look at that separately if it's worth doing.

Verified end to end after both changes: the bundle unzips straight into a web root, the console renders, all APIs return 200, and a request log from the running app matches the shipped file list exactly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment on lines +1212 to +1227
* @param i source
* @param o destination
*/
/**
* Build descriptors that ride along inside an application jar's META-INF
* but are not application resources. Every non-class input file is copied
* into the output by basename, so without this filter a Maven-built app
* leaks its pom.xml (dependency list and all), pom.properties and
* MANIFEST.MF into the bundle -- and for the JavaScript target that bundle
* IS a public document root.
*/
private static boolean isBuildMetadata(String name) {
return "pom.xml".equals(name)
|| "pom.properties".equals(name)
|| "MANIFEST.MF".equals(name);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. isBuildMetadata() now sits above the Javadoc block, so @param i / @param o reattach to copy(InputStream, OutputStream).

Parser.parse(f);
} else {
if(!f.isDirectory()) {
if(!f.isDirectory() && !isBuildMetadata(f.getName())) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the predicate is path-aware now. It walks up the parents and only returns true when the file sits under a META-INF directory, so an app resource that happens to be named pom.xml is still copied.

Comment thread maven/parparvm/pom.xml
Comment on lines +261 to +263
<!-- No theme-resolution path yields tzone_theme.res; the one
mention of it in the port is inside a comment. -->
<exclude name="assets/tzone_theme.res"/>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option (a). tzone_theme.res is genuinely not shipped and no runtime path can select it — its only mention in the port is inside a comment. The PR description was stale; it has been rewritten and now lists the file among the excluded fixtures with that reasoning.

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • Tests: 410 total, 0 failed, 14 skipped

Benchmark Results

  • Execution Time: 27185 ms

  • Hotspots (Top 20 sampled methods):

    • 22.60% java.util.ArrayList.indexOf (493 samples)
    • 5.78% com.codename1.tools.translator.BytecodeMethod.addToConstantPool (126 samples)
    • 4.86% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (106 samples)
    • 3.35% java.lang.StringBuilder.append (73 samples)
    • 2.75% com.codename1.tools.translator.Parser.cn1EnsureSubclassIndex (60 samples)
    • 2.75% com.codename1.tools.translator.BytecodeMethod.optimize (60 samples)
    • 2.66% org.objectweb.asm.tree.analysis.Analyzer.analyze (58 samples)
    • 2.15% com.codename1.tools.translator.Parser.generateClassAndMethodIndexHeader (47 samples)
    • 1.88% com.codename1.tools.translator.Parser.classIndex (41 samples)
    • 1.65% org.objectweb.asm.tree.analysis.Analyzer.findSubroutine (36 samples)
    • 1.42% java.lang.System.identityHashCode (31 samples)
    • 1.33% com.codename1.tools.translator.BytecodeMethod.appendCMethodPrefix (29 samples)
    • 1.19% java.lang.Object.hashCode (26 samples)
    • 1.15% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (25 samples)
    • 1.10% org.objectweb.asm.ClassReader.readCode (24 samples)
    • 1.05% java.lang.StringCoding.encode (23 samples)
    • 0.96% com.codename1.tools.translator.ByteCodeClass.findDeclaredMethod (21 samples)
    • 0.96% java.util.HashMap.hash (21 samples)
    • 0.92% java.lang.String.equals (20 samples)
    • 0.87% com.codename1.tools.translator.Parser.resolveDupForms (19 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 146 screenshots: 146 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 80ms / native 4ms = 20.0x speedup
SIMD float-mul (64K x300) java 59ms / native 3ms = 19.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 197.000 ms
Base64 CN1 decode 120.000 ms
Base64 SIMD encode 99.000 ms
Base64 encode ratio (SIMD/CN1) 0.503x (49.7% faster)
Base64 SIMD decode 82.000 ms
Base64 decode ratio (SIMD/CN1) 0.683x (31.7% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 21.000 ms
Image createMask (SIMD on) 15.000 ms
Image createMask ratio (SIMD on/off) 0.714x (28.6% faster)
Image applyMask (SIMD off) 40.000 ms
Image applyMask (SIMD on) 155.000 ms
Image applyMask ratio (SIMD on/off) 3.875x (287.5% slower)
Image modifyAlpha (SIMD off) 31.000 ms
Image modifyAlpha (SIMD on) 26.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.839x (16.1% faster)
Image modifyAlpha removeColor (SIMD off) 37.000 ms
Image modifyAlpha removeColor (SIMD on) 26.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.703x (29.7% faster)

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 217 screenshots: 217 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 146 screenshots: 146 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 56ms / native 3ms = 18.6x speedup
SIMD float-mul (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 246.000 ms
Base64 CN1 decode 130.000 ms
Base64 SIMD encode 65.000 ms
Base64 encode ratio (SIMD/CN1) 0.264x (73.6% faster)
Base64 SIMD decode 57.000 ms
Base64 decode ratio (SIMD/CN1) 0.438x (56.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 13.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.692x (30.8% faster)
Image applyMask (SIMD off) 27.000 ms
Image applyMask (SIMD on) 20.000 ms
Image applyMask ratio (SIMD on/off) 0.741x (25.9% faster)
Image modifyAlpha (SIMD off) 16.000 ms
Image modifyAlpha (SIMD on) 13.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.813x (18.8% faster)
Image modifyAlpha removeColor (SIMD off) 19.000 ms
Image modifyAlpha removeColor (SIMD on) 13.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.684x (31.6% faster)

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 148 screenshots: 148 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 248 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 79ms / native 4ms = 19.7x speedup
SIMD float-mul (64K x300) java 106ms / native 5ms = 21.2x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 181.000 ms
Base64 CN1 decode 135.000 ms
Base64 native encode 936.000 ms
Base64 encode ratio (CN1/native) 0.193x (80.7% faster)
Base64 native decode 366.000 ms
Base64 decode ratio (CN1/native) 0.369x (63.1% faster)
Base64 SIMD encode 55.000 ms
Base64 encode ratio (SIMD/CN1) 0.304x (69.6% faster)
Base64 SIMD decode 49.000 ms
Base64 decode ratio (SIMD/CN1) 0.363x (63.7% faster)
Base64 encode ratio (SIMD/native) 0.059x (94.1% faster)
Base64 decode ratio (SIMD/native) 0.134x (86.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 5.000 ms
Image createMask ratio (SIMD on/off) 0.455x (54.5% faster)
Image applyMask (SIMD off) 92.000 ms
Image applyMask (SIMD on) 62.000 ms
Image applyMask ratio (SIMD on/off) 0.674x (32.6% faster)
Image modifyAlpha (SIMD off) 46.000 ms
Image modifyAlpha (SIMD on) 39.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.848x (15.2% faster)
Image modifyAlpha removeColor (SIMD off) 42.000 ms
Image modifyAlpha removeColor (SIMD on) 41.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.976x (2.4% faster)

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 146 screenshots: 146 matched.
Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 62ms / native 5ms = 12.4x speedup
SIMD float-mul (64K x300) java 62ms / native 5ms = 12.4x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 199.000 ms
Base64 CN1 decode 126.000 ms
Base64 SIMD encode 101.000 ms
Base64 encode ratio (SIMD/CN1) 0.508x (49.2% faster)
Base64 SIMD decode 93.000 ms
Base64 decode ratio (SIMD/CN1) 0.738x (26.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 24.000 ms
Image createMask (SIMD on) 19.000 ms
Image createMask ratio (SIMD on/off) 0.792x (20.8% faster)
Image applyMask (SIMD off) 54.000 ms
Image applyMask (SIMD on) 48.000 ms
Image applyMask ratio (SIMD on/off) 0.889x (11.1% faster)
Image modifyAlpha (SIMD off) 47.000 ms
Image modifyAlpha (SIMD on) 47.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.000x (0.0% slower)
Image modifyAlpha removeColor (SIMD off) 57.000 ms
Image modifyAlpha removeColor (SIMD on) 193.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 3.386x (238.6% slower)

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 147 screenshots: 147 matched.
Native Linux port (x64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub x64 runner. Baseline: scripts/linux/screenshots.

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 147 screenshots: 147 matched.
Native Linux port (arm64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub arm64 runner. Baseline: scripts/linux/screenshots-arm.

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 181 screenshots: 181 matched.
✅ JavaScript-port screenshot tests passed.

Three artifacts shipped in every JavaScript app that should not have.

video.js + RecordRTC (~944KB) were already meant to be opt-in. VideoJS is
only ever reached from HTML5Implementation.captureVideo(), which calls
VideoJS.init() behind a try/catch and, when it fails, logs "VideoJS is not
loaded, using default captureVideo behaviour.  Add the
javascript.includeVideoJS build hint..." and falls back. The libraries are
lazy-loaded at runtime by ScriptTool. So the hint documented an opt-in that
nothing on the build side implemented: every app paid for the library
whether or not it captured video. Honour the hint.

samplerate.min.js (~485KB) is unconditional dead weight. Nothing loads it by
path; js/fontmetrics.js only probes for an already-defined Samplerate global
("use libsamplerate if it is available") and nothing ever defines one.

vm_protocol.md and jso-bridge-dispatch-ids.txt are developer artifacts, and
the translator's output directory becomes the app's PUBLIC web root.
vm_protocol.md documents the worker boundary and is checked in under
vm/ByteCodeTranslator/src/javascript/, so copying it into every deployed app
published documentation nobody reads from there.
jso-bridge-dispatch-ids.txt is a sidecar for the dispatch-id mangler, which
is opt-in and off by default (-Dparparvm.js.manglesigs=1); the class walk
that builds it is what the mangler needs, and nothing reads the emitted file
at all. Both now require -Dparparvm.js.diagnostics.

Note reachability cannot decide the media case: HTML5Implementation
references the media classes itself, so they survive culling even in an app
that plays and records nothing (HTML5MediaRecorder still had 129 references
in a console bundle). The build hint is the right gate.

The integration test opts into diagnostics so it still covers
vm_protocol.md; the core-slice test drops that assertion, since
translated_app.js already proves the translator ran.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 13:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Parser.parse(f);
} else {
if(!f.isDirectory()) {
if(!f.isDirectory() && !isBuildMetadata(f.getName())) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — see the reply on the other thread: the check now requires a META-INF ancestor, so only real jar metadata is skipped.

Comment on lines +1223 to +1226
private static boolean isBuildMetadata(String name) {
return "pom.xml".equals(name)
|| "pom.properties".equals(name)
|| "MANIFEST.MF".equals(name);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the filter now requires a META-INF ancestor rather than matching on basename alone.

Comment on lines +45 to +48
if (emitDiagnostics()) {
writeProtocol(outputDirectory);
writeJsoBridgeManifest(outputDirectory, classes);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. emitDiagnostics() parses the value and accepts 1 or true (case-insensitive) instead of merely checking for presence, so -Dparparvm.js.diagnostics= no longer turns diagnostics on.

Comment on lines +55 to +56
static boolean emitDiagnostics() {
return System.getProperty("parparvm.js.diagnostics") != null;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the property is parsed for 1/true now, matching the documented contract.

Comment thread maven/parparvm/pom.xml
Comment on lines +261 to +263
<!-- No theme-resolution path yields tzone_theme.res; the one
mention of it in the port is inside a comment. -->
<exclude name="assets/tzone_theme.res"/>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option (a): tzone_theme.res is genuinely not shipped, and the PR description was stale. Rewritten — the file is now listed among the excluded fixtures, with the reason: no theme-resolution path yields it, and its only mention in the port is inside a comment.

Comment thread maven/parparvm/pom.xml
Comment on lines +287 to +293
<zipfileset dir="${project.basedir}/../../Themes" prefix="webapp/assets">
<include name="iOS7Theme.res"/>
<include name="iPhoneTheme.res"/>
<include name="iOSModernTheme.res"/>
<include name="androidTheme.res"/>
<include name="android_holo_light.res"/>
<include name="AndroidMaterialTheme.res"/>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thread as above — description rewritten. tzone_theme.res is excluded on purpose and is now documented as excluded.

Comment on lines +171 to +175
// Zip the dist FLAT. The bundle is meant to be unpacked directly
// into a web root, so a "<MainClass>-js/" wrapper only forces every
// consumer to flatten it first. (The old cloud/TeaVM bundle was flat
// too, so this also keeps deployment scripts working across both.)
zipDirectory(distDir, jsOutputZip, null);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed it is compatibility-affecting, and it is deliberate: removing that wrapper hop is the point of this change — the build should hand back a tree you can serve, not one you have to unwrap first. I have not made it configurable, because a toggle would leave both layouts alive forever and consumers would have to handle each.

Instead the PR description now opens with a ⚠️ section calling it out explicitly, naming the pattern that breaks (unzip … && cp -R <MainClass>-js/. dest/) and the fix (drop the hop), so it can be lifted into the release notes.

Comment on lines +236 to +239
File samplerate = new File(js, "samplerate.min.js");
if (samplerate.isFile()) {
samplerate.delete();
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed for both deletions. samplerate.min.js checks the delete() return value, and the js/videojs tree is re-tested with exists() after delTree(). Either failure logs a WARNING: … it will ship in the bundle.

I kept it non-fatal deliberately: the consequence is a bundle carrying a dead file, which is not worth failing an otherwise good build over — but it will no longer happen silently.

@shai-almog

shai-almog commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 143 screenshots: 143 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 308 seconds

Build and Run Timing

Metric Duration
Simulator Boot 62000 ms
Simulator Boot (Run) 2000 ms
App Install 17000 ms
App Launch 3000 ms
Test Execution 955000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 72ms / native 3ms = 24.0x speedup
SIMD float-mul (64K x300) java 63ms / native 3ms = 21.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 231.000 ms
Base64 CN1 decode 451.000 ms
Base64 native encode 1056.000 ms
Base64 encode ratio (CN1/native) 0.219x (78.1% faster)
Base64 native decode 651.000 ms
Base64 decode ratio (CN1/native) 0.693x (30.7% faster)
Base64 SIMD encode 148.000 ms
Base64 encode ratio (SIMD/CN1) 0.641x (35.9% faster)
Base64 SIMD decode 82.000 ms
Base64 decode ratio (SIMD/CN1) 0.182x (81.8% faster)
Base64 encode ratio (SIMD/native) 0.140x (86.0% faster)
Base64 decode ratio (SIMD/native) 0.126x (87.4% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 10.000 ms
Image createMask (SIMD on) 5.000 ms
Image createMask ratio (SIMD on/off) 0.500x (50.0% faster)
Image applyMask (SIMD off) 127.000 ms
Image applyMask (SIMD on) 139.000 ms
Image applyMask ratio (SIMD on/off) 1.094x (9.4% slower)
Image modifyAlpha (SIMD off) 275.000 ms
Image modifyAlpha (SIMD on) 107.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.389x (61.1% faster)
Image modifyAlpha removeColor (SIMD off) 156.000 ms
Image modifyAlpha removeColor (SIMD on) 57.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.365x (63.5% faster)

- isBuildMetadata() is path-aware: it only skips pom.xml /
  pom.properties / MANIFEST.MF that sit under a META-INF directory,
  so an app resource that happens to carry one of those names is
  still copied into the bundle.
- Move the helper above copy()'s Javadoc; inserting it in between
  had detached the @param i / @param o lines from the method.
- emitDiagnostics() parses parparvm.js.diagnostics for 1/true rather
  than testing for presence, matching the documented contract.
- Report a failed prune instead of silently shipping the file: both
  js/videojs and js/samplerate.min.js verify the deletion happened
  and log a warning if it did not.
- Add the missing licence headers to JavascriptBundleWriter and
  JavascriptCn1CoreCompletenessTest (check-copyright-headers).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 16:04
@shai-almog shai-almog changed the title JavaScript port: wire the native themes from Themes/, drop unused demo fixtures JavaScript port: emit a bundle that is ready to deploy as-is Jul 25, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@shai-almog
shai-almog merged commit a4d13a5 into master Jul 25, 2026
48 checks passed
@shai-almog
shai-almog deleted the fix/js-port-prune-demo-assets branch July 25, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants