Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2da10f1
Switch initializr JavaScript build to the local ParparVM target
shai-almog Jun 8, 2026
8dff0c2
Authorize local JS build via the logged-in CN1 account
shai-almog Jun 8, 2026
c5ed5ff
initializr: declare Enterprise tier for the local JavaScript build
shai-almog Jun 8, 2026
994ffb9
website: flatten the local JavaScript bundle's wrapper directory
shai-almog Jun 8, 2026
0caac58
website: include app icon in the local Initializr JS bundle
shai-almog Jun 8, 2026
b7e602f
js-port(worker): define cn1_get_native_interfaces registry in the worker
shai-almog Jun 9, 2026
ef67e8c
website: build the Initializr against the local 8.0-SNAPSHOT plugin
shai-almog Jun 9, 2026
424534c
js-port: implement NativeInterface support (runs on the main thread)
shai-almog Jun 9, 2026
88ff91f
js-port: full type marshalling for native interfaces
shai-almog Jun 9, 2026
cdc6021
js-port: wrap PeerComponent across the native-interface bridge
shai-almog Jun 9, 2026
7d3e901
Merge remote-tracking branch 'origin/master' into initializr-local-ja…
shai-almog Jun 9, 2026
5259c7d
js-port: minify emitted application JS (strip pretty-print whitespace)
shai-almog Jun 9, 2026
998c677
js-port: synchronous virtual dispatch for CHA-proven non-suspending c…
shai-almog Jun 10, 2026
74e70bc
Merge remote-tracking branch 'origin/master' into initializr-local-ja…
shai-almog Jun 10, 2026
b283804
js-port: survive host timer throttling in the green-thread scheduler
shai-almog Jun 10, 2026
628466b
js-port: minify generated function identifiers (bridge-aware)
shai-almog Jun 9, 2026
517c774
js-port: exclude ALL native methods from identifier minification
shai-almog Jun 9, 2026
68c1cb3
js-port: protect runtime-constructed bridge names from ident minifica…
shai-almog Jun 9, 2026
3e2d425
js-port: fix ident-minify bridge-name protection + app-font path fall…
shai-almog Jun 11, 2026
dc72b8c
js-port: fix Initializr boot/interactivity + guard per-element bridge…
shai-almog Jun 11, 2026
407555f
js-port: extend interpreter peephole collapses to sync virtual dispatch
shai-almog Jun 11, 2026
845ba18
js-port: peephole-collapse the call-result temp and identity copy-pairs
shai-almog Jun 11, 2026
ce02670
js-port: deferred-expression lowering for constants and local reads
shai-almog Jun 11, 2026
319403c
js-port: defer single-hop field reads in the straight-line emitter
shai-almog Jun 11, 2026
38f10d1
js-port: 3-char aliases for the virtual-dispatch helper family
shai-almog Jun 11, 2026
a21df27
js-port: structured (labeled-break) emission for acyclic-forward CFGs
shai-almog Jun 11, 2026
f4d6eb1
js-port: structured emission for natural loops (labeled for(;;)/conti…
shai-almog Jun 12, 2026
3370531
js-port: switch structuring, SSA expression fusion, cooperative-atomi…
shai-almog Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/website-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ jobs:
WEBSITE_INCLUDE_DEVGUIDE: "true"
WEBSITE_INCLUDE_INITIALIZR: "auto"
WEBSITE_INCLUDE_PLAYGROUND: "auto"
# The Initializr's JavaScript app is built with the local ParparVM
# target, whose builder lives in the repo (8.0-SNAPSHOT) plugin rather
# than the pinned release. Bootstrap the local snapshot artifacts so
# the initializr (and the other site apps) build against repo HEAD.
WEBSITE_BOOTSTRAP_CN1_SNAPSHOTS: "true"
# PR previews build with future-dated posts visible so reviewers
# can read posts staged for later in the week. Production deploys
# (push to master) keep the default so future posts only appear
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,16 @@ private void __init() {
document = window.getDocument();
canvas = (HTMLCanvasElement)document.createElement("canvas");
outputCanvas = (HTMLCanvasElement)document.getElementById("codenameone-canvas");
outputCanvas.getStyle().setProperty("pointer-events", "none");
// The canvas must be hit-testable from the start: it boots with no
// active peers, and the per-event listeners installed later only
// flip pointer-events to "none" when the point is over a native
// peer. Booting with "none" relied on the window-level restore
// listener flipping it back on the first event -- but that restore
// round-trips through the worker bridge, so the initial pointer
// DOWN is always lost and the first gesture after load is silently
// swallowed (observed on the Initializr as scroll/drag doing
// nothing).
outputCanvas.getStyle().setProperty("pointer-events", "auto");
peersContainer = (HTMLElement)document.createElement("div");
peersContainer.setAttribute("id", "cn1-peers-container");
outputCanvas.getParentNode().insertBefore(peersContainer, outputCanvas);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2026 Codename One and contributors.
* Licensed under the PolyForm Noncommercial License 1.0.0.
* You may use this file only in compliance with that license.
* The license notice for this subtree is available in Ports/JavaScriptPort/LICENSE.md.
*/
package com.codename1.impl.platform.js;

/**
* Host bridge that dispatches Codename One {@code NativeInterface} method calls
* to their JavaScript implementation registered in {@code cn1_native_interfaces}.
*
* <p>The generated {@code <Interface>Impl} classes (emitted by the JavaScript
* builder) delegate every interface method to one of the {@code call*} natives
* below, picked by the method's return type. These natives are runtime-
* implemented in {@code parparvm_runtime.js}: the worker suspends, the call is
* replayed on the <em>main thread</em> (via {@code browser_bridge.js}) where the
* developer-authored JS stub runs with full DOM access and completes the call
* through its callback, and the worker resumes with the result coerced to the
* declared Java type.</p>
*
* <p>Supported types mirror {@code NativeInterface}: all primitives, {@code String},
* primitive arrays plus {@code String[]} (via {@link #callArray}), and
* {@code com.codename1.ui.PeerComponent} (routed through {@link #callObject}).</p>
*
* <p>{@code iface} is the interface class name with dots replaced by underscores
* (the {@code cn1_native_interfaces} registry key), {@code method} is the
* trailing-underscore method key (e.g. {@code "isDarkMode_"}), and {@code args}
* holds the (boxed) Java arguments, or an empty array for a no-arg method.</p>
*/
public final class NativeInterfaceBridge {
private NativeInterfaceBridge() {
}

public static native boolean callBoolean(String iface, String method, Object[] args);

public static native byte callByte(String iface, String method, Object[] args);

public static native short callShort(String iface, String method, Object[] args);

public static native int callInt(String iface, String method, Object[] args);

public static native char callChar(String iface, String method, Object[] args);

public static native long callLong(String iface, String method, Object[] args);

public static native float callFloat(String iface, String method, Object[] args);

public static native double callDouble(String iface, String method, Object[] args);

public static native String callString(String iface, String method, Object[] args);

public static native Object callObject(String iface, String method, Object[] args);

public static native void callVoid(String iface, String method, Object[] args);

/**
* Array-returning call. {@code componentToken} identifies the element type so
* the runtime can build the correctly-typed Java array: {@code "JAVA_INT"},
* {@code "JAVA_BYTE"}, {@code "JAVA_LONG"}, {@code "JAVA_DOUBLE"},
* {@code "JAVA_FLOAT"}, {@code "JAVA_BOOLEAN"}, {@code "JAVA_CHAR"},
* {@code "JAVA_SHORT"} or {@code "java_lang_String"}. The caller casts the
* result to the concrete array type.
*/
public static native Object callArray(String iface, String method, Object[] args, String componentToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,36 @@ public class ArrayBufferInputStream extends InputStream {
int pos = 0;
int len;
String src;
// Worker-local copy of the backing buffer, materialised lazily on the
// FIRST single-byte read. ``buf.get(pos++)`` is a JSO-bridge virtual
// dispatch (string-parsed method id + wrapper unwrap per call);
// ``Resources.load(theme.res)`` issues hundreds of thousands of
// single-byte reads through DataInputStream, which made the
// Initializr's boot crawl for minutes. One bulk copy turns every
// subsequent read into a plain Java array access. Callers that only
// bulk-read (media) or grab the blob/buffer never pay the copy.
private byte[] local;

public ArrayBufferInputStream(Uint8Array buf, String type) {
this.buf = buf;
this.type=type;
this.len = buf.getByteLength();
}

private void ensureLocal() {
if (local == null) {
local = new byte[len];
readBulkImpl(buf, 0, local, 0, len);
}
}

@Override
public int read() throws IOException {
if ( pos >= len ){
return -1;
}
return buf.get(pos++);
ensureLocal();
return local[pos++] & 0xFF;
}

@Override
Expand All @@ -51,6 +69,11 @@ public int read(byte[] b, int off, int length) throws IOException {
if (n > avail) {
n = avail;
}
if (local != null) {
System.arraycopy(local, pos, b, off, n);
pos += n;
return n;
}
// Native intrinsic: one JS-side loop copies n bytes from the
// backing Uint8Array into the Java byte[] without per-byte
// virtual dispatch through the cooperative scheduler. This
Expand Down Expand Up @@ -99,6 +122,7 @@ public int available() throws IOException {
@Override
public void close() throws IOException {
buf = null;
local = null;
len = 0;
}

Expand Down
14 changes: 14 additions & 0 deletions Ports/JavaScriptPort/src/main/webapp/port.js
Original file line number Diff line number Diff line change
Expand Up @@ -3413,6 +3413,7 @@ bindCiFallbackWithMethodId("Form.addComponentNullContentPaneGuard", formAddCompo

const cn1ssCompleteMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_Cn1ssDeviceRunnerHelper_complete_java_lang_Runnable";
const cn1ssEmitChannelMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_Cn1ssDeviceRunnerHelper_emitChannel_byte_1ARRAY_java_lang_String_java_lang_String";
const cn1ssBridgeCountsMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_Cn1ssDeviceRunnerHelper_jsBridgeCallCounts_R_java_lang_String";
const baseTestCreateFormMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_BaseTest_createForm_java_lang_String_com_codename1_ui_layouts_Layout_java_lang_String_R_com_codename1_ui_Form";
const baseTestRegisterReadyCallbackMethodId = "cn1_com_codenameone_examples_hellocodenameone_tests_BaseTest_registerReadyCallback_com_codename1_ui_Form_java_lang_Runnable";
const baseTestFormSubclassClassId = "com_codenameone_examples_hellocodenameone_tests_BaseTest_1";
Expand Down Expand Up @@ -5128,6 +5129,19 @@ bindCiFallback("Cn1ssDeviceRunnerHelper.emitCurrentFormScreenshotDom", [
return null;
});

// Bridge-call counters for BridgeBulkTransferGuardTest: large-volume
// transfers must cost bridge calls proportional to operations, not bytes.
bindCiFallback("Cn1ssDeviceRunnerHelper.jsBridgeCallCounts", [
cn1ssBridgeCountsMethodId,
cn1ssBridgeCountsMethodId + "__impl"
], function*() {
// _L is the runtime's exported string-literal constructor (the same one
// every translated call site uses), so the return value is a real
// java.lang.String object.
return _L("jso=" + (jvm.__cn1JsoDispatchCount | 0)
+ ":host=" + (jvm.__cn1HostCallCount | 0));
});

bindCiFallback("Cn1ssDeviceRunnerHelper.emitChannelFastJs", [
cn1ssEmitChannelMethodId,
cn1ssEmitChannelMethodId + "__impl"
Expand Down
Loading
Loading