Playground: build via local ParparVM JavaScript target#5250
Conversation
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 128 screenshots: 128 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 125 screenshots: 125 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 121 screenshots: 121 matched. |
|
Compared 125 screenshots: 125 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 127 screenshots: 127 matched. |
|
Compared 127 screenshots: 127 matched. |
|
Compared 128 screenshots: 128 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 125 screenshots: 125 matched. Benchmark ResultsDetailed Performance Metrics
|
3e84cf7 to
0684ad9
Compare
|
Compared 124 screenshots: 124 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 128 screenshots: 128 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Migrate the Playground off the pinned old release + cloud `javascript` build target onto the local ParparVM `local-javascript` target, the same path the initializr uses. Playground changes (scripts/cn1playground/): - javascript/pom.xml: codename1.defaultBuildTarget javascript -> local-javascript - build.sh / build.bat: javascript target -> local-javascript - pom.xml: drop the one-release `cn1.registry.version` (7.0.234) pin. The bean-shell access registry now tracks the current API directly. A new cn1.accessRegistry.useLocalSources property (true under the cn1-local-workspace profile) makes the registry generate from the repo's own CN1 sources, since 8.0-SNAPSHOT has no source jars on Maven Central. - common/pom.xml: pass that property through to the registry generator as CN1_ACCESS_USE_LOCAL_SOURCES. - tools/GenerateCN1AccessRegistry.java: remove the security.* / nfc.* class exclusions (they worked around the legacy cloud TeaVM backend lagging the release channel; the local target builds the current sources). Keep the structural exclusions (Accessor/IOAccessor internals, and Simd whose alloca scratch arrays cannot escape the reflection bridge under the bytecode-compliance check). Also exclude the com.codename1.testing.junit package: it is the JavaSE-port JUnit 5 test-extension API (not a runtime API a playground script can use, and not on the common compile classpath), which un-pinning the registry version newly pulled in and broke the build. Fix array-component varargs codegen: emit `new byte[len][]`, not the malformed `new byte[][len]`, for `T[]...`. - tools/generate-cn1-access-registry.sh: drop the registry-version logic. - README / tools/README: document the new path. JS-port translator fixes (vm/ByteCodeTranslator/) needed for the Playground's full-API reflective registry: - JavascriptMethodGenerator: support array class literals (`ldc [B`, `String[].class`, ...) via jvm.getArrayClass(component, dims).classObject. The registry emits these for every array-typed parameter; the JS backend previously only handled object class literals and threw "Unsupported ldc constant". - Parser: rethrow Errors (e.g. OutOfMemoryError) from writeOutput instead of swallowing them, which had let the translator exit 0 with a truncated dist. Plugin / build wiring: - JavaScriptBuilder: let a -Xmx in CN1_TRANSLATOR_OPTS override the default 512m translator heap. - The Playground keeps nearly the whole API reachable, so the JS RTA tree-shaking pass cannot prune much yet runs 100min+. build.sh/build.bat and the website build_playground_for_site set CN1_TRANSLATOR_OPTS to disable RTA (-Dparparvm.js.rta.off) and raise the heap (-Xmx6g); the website extraction flattens the single wrapper dir so index.html lands at the served root. Verified locally: the local-javascript build produces a complete bundle (index.html, worker.js, translated_app + chunks, parparvm_runtime.js, browser_bridge.js, js/ assets, themes, editor html.tar, native-interface stub) that loads in headless Chromium with no fatal JS/VM errors, and the playground language smoke tests pass (registry regenerated in release mode, 325/325 syntax, 312/312 paint, 20/20 preview). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0684ad9 to
ebbb018
Compare
Cloudflare Preview
|
JavascriptBundleWriter.hoistStringConstants emits top-level `const _q<alias>="..."` aliases for repeated string literals, but it reset the alias counter to 0 for every chunk. The translated_app chunks are concatenated into one worker scope via importScripts, so two chunks each declaring e.g. `const _q0O` (with different string values) is a `SyntaxError: redeclaration of const _q0O` that aborts worker startup. This only triggered once a bundle was large enough to split into multiple chunks (>20 MB) -- the Playground is the first such app; smaller local-javascript apps (initializr, HelloCodenameOne) are single-chunk and were unaffected. Thread one shared alias counter through every chunk so each gets a disjoint alias range -- exactly the naming a single un-split chunk would produce. Verified: node --check on the concatenated 57 MB Playground bundle parses cleanly (0 cross-chunk duplicate const names). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The ParparVM localforage shim (synchronous-callback, localStorage-backed)
bailed out if a real `window.localforage` was already present:
if (window.localforage && typeof window.localforage.setItem === "function") return;
But fontmetrics.js bundles a real localForage 1.7.3 and globally exposes
it, and it loads BEFORE the shim. So the shim bailed, CN1 Storage hit the
real localForage's Promise-based callback path, and the worker-bridged
callback failed with `TypeError: b is not a function` (localForage's
executeCallback invoking a non-function) right after the app's main()
ran -- the Playground is the first local-javascript app to touch Storage
on boot.
The worker can't pump the async microtask loop the real localForage
relies on, so the synchronous shim MUST own window.localforage. Install
unconditionally, overriding any real localForage; only skip re-installing
over ourselves (idempotent via a __cn1ShimInstalled marker). fontmetrics
keeps its own bundled instance (referenced through its module closure) for
font-metric caching.
Verified: the Playground bundle boots in headless Chromium with no
`b is not a function` (0 fatal JS errors) where it previously threw on
every Storage access.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrates the Playground off the pinned old release + cloud
javascriptbuild target onto the local ParparVMlocal-javascripttarget — the same path the initializr uses (#5200) — and removes the class-exclusion list and version pinning that worked around the lagging cloud TeaVM backend.Playground (
scripts/cn1playground/)javascript/pom.xmlcodename1.defaultBuildTargetandbuild.sh/build.batswitchjavascript→local-javascript. The cloudjavascripttarget remains a fallback.cn1.registry.version(7.0.234) pin. The bean-shell access registry now tracks the current API directly. Newcn1.accessRegistry.useLocalSourcesproperty (true under thecn1-local-workspaceprofile) generates the registry from the repo's own CN1 sources (8.0-SNAPSHOT has no source jars on Central);common/pom.xmlpasses it to the generator asCN1_ACCESS_USE_LOCAL_SOURCES.GenerateCN1AccessRegistry.java): removed thesecurity.*/nfc.*exclusions — those were cloud-TeaVM-lag workarounds, and the local target builds current sources. Kept the structural exclusions:Accessor/IOAccessorinternals, andSimd(its alloca scratch arrays may not escape the reflection bridge under the bytecode-compliance check, which the local target enforces too). Also fixed an array-component varargs codegen bug surfaced by re-including NFC: emitnew byte[len][], not the malformednew byte[][len], forT[]...params.JS-port translator (
vm/ByteCodeTranslator/)The Playground's reflective registry references nearly the whole API, exercising paths a normal app doesn't:
ldcclass literals and threwUnsupported ldc constanton array literals (byte[].class,String[].class), which the registry emits for every array-typed parameter. Now lowered tojvm.getArrayClass(component, dims).classObject(cached under the same name array instances use).Parser.writeOutputcaughtThrowablebut only rethrewException, so anOutOfMemoryErrormid-emit let the translator exit 0 with a truncated dist (parparvm_runtime.jsbut noworker.js/translated_app.js). Now rethrowsErrors so the build fails loudly.Plugin / build wiring
JavaScriptBuilder: a-XmxinCN1_TRANSLATOR_OPTSnow overrides the default 512m translator heap.build.sh/build.batand the websitebuild_playground_for_sitesetCN1_TRANSLATOR_OPTS=-Dparparvm.js.rta.off -Xmx6g; the website extraction flattens the single wrapper dir soindex.htmllands at the served root (mirroring the initializr path).Verification
Built locally with the local 8.0-SNAPSHOT plugin: the
local-javascriptbuild produces a complete bundle (index.html,worker.js,translated_app+ 6 chunks,parparvm_runtime.js,browser_bridge.js,js/assets, themes, Monaco editorhtml.tar, native-interface stub) that loads in headless Chromium with no fatal JS/VM errors. The regenerated registry now includescom.codename1.security.*/com.codename1.nfc.*and still excludes the internals + Simd.Note: most of the diff is the regenerated
bsh/cn1/GeneratedCN1Access*.java(checked-in generated source, regenerated each build).🤖 Generated with Claude Code