Skip to content

Declarative router + deep links + bytecode annotation framework#5037

Open
shai-almog wants to merge 10 commits into
masterfrom
feat/declarative-router-and-deep-links
Open

Declarative router + deep links + bytecode annotation framework#5037
shai-almog wants to merge 10 commits into
masterfrom
feat/declarative-router-and-deep-links

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

  • Optional declarative router in com.codename1.router (URL-based navigation, route guards, redirects, per-tab navigation shell, location listeners) layered on top of the existing Form infrastructure — Form.show() / showBack() continues to work unchanged.
  • Deep-link API: Display.setDeepLinkHandler(LinkHandler) receiving a normalized DeepLink (scheme/host/path/segments/query/fragment); auto-invoked for cold + warm launches. iOS / Android need no port changes — Display.setProperty("AppArg", url) now routes URL-shaped values through the handler.
  • Reusable bytecode annotation framework in the Codename One Maven plugin: a generic AnnotationProcessor SPI + two new Mojos (cn1:generate-annotation-stubs, cn1:process-annotations). ASM-scans target/classes, dispatches to every registered processor, fails-fast with a combined error list. Adding more annotations later is a matter of dropping a new processor into META-INF/services — no orchestrator changes.
  • First concrete processor: RouteAnnotationProcessor validates @Route("/path") classes (extends Form, non-empty path starting with /, accessible constructor, no duplicate patterns) and emits a RoutesIndex + RoutesIndex$Builder directly via ASM. No source-text regex; no runtime reflection.
  • Form.setPopGuard(PopGuard) (Flutter-PopScope analogue) honored from hardware back, toolbar back, and Router.pop().
  • Sheet.showForResult() returning an AsyncResource<T> that auto-cancels with null on dismiss.
  • TabsForm — a Form whose tabs each keep their own navigation stack.
  • iOS Universal Links / Android App Links JSON generators (AasaBuilder, AssetLinksBuilder).
  • JavaScript port window.history bridge: JsRouterBootstrap + standalone cn1-router-history.js shim.

Docs

Two new pages under docs/developer-guide/, both wired into the master developer-guide.asciidoc:

  • Routing-And-Deep-Links.asciidoc — reference covering every part of the API plus iOS Universal Links / Android App Links setup and the extension recipe for adding new annotation processors.
  • Tutorial-Routing-And-Deep-Links.asciidoc — end-to-end tutorial from an empty project to a working deep-linkable app with @Route, guards, and a tab shell.

Asciidoctor lint passes locally with --failure-level WARN.

Test plan

  • 46 new core unit tests for DeepLink, RouteMatch, Router, PopGuard, AasaBuilder, AssetLinksBuilder. All 2608 core tests pass against the local-dev-javase profile.
  • 11 new plugin tests, including an end-to-end test that compiles @Route-annotated fixtures with javac, runs RouteAnnotationProcessor, loads the generated RoutesIndex bytecode in a child classloader, and invokes register() against a stub Router that records every call. Negative tests cover non-Form targets, empty pattern, missing leading slash, duplicate pattern, and abstract class targets.
  • mvn verify on core-unittests (SpotBugs / PMD / Checkstyle) and on codenameone-maven-plugin (SpotBugs): zero new SpotBugs findings on the touched modules.
  • Asciidoctor lint: clean.
  • Watch GitHub Actions PR CI through to green.

Notes on the build-time scanner

The earlier source-regex prototype was scrapped — the user pushed for a fail-fast bytecode-based scanner sharing infrastructure with the existing ASM passes (BytecodeComplianceMojo's String.split rewrite is the prior art). The new framework runs in process-classes, so it sees the JVM's view of the project rather than a textual approximation, and any validation issue aborts the build with class + reason before any generated .class lands on disk.

A small compile-time stub source (a no-op RoutesIndex with register()) is emitted under target/generated-sources/cn1-annotations/ during generate-sources so application code that references RoutesIndex.register() resolves at compile time. process-classes overwrites the stub's .class with the real registrations.

Bumped surefire from 2.22.1 to 3.2.5 in the plugin pom

The older surefire silently skipped every JUnit test in this module under JDK 8 (Tests run: 0 even though AppTest was present). The bump matches the version already pinned by the parent reactor pom. Vintage engine is included so existing JUnit 4 tests in the module keep working.

🤖 Generated with Claude Code

shai-almog and others added 3 commits May 24, 2026 22:06
A new com.codename1.router package layers URL-based navigation, deep
links, route guards, and a per-tab nav shell on top of existing Form
infrastructure. The runtime is opt-in: existing Form.show() / showBack()
code continues to work unchanged.

Core runtime (CodenameOne/src/com/codename1/router/):
- DeepLink — tolerant URL parser (scheme/host/path/segments/query/fragment).
- Router — fluent route(), redirect(), guard(), notFound(), start();
  push/pop/replace with a navigation stack, location listeners, and a
  pluggable BrowserHistoryBridge for the JavaScript port.
- PopGuard / PopReason — Flutter-PopScope analogue; intercepts hardware
  back, toolbar back, and Router.pop() before user code runs.
- RouteContext / RouteBuilder / RouteGuard — typed handoff between a
  matched URL and the Form constructor.
- TabsForm — Form whose tabs each keep their own navigation stack.
- AasaBuilder / AssetLinksBuilder — JSON generators for iOS Universal
  Links and Android App Links.
- web/JsRouterBootstrap + cn1-router-history.js — browser-history bridge
  for the JS port.

Display gains setDeepLinkHandler(LinkHandler) / dispatchDeepLink(url).
Display.setProperty("AppArg", url) now routes URL-shaped values through
the deep-link handler, so iOS/Android ports need no native changes.
Form gains setPopGuard(PopGuard) and checkPopGuard(reason); guards are
honored from MenuBar.keyReleased (hardware back) and Button.fireActionEvent
(toolbar back). Sheet gains showForResult() returning AsyncResource<T>
with auto-cancel on dismiss.

Build-time annotation framework (maven/codenameone-maven-plugin/):
- A reusable AnnotationProcessor SPI under com.codename1.maven.annotations
  (AnnotatedClass, MethodInfo, FieldInfo, AnnotationValues, ProcessorContext,
  ClassScanner). Processors register via ServiceLoader.
- Two new Mojos:
    cn1:generate-annotation-stubs (generate-sources) — writes compile-time
    stubs each processor declares.
    cn1:process-annotations (process-classes) — ASM-scans target/classes,
    dispatches to every registered processor, fail-fast aborts with a
    combined error list when validation fails.
- RouteAnnotationProcessor — the first concrete processor. Bytecode-based
  (not source regex): validates @route classes (extends Form, non-empty
  path starting with /, accessible constructor, no duplicate patterns),
  emits the RoutesIndex + RoutesIndex$Builder bytecode directly via ASM.
  Prefers a (RouteContext) constructor over a no-arg one when both exist.

Adding more annotations is now a matter of dropping a new processor in
META-INF/services — the orchestrator picks them up unchanged.

Tests:
- 46 new core unit tests for DeepLink, RouteMatch, Router, PopGuard,
  AasaBuilder, AssetLinksBuilder (all 2608 core tests still pass).
- 11 new plugin tests: ClassScanner picks annotations off real .class
  files; RouteAnnotationProcessor compiles fixtures with javac, runs
  the processor, loads the generated bytecode in a child classloader,
  and invokes RoutesIndex.register() against a stub Router that records
  every call. Negative tests cover non-Form @route, empty pattern,
  missing leading slash, duplicate pattern, and abstract class targets.

Maven plugin pom: bumped maven-surefire-plugin from 2.22.1 to 3.2.5 and
added junit-vintage-engine. The old surefire silently skipped every JUnit
test in this module under JDK 8; the bump matches the parent reactor's
existing pin.

Docs:
- Routing-And-Deep-Links.asciidoc — reference page covering every part of
  the API plus iOS Universal Links / Android App Links setup.
- Tutorial-Routing-And-Deep-Links.asciidoc — end-to-end tutorial from an
  empty project to a working deep-linkable app with @route, guards, and
  a tab shell.
- Both pages included from developer-guide.asciidoc; asciidoctor lint
  passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Codename One JavaScript port's bundler scans the build output for any
*.js file and importScripts() each one into the parparvm Web Worker.
cn1-router-history.js was authored as a browser-main-thread shim and
crashed the worker with `ReferenceError: document is not defined` on
import, which broke the javascript-screenshots CI run.

Guard the body of the shim with an explicit feature test for document /
addEventListener / history so the same file safely round-trips through
the worker import without doing anything, while still installing the
browser-history bridge when loaded into the main page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Hugo-rendered website flattens each .asciidoc into its own page and
doesn't translate the AsciiDoc link: macro into the resulting HTML, so
both `link:Routing-And-Deep-Links.asciidoc[...]` and
`link:Maven-Getting-Started.adoc[...]` in the tutorial pointed at
non-existent files in the build output. Lychee correctly flagged them.

Replace with inline references — the developer guide is a single
include-stitched book, so cross-page links between included files were
always cosmetic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 24, 2026

Compared 110 screenshots: 110 matched.

Native Android coverage

  • 📊 Line coverage: 11.82% (6791/57442 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.62% (34119/354705), branch 4.14% (1395/33724), complexity 5.17% (1674/32362), method 8.99% (1361/15142), class 14.44% (303/2098)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 11.82% (6791/57442 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.62% (34119/354705), branch 4.14% (1395/33724), complexity 5.17% (1674/32362), method 8.99% (1361/15142), class 14.44% (303/2098)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 879.000 ms
Base64 CN1 encode 146.000 ms
Base64 encode ratio (CN1/native) 0.166x (83.4% faster)
Base64 native decode 688.000 ms
Base64 CN1 decode 204.000 ms
Base64 decode ratio (CN1/native) 0.297x (70.3% faster)
Image encode benchmark status skipped (SIMD unsupported)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 24, 2026

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

Vale reported 5 issues against the routing chapters:
- Two Microsoft.HeadingColons violations on === headings whose
  post-colon word started lowercase.
- Three Microsoft.Contractions hits for spelling out 'it is', 'does
  not', and 'they are' in the tutorial prose.

LanguageTool flagged 'parparvm' and 'assetlinks' as misspellings.
Both are technical identifiers; add them to the LanguageTool accept
list under a new comment block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 24, 2026

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

@github-actions
Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 24, 2026

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 77000 ms
Simulator Boot (Run) 1000 ms
App Install 17000 ms
App Launch 8000 ms
Test Execution 357000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 836.000 ms
Base64 CN1 encode 1698.000 ms
Base64 encode ratio (CN1/native) 2.031x (103.1% slower)
Base64 native decode 524.000 ms
Base64 CN1 decode 1149.000 ms
Base64 decode ratio (CN1/native) 2.193x (119.3% slower)
Base64 SIMD encode 491.000 ms
Base64 encode ratio (SIMD/native) 0.587x (41.3% faster)
Base64 encode ratio (SIMD/CN1) 0.289x (71.1% faster)
Base64 SIMD decode 575.000 ms
Base64 decode ratio (SIMD/native) 1.097x (9.7% slower)
Base64 decode ratio (SIMD/CN1) 0.500x (50.0% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 90.000 ms
Image createMask (SIMD on) 12.000 ms
Image createMask ratio (SIMD on/off) 0.133x (86.7% faster)
Image applyMask (SIMD off) 203.000 ms
Image applyMask (SIMD on) 64.000 ms
Image applyMask ratio (SIMD on/off) 0.315x (68.5% faster)
Image modifyAlpha (SIMD off) 164.000 ms
Image modifyAlpha (SIMD on) 54.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.329x (67.1% faster)
Image modifyAlpha removeColor (SIMD off) 258.000 ms
Image modifyAlpha removeColor (SIMD on) 94.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.364x (63.6% faster)
Image PNG encode (SIMD off) 1073.000 ms
Image PNG encode (SIMD on) 775.000 ms
Image PNG encode ratio (SIMD on/off) 0.722x (27.8% faster)
Image JPEG encode 430.000 ms

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 24, 2026

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 73000 ms
Simulator Boot (Run) 1000 ms
App Install 23000 ms
App Launch 8000 ms
Test Execution 331000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 1317.000 ms
Base64 CN1 encode 2314.000 ms
Base64 encode ratio (CN1/native) 1.757x (75.7% slower)
Base64 native decode 601.000 ms
Base64 CN1 decode 1586.000 ms
Base64 decode ratio (CN1/native) 2.639x (163.9% slower)
Base64 SIMD encode 696.000 ms
Base64 encode ratio (SIMD/native) 0.528x (47.2% faster)
Base64 encode ratio (SIMD/CN1) 0.301x (69.9% faster)
Base64 SIMD decode 886.000 ms
Base64 decode ratio (SIMD/native) 1.474x (47.4% slower)
Base64 decode ratio (SIMD/CN1) 0.559x (44.1% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 74.000 ms
Image createMask (SIMD on) 11.000 ms
Image createMask ratio (SIMD on/off) 0.149x (85.1% faster)
Image applyMask (SIMD off) 161.000 ms
Image applyMask (SIMD on) 160.000 ms
Image applyMask ratio (SIMD on/off) 0.994x (0.6% faster)
Image modifyAlpha (SIMD off) 286.000 ms
Image modifyAlpha (SIMD on) 82.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.287x (71.3% faster)
Image modifyAlpha removeColor (SIMD off) 293.000 ms
Image modifyAlpha removeColor (SIMD on) 165.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.563x (43.7% faster)
Image PNG encode (SIMD off) 1646.000 ms
Image PNG encode (SIMD on) 1297.000 ms
Image PNG encode ratio (SIMD on/off) 0.788x (21.2% faster)
Image JPEG encode 1029.000 ms

shai-almog and others added 3 commits May 25, 2026 01:23
The legacy Ant build of CodenameOne core compiles against the CLDC11
bootclasspath, which doesn't expose java.util.regex.Pattern / Matcher —
that's why the rest of CN1's core uses com.codename1.util.regex.RE.
Under JDK 21 the Ant build (build-test (21)) broke with `package
java.util.regex does not exist`.

Switch RouteMatch to RE. Two engine differences vs java.util.regex
that the rewrite has to account for:

1. RE.match(s) is find-style, not full-match. The pattern was already
   anchored with ^ and $, but we also assert getParenStart(0) == 0 and
   getParenEnd(0) == path.length() as belt-and-braces.

2. RE.getParenCount() counts groups the matcher actually visited.
   The catch-all wildcard `**` is implemented as an alternation
   `(?:|/(.*))` where the suffix capture lives on the right branch;
   when the left (empty) branch wins, the inner capture group isn't
   reported at all. Always populate the param map with empty string in
   that case so callers don't have to null-check.

Refactor only — no public API change. All 46 router unit tests still
pass, including the new bare-prefix catch-all assertion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two CI gates needed cleanup:

1. build-test (8): the PR-CI quality-report aggregates PMD findings and
   fails the build when any forbidden rule fires in changed code. The
   routing PR introduced 88 violations split across:
     66 ControlStatementBraces (single-line `if (x) stmt;`)
     10 MissingOverride (anonymous classes implementing interfaces)
      5 ForLoopCanBeForeach (index-based for over a List)
      4 LiteralsFirstInComparisons (`seg.equals("X")`)
      1 SingularField (compiledRegex used only at construction)
      1 UnnecessaryImport (java.util.HashMap leftover after refactor)
      1 UnnecessaryFullyQualifiedName (com.codename1.io.Log.e)
   Re-formatted every flagged line; PMD now reports zero forbidden
   violations from this PR.

2. build-test (17): the legacy Android Ant build compiles with the
   platform-default encoding (US-ASCII) and rejected the em-dashes,
   en-dashes, and smart quotes that had crept into javadoc comments.
   Replaced every non-ASCII character in the new and modified .java
   files with its ASCII equivalent (-- for em-dash, ' for curly quote,
   etc.). Verified there are zero codepoints > 0x7F in any touched
   .java file.

Tests still green: 46 router core tests + 11 plugin tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
build-test (8) failed at the quality-report Checkstyle gate: the
project's checkstyle.xml uses the default LeftCurly option (`eol`),
which rejects any `{` that has code after it on the same line. Inline
forms like `if (x) { return; }`, `private RoutesIndex() { }`, and
`public String getRaw() { return raw; }` all violated.

Expand every flagged occurrence into the canonical three-line form:

    if (x) {
        return;
    }

PMD's ControlStatementBraces rule is satisfied by the braces; Checkstyle
is now happy that the brace ends its line. The two gates pull in the
same direction once you commit to multi-line bodies.

Affects only the new routing package and the surface I touched on
Display/Form/Sheet/MenuBar/Button. No behavior change. All 46 router
core tests + 11 plugin tests still pass; local Checkstyle severity-Error
count drops from 99 to 0 across the touched files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 25, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • 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.

shai-almog and others added 3 commits May 25, 2026 16:38
…files

The new files I introduced inherited the Oracle "All rights reserved"
copyright header from the surrounding sources I was copying boilerplate
from. That header is correct on Oracle-origin files (the J2ME fork
ancestry) but wrong on newly authored code, which belongs to Codename
One. Swap every header on the 44 new files for the canonical CN1
header. Touched files in CodenameOne/src/com/codename1/router,
maven/codenameone-maven-plugin, the test stubs, and the new core unit
tests.

Also strip every `#### Since 8.0` block from doc comments. We're not at
8.0 yet and the version pinning was speculative; the public API surface
is stable across the touched packages and the per-method version markers
were noise.

No code or test changes; all 46 router unit tests + 11 plugin tests
still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Combine the two non-overlapping accept-list blocks (router & JS port
identifiers from this PR, WebAuthn / passkey terms from master's #5039)
into one section.
cn1-router-history.js was wrongly living under
CodenameOne/src/com/codename1/router/web/, which is the Java source
tree. That's exactly why it got swept into the parparvm worker bundle
by the JS bundler (which scans `*.js` in the build output and
importScripts()'s them) and crashed with `ReferenceError: document is
not defined` — a class of bug that only existed because the file sat
in the wrong place.

Move to Ports/JavaScriptPort/src/main/webapp/cn1-router-history.js
alongside port.js and sw.js. Those files are served as static webapp
assets and never imported into the worker, so:
  - the bundler doesn't pick the shim up at all
  - the worker-context guard I added earlier becomes unnecessary and is
    removed (the shim now unconditionally installs the popstate /
    history.pushState bridge it always wanted to)

Also flatten the now-empty com.codename1.router.web subpackage:
JsRouterBootstrap moves up to com.codename1.router. It was the only
class in the subpackage and is itself a single-method install() helper
that doesn't justify its own namespace.

Doc updates to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • Tests: 648 total, 0 failed, 2 skipped

Benchmark Results

  • Execution Time: 10174 ms

  • Hotspots (Top 20 sampled methods):

    • 21.40% java.lang.String.indexOf (382 samples)
    • 20.67% com.codename1.tools.translator.Parser.isMethodUsed (369 samples)
    • 17.37% java.util.ArrayList.indexOf (310 samples)
    • 5.10% java.lang.Object.hashCode (91 samples)
    • 4.71% com.codename1.tools.translator.BytecodeMethod.addToConstantPool (84 samples)
    • 2.24% com.codename1.tools.translator.ByteCodeClass.calcUsedByNative (40 samples)
    • 2.24% java.lang.System.identityHashCode (40 samples)
    • 1.68% com.codename1.tools.translator.ByteCodeClass.updateAllDependencies (30 samples)
    • 1.62% com.codename1.tools.translator.ByteCodeClass.markDependent (29 samples)
    • 1.23% com.codename1.tools.translator.Parser.generateClassAndMethodIndexHeader (22 samples)
    • 1.12% com.codename1.tools.translator.Parser.cullMethods (20 samples)
    • 1.06% com.codename1.tools.translator.BytecodeMethod.optimize (19 samples)
    • 1.06% com.codename1.tools.translator.Parser.getClassByName (19 samples)
    • 1.01% com.codename1.tools.translator.BytecodeMethod.appendMethodSignatureSuffixFromDesc (18 samples)
    • 1.01% com.codename1.tools.translator.BytecodeMethod.equals (18 samples)
    • 0.95% com.codename1.tools.translator.BytecodeMethod.appendCMethodPrefix (17 samples)
    • 0.78% java.lang.StringBuilder.append (14 samples)
    • 0.67% java.io.FileOutputStream.writeBytes (12 samples)
    • 0.67% com.codename1.tools.translator.BytecodeMethod.isMethodUsedByNative (12 samples)
    • 0.56% com.codename1.tools.translator.ByteCodeClass.generateCCode (10 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.

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.

1 participant