Skip to content

Commit 0857312

Browse files
committed
Fixed screenshot-helper recursion regression (again)
1 parent d95ba83 commit 0857312

2 files changed

Lines changed: 44 additions & 15 deletions

File tree

Ports/JavaScriptPort/STATUS.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,22 @@ What Was Fixed In This Pass
147147
- Motivation:
148148
- White-frame capture can occur when center-only sampling misses rendered content (e.g., content concentrated away from center).
149149

150+
13. Fixed screenshot-helper recursion regression that collapsed streams to `default`.
151+
- File:
152+
- `Ports/JavaScriptPort/src/main/webapp/port.js`
153+
- CI symptom:
154+
- `run-javascript-screenshot-tests` reported:
155+
- `ERROR: No meaningful screenshots decoded (only default/bootstrap streams were present)`
156+
- Browser logs showed repeated:
157+
- `originalResolved=translated:...emitCurrentFormScreenshot...` followed by
158+
- `originalInvokeErr=Maximum call stack size exceeded`
159+
- Then only `CN1SS:default` chunks were emitted.
160+
- Changes:
161+
- Prefer translated `__impl` method resolution over non-impl wrapper.
162+
- Added re-entry guard (`cn1ssEmitCurrentFormScreenshotInvokeDepth`) so recursive original calls are bypassed into deterministic host fallback instead of stack overflow.
163+
- Expected effect:
164+
- Restore named screenshot stream emission (`CN1SS:<test>`) instead of collapsing to `default`-only stream.
165+
150166
Known Failing Symptoms (Latest CI Logs/Artifacts)
151167
-------------------------------------------------
152168

@@ -179,12 +195,14 @@ Priority Next Steps
179195
- Confirm `settleChanged`, `canvasSig`, and `canvasSource` diagnostics vary across tests.
180196
2. Validate size normalization after large-canvas gating:
181197
- Expect screenshot dimensions to remain consistent at app target size (no `120x80`/`4x4` non-bootstrap outputs).
182-
3. Validate `originalResolved=translated:...` vs `originalMissing=1` in CI browser log after translated-method preservation patch.
183-
4. If white-frame reuse persists, capture and compare per-test `settleSig`/`canvasSig`/`canvasSource` to identify whether paint is not happening or capture target is still wrong.
184-
5. Fix per-test null receiver/init path (`__classDef` null) at first failing stack, not via broad fallbacks.
185-
6. Fix missing `Button.initLaf(UIManager)` symbol resolution in worker runtime path.
186-
7. Fix worker-mode orientation lock path so DOM access is host-bridge mediated (no direct `document` access in worker).
187-
8. Confirm VM completeness stability in CI with parser/runtime patches (`expected 7` consistently).
198+
3. Validate no `originalInvokeErr=Maximum call stack size exceeded` in CI browser log for screenshot helper path.
199+
4. Validate `CN1SS` named test streams are emitted again (not only `default/bootstrap`).
200+
5. Validate `originalResolved=translated:...__impl` (or equivalent non-recursive path) in CI browser log after translated-method preservation patch.
201+
6. If white-frame reuse persists, capture and compare per-test `settleSig`/`canvasSig`/`canvasSource` to identify whether paint is not happening or capture target is still wrong.
202+
7. Fix per-test null receiver/init path (`__classDef` null) at first failing stack, not via broad fallbacks.
203+
8. Fix missing `Button.initLaf(UIManager)` symbol resolution in worker runtime path.
204+
9. Fix worker-mode orientation lock path so DOM access is host-bridge mediated (no direct `document` access in worker).
205+
10. Confirm VM completeness stability in CI with parser/runtime patches (`expected 7` consistently).
188206

189207
Files Touched In This Pass
190208
--------------------------

Ports/JavaScriptPort/src/main/webapp/port.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3116,6 +3116,7 @@ function emitCn1ssChunks(base64, testName, channelName) {
31163116

31173117
const cn1ssEmitCurrentFormScreenshotMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_Cn1ssDeviceRunnerHelper_emitCurrentFormScreenshot_java_lang_String_java_lang_Runnable";
31183118
const cn1ssHelperClassName = "com_codenameone_examples_hellocodenameone_tests_Cn1ssDeviceRunnerHelper";
3119+
let cn1ssEmitCurrentFormScreenshotInvokeDepth = 0;
31193120

31203121
function isFallbackFunctionForSymbol(fn, symbol) {
31213122
return !!(fn && fn.__cn1CiFallbackSymbol === symbol);
@@ -3162,18 +3163,28 @@ bindCiFallback("Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshotDom", [
31623163
const normalizedTest = resolveCn1ssTestName(test);
31633164
let shouldUseDomFallback = true;
31643165
const originalResolved = resolveTranslatedMethodCandidate([
3165-
cn1ssEmitCurrentFormScreenshotMethodId,
3166-
cn1ssEmitCurrentFormScreenshotMethodId + "__impl"
3166+
// Prefer translated __impl first. The non-impl wrapper may dispatch via
3167+
// rebound globals and recurse into this fallback.
3168+
cn1ssEmitCurrentFormScreenshotMethodId + "__impl",
3169+
cn1ssEmitCurrentFormScreenshotMethodId
31673170
], cn1ssHelperClassName, fallbackSymbol);
31683171
if (originalResolved && typeof originalResolved.fn === "function") {
3169-
try {
3170-
emitDiagLine("PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalResolved=" + originalResolved.source);
3171-
yield* originalResolved.fn(testName, completion);
3172-
return null;
3173-
} catch (originalErr) {
3174-
emitDiagLine("PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalInvokeErr="
3175-
+ String(originalErr && originalErr.message ? originalErr.message : originalErr));
3172+
if (cn1ssEmitCurrentFormScreenshotInvokeDepth > 0) {
3173+
emitDiagLine("PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalReentryBypass=1");
31763174
shouldUseDomFallback = true;
3175+
} else {
3176+
try {
3177+
cn1ssEmitCurrentFormScreenshotInvokeDepth++;
3178+
emitDiagLine("PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalResolved=" + originalResolved.source);
3179+
yield* originalResolved.fn(testName, completion);
3180+
return null;
3181+
} catch (originalErr) {
3182+
emitDiagLine("PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalInvokeErr="
3183+
+ String(originalErr && originalErr.message ? originalErr.message : originalErr));
3184+
shouldUseDomFallback = true;
3185+
} finally {
3186+
cn1ssEmitCurrentFormScreenshotInvokeDepth = Math.max(0, cn1ssEmitCurrentFormScreenshotInvokeDepth - 1);
3187+
}
31773188
}
31783189
} else {
31793190
emitDiagLine("PARPAR:DIAG:FALLBACK:cn1ssEmitCurrentFormScreenshotDom:originalMissing=1");

0 commit comments

Comments
 (0)