Skip to content

Commit e64589e

Browse files
committed
Updated architecture to use workers
1 parent 00cb96c commit e64589e

2 files changed

Lines changed: 44 additions & 89 deletions

File tree

Ports/JavaScriptPort/STATUS.md

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,49 +8,54 @@ Last updated: 2026-04-09
88
Current State
99
-------------
1010

11-
- Startup/protocol is no longer the primary blocker. Main remaining blockers are in screenshot correctness and screenshot pipeline throughput.
12-
- `ensureDisplayEdt()` and diagnostics remain active in `port.js`.
13-
- Form constructor `IllegalStateException` bypass now attempts recovery instead of returning `null`:
14-
- calls default `Form` constructor
15-
- reapplies layout
16-
- reapplies title (for title+layout constructor)
17-
- emits `PARPAR:DIAG:FALLBACK:formCtor*:recoverApplied=1` markers
18-
- CI artifact behavior and fresh local rebuild behavior are currently diverged (details below).
11+
- Architecture direction has been explicitly shifted to worker-first execution for ParparVM (EDT and VM scheduler in worker, browser UI/native host on main thread).
12+
- `browser_bridge.js` is now worker-only. Main-thread VM mode and mode toggles were removed.
13+
- If worker support is missing, runtime now fails explicitly with:
14+
- `PARPAR:worker-mode-required`
15+
- `PARPAR:DIAG:FIRST_FAILURE:category=worker_missing`
16+
- Worker host-call misses now emit explicit first-failure diagnostics:
17+
- `PARPAR:DIAG:FIRST_FAILURE:category=host_call_unhandled`
18+
- `PARPAR:DIAG:FIRST_FAILURE:symbol=<nativeSymbol>`
19+
- Latest CI artifacts still ran `main-thread-mode` (before this change) and timed out before `CN1SS:SUITE:FINISHED`.
20+
- Existing form-constructor recovery diagnostics remain active in `port.js` and are still relevant while migrating.
1921

2022
Next Steps
2123
----------
2224

23-
1. Unify build provenance first:
24-
- Confirm CI bundle contains expected translated `Cn1ssDeviceRunner` variant.
25-
- In generated `translated_app.js`, verify whether runner uses `TEST_CLASSES` (old list path) or `DEFAULT_TEST_CLASSES/prependedTest` (new array path).
26-
- This directly changes failure mode and must be deterministic before further triage.
27-
2. Reduce EDT starvation in screenshot emission:
28-
- Current fresh local run advances to 11 tests, then stalls after `DrawImage` due very large `CN1SS:<name>:<chunk>` emissions.
29-
- Add bounded chunk/preview strategy for extremely large screenshots and move heavy conversion off hot EDT path where possible.
30-
3. Keep form-constructor fallback bounded:
31-
- `IllegalStateException` still occurs frequently.
32-
- Recovery now preserves object state better, but we need to reduce recursive/looping constructor retry behavior and make one-shot recovery per form instance.
33-
4. After throughput fix, run 3 repeated local runs and one CI run:
34-
- Exit gate is `CN1SS:SUITE:FINISHED` + 33 screenshot streams + no repeated stream collapse.
25+
1. Validate worker-only boot in CI and local:
26+
- Required markers: `PARPAR:worker-mode`, `PARPAR:DIAG:BOOT:bridgeMode=worker`.
27+
- Any `main-thread-mode` marker now indicates stale artifact or wrong bundle.
28+
2. Separate VM/EDT execution from main-thread host services cleanly:
29+
- Keep VM/EDT scheduling in worker.
30+
- Ensure main-thread browser APIs are reached through explicit host-call handlers rather than direct worker DOM access.
31+
3. Re-triage screenshot correctness in worker mode only:
32+
- Re-run screenshot suite and classify first blocker using the existing `TOP_BLOCKER` output.
33+
- Prioritize deterministic runtime failures before throughput tuning.
34+
4. Restore full screenshot count and correctness:
35+
- Exit gate remains `CN1SS:SUITE:FINISHED` with expected screenshot artifacts and no `BROWSER:PARPAR_ERROR`.
3536

3637
Important Notes
3738
--------------
3839

39-
- Fresh local rebuild (`/tmp/cn1-js-fresh*.zip`) now translates current runner code and shows 11 unique tests before timeout.
40-
- Existing CI artifact in `javascript-ui-tests/HelloCodenameOne-js/translated_app.js` still shows old list-based runner (`TEST_CLASSES`) and produces only 5 screenshot streams with suite completion.
41-
- This means there are at least two active failure modes:
42-
1. old-runner path: suite finishes with only 5 streams (wrong collapse)
43-
2. new-runner path: progresses further but times out during heavy screenshot emission
40+
- Current CI artifact (`~/Downloads/javascript-ui-tests/browser.log`) shows:
41+
- `PARPAR:main-thread-mode`
42+
- `PARPAR:DIAG:BOOT:bridgeMode=main-thread`
43+
- timeout with `TOP_BLOCKER=unknown|none|none`
44+
- This is consistent with the new migration priority: enforce worker mode first, then debug screenshot behavior.
4445

4546
Known Important Context
4647
-----------------------
4748

4849
- Useful diagnostics to grep:
50+
- `PARPAR:worker-mode`
51+
- `PARPAR:DIAG:BOOT:bridgeMode=worker`
52+
- `PARPAR:DIAG:FIRST_FAILURE:category=worker_missing`
4953
- `PARPAR:DIAG:FALLBACK:lambdaBridge:capturedTest=...:capturedIndex=...`
5054
- `PARPAR:DIAG:FALLBACK:formCtorLayout:bypassIllegalState=1`
5155
- `PARPAR:DIAG:FALLBACK:formCtorLayout:recoverApplied=1`
5256
- `CN1SS:INFO:suite starting test=...`
5357
- `CN1SS:SUITE:FINISHED`
5458
- Current local patch set touches:
59+
- `vm/ByteCodeTranslator/src/javascript/browser_bridge.js`
5560
- `Ports/JavaScriptPort/src/main/webapp/port.js`
5661
- `scripts/hellocodenameone/common/src/main/java/com/codenameone/examples/hellocodenameone/tests/Cn1ssDeviceRunner.java`

vm/ByteCodeTranslator/src/javascript/browser_bridge.js

Lines changed: 14 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@
8686
invoke: function(symbol, args, target, id) {
8787
var handler = this.handlers[symbol];
8888
if (!handler) {
89+
diag('FIRST_FAILURE', 'category', 'host_call_unhandled');
90+
diag('FIRST_FAILURE', 'symbol', symbol);
8991
postHostCallback(target, id, null, 'Unhandled host call ' + symbol);
9092
return;
9193
}
@@ -157,50 +159,6 @@
157159
return worker;
158160
}
159161

160-
function loadScript(src, callback) {
161-
log('load-script:' + src);
162-
var script = document.createElement('script');
163-
script.src = src;
164-
script.onload = function() {
165-
callback(null);
166-
};
167-
script.onerror = function(err) {
168-
callback(err || new Error('Failed to load ' + src));
169-
};
170-
document.head.appendChild(script);
171-
}
172-
173-
function installMainThreadMode(onReady) {
174-
log('main-thread-mode');
175-
diag('BOOT', 'bridgeMode', 'main-thread');
176-
global.__cn1ParparDispatchMessage = function(data) {
177-
handleVmMessage(data, null);
178-
};
179-
loadScript('parparvm_runtime.js', function(runtimeErr) {
180-
if (runtimeErr) {
181-
global.__parparError = { type: 'error', message: String(runtimeErr) };
182-
return;
183-
}
184-
loadScript('translated_app.js', function(appErr) {
185-
if (appErr) {
186-
global.__parparError = { type: 'error', message: String(appErr) };
187-
return;
188-
}
189-
if (typeof global.__parparInstallNativeBindings === 'function') {
190-
global.__parparInstallNativeBindings();
191-
diag('INIT', 'nativeRebind', 'applied');
192-
}
193-
loadScript('port.js', function(portErr) {
194-
if (portErr) {
195-
log('optional-script-missing:port.js');
196-
}
197-
log('translated-app-ready');
198-
onReady();
199-
});
200-
});
201-
});
202-
}
203-
204162
var appStarter = null;
205163

206164
global.startParparVmApp = function() {
@@ -213,27 +171,19 @@
213171
}
214172
};
215173

216-
if (global.cn1UseWorkerVm) {
217-
var worker = installWorkerMode();
218-
appStarter = function() {
219-
worker.postMessage({ type: 'start' });
220-
};
221-
} else {
222-
installMainThreadMode(function() {
223-
appStarter = function() {
224-
if (global.jvm && typeof global.jvm.start === 'function') {
225-
log('jvm.start.begin');
226-
diag('LIFECYCLE_START', 'jvm.start', 'begin');
227-
global.jvm.start();
228-
log('jvm.start.end');
229-
}
230-
};
231-
log('appStarter-ready');
232-
if (global.cn1Initialized) {
233-
appStarter();
234-
}
235-
});
174+
if (typeof Worker !== 'function') {
175+
var missingWorkerMessage = 'ParparVM requires Worker support; non-worker mode is not supported';
176+
log('worker-mode-required');
177+
diag('BOOT', 'bridgeMode', 'worker-only');
178+
diag('FIRST_FAILURE', 'category', 'worker_missing');
179+
diag('FIRST_FAILURE', 'message', missingWorkerMessage);
180+
global.__parparError = { type: 'error', message: missingWorkerMessage };
181+
return;
236182
}
183+
var worker = installWorkerMode();
184+
appStarter = function() {
185+
worker.postMessage({ type: 'start' });
186+
};
237187

238188
if (document.readyState === 'loading') {
239189
document.addEventListener('DOMContentLoaded', global.startParparVmApp);

0 commit comments

Comments
 (0)