Skip to content

Commit 2a60bb9

Browse files
Copilotshai-almog
andauthored
Capture main-thread canvas for JS screenshots instead of blank worker OffscreenCanvas
Agent-Logs-Url: https://github.com/codenameone/CodenameOne/sessions/b7fa2e59-a288-4ae6-9bea-d304c7f0bda8 Co-authored-by: shai-almog <67850168+shai-almog@users.noreply.github.com>
1 parent a6c50f3 commit 2a60bb9

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

  • Ports/JavaScriptPort/src/main/webapp

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3174,6 +3174,9 @@ function emitCn1ssChunks(base64, testName, channelName) {
31743174
emitDiagLine(prefix + ":" + test + ":" + index + ":");
31753175
cn1ssChunkIndexByStream[streamKey] = nextIndex + 1;
31763176
}
3177+
// Emit END marker matching the Java emitChannel convention so the
3178+
// downstream cn1ss_list_tests / cn1ss_decode helpers can detect the stream.
3179+
emitDiagLine(prefix + ":END:" + test);
31773180
}
31783181

31793182
const cn1ssEmitCurrentFormScreenshotMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_Cn1ssDeviceRunnerHelper_emitCurrentFormScreenshot_java_lang_String_java_lang_Runnable";
@@ -3315,9 +3318,34 @@ bindCiFallback("Cn1ssDeviceRunnerHelper.emitChannelFastJs", [
33153318
cn1ssEmitChannelMethodId,
33163319
cn1ssEmitChannelMethodId + "__impl"
33173320
], function*(payloadBytes, testName, channelName) {
3318-
const base64 = byteArrayToBase64(payloadBytes);
33193321
const test = resolveCn1ssTestName(toCn1StringValue(testName));
33203322
const channel = toCn1StringValue(channelName);
3323+
// For the primary screenshot channel (empty channel name), the Java-side
3324+
// Display.screenshot() in the worker reads from OffscreenCanvas which
3325+
// may not reflect the main-thread visible canvas. Replace the payload
3326+
// with a main-thread canvas capture via the host bridge when available.
3327+
if (!channel && jvm && typeof jvm.invokeHostNative === "function" && !cn1ssScreenshotEmitted[test]) {
3328+
try {
3329+
yield jvm.invokeHostNative("__cn1_wait_for_ui_settle__", [{
3330+
reason: "screenshot:" + test,
3331+
maxFrames: 18,
3332+
stableFrames: 2
3333+
}]);
3334+
const hostResult = yield jvm.invokeHostNative("__cn1_capture_canvas_png__", []);
3335+
const capturedDataUrl = hostResult == null ? "" : String(hostResult);
3336+
if (capturedDataUrl && capturedDataUrl.indexOf("data:image/") === 0) {
3337+
cn1ssScreenshotEmitted[test] = true;
3338+
const comma = capturedDataUrl.indexOf(",");
3339+
const hostBase64 = comma >= 0 ? capturedDataUrl.substring(comma + 1) : "";
3340+
emitDiagLine("PARPAR:DIAG:FALLBACK:emitChannelFastJs:hostCapture=1:test=" + test + ":len=" + hostBase64.length);
3341+
emitCn1ssChunks(hostBase64, test, channel);
3342+
return null;
3343+
}
3344+
} catch (_hostErr) {
3345+
emitDiagLine("PARPAR:DIAG:FALLBACK:emitChannelFastJs:hostCaptureErr=" + String(_hostErr && _hostErr.message ? _hostErr.message : _hostErr));
3346+
}
3347+
}
3348+
const base64 = byteArrayToBase64(payloadBytes);
33213349
emitCn1ssChunks(base64, test, channel);
33223350
return null;
33233351
});

0 commit comments

Comments
 (0)