Last updated: 2026-04-12
- Input artifacts analyzed:
~/Downloads/job-logs.txt~/Downloads/javascript-ui-tests/browser.log
- Confirmed in that artifact set:
- Suite completes (
CN1SS:SUITE:FINISHED) and 32 named streams decode. - Most PNGs are still identical/white (
canvasSig=7263bb45repeated). - Screenshot helper repeatedly falls back due:
PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalInvokeErr=Error: Missing JS member get for host receiver
- Suite completes (
- New code changes in workspace (not CI-validated yet):
- Host/runtime JSO bridge now supports array-like indexed fallback for
get(index)/set(index,value)when no callable member exists. - Host bridge attempts to avoid per-pixel host RPC by cloning typed-array payloads.
- Host bridge has explicit
getter:datafast-return clone path. - BaseTest on-show lambda shim now guards missing
target.__classDefby resolving class metadata fromtarget.__class. - Screenshot fallback now logs short
originalInvokeStackfor first-failure localization.
- Host/runtime JSO bridge now supports array-like indexed fallback for
- Important caveat from local replay:
- Replaying patched runtime against the previously archived CI zip can regress to timeout and show
originalInvokeErr=Cannot read properties of null (reading '__classDef')during per-test screenshot emission. - This indicates the first blocker has shifted from missing host
.getto a null receiver/class-init path in translated screenshot execution.
- Replaying patched runtime against the previously archived CI zip can regress to timeout and show
- Worker-only architecture is active:
- VM/EDT runs in
worker.js. - Browser/DOM access routes through host bridge (
browser_bridge.js+ host-call messages).
- VM/EDT runs in
- CI/local logs now reach:
CN1SS:SUITE:FINISHEDTOP_BLOCKER=none|none|none
- The screenshot pipeline now decodes/report-generates reliably from logs, but screenshot content is still mostly wrong (white-frame capture path is still being used in CI artifacts).
- New patch (not yet CI-validated in this document revision): worker-side fallback screenshot path now waits for a host-side UI-settle barrier before ready-callback dispatch and before canvas capture, to avoid pre-paint frame capture.
- Note: a short-lived
forceShow()experiment inBaseTest.registerReadyCallbackwas reverted because it caused re-entrant callback loops and preventedCN1SS:SUITE:FINISHED. - New patch (not yet CI-validated in this document revision): host screenshot capture now tracks the real draw target canvas and includes off-DOM canvases reachable via host refs.
- New patch (not yet CI-validated in this document revision): screenshot candidate selection now prioritizes near-screen-sized canvases to prevent tiny offscreen buffers from being selected (fixes unexpected
120x80/4x4outputs). - New patch (not yet CI-validated in this document revision): native rebinding now preserves overwritten translated JS method functions in
jvm.translatedMethodsfor targeted fallback/original resolution. - New patch (not yet CI-validated in this document revision): canvas visual scoring now samples multiple regions (not only center), to better detect non-white drawn content.
-
Screenshot report pipeline no longer aborts immediately on
CN1SS:ERRlines, and syntheticdefaultstream no longer causes fatal decode failure when named streams exist.- File:
scripts/run-javascript-screenshot-tests.sh - Fixes:
- Continue after
cn1ss_print_lognon-zero status (report generation still runs). - Filter out synthetic
defaultstream when named streams are present. - Treat residual synthetic
defaultdecode failures as non-fatal in multi-stream runs.
- Continue after
- Verified locally:
- Replaying latest
javascript-device-runner.lognow exits0, writes compare/comment artifacts, and does not fail ondefault.
- Replaying latest
- File:
-
Runtime key/identity robustness hardening in ParparVM.
- File:
vm/ByteCodeTranslator/src/javascript/parparvm_runtime.js - Changes:
System.identityHashCode(Object)now assigns stable ids for non-VM JS objects using direct__idwhen possible andWeakMapfallback otherwise.HashMap.areEqualKeys(Object,Object)now handles Java-string/JS-string comparison safely before virtual dispatch.
- Motivation:
- Addresses suspected object-identity/equality instability contributing to map lookup anomalies and flaky behavior.
- File:
-
Host screenshot canvas selection switched from "largest canvas only" to content-aware selection.
- File:
vm/ByteCodeTranslator/src/javascript/browser_bridge.js - Changes:
- Added canvas visual scoring (opaque/non-white sampled content) and area tie-break.
- Added diagnostics for selected canvas (
canvasCount,canvasPick,canvasArea,canvasScore,pngLen).
- Motivation:
- Current CI artifacts show 29/32 screenshots with identical hash (white/blank frame reuse), indicating we were repeatedly capturing the wrong canvas.
- File:
-
Added LinkedHashMap non-null-key native lookup override.
- Files:
vm/ByteCodeTranslator/src/javascript/parparvm_runtime.jsvm/ByteCodeTranslator/src/com/codename1/tools/translator/JavascriptNativeRegistry.java
- Changes:
cn1_java_util_LinkedHashMap_findNonNullKeyEntry_java_lang_Object_int_int_R_java_util_HashMap_Entrynow delegates to the runtime HashMap lookup native.
- Motivation:
- CI flake in
JavascriptCn1CoreCompletenessTest(expected 7 got 3) points to JSON map key lookup path instability on worker runtime.
- CI flake in
- Files:
-
Fixed
Object.getClass()null handling to throw Java NPE instead of raw JS TypeError.- File:
vm/ByteCodeTranslator/src/javascript/parparvm_runtime.js - Fix:
cn1_java_lang_Object_getClass*native now throwsjava_lang_NullPointerExceptionwhen receiver is null.
- Motivation:
- Avoids leaking JS
Cannot read properties of null (reading '__classDef')from core object/class paths.
- Avoids leaking JS
- File:
-
Hardened worker harness result parsing for VM tests.
- File:
vm/tests/src/test/java/com/codename1/tools/translator/JavascriptRuntimeSemanticsTest.java - Fix:
- Extract JSON fields from the last JSON object line containing
"type"instead of scanning entire stdout blindly.
- Extract JSON fields from the last JSON object line containing
- Motivation:
- Reduces false extraction of intermediate
"result"fields in noisy worker output.
- Reduces false extraction of intermediate
- Local check:
JavascriptCn1CoreCompletenessTest#executesMeaningfulCodenameOneCoreSliceInWorkerRuntimepasses locally after this update.
- File:
-
Added explicit host-side UI settle barrier and wired it into screenshot readiness/capture flow.
- Files:
vm/ByteCodeTranslator/src/javascript/browser_bridge.jsPorts/JavaScriptPort/src/main/webapp/port.js
- Changes:
- New host native
__cn1_wait_for_ui_settle__waits across RAF frames and monitors canvas signature/score stability. BaseTest.registerReadyCallbackImmediatenow waits on host UI settle before invoking callback.Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshotDomnow waits on host UI settle before__cn1_capture_canvas_png__.- Added diagnostics:
PARPAR:DIAG:SCREENSHOT_START:settleReason=...PARPAR:DIAG:SCREENSHOT_START:settleChanged=...PARPAR:DIAG:FALLBACK:baseTestRegisterReady:afterUiSettle=1:...
- New host native
- Motivation:
- CI showed near-identical screenshot payloads (same hash/size) indicating repeated capture of a stale frame rather than per-test painted UI.
- Files:
-
Reverted force-show experiment due re-entrancy regression.
- File:
Ports/JavaScriptPort/src/main/webapp/port.js
- Observation:
- Calling
Form.show()insideBaseTest.registerReadyCallbackImmediatecaused repeatedregisterReadyCallback/settle cycles on the same test and CI timeout before suite completion.
- Calling
- Action:
- Removed
forceShow()from this fallback path. - Kept the host-side settle barrier and diagnostics (non-recursive).
- Removed
- File:
-
Added draw-target aware screenshot capture in browser bridge.
- File:
vm/ByteCodeTranslator/src/javascript/browser_bridge.js
- Changes:
- Host JSO bridge now records the last canvas that received draw operations.
- Screenshot candidate selection now includes:
- DOM canvases
- last draw target canvas
- canvases reachable through host refs (including context
.canvas)
- Added diagnostic:
PARPAR:DIAG:SCREENSHOT_START:canvasSource=...(dom,lastDraw,hostRef,hostRefCanvas)
- Motivation:
- Current logs show active drawing calls while DOM-canvas snapshots remain static/white; this addresses likely off-DOM/back-buffer capture misses.
- File:
-
Added large-canvas gating for screenshot candidate selection.
- File:
vm/ByteCodeTranslator/src/javascript/browser_bridge.js
- Changes:
- Evaluate all candidate canvases, compute max area, and prefer candidates with area >= 45% of max (with floor at 65536).
- Only fall back to tiny-canvas pool if no large candidates exist.
- Added diagnostics:
PARPAR:DIAG:SCREENSHOT_START:canvasConsidered=...PARPAR:DIAG:SCREENSHOT_START:canvasLargeCount=...PARPAR:DIAG:SCREENSHOT_START:canvasMinLargeArea=...
- Motivation:
- Latest artifacts showed mixed dimensions (
120x80,4x4) and colored tiny captures, indicating offscreen utility buffers were being selected.
- Latest artifacts showed mixed dimensions (
- Added translated-method preservation during native rebinding.
- Files:
vm/ByteCodeTranslator/src/javascript/parparvm_runtime.jsPorts/JavaScriptPort/src/main/webapp/port.js
- Changes:
- Runtime now records pre-override translated functions in
jvm.translatedMethodswhen installing/reinstalling natives. Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshot...fallback resolution now checksjvm.translatedMethodsbefore globals/class tables.- CI fallback wrappers are tagged (
__cn1CiFallbackSymbol) so resolution can skip recursive self-selection.
- Runtime now records pre-override translated functions in
- Motivation:
originalMissing=1persisted even though translated helper symbols exist intranslated_app.js; rebinding order was losing discoverability of original translated handlers.
- Improved screenshot canvas scoring robustness.
- File:
vm/ByteCodeTranslator/src/javascript/browser_bridge.js
- Changes:
- Replaced single-center 48x48 sample with multi-region sampling (center, corners, and edge midpoints).
- Score still prefers non-white/opaque content, but now reflects content distribution across the frame.
- Motivation:
- White-frame capture can occur when center-only sampling misses rendered content (e.g., content concentrated away from center).
- Fixed screenshot-helper recursion regression that collapsed streams to
default.
- File:
Ports/JavaScriptPort/src/main/webapp/port.js
- CI symptom:
run-javascript-screenshot-testsreported:ERROR: No meaningful screenshots decoded (only default/bootstrap streams were present)
- Browser logs showed repeated:
originalResolved=translated:...emitCurrentFormScreenshot...followed byoriginalInvokeErr=Maximum call stack size exceeded
- Then only
CN1SS:defaultchunks were emitted.
- Changes:
- Prefer translated
__implmethod resolution over non-impl wrapper. - Added re-entry guard (
cn1ssEmitCurrentFormScreenshotInvokeDepth) so recursive original calls are bypassed into deterministic host fallback instead of stack overflow.
- Prefer translated
- Expected effect:
- Restore named screenshot stream emission (
CN1SS:<test>) instead of collapsing todefault-only stream.
- Restore named screenshot stream emission (
- Added JSO bridge indexed-access compatibility for array-like receivers.
- Files:
vm/ByteCodeTranslator/src/javascript/browser_bridge.jsvm/ByteCodeTranslator/src/javascript/parparvm_runtime.js
- Changes:
- If a bridged
methodcall has memberget/setand receiver is array-like (length), map to indexed element access when no callable JS member exists.
- If a bridged
- Motivation:
- Fixes deterministic screenshot-path failure:
Missing JS member get for host receiver
- Seen when translated code accesses pixel buffers via
get(index).
- Fixes deterministic screenshot-path failure:
- Added host bridge typed-array transfer fast paths.
- File:
vm/ByteCodeTranslator/src/javascript/browser_bridge.js
- Changes:
hostResult()now clones/returns typed-array andArrayBuffervalues directly instead of always creating host refs.- Added explicit
getter:datadirect-clone return path in__cn1_jso_bridge__.
- Motivation:
- Prevents pathological per-element host RPC loops during pixel-buffer reads.
- Status:
- Local replay indicates this removes the old
Missing JS member get...failure, but uncovers a later null__classDefpath that still needs repair.
- Local replay indicates this removes the old
- Hardened BaseTest on-show lambda shim for missing class definition.
- File:
Ports/JavaScriptPort/src/main/webapp/port.js
- Changes:
target.__classDefaccess now falls back tojvm.classes[target.__class]and exits safely with diagnostic if unresolved.
- Motivation:
- Targets recurring per-test failure signature:
Cannot read properties of null (reading '__classDef')
- This is now the highest-priority blocker after
.getbridge repair.
- Targets recurring per-test failure signature:
- Fixed Worker-to-main-thread console forwarding for CN1SS output and System.out.println.
- Files:
vm/ByteCodeTranslator/src/javascript/parparvm_runtime.jsPorts/JavaScriptPort/src/main/webapp/port.jsvm/ByteCodeTranslator/src/javascript/browser_bridge.jsscripts/run-javascript-headless-browser.mjs
- Root cause:
System.out.println()in the VM Worker maps toprintToConsole()which only callsconsole.log()in the Worker context.- Playwright
page.on('console')does not reliably capture Web Worker console messages emitted during async VM execution (only synchronous module-load-time messages appear). - Consequently,
CN1SS:SUITE:FINISHEDand all test chunk data never reach the log file, causing the shell harness to time out.
- Changes:
printToConsole()now also callsemitVmMessage({ type: 'log', message })to forwardSystem.out.printlnoutput to the main thread viapostMessage.emitDiagLine()in port.js now also callspostMessage({ type: 'log', message })to forward CN1SS chunk data and diagnostic lines.browser_bridge.jsdetects app lifecycle start from worker log messages and setswindow.cn1Started = trueon the main thread.run-javascript-headless-browser.mjsnow detectsCN1SS:SUITE:FINISHEDin console output and exits early instead of running to its full timeout.
- Expected effect:
CN1SS:SUITE:FINISHEDreliably appears in the browser log, resolving the CI timeout.- All CN1SS chunk data reaches Playwright, enabling screenshot extraction.
- Playwright exits promptly after suite completion, saving CI time.
- Fixed screenshot hang caused by canvasToBlob async callback across worker boundary.
- File:
Ports/JavaScriptPort/src/main/webapp/port.js - Root cause:
- The translated screenshot method calls
ImageIO.save()which callsBlobUtil.canvasToBlob(). That method uses the asyncHTMLCanvasElement.toBlob(BlobCallback)browser API. In the worker architecture the BlobCallback is a Java object that cannot be invoked from the host thread, socanvasToBlob()hangs forever inwhile (!complete) { lock.wait(200); }.
- The translated screenshot method calls
- Fix:
emitCurrentFormScreenshotDomnow always uses the DOM-based host bridge capture path (__cn1_capture_canvas_png__) instead of the translated screenshot method. This avoids async callbacks entirely.
- Also added
Uint8ClampedArrayto the JSOinferFnfor proper type recognition when wrapping typed arrays received from the host.
- File:
- Screenshot suite finishes but many tests fail during
runTest. - Latest primary blocker progression:
- Earlier blocker in CI artifacts:
Missing JS member get for host receiver. - After bridge compatibility work in local replay: blocker shifts to
Cannot read properties of null (reading '__classDef')in translated screenshot helper path.
- Earlier blocker in CI artifacts:
- Repeated deterministic blockers in browser log:
TabsScreenshotTest:cn1_com_codename1_ui_Button_initLaf_com_codename1_ui_plaf_UIManager is not definedOrientationLockScreenshotTest:document is not defined- Multiple tests:
TypeError: Cannot read properties of null (reading '__classDef')- Seen in
ValidatorLightweightPickerScreenshotTest,InPlaceEditViewTest,StreamApiTest,TimeApiTest.
- Seen in
- Timeout-only tests still timeout by design/behavior (
MediaPlayback...,BytecodeTranslatorRegression..., selected API tests). - Screenshot pixels are still wrong in CI (host-canvas fallback path remains dominant in logs).
- Local note from current workspace revalidation:
- Fresh locally built bundle (
/tmp/hellocodenameone-javascript-port-local.zip) currently emits onlybootstrap_placeholderas a named stream. - Browser diagnostics in that run show repeated:
PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalMissing=1PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:noCanvas=1:test=...
- This local symptom differs from the latest CI artifacts (which still emit 32 screenshots, mostly white), so CI confirmation is required before accepting/rejecting the current translated-method resolution patch.
- Fresh locally built bundle (
JavascriptCn1CoreCompletenessTest.executesMeaningfulCodenameOneCoreSliceInWorkerRuntimehas reported flakyexpected: <7> but was: <3>in CI.- Local single-method repetition passed in this workspace after the runtime hardening above, but CI confirmation is still required.
- Validate CI output after UI-settle barrier:
- Expect non-identical PNG hashes for distinct tests.
- Confirm
settleChanged,canvasSig, andcanvasSourcediagnostics vary across tests.
- Validate size normalization after large-canvas gating:
- Expect screenshot dimensions to remain consistent at app target size (no
120x80/4x4non-bootstrap outputs).
- Expect screenshot dimensions to remain consistent at app target size (no
- Validate no
originalInvokeErr=Maximum call stack size exceededin CI browser log for screenshot helper path. - Validate
CN1SSnamed test streams are emitted again (not onlydefault/bootstrap). - Validate
originalResolved=translated:...__impl(or equivalent non-recursive path) in CI browser log after translated-method preservation patch. - If white-frame reuse persists, capture and compare per-test
settleSig/canvasSig/canvasSourceto identify whether paint is not happening or capture target is still wrong. - Fix per-test null receiver/init path (
__classDefnull) at first failing stack in translated screenshot/helper execution (no new broad fallbacks). - Fix missing
Button.initLaf(UIManager)symbol resolution in worker runtime path. - Fix worker-mode orientation lock path so DOM access is host-bridge mediated (no direct
documentaccess in worker). - Confirm VM completeness stability in CI with parser/runtime patches (
expected 7consistently).
vm/ByteCodeTranslator/src/javascript/browser_bridge.jsPorts/JavaScriptPort/src/main/webapp/port.jsPorts/JavaScriptPort/STATUS.md