Skip to content

Parley: full-stack messaging sample, WebRTC and ECDH/HKDF in core - #6059

Merged
shai-almog merged 34 commits into
masterfrom
parley-messaging
Oct 22, 2026
Merged

shai-almog merged 34 commits into
masterfrom
parley-messaging

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

A third full-stack sample, a sibling of Wayline and Savor: Parley, an instant messenger at scripts/parley. It is offered as the PARLEY Initializr template. Two framework gaps it needed are closed in core.

Core

  • Security: KeyGenerator.ec(256) (P-256), KeyAgreement.ecdh and Hkdf (RFC 5869) on every port, with test vectors.
  • WebRTC: the new com.codename1.webrtc package, with PeerConnection, local media, VideoView and ICE.
    • Android uses the webrtc-sdk AAR and iOS uses WebRTC-SDK. Both are pulled in by PlatformFeatureCatalog only when the package is referenced.
    • The browser uses RTCPeerConnection.
    • The simulator uses a loopback.
    • The app owns signalling.

Parley

  • 1:1 and group chats, media and voice notes.
  • End-to-end encryption: X3DH over P-256 plus a double ratchet. Groups fan out to each member device. Safety numbers.
  • Multi-device.
  • Privacy: disappearing messages, receipt and typing toggles, last-seen visibility, block and report, app lock, screen security.
  • Live WebSocket and push.
  • Voice and video calls with the system call UI and VoIP push, plus TURN credentials.
  • Telegram and WhatsApp Cloud bridges, off unless configured.
  • Admin console and browser hosting.

CI and docs

  • parley.yml runs:
    • the backend tests
    • the simulator and browser e2e
    • the template check
    • the Android and iOS builds
  • User's and implementor's guide chapters, a WebRTC chapter and an ECDH/HKDF section.
  • A full-stack template generated for Java 17 now also raises the root pom's compiler level. The server and the shared module inherit that level.

🤖 Generated with Claude Code

shai-almog and others added 7 commits October 20, 2026 09:07
…port

KeyGenerator.ec, KeyAgreement.ecdh and Hkdf (RFC 5869, pure Java, shared with
the backend). JavaSE and Android use the JCA; iOS Security.framework, Linux
OpenSSL EVP, Windows BCrypt and the browser Web Crypto. EcP256Codec keeps the
DER in Java so every port hands out byte-identical SPKI/PKCS#8.

Fixes ECDSA on iOS (cn1_crypto_sign loaded every key as RSA) and in the
browser (the bridge refused EC signatures outright).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reactor, shared DTO/RestClient contracts, and the Codename One backend:
accounts, devices and prekeys, conversations and groups, the per-device
envelope queue, media blobs, live frames and push, privacy and moderation,
call signalling with TURN credentials, Telegram and WhatsApp Cloud bridges,
demo seed and bot. Client modules follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… ports

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ow menu

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the PARLEY full-stack template, parley.yml (backend, simulator and
browser e2e, template, Android and iOS builds), the user's and implementor's
guide chapters, a WebRTC chapter and the ECDH/HKDF security section. A
full-stack template generated for Java 17 now raises the root pom's compiler
level too, which the server and the shared module inherit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-21T06:11:46.353455Z 25fec8b Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ✅ ByteCodeTranslator: 0 findings (no issues)
    • ✅ android: 0 findings (no issues)
    • ✅ android-compat: 0 findings (no issues)
    • ✅ android-res-compiler: 0 findings (no issues)
    • ✅ backend: 0 findings (no issues)
    • ✅ backend-test: 0 findings (no issues)
    • ✅ build-engine: 0 findings (no issues)
    • ✅ build-hint-catalog: 0 findings (no issues)
    • ✅ build-hint-tools: 0 findings (no issues)
    • ✅ codenameone-gradle-plugin: 0 findings (no issues)
    • ✅ codenameone-maven-plugin: 0 findings (no issues)
    • ✅ core-unittests: 0 findings (no issues)
    • ✅ ios: 0 findings (no issues)
    • ✅ javac: 0 findings (no issues)
    • ✅ project-model: 0 findings (no issues)
  • ✅ PMD: 0 findings (no issues) [Report archive]
  • ✅ Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34a51b397c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Ports/iOSPort/nativeSources/CN1WebRTC.m Outdated
Comment thread Ports/Android/src/com/codename1/impl/android/webrtc/AndroidWebRtc.java Outdated
Comment thread Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java
Comment thread scripts/parley/backend/src/main/resources/db/migration/V3__messaging.sql Outdated
Comment thread Ports/iOSPort/nativeSources/CN1WebRTC.m
@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 12 screenshots: 12 matched.
✅ JavaSE simulator integration screenshots matched stored baselines.

@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 214 screenshots: 214 matched.
✅ JavaScript-port screenshot tests passed.

@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 178 screenshots: 178 matched.

Native Android coverage

  • 📊 Line coverage: 17.40% (30683/176345 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 15.70% (144927/923101), branch 10.67% (10017/93896), complexity 8.23% (7453/90604), method 12.02% (5159/42930), class 20.76% (1060/5105)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • com.codename1.androidcompat.rt.com.codename1.androidcompat.rt.TextXmlPullParser – 0.00% (0/623 lines covered)
      • com.codename1.androidcompat.androidx.constraintlayout.core.widgets.com.codename1.androidcompat.androidx.constraintlayout.core.widgets.Flow – 0.00% (0/576 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 17.40% (30683/176345 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 15.70% (144927/923101), branch 10.67% (10017/93896), complexity 8.23% (7453/90604), method 12.02% (5159/42930), class 20.76% (1060/5105)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • com.codename1.androidcompat.rt.com.codename1.androidcompat.rt.TextXmlPullParser – 0.00% (0/623 lines covered)
      • com.codename1.androidcompat.androidx.constraintlayout.core.widgets.com.codename1.androidcompat.androidx.constraintlayout.core.widgets.Flow – 0.00% (0/576 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 245ms / native 171ms = 1.4x speedup
SIMD float-mul (64K x300) java 157ms / native 135ms = 1.1x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 63.000 ms
Base64 CN1 decode 86.000 ms
Base64 native encode 579.000 ms
Base64 encode ratio (CN1/native) 0.109x (89.1% faster)
Base64 native decode 370.000 ms
Base64 decode ratio (CN1/native) 0.232x (76.8% faster)
Image encode benchmark status skipped (SIMD unsupported)

shai-almog and others added 3 commits October 20, 2026 13:14
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…screenshots

Server: a stale device copy is detected by device and owner, direct chats
are unique in the database, each person holds one call line, and the
offer and early ICE wait for a callee that was not connected.

Client: call failures only end the call they belong to, a repeated offer
is ignored, the media cache is bounded and cleared on wipe, acks survive
a restart, expiry runs from the summary, and a registration answer is
only applied to the identity it was sent for.

Ports: iOS queues ICE until the remote description is set and detaches
remote tracks on close; Android enters communication mode for a call;
the browser WebRTC runs in the host bridge; the JavaSE desktop app has
no simulator WebRTC.

UI: the chat composer carries the bottom safe area, the title is centred
on its avatar and buttons, and segmented choices always show the chosen
option. Guide images were recaptured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Flutter vs Codename One

Same application, built both ways: Flutter's AOT compile of the gallery, and the identical Dart source transpiled to Java on Codename One. Lower is better for every metric, so a ratio above 1.00x means Codename One is ahead by that factor.

android

9 interleaved rounds; host load 0.58, 1.75, 1.49

Metric Codename One Flutter Ratio Winner
Installed size 78.2 MB 95.8 MB 1.23x Codename One
Executable code 4.6 MB 20.6 MB 4.43x Codename One
Download size (zipped) 78.2 MB 95.8 MB 1.23x Codename One
Cold start to first frame on screen 384 ms 1686 ms 3.74x Codename One
Memory at rest 46.1 MB 78.6 MB 1.71x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 9 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 89 ms 188 ms 2.11x
longArithmetic 64 ms 59 ms 0.92x
mathTranscendental 225 ms 364 ms 1.62x
arraySequential 27 ms 36 ms 1.33x
arrayRandom 255 ms 429 ms 1.68x
objectAllocation 68 ms 51 ms 0.75x
valueEscape 7 ms 7 ms 1.00x
hashMapChurn 137 ms 320 ms 2.34x
stringBuilding 95 ms 129 ms 1.36x
recursion 85 ms 274 ms 3.22x
quicksortBench 129 ms 155 ms 1.20x
Geometric mean 1.46x

Gate: within tolerance against scripts/flutter-bench/baseline.

Android sizes are for the arm64-v8a slice a phone is delivered, on both sides; Flutter's release apk carries three ABIs and would otherwise count its engine about three times.
Android start-up and memory come from an x86_64 emulator with a software GPU. They compare the two runtimes on one machine; they are not phone timings, and a renderer that leans on the GPU is penalised more there.
This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

ios

9 interleaved rounds; host load 31.82, 37.45, 29.76

Metric Codename One Flutter Ratio Winner
Installed size 107.8 MB 110.5 MB 1.02x Codename One
Executable code 16.8 MB 19.1 MB 1.14x Codename One
Download size (zipped) 79.9 MB 81.9 MB 1.02x Codename One
Cold start to first frame on screen -- -- -- not measured
Memory at rest -- -- -- not measured

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Not measured: iOS compute is not measured: a device build needs signed hardware, and on the simulator Flutter runs its JIT debug engine rather than AOT code. The macOS row runs the same ParparVM and Dart AOT compilers on the same Apple silicon.

Gate: within tolerance against scripts/flutter-bench/baseline. Smaller than its baseline, which does not fail the gate: Executable code -9.20%; Installed size -1.55%; Download size (zipped) -0.76% -- rebaseline to tighten. To accept the move, download this platform's baseline-<platform>.json artifact and run python3 scripts/flutter-bench/flutter_baseline.py calibrate --pr 6059 --reason "<why these moved>" baseline-ios.json, then commit the overlay it writes.

iOS start-up and memory are not measured here: Flutter cannot AOT-compile for the simulator, so a simulator run would time a JIT debug build against a release build. Sizes come from release device bundles; timings need signed hardware.
This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

javascript

9 interleaved rounds; host load 2.19, 1.25, 0.54

Metric Codename One Flutter Ratio Winner
Installed size 103.9 MB 122.5 MB 1.18x Codename One
Executable code 12.8 MB 25.2 MB 1.97x Codename One
Download size (zipped) 76.3 MB 84.1 MB 1.10x Codename One
Cold start to first frame on screen -- -- -- not measured
Memory at rest -- -- -- not measured

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 645 ms wrong result Flutter: wrong result
longArithmetic 5026 ms did not run Flutter: did not run
mathTranscendental 561 ms did not run Flutter: did not run
arraySequential 227 ms 82 ms 0.36x
arrayRandom 1037 ms wrong result Flutter: wrong result
objectAllocation 38 ms 27 ms 0.71x
valueEscape 110 ms 7 ms 0.06x
hashMapChurn 1038 ms 245 ms 0.24x
stringBuilding 523 ms 107 ms 0.20x
recursion 506 ms 490 ms 0.97x
quicksortBench 402 ms wrong result Flutter: wrong result
Geometric mean 0.30x

Gate: within tolerance against scripts/flutter-bench/baseline; BEHIND FLUTTER on Compute (geomean of the VM workloads) (reported, not gated: a loss to Flutter on the web is currently accepted).

the JavaScript adapter needs a Chrome DevTools driver; sizes are reported and timings are not
This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

linux

9 interleaved rounds; host load 0.3, 2.5, 1.95

Metric Codename One Flutter Ratio Winner
Installed size 111.1 MB 143.8 MB 1.29x Codename One
Executable code 13.9 MB 16.1 MB 1.16x Codename One
Download size (zipped) 80.8 MB 92.9 MB 1.15x Codename One
Cold start to first frame on screen 123 ms 187 ms 1.54x Codename One
Memory at rest 85.1 MB 226.1 MB 2.66x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 9 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 65 ms 160 ms 2.46x
longArithmetic 49 ms 50 ms 1.02x
mathTranscendental 185 ms 203 ms 1.10x
arraySequential 13 ms 30 ms 2.31x
arrayRandom 186 ms 200 ms 1.07x
objectAllocation 20 ms 28 ms 1.40x
valueEscape 4 ms 6 ms 1.50x
hashMapChurn 35 ms 260 ms 7.43x
stringBuilding 26 ms 85 ms 3.27x
recursion 67 ms 230 ms 3.43x
quicksortBench 120 ms 128 ms 1.07x
Geometric mean 1.92x

Gate: within tolerance against scripts/flutter-bench/baseline. Smaller than its baseline, which does not fail the gate: Download size (zipped) -0.01% -- rebaseline to tighten. To accept the move, download this platform's baseline-<platform>.json artifact and run python3 scripts/flutter-bench/flutter_baseline.py calibrate --pr 6059 --reason "<why these moved>" baseline-linux.json, then commit the overlay it writes.

This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

macos

9 interleaved rounds; host load 7.61, 24.45, 28.76

Metric Codename One Flutter Ratio Winner
Installed size 123.6 MB 139.4 MB 1.13x Codename One
Executable code 32.5 MB 47.9 MB 1.48x Codename One
Download size (zipped) 85.4 MB 93.3 MB 1.09x Codename One
Cold start to first frame on screen 463 ms 579 ms 1.48x Codename One
Memory at rest 36.5 MB 56.1 MB 1.55x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 8 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 111 ms 253 ms 2.28x
longArithmetic 73 ms 68 ms 0.93x
mathTranscendental 310 ms 324 ms 1.04x
arraySequential 11 ms 43 ms 3.91x
arrayRandom 289 ms 316 ms 1.09x
objectAllocation 53 ms 26 ms 0.49x
valueEscape 7 ms 13 ms 1.86x
hashMapChurn 39 ms 195 ms 5.00x
stringBuilding 27 ms 107 ms 3.96x
recursion 139 ms 270 ms 1.94x
quicksortBench 127 ms 135 ms 1.06x
Geometric mean 1.71x

Gate: within tolerance against scripts/flutter-bench/baseline. Smaller than its baseline, which does not fail the gate: Executable code -7.99%; Installed size -2.23%; Download size (zipped) -1.32% -- rebaseline to tighten. To accept the move, download this platform's baseline-<platform>.json artifact and run python3 scripts/flutter-bench/flutter_baseline.py calibrate --pr 6059 --reason "<why these moved>" baseline-macos.json, then commit the overlay it writes.

This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

windows

9 interleaved rounds

Metric Codename One Flutter Ratio Winner
Installed size 107.5 MB 121.1 MB 1.13x Codename One
Executable code 11.2 MB 14.1 MB 1.26x Codename One
Download size (zipped) 77.7 MB 86.4 MB 1.11x Codename One
Cold start to first frame on screen 156 ms 237 ms 1.64x Codename One
Memory at rest 58.1 MB 92.8 MB 1.59x Codename One

Start-up and memory at rest are judged round by round: the ratio is the median of the per-round ratios, each from two launches made back to back, and the times and sizes shown are each side's median, so the ratio need not equal their quotient. Codename One was ahead in 9 of 9 rounds on cold start to first frame on screen; 9 of 9 rounds on memory at rest.

Compute -- the VM workloads (vm/benchmarks), run inside each app; time is the best of the app's own repetitions, higher ratio means Codename One is faster.

Workload Codename One Flutter Ratio
intArithmetic 83 ms 218 ms 2.63x
longArithmetic 53 ms 57 ms 1.07x
mathTranscendental 174 ms 204 ms 1.17x
arraySequential 9 ms 39 ms 4.33x
arrayRandom 254 ms 314 ms 1.24x
objectAllocation 34 ms 44 ms 1.29x
valueEscape 1 ms 12 ms 12.00x
hashMapChurn 43 ms 268 ms 6.23x
stringBuilding 25 ms 109 ms 4.36x
recursion 142 ms 220 ms 1.55x
quicksortBench 158 ms 149 ms 0.94x
Geometric mean 2.33x

Gate: within tolerance against scripts/flutter-bench/baseline. Smaller than its baseline, which does not fail the gate: Executable code -11.90%; Installed size -1.43%; Download size (zipped) -0.92% -- rebaseline to tighten. To accept the move, download this platform's baseline-<platform>.json artifact and run python3 scripts/flutter-bench/flutter_baseline.py calibrate --pr 6059 --reason "<why these moved>" baseline-windows.json, then commit the overlay it writes.

This platform's adapter has not been exercised end to end before; treat the first published run as the thing under review.

Codename One wins 26 of 26 measured metrics across 6 platform(s).

shai-almog and others added 3 commits October 20, 2026 14:36
…f Try it

A call needs a second device the Playground does not have, and the
Parley security rules are server code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r admin menu pick

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 193 screenshots: 193 matched.
Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 56ms / native 4ms = 14.0x speedup
SIMD float-mul (64K x300) java 56ms / native 4ms = 14.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 80.000 ms
Base64 CN1 decode 96.000 ms
Base64 SIMD encode 120.000 ms
Base64 encode ratio (SIMD/CN1) 1.500x (50.0% slower)
Base64 SIMD decode 107.000 ms
Base64 decode ratio (SIMD/CN1) 1.115x (11.5% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 9.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.444x (55.6% faster)
Image applyMask (SIMD off) 29.000 ms
Image applyMask (SIMD on) 29.000 ms
Image applyMask ratio (SIMD on/off) 1.000x (0.0% slower)
Image modifyAlpha (SIMD off) 39.000 ms
Image modifyAlpha (SIMD on) 28.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.718x (28.2% faster)
Image modifyAlpha removeColor (SIMD off) 88.000 ms
Image modifyAlpha removeColor (SIMD on) 21.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.239x (76.1% faster)

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

if ((x509[p] & 0x80) == 0) { innerLen = x509[p]; p++; }
else { sl = x509[p] & 0x7f; p++; innerLen = 0; for (int i = 0; i < sl; i++) innerLen = (innerLen << 8) | x509[p + i]; p += sl; }

P1 Badge Bounds-check every DER length before reading it

A malformed or truncated RSA SPKI can end immediately after the inner SEQUENCE tag; it passes the preceding tag check and these accesses then read beyond x509Len. The analogous PKCS#8 parser below has the same unchecked length-byte and length-body reads, so a key supplied through the public PublicKey or PrivateKey APIs can crash the iOS process instead of producing a CryptoException. Parse every tag and length with bounds and overflow checks before advancing the cursor.


var random = new Uint8Array(request.length | 0);
cryptoApi.getRandomValues(random);

P2 Badge Fill large browser random buffers in bounded chunks

crypto.getRandomValues() rejects any single typed array larger than 65,536 bytes, while SecureRandom.fill() exposes arbitrary Java byte arrays without documenting that browser-only ceiling. A browser call such as SecureRandom.bytes(65537) therefore fails even though the same API works on other ports. Fill the output in slices no larger than the Web Crypto quota.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vm/ByteCodeTranslator/src/javascript/browser_bridge.js Outdated
Comment thread vm/ByteCodeTranslator/src/javascript/browser_bridge.js Outdated
@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 193 screenshots: 193 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 56ms / native 4ms = 14.0x speedup
SIMD float-mul (64K x300) java 63ms / native 4ms = 15.7x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 74.000 ms
Base64 CN1 decode 90.000 ms
Base64 SIMD encode 107.000 ms
Base64 encode ratio (SIMD/CN1) 1.446x (44.6% slower)
Base64 SIMD decode 104.000 ms
Base64 decode ratio (SIMD/CN1) 1.156x (15.6% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 11.000 ms
Image createMask (SIMD on) 5.000 ms
Image createMask ratio (SIMD on/off) 0.455x (54.5% faster)
Image applyMask (SIMD off) 43.000 ms
Image applyMask (SIMD on) 49.000 ms
Image applyMask ratio (SIMD on/off) 1.140x (14.0% slower)
Image modifyAlpha (SIMD off) 59.000 ms
Image modifyAlpha (SIMD on) 30.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.508x (49.2% faster)
Image modifyAlpha removeColor (SIMD off) 24.000 ms
Image modifyAlpha removeColor (SIMD on) 14.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.583x (41.7% faster)

ParparVM vs HotSpot (JDK 25): Windows x64

Runner CPU: AMD64 Family 25 Model 1 Stepping 1, AuthenticAMD (baseline windows-x64@amd64-family-25-model-1-authenticamd)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.22x (base 1.22x, -0.4%) 0.76x (base 0.94x, -18.7%) ok
translator (self) 4 0.54x (base 0.60x, -10.9%) 0.62x (base 0.54x, +13.8%) ok
intArithmetic 4 1.17x (base 1.10x, +6.0%) 0.06x (base 0.06x, +4.6%) ok
longArithmetic 4 1.08x (base 1.08x, -0.0%) 0.05x (base 0.05x, +0.9%) ok
mathTranscendental 4 0.77x (base 0.79x, -2.2%) 0.06x (base 0.06x, -4.6%) ok
arraySequential 4 1.40x (base 1.36x, +3.0%) 0.39x (base 0.39x, +0.2%) ok
arrayRandom 4 1.19x (base 1.06x, +12.1%) 0.23x (base 0.23x, -0.1%) ok
objectAllocation 4 1.58x (base 1.56x, +1.1%) 0.31x (base 0.39x, -18.6%) ok
valueEscape 4 0.10x (base 0.10x, +0.4%) 0.04x (base 0.04x, -0.1%) ok
hashMapChurn 4 1.73x (base 1.80x, -3.7%) 0.10x (base 0.09x, +3.9%) ok
stringBuilding 4 1.30x (base 1.22x, +7.1%) 0.32x (base 0.32x, +0.5%) ok
recursion 4 1.49x (base 1.49x, -0.2%) 0.06x (base 0.06x, -1.2%) ok
quicksort 4 1.13x (base 1.13x, -0.2%) 0.12x (base 0.12x, -0.2%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 193 screenshots: 193 matched.
Native Linux port (x64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub x64 runner. Baseline: scripts/linux/screenshots.

ParparVM vs HotSpot (JDK 25): Linux x64

Runner CPU: AMD EPYC 9V45 96-Core Processor (baseline linux-x64@amd-epyc-9v45-96-core-processor)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.92x (base 0.92x, +0.9%) 0.88x (base 0.84x, +4.4%) ok
translator (self) 4 0.57x (base 0.64x, -11.5%) 0.51x (base 0.45x, +12.6%) ok
intArithmetic 4 1.00x (base 1.00x, +0.0%) 0.05x (base 0.06x, -2.1%) ok
longArithmetic 4 0.99x (base 0.99x, -0.0%) 0.06x (base 0.07x, -24.5%) ok
mathTranscendental 4 1.18x (base 1.20x, -1.3%) 0.08x (base 0.06x, +33.8%) ok
arraySequential 4 2.94x (base 2.91x, +1.2%) 0.36x (base 0.36x, -0.1%) ok
arrayRandom 4 1.04x (base 1.04x, +0.4%) 0.21x (base 0.23x, -7.6%) ok
objectAllocation 4 1.72x (base 1.61x, +6.9%) 0.26x (base 0.24x, +9.7%) ok
valueEscape 4 0.10x (base 0.10x, +1.5%) 0.04x (base 0.04x, +2.5%) ok
hashMapChurn 4 1.29x (base 1.31x, -1.4%) 0.09x (base 0.09x, +4.5%) ok
stringBuilding 4 1.57x (base 1.58x, -0.3%) 0.22x (base 0.22x, +2.8%) ok
recursion 4 1.35x (base 1.34x, +0.8%) 0.06x (base 0.08x, -25.5%) ok
quicksort 4 1.05x (base 1.06x, -0.8%) 0.11x (base 0.11x, +0.4%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 193 screenshots: 193 matched.
Native Linux port (arm64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub arm64 runner. Baseline: scripts/linux/screenshots-arm.

ParparVM vs HotSpot (JDK 25): Linux arm64

Runner CPU: Neoverse-N2 (baseline linux-arm64@neoverse-n2)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.93x (base 1.02x, -9.1%) 0.77x (base 0.93x, -17.7%) ok
translator (self) 4 0.74x (base 0.70x, +5.4%) 0.47x (base 0.51x, -7.9%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.03x (base 0.03x, -1.8%) ok
longArithmetic 4 0.79x (base 0.79x, -0.1%) 0.03x (base 0.03x, -3.4%) ok
mathTranscendental 4 1.10x (base 1.10x, +0.3%) 0.03x (base 0.03x, -0.3%) ok
arraySequential 4 0.35x (base 0.36x, -3.5%) 0.37x (base 0.37x, +0.4%) ok
arrayRandom 4 0.93x (base 0.94x, -0.3%) 0.20x (base 0.20x, +0.1%) ok
objectAllocation 4 1.95x (base 1.77x, +10.5%) 0.37x (base 0.37x, -0.4%) ok
valueEscape 4 0.51x (base 0.51x, -0.1%) 0.03x (base 0.03x, -1.2%) ok
hashMapChurn 4 0.84x (base 0.84x, +0.3%) 0.12x (base 0.12x, -3.7%) ok
stringBuilding 4 1.44x (base 1.57x, -8.0%) 0.26x (base 0.26x, -0.4%) ok
recursion 4 1.56x (base 1.43x, +8.9%) 0.03x (base 0.04x, -4.6%) ok
quicksort 4 0.99x (base 0.99x, +0.2%) 0.09x (base 0.09x, -0.0%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 193 screenshots: 193 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 50ms / native 2ms = 25.0x speedup
SIMD float-mul (64K x300) java 49ms / native 3ms = 16.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 61.000 ms
Base64 CN1 decode 70.000 ms
Base64 SIMD encode 78.000 ms
Base64 encode ratio (SIMD/CN1) 1.279x (27.9% slower)
Base64 SIMD decode 73.000 ms
Base64 decode ratio (SIMD/CN1) 1.043x (4.3% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 24.000 ms
Image applyMask (SIMD on) 27.000 ms
Image applyMask ratio (SIMD on/off) 1.125x (12.5% slower)
Image modifyAlpha (SIMD off) 24.000 ms
Image modifyAlpha (SIMD on) 20.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.833x (16.7% faster)
Image modifyAlpha removeColor (SIMD off) 29.000 ms
Image modifyAlpha removeColor (SIMD on) 21.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.724x (27.6% faster)

ParparVM vs HotSpot (JDK 25): Windows arm64

Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline windows-arm64@armv8-64-bit-family-8-model-d49-microsoft-corporation)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.02x (base 1.11x, -8.1%) 0.76x (base 0.75x, +1.1%) ok
translator (self) 4 0.87x (base 0.84x, +3.4%) 0.49x (base 0.51x, -3.8%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.06x (base 0.06x, +1.6%) ok
longArithmetic 4 0.79x (base 0.80x, -0.3%) 0.06x (base 0.06x, +1.9%) ok
mathTranscendental 4 0.72x (base 0.72x, -0.2%) 0.06x (base 0.06x, +0.5%) ok
arraySequential 4 0.38x (base 0.46x, -17.2%) 0.39x (base 0.39x, -0.1%) ok
arrayRandom 4 0.94x (base 0.94x, -0.1%) 0.23x (base 0.23x, -0.0%) ok
objectAllocation 4 1.81x (base 2.81x, -35.5%) 0.40x (base 0.43x, -6.6%) ok
valueEscape 4 0.76x (base 0.76x, +0.1%) 0.05x (base 0.05x, +2.2%) ok
hashMapChurn 4 0.99x (base 0.98x, +0.7%) 0.12x (base 0.12x, -3.2%) ok
stringBuilding 4 1.54x (base 1.43x, +8.1%) 0.27x (base 0.27x, -0.5%) ok
recursion 4 1.42x (base 1.46x, -2.8%) 0.06x (base 0.07x, -0.2%) ok
quicksort 4 1.00x (base 1.00x, +0.4%) 0.12x (base 0.12x, -0.1%) ok

Result: no regression

shai-almog and others added 4 commits October 21, 2026 11:45
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ript size row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… run them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 176 screenshots: 176 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 1171 seconds

Build and Run Timing

Metric Duration
Simulator Boot 52000 ms
Simulator Boot (Run) 1000 ms
App Install 13000 ms
App Launch 1000 ms
Test Execution 423000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 81ms / native 5ms = 16.2x speedup
SIMD float-mul (64K x300) java 95ms / native 4ms = 23.7x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 62.000 ms
Base64 CN1 decode 111.000 ms
Base64 native encode 1387.000 ms
Base64 encode ratio (CN1/native) 0.045x (95.5% faster)
Base64 native decode 1484.000 ms
Base64 decode ratio (CN1/native) 0.075x (92.5% faster)
Base64 SIMD encode 115.000 ms
Base64 encode ratio (SIMD/CN1) 1.855x (85.5% slower)
Base64 SIMD decode 60.000 ms
Base64 decode ratio (SIMD/CN1) 0.541x (45.9% faster)
Base64 encode ratio (SIMD/native) 0.083x (91.7% faster)
Base64 decode ratio (SIMD/native) 0.040x (96.0% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 8.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.250x (75.0% faster)
Image applyMask (SIMD off) 354.000 ms
Image applyMask (SIMD on) 33.000 ms
Image applyMask ratio (SIMD on/off) 0.093x (90.7% faster)
Image modifyAlpha (SIMD off) 29.000 ms
Image modifyAlpha (SIMD on) 22.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.759x (24.1% faster)
Image modifyAlpha removeColor (SIMD off) 43.000 ms
Image modifyAlpha removeColor (SIMD on) 44.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.023x (2.3% slower)

@shai-almog

shai-almog commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 236 screenshots: 236 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

@shai-almog

shai-almog commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 179 screenshots: 179 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 417 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 70ms / native 4ms = 17.5x speedup
SIMD float-mul (64K x300) java 68ms / native 2ms = 34.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 72.000 ms
Base64 CN1 decode 81.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 13.000 ms
Image createMask (SIMD on) 5.000 ms
Image createMask ratio (SIMD on/off) 0.385x (61.5% faster)
Image applyMask (SIMD off) 87.000 ms
Image applyMask (SIMD on) 70.000 ms
Image applyMask ratio (SIMD on/off) 0.805x (19.5% faster)
Image modifyAlpha (SIMD off) 72.000 ms
Image modifyAlpha (SIMD on) 73.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.014x (1.4% slower)
Image modifyAlpha removeColor (SIMD off) 85.000 ms
Image modifyAlpha removeColor (SIMD on) 74.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.871x (12.9% faster)

ParparVM vs HotSpot (JDK 25): macOS arm64

Runner CPU: Apple M1 (Virtual) (baseline macos-arm64)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (HelloCodenameOne) 3 0.95x (base 0.96x, -1.0%) 0.89x (base 0.93x, -4.0%) ok
translator (self) 3 0.61x (base 0.62x, -2.0%) 0.51x (base 0.58x, -10.7%) ok
intArithmetic 3 1.07x (base 1.03x, +3.4%) 0.12x (base 0.12x, +0.7%) ok
longArithmetic 3 0.99x (base 1.03x, -3.7%) 0.11x (base 0.07x, +63.5%) ok
mathTranscendental 3 0.92x (base 1.01x, -9.1%) 0.12x (base 0.12x, +0.1%) ok
arraySequential 3 0.51x (base 0.42x, +22.5%) 0.53x (base 0.53x, -0.1%) ok
arrayRandom 3 0.99x (base 0.99x, +0.5%) 0.32x (base 0.32x, +0.2%) ok
objectAllocation 3 1.01x (base 1.11x, -8.6%) 0.86x (base 0.72x, +19.1%) ok
valueEscape 3 0.51x (base 0.51x, -0.4%) 0.08x (base 0.09x, -4.1%) ok
hashMapChurn 3 1.01x (base 1.18x, -13.8%) 0.07x (base 0.07x, +11.4%) ok
stringBuilding 3 0.90x (base 0.84x, +7.0%) 0.47x (base 0.46x, +0.7%) ok
recursion 3 1.25x (base 1.24x, +0.9%) 0.12x (base 0.12x, +0.5%) ok
quicksort 3 0.94x (base 1.01x, -7.6%) 0.11x (base 0.11x, +0.2%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 176 screenshots: 176 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 2437 seconds

Build and Run Timing

Metric Duration
Simulator Boot 113000 ms
Simulator Boot (Run) 1000 ms
App Install 17000 ms
App Launch 4000 ms
Test Execution 532000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 109ms / native 3ms = 36.3x speedup
SIMD float-mul (64K x300) java 174ms / native 4ms = 43.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 111.000 ms
Base64 CN1 decode 70.000 ms
Base64 native encode 1210.000 ms
Base64 encode ratio (CN1/native) 0.092x (90.8% faster)
Base64 native decode 1064.000 ms
Base64 decode ratio (CN1/native) 0.066x (93.4% faster)
Base64 SIMD encode 198.000 ms
Base64 encode ratio (SIMD/CN1) 1.784x (78.4% slower)
Base64 SIMD decode 221.000 ms
Base64 decode ratio (SIMD/CN1) 3.157x (215.7% slower)
Base64 encode ratio (SIMD/native) 0.164x (83.6% faster)
Base64 decode ratio (SIMD/native) 0.208x (79.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 5.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.600x (40.0% faster)
Image applyMask (SIMD off) 44.000 ms
Image applyMask (SIMD on) 219.000 ms
Image applyMask ratio (SIMD on/off) 4.977x (397.7% slower)
Image modifyAlpha (SIMD off) 189.000 ms
Image modifyAlpha (SIMD on) 52.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.275x (72.5% faster)
Image modifyAlpha removeColor (SIMD off) 77.000 ms
Image modifyAlpha removeColor (SIMD on) 102.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.325x (32.5% slower)

@shai-almog

shai-almog commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 171 screenshots: 171 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

…are dropped or re-anchored); Parley's own JS size overlay is covered by #5976's and goes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
Rows master had already moved made it unreadable; same repair as
3702c6c on parley-messaging, so the two branches merge cleanly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…op of master

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
…lent sim audio

- Core gaming classes: foreach loops and documented NOPMD on the intentional
  identity checks and the per-frame scratch matrix; AnimatedModel and
  ParticleEmitter javadoc examples are complete runnable programs.
- Guide: Playground opt-out for sample code, the MCP link uses the chapter's
  generated id again (the explicit anchor broke the website's links),
  LanguageTool terms.
- Skirmish: placeholder android.licenseKey for its in-app purchases; Sfx only
  uses a native mixer, so a simulator without an audio device stays silent
  instead of starting a browser engine per sound.
- From #6059: perf-baseline overlay 5976 re-measured, starter-launchers macOS
  timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
…r already moved are dropped or re-anchored)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog and others added 2 commits October 22, 2026 08:03
…rrent master

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ly pointer

#6073 gives any browser with a fine pointer desktop scrollbars. Headless
Chromium reports a mouse, so every scrollable screen in the phone-sized
suite gained an always-visible gutter and 48 goldens stopped matching.
Answer only (any-pointer: fine) as a touch device would; the coarse query
isPrimaryPointerMouse() reads keeps Chromium's answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog
shai-almog merged commit ec55724 into master Oct 22, 2026
144 of 154 checks passed
@shai-almog
shai-almog deleted the parley-messaging branch October 22, 2026 10:33
shai-almog added a commit that referenced this pull request Oct 22, 2026
Takes master's #5976 baseline overlays (repaired in #6059) over this branch's
deletion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
#6059 rebaselined the JavaScript and Linux gallery size rows from the
same values this PR did, so those rows are dropped here to be measured
again on top of it. The x64 translator override starts from the row as
master now reads it, after #6059 removed the stale #5976 entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
* Add pure-logic Java class library additions to JavaAPI and CLDC11

java.util.function, java.util.stream, java.time, java.text, collections,
java.util.concurrent, non-file java.io streams, java.lang members,
MessageDigest/SecureRandom, charsets and UUID. Host-backed APIs (files,
nio.file, prefs, logging, URL, resource bundles, service loader, modules)
are left as on master. JdkHost is a narrow internal hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Install the narrow JdkHost from the ParparVM ports

CoreJdkHost serves the EDT waits, log, secure random, digests and locale
number symbols; JavaSE and Android carry a copy of JdkHost for the core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Translator runtime support and bulk conformance tests for the class library

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Rewrite every String regex member onto com.codename1.util.regex

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: review fixes and CI root causes

- No object serialization: ObjectInput, ObjectOutput and Externalizable are
  back to master's empty interfaces in vm/JavaAPI and gone from Ports/CLDC11.
- Concurrency reads one monotonic clock (BlockingWait.now, System.nanoTime)
  for every deadline and delay, so a wall-clock change cannot fire a timed
  wait or a scheduled task early or late.
- A positive timeout under a millisecond is rounded up instead of being
  due immediately (BlockingWait.millis), at every timed call site.
- FutureTask consumes the runner's interrupt only when cancel(true)
  delivered it; cancel(false) leaves the thread's status alone.
- Character: the unassigned Greek code points are not letters.
- CoreJdkHost finds the locale's separators between any script's decimal
  digits, not only ASCII ones.
- Bulk checks: sub-millisecond timed get, cancel(false) interrupt status.
- CI: copyright exclusions for the Harmony/OpenJDK-derived classes, the
  backend javadoc run no longer documents the class library's internal
  com.codename1.impl, CodeQL no longer resolves the JDK's SecureRandom to
  the device class library's copy, and the flutter-bench size overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: second round of review fixes

- Duration.dividedBy is exact past 292 years: the magnitude is divided as
  an unsigned 128-bit number when the nanosecond count overflows a long.
- Character: the unassigned CJK compatibility code points are not letters.
- Math.scalb's clamp counts all 53 (24) significand bits, so an extreme
  negative factor underflows to a signed zero; cbrt scales subnormals.
- ScheduledPool saturates a fixed rate's next deadline and consumes only
  the interrupt cancel(true) delivered.
- PrintWriter.checkError reports a wrapped PrintWriter's failure.
- Matcher stays exhausted after a zero-width match at the region end.
- Bulk checks for each, and MatcherExhaustionTest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: third round of review fixes and baselines

- tanh: Lambert continued fraction for |x| < 1 (within 1.05 ulp).
- String(byte[], int, int, ...): range checked before the native reads it.
- Pool: a worker thread that fails to start gives its slot back.
- Character: CJK extension ranges split at their unassigned gaps.
- Recalibrate the Linux flutter size row and the windows-arm64 hello RAM row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: fourth round of review fixes and baselines

- CompletableFuture: completions drain a per-thread queue, so a long
  chain cannot overflow the stack; a waiter that times out or is
  interrupted is taken off the stack.
- Character: script letters are a table generated from JDK 21's data.
- StringBuffer.compareTo: snapshots the other buffer, no nested locks.
- DateTimeFormatter: each X/x/Z width parses only its own offset form.
- Math.hypot: compensated, within 1 ulp.
- ScheduledPool: re-checks cancellation after claiming the runner.
- Recalibrate the Linux flutter size row and the linux-x64 translator RAM row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: fifth round of review fixes

- Locale.forLanguageTag: only '-' separates subtags.
- MessageFormat: clone keeps, and equals compares, formats the pattern
  cannot spell.
- Collectors.flatMapping: the consuming failure wins, close's is suppressed.
- StreamState.abandon: releases every stage after an Error too.
- CountDownLatch.await: throws for an interrupted caller on an open latch.
- Comments on why the pool's workers survive a failed task and why
  CharSequence streams read eagerly.
- Recalibrate the Linux flutter size row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: sixth round of review fixes

- Regex: ? and {0,1} take their one round of a group that can only match
  empty, so "(^)?" captures the empty string, as the JDK does.
- ZoneId.of: a region ID starts with a letter.
- InputStreamReader/OutputStreamWriter.getEncoding: null once closed.
- BufferedWriter.close: the flush failure wins, close's is suppressed.
- DecimalFormatSymbols: comment on why US NaN stays U+FFFD (JDK 8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API additions: seventh round of review fixes

- Pool.execute: a command that needs a new worker is handed to it, never
  queued, so a thread that fails to start cannot leave it run by another;
  a command queued meanwhile gets a replacement worker.
- BufferedOutputStream.close: the flush failure wins, close's is suppressed.
- ScheduledPool: deadlines saturate, so a huge delay is not already due.
- Collectors: identity-finish collectors report IDENTITY_FINISH, toSet
  also UNORDERED.
- CopyOnWriteArrayList.addAll: snapshot the source before locking.
- PrintWriter: an InterruptedIOException re-interrupts the thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: URI query split, null arguments, ill-formed locale tags

- URI splits the query at the first '?', so later ones stay in the query.
- String charset-name overloads, Clock.fixed and SecureRandom's seed array
  refuse null as the JDK does.
- Locale.toLanguageTag writes und for an ill-formed language and drops an
  ill-formed region.
- Comments on why String.lines stays eager and why a negative grouping
  size is accepted (JDK 8 to 18 behaviour).
- windows-x64 hello RAM perf baseline recalibrated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: FutureTask run-once, ranges, overflow, reentrant removeIf

- FutureTask records the outcome before releasing the runner, so a
  concurrent run() cannot call the task twice, and no longer clears an
  interrupt that may not be the cancellation's.
- String.indexOf(int, int, int) searches a supplementary code point as
  its pair and requires it wholly inside the range.
- UUID.fromString refuses a component past Long.MAX_VALUE.
- CopyOnWriteArrayList.removeIf keeps a predicate's own change and throws
  ConcurrentModificationException instead of overwriting it.
- PrintWriter refuses a null Writer.
- Comment on why an unstarted worker still runs its first task after
  shutdownNow (ThreadPoolExecutor does the same).
- Linux flutter size baseline recalibrated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: ISO offsets, negative zero year, addAllAbsent lock order

- ISO offset parsing refuses the compact +HHMM and +HHMMss forms.
- An ISO date refuses the year -0000.
- CopyOnWriteArrayList.addAllAbsent snapshots its source before locking,
  as addAll does, so two lists adding each other cannot deadlock.
- Comments on why an empty ChoiceFormat alternative keeps the JDK 8
  answer and why Matcher.results does not fail fast on misuse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: zero multiplier parse, null buffers, variants, RandomAccess

- DecimalFormat with a zero multiplier parses zero as NaN and anything
  else as an infinity, instead of returning the number unchanged.
- BufferedReader and BufferedWriter refuse a null delegate.
- Locale.toLanguageTag leaves out a variant that cannot be written as a
  private-use subtag.
- List.reversed() of a RandomAccess list is RandomAccess too.
- Conformance checks, including that sharp s keeps its case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: List/Set spliterator characteristics, chunked String writes

- List's default spliterator reports ORDERED and Set's DISTINCT.
- BufferedWriter.write(String, int, int) copies through its own buffer a
  chunk at a time instead of allocating a copy of the whole range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: scheduled cancel race, runAndReset, allOf, edge cases

- ScheduledPool: cancel(true) re-checks the runner while marked
  INTERRUPTING and the run waits that out on leaving, so an interrupt can
  no longer reach a worker that has moved on to another task.
- FutureTask.runAndReset records a failure before releasing the runner.
- CompletableFuture.allOf copies the caller's array.
- Instant.until(MILLIS) works from the deltas, so instants near MIN and
  MAX no longer overflow.
- StringBuilder.repeat with a zero count returns before validating.
- windows-arm64 translator RAM perf baseline recorded as measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: adapter characteristics, CharSequence.compare, null streams

- Collectors.mapping, filtering and flatMapping keep the downstream
  collector's characteristics; collectingAndThen drops only
  IDENTITY_FINISH.
- CharSequence.compare uses a Comparable type's own order when both
  arguments are of that type.
- InputStreamReader and OutputStreamWriter refuse a null stream in their
  Charset constructors.
- RAM perf baselines recorded as measured for linux-x64, windows-x64 and
  macos-arm64, which all improved on new runner CPUs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: backtracking \R, continued property keys, close on Error

- \R in the regex engine is no longer atomic, so a CR LF pair splits
  when what follows needs the LF (\R\R matches CR LF, as Java 9+ does).
- Properties.load takes an = or : on the line after a key ended by
  blanks and a continuation.
- BufferedOutputStream and BufferedWriter close the delegate when
  flushing throws an Error.
- Comment on why the Matcher replace callbacks do not fail fast.
- Linux flutter size baseline recalibrated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: URI relative references, sorted spliterators, leap seconds

- URI: a reference without a scheme is not absolute (resolve() handed every
  relative reference back unresolved), an empty path is "" not null, a
  relative path merges with the base directory, and normalize() keeps the
  path's own leading and trailing slashes.
- Spliterators: an iterator spliterator declared SORTED reports natural order.
- ISO instants: only 23:59:60 is a leap second.
- DecimalFormat: a null affix is stored, as JDK 8 stores it.
- Charset copies its alias array; deadlines are overflow safe for any clock
  origin.
- Comments for the ideographic blocks and BufferedWriter locking.
- windows-arm64 hello RAM baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: concat null checks, fixed-rate deadlines, removeIf

- Int/Long/DoubleStream.concat check both arguments before consuming one.
- ScheduledPool: the fixed-rate step is overflow safe for any clock origin,
  and shutdownNow() no longer answers a fixed-rate task twice when its
  wrapper is already queued in the pool.
- CopyOnWriteArrayList.removeIf throws ConcurrentModificationException when
  the predicate changed the list, as filter() does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: null checks, invokeAll validation, immutable sublists

- PrintWriter refuses a null OutputStream at construction.
- invokeAll wraps every task, refusing a null, before submitting any.
- Period.addTo/subtractFrom refuse a null temporal even for a zero period.
- List.of(...).subList is an immutable copy, so clear() on an empty range
  still throws.
- Comments for PrintWriter locking and recursive computeIfAbsent (JDK 8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: close suppression, removeIf check order, subList IAE

- BufferedWriter/BufferedOutputStream.close attach a delegate close failure
  of any kind to the flush failure instead of losing the original.
- CopyOnWriteArrayList.removeIf checks for a reentrant change before its
  nothing-removed return.
- List.of(...).subList throws IllegalArgumentException for reversed bounds.
- Comments for the MessageFormat argument ceiling (JDK 8 has none) and the
  default uncaught-exception handler field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: failures skip the executor, X- charsets, unordered set

- CompletableFuture: thenApply/thenAccept/thenRun/thenCompose (async) pass
  an upstream failure on at once instead of submitting a step a shut-down
  executor would reject in its place.
- Charset.isRegistered is false for the reserved X- prefix.
- Collectors.toUnmodifiableSet reports UNORDERED.
- A note at the NaN canonicalization on the raw-bits methods sharing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: variant tags, date literals, stream and regex order

- Locale.toLanguageTag writes the well-formed leading variant subtags as
  they are and only the rest as x-lvariant, as JDK 8 does.
- SimpleDateFormat (and MessageFormat date arguments) check each literal.
- URI.normalize keeps an unmatched ".." without adding a slash.
- Stream.collect checks the stream's state before calling the supplier.
- The rewritten String regex members check the receiver first.
- Comment: a terminated shutdown hook is accepted, as on JDK 8.
- windows-x64 (AMD family 26) baseline from a second sample.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: allOf/anyOf null checks, runner release, characteristics

- CompletableFuture.allOf/anyOf check every input before installing any
  callback.
- FutureTask releases its runner even when done() throws.
- Int/Long/DoublePipeline.collect check the stream before the supplier.
- groupingBy reports IDENTITY_FINISH when its downstream does.
- String.indexOf(int,int,int) answers -1 for a value that is no code point.
- The literal split shortcut leaves a lone surrogate to the engine.
- Comments: partitioningBy is never IDENTITY_FINISH; the sharp s is below
  the Latin-1 upper-casing range.
- Perf rows for linux-x64 EPYC and windows-x64 Intel from this run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: prefixed zone syntax, yield interrupt, CLDC parity

ZoneId.of validates the region syntax of a UTC/GMT/UT-prefixed ID with
no sign; Thread.yield leaves the interrupt status set; COWAL removeAll
and retainAll check for a reentrant change before the nothing-removed
return. The CLDC DateTimeFormatter accepts a leap second only at 23:59,
and the CLDC ScheduledPool.shutdownNow no longer lists an owed fixed-rate
firing twice. Duration.ZERO.addTo(null) stays as JDK 8 has it.
Flutter linux download-size baseline moved by 2 bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: authority-only resolve, runAndReset release, CHM views

URI.resolve puts a root slash before a relative path merged onto a base
with an authority and an empty path, so "a" against http://h is
http://h/a, not http://ha. FutureTask.runAndReset releases its runner
even when done() throws. ConcurrentHashMap's values view rejects a null
query and the plain keySet view rejects addAll even for an empty input.
The android-compat test cleanup resets dark mode and refreshes the
configuration, which a test order that ran ResumeConfigurationTest
first left dark.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: URI scheme grammar, ZZZZ parse, weak-map lookup

URI rejects a colon in the first segment of a relative path, and a
scheme must start with a letter and may hold "+" and "." (svn+ssh).
DateTimeFormatter parses ZZZZ as the localized GMT offset it prints.
WeakHashMap compares with the queried key's equals. Properties keeps the
empty entry a last line of only a backslash makes. The perf overlay
drops three rows master's pr/6045.json already re-recorded from the same
value, which the baseline gate refuses to see twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: full localized offset, stats toString, done stages

OOOO and ZZZZ parse only the full localized offset (GMT+08:00), as the
JDK does. Int/Long/DoubleSummaryStatistics print the JDK's summary. A
CompletableFuture dependent completed by hand skips its action. A
reversed view hands bulk changes to the backing list, so an unmodifiable
one refuses even a no-op. NavigationTest uninstalls its static dispatcher
and LocalContinuityTest clears it: one left behind answered a Form for
any route and made an unknown route restorable. linux-x64
objectAllocation RAM recorded lower.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: extreme instants, aggregate time conflicts, Month, combined stages

Instant.parse round-trips Instant.MIN/MAX, N/A fields conflict-check
against component fields, a bare Month formats, and thenCombine /
applyToEither skip their action once the dependent is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: day-of-year conflicts, bound spliterators, atomic addAllAbsent, script letters

Word boundaries take counted quantifiers, a day-of-year is checked
against the resolved date, the first estimateSize binds a collection
spliterator, addAllAbsent publishes once, and the script letter table
covers its blocks whole. Records the linux Flutter size and the linux
arm64 translator RAM moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: extlang subtags, CHM entry-set add, racy blockUi check

forLanguageTag reads extended language subtags, ConcurrentHashMap's
entry set writes through on add, and the blockUi conformance check
expects a second blocking wait only when the join really waits.
Records the linux Flutter size and linux x64 translator RAM moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Java API review fixes: custom temporal units, parse past the end, snippet name clash

TemporalUnit.isSupportedBy probes like the JDK instead of recursing,
DateFormat.parse fails cleanly at a start past the end, and the
Playground's auto-import prefers the one Codename One class when the
device library adds a JDK class of the same name (SecureRandom,
Temporal). Drops seven doc-snippet baseline entries that now run and
records the linux x64 stringBuilding and windows x64 translator moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Unmodifiable lists reject every mutation, stack traces print suppressed throwables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Map.of views reject clear, initializr build test prints the end of a failed build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Offset-only parses, MessageFormat clones its subformats, async stages use defaultExecutor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* usePattern keeps zero-width advancement, reversed views snapshot aliased input

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Zero offsets print as zero, ISO instants need offset minutes, U+180E is not white space

Drops the windows-x64 recursion rebaseline that master's baseline fold superseded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* A continuation can join a nested dependent, CHM view removeIf keeps replaced mappings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Regex by code point with Unicode tables; randomUUID needs a secure source

- Pattern matches, repeats and backtracks by code point, so "." and a
  class take a whole surrogate pair, and classes hold code points above
  U+FFFF.
- Scripts, blocks and general categories, and UNICODE_CHARACTER_CLASS
  ((?U)), are answered from the generated Unicode 15.0 tables in
  UnicodeTables rather than refused.
- UUID.randomUUID throws without a secure random source instead of
  falling back to a clock-seeded generator.
- ChoiceFormat writes an infinite limit as "<" explicitly rather than
  through a NaN comparison ParparVM answers differently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* PMD fixes in the regex engine; rebaseline Flutter size for the Unicode tables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Recalibrate linux x64 translator and objectAllocation perf rows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Regex review: pairs in escapes and quotes, JDK search rule, tables for every property

- A search skips the positions inside a surrogate pair when the pattern
  names a supplementary code point or a surrogate, as the JDK's StartS
  does, so a negated class no longer matches half a pair.
- Two backslash-u escapes spelling a pair are one code point, and
  \Q...\E quotes code points, inside a class and out (Pattern.quote of
  an emoji matched nothing).
- The JDK's binary properties and the general categories answer from
  UnicodeTables for all of Unicode; IsWhite_Space no longer takes
  U+001C-U+001F, and a case category under CASE_INSENSITIVE takes Lu, Ll
  and Lt as on the JDK.
- Ports/CLDC11 Random: a no-break space in a comment failed an ASCII
  compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Regex review 2: properties skip pair halves, caseless back references and classes, marks in words

- A pattern with a Unicode property or a (?U) shorthand skips the
  positions inside a pair, as the JDK's search does, so [^\p{L}] no
  longer takes half a supplementary letter.
- A caseless back reference compares code points.
- A caseless Unicode class also tries the lower form of the upper one,
  so (?iu)[a-z] takes U+0131 and U+017F as on the JDK.
- \b and \B count a non-spacing mark after a letter or digit as part of
  the word, and read the lone high half before a position inside a pair.
- usePattern keeps the match and drops its groups; group(0) is null.
- \p{all}.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Regex review 3: unbounded single-atom lookbehind, quantified \R keeps its pair

- A lookbehind may repeat one character without bound, as on JDK 21
  ("(?<=a+)b"); a group repeated without bound or a back reference
  inside one is still refused, as there.
- A quantifier repeats \R whole, so each round takes \r\n as a pair.
- Code comments on the JDK parser accidents left alone: a leading {1},
  x{1}{2}, and [a&&&b].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Regex review 4 (fuzzing): escaped pairs, COMMENTS before a suffix, folded class members

- An escaped supplementary character is one atom under a quantifier.
- COMMENTS mode skips whitespace before the ? or + of a quantifier.
- A single class member under UNICODE_CASE also stands for its folded
  form, so (?iu)[ı] takes "I" as on the JDK.
- A possessive repeat of an empty group takes its round and sets it.
- (?) is refused.
- Code comments on the JDK accidents left alone: which positions inside
  a pair its search accepts, the inner groups of repeated empty groups,
  and its && grammar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Rebaseline Flutter linux size for the regex code-point work

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Rebase the size and perf overlays onto master's #6059

#6059 rebaselined the JavaScript and Linux gallery size rows from the
same values this PR did, so those rows are dropped here to be measured
again on top of it. The x64 translator override starts from the row as
master now reads it, after #6059 removed the stale #5976 entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
…e build-time compiler (#6032)

* CSSThemeCompiler: #Constants, font-size and box semantics matching the build-time compiler

Fixes #6024.

- #Constants is a constants block like @constants, wherever it sits; constant
  and custom-property names keep their case and quoted values are unquoted.
- font-family/font-size build a Font with the build-time compiler's unit
  conversions, per UIID state, even when declared in separate rules.
- padding/margin expand 1-4 values into top,bottom,left,right storage order
  and emit padUnit/marUnit per side (px/pt pixels, mm/cm, %, rem, vw...).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: color and image constants, state fonts inherit the base

- Unquoted color literals in a constants block are stored as plain hex, as the
  build-time compiler stores them; consumers parse them with parseInt(v, 16).
- A constant whose name ends in Image resolves to the resource image and a
  missing one fails the compile; getThemeImageConstant casts to Image, which
  is unchecked on iOS.
- Fonts are built after all rules: a state that sets only family or size takes
  the other from the base style (and a dark style from the light one).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: constants in source order, var() color constants, derive-aware state fonts

- Constants blocks are applied again in source order, so a later declaration
  wins against :root and in-rule custom properties; the first pass still makes
  them visible to rules above the block.
- A constant written as var(--x) is normalized to plain hex once resolved if
  it is a color.
- A state font missing family or size completes it from the UIID's base style
  and then each cn1-derive parent's matching state and base, as the build-time
  compiler's flattening does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: resolve var() before looking up an image constant

An image constant written as var(--x) is looked up once variables are
resolved, so a custom property declared after the constants block (or in
:root) no longer fails the compile with an unresolved image name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: defer image constants past rules, quote-aware rule braces, state-first font fallback

Image constants are looked up after every rule ran, so a cn1-mutable-image
can supply one. Only the winning declaration of a constant decides whether
it is reinterpreted as an image or a var() color. A quoted brace no longer
ends a rule. A state font searches the matching state along the derive
chain before any unselected style. The GUI builder normalizer keeps the
units the compiler already stored instead of resetting them to px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: rgba() and quoted constants, quote-aware comments, cyclic vars, * font fallback

rgba() color constants are stored as their RGB hex. A quoted constant is
a string: its var() text is not resolved, and comment delimiters inside
quotes are text. A cyclic var() reference is a syntax error instead of a
compile that never returns. A state font falls back to the * style after
the derive chain. The GUI builder test that used font-size as its example
of an unsupported declaration now uses font-style, since the canvas
compiler supports font-size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: every rule resolves var() against the final constants

All constants -- #Constants entries, :root and in-rule custom properties --
are stored in source order before any rule runs, so a rule between two
declarations of a constant sees the last one, as the build-time compiler
does. Unquoted custom properties keep their var() text and resolve where
they are used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: cn1rgb constants, literal aliases, state derives in fonts, CSS hex escapes

cn1rgb()/cn1rgba() color constants are stored as hex like rgb()/rgba().
A quoted constant stays text when reached through another constant. A
state font follows the state's own cn1-derive. Quoted values decode CSS
hexadecimal escapes. The GUI builder no longer reports #Constants entries
as declarations the canvas drops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: match the build-time compiler on ordering, * fonts, % insets and size keywords

Custom properties take effect where they are declared, as the build-time
parser's callbacks do; #Constants stay visible to every rule, and only the
winning declaration of a name is re-applied in source order. The * style
no longer feeds fonts, since the build-time compiler ignores universal
rules. A state's own cn1-derive is followed at every hop. Font-size
keywords match exactly, and percentage padding/margin is rejected like
the build-time compiler rejects it. An alias of a quoted constant stays
text. The GUI builder's constants-block check ignores quoted braces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: per-compile constant typing, sibling-state derives, no relative size keywords

Only constants declared by this compile are resolved, so a literal from an
earlier compile into the same theme keeps its text. A cn1-derive declared
in any state applies to the UIID's other states for fonts, as the
build-time compiler does. smaller/larger are rejected, since neither
compiler resolves them against the inherited size. The build-time
compiler now emits decimal constants instead of dropping them. The GUI
builder resolves image constants from the project's res folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: in-rule custom property order, last state derive wins, incremental fonts, CRLF continuations

Also rejects unitless decimal insets, picks the GUI builder's image variant
for the display density and drops the identity comparison PMD flagged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: earlier compiles' constants stay text, same-state recompiles keep the font

GUI builder: pick image variants the way MultiImage.getBest() does and stop
accepting a loose image file the build-time compiler would not find.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: strip !important, keep system font families and earlier color aliases

GUI builder: search res/Theme before other theme folders. The test
implementation now reports the face and size a system font was created with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a quoted custom property stays a string token in styles

GUI builder: accept upper-case .PNG variants; document why the denser-only
fallback stays deterministic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: last derive wins for every state, build-time family walk, CSS number syntax

GUI builder: density variants match in any case. Documents why quoted typing
is not recovered across separate compile() calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: #Constants aliases resolve where declared

GUI builder: unnamed PNG variants count as medium density and the parent
folder's res is searched, as the build-time compiler does. Documents why an
incremental derive change does not rebuild earlier fonts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: #Constants in source order, var() fallbacks; CSSTheme: font-size medium

The build-time parser resolves var() as it reads each declaration, so a rule
above a #Constants block no longer sees it; the runtime-only @constants block
keeps applying first. The build-time compiler stored font-size: medium as a
zero-size pixel font.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: track the open quote for !important, reject #Constants lengths; GUI builder: case-sensitive density names

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: #Constants stores numbers as the build does, rejects tokens it drops; CSSTheme: system-ui is generic

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: keyword size keeps an inherited native family, font-size 0, escaped/non-ASCII identifiers, whitespace in var()

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: drop constants with an undefined var(), reject unterminated var() and exponent insets, integer px font sizes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: only --name declarations are variables, dark fonts stand alone, typed fallbacks, ! important

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a color or number named ...Image is not an image; image aliases resolve where declared

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: #Constants aliases resolve against earlier declarations only, Default.* at the root, * sets no font, escaped image names and bangs; GUI builder: a corrupt variant fails the folder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a plain #Constants entry no longer hides a custom property of the same name from var()

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a later :root property does not change an exported constant, exponent constants are rejected, escaped font families are decoded

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: variables kept apart from exported constants, multi-token aliases export the leading token, exponent insets and raw newlines in strings rejected

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: constant names must be identifiers, image aliases decode escaped names, exponent font sizes rejected; GUI builder: support probe resolves project images

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a direct multi-token constant exports its leading token; GUI builder: a directory named x.png is not a variant

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: an image alias of a color or number is typed as one; escaped colons in declaration names

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* GUI builder: cache canvas support per declaration value, not per property

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: legacy @constants stay overridable, self-referencing custom properties are a cycle, pressed derives stay in their state, percentage rgb() channels; CSSTheme: percentage rgb() channels were read as 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: image constants look up their leading token; escaped #Constants names count as redeclarations

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: quoted image names survive alias chains, escaped semicolons stay in identifiers, dark fonts ignore light derives; both compilers clamp out-of-range rgb() channels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: an escaped quote outside a string opens no string

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: dark font chains read only dark derives, #Constants in a selector list, cn1-derive targets unquoted and decoded, hex escapes end at any CSS whitespace

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: escaped var() names decoded, --digit custom properties, empty rgb() components rejected; GUI builder: #Constants in selector lists, corrupt unselected variants no longer fail the folder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a pressed-only derive inherits the target's normal font; GUI builder: a mixed #Constants selector list is still probed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: escaped alias targets decoded for type lookup; a dark element's derive leads to the light target

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: legacy @constants aliases stay live until the final pass; an image constant of a url() or dimension is left out

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: quoted var() fallbacks stay text, escaped custom property names decoded everywhere, a redefined exported constant retypes later aliases

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: universal rules set no style property; a functional color constant takes its leading token

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a pressed derive wins over the owner's, a size-only rule keeps a system font's style, an unquoted url() keeps its semicolon

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: only CSS whitespace ends a hex escape inside a string

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a universal derive is ignored; a quoted image variable stays text for its aliases

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: quoted image fallbacks keep the whole name, image-named chains typed by their leading token, universal font-size not validated, escaped #Constants selector recognised

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: escaped commas stay in a family name, an unsupported var() fallback is rejected like a direct one, hex escapes take ASCII digits only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: nested quoted fallbacks stay text, an image constant's url() fallback is left out, an undefined font-size variable is passed over; GUI builder keeps the last medium variant like the build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: a UIID's font reaches its selected, pressed and disabled states, as in the build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: an alias of a quoted constant keeps its text, not read again as a number

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Baselines: take #6059's repair of #5976's merged overlays (rows master already moved are dropped or re-anchored)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: fold CSS keywords, property names, colors and media queries with an ASCII fold, not the device locale

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: carry unselected styles and derives into every state, per-side padding/margin, rgba/transparent/opacity, the full CSS named-color table

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: prefix UIIDs for platform/density/device @media like the build, keep .unselected rules out of the other states

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: write @cn1-bind keys for var() colors, accept --var lengths in #Constants, drop combinator selectors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: carry only the bare rule's values into states, drop compound media queries, decode escaped UIIDs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: compile .unselected as a layer over the bare rule, keep hex escapes out of the combinator check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Baselines: calibrate linux binary size for the runtime CSS theme compiler's parity code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CSSThemeCompiler: use HashMap for the compile's own scratch maps

The compiler runs on the EDT, so Hashtable's locking buys nothing. Only
the theme map itself stays a Hashtable, since that is the Resources API type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
#6052)

* Add native file open/save dialog API with filters, options, hints and previews

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaSE: native file open/save dialogs with filter list, options and preview

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* JavaScript port: open dialog via the browser picker, save as a named download

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Linux port: GtkFileChooser open/save dialogs with filters, choices and options

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Developer guide: open and save dialogs, feature matrix by platform

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: satisfy PMD CloseResource and UnnecessaryConstructor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Android: native file open/save dialogs over the Storage Access Framework

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* iOS: native file open/save dialogs via UIDocumentPickerViewController

Open uses initForOpeningContentTypes (filter UTTypes, extensions, folder),
multi-select, directoryURL and shouldShowFileExtensions; picked items are
copied to tmp. Save stages content in the caches dir off the EDT and exports
it with initForExportingURLs asCopy. Results return through a per-request id
and are delivered on the EDT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Android file dialogs: close both streams when copying a picked document

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Windows port: IFileOpenDialog/IFileSaveDialog open/save dialogs with filters, options and hints

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* macOS: native open/save dialogs over NSOpenPanel/NSSavePanel

Filters become an accessory popup that switches the allowed types, options
render as checkbox/popup/text controls in the same accessory stack, and the
MAC_* hints map to the panel properties. Answers use NativeFileDialogCodec;
saves are written through completeSaveDialog. No accessory Component or
preview on the Mac yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: accessory and preview are not hosted by the macOS panels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: fix CI gates and address review findings

- Copyright headers on the new tests; classify the fallback save form in
  FrameworkChromeNeverWindowsTest; Vale quote punctuation in the guide.
- Linux: add the filter's extension in the GTK native and confirm the
  overwrite of that name, since GTK only checked the typed basename.
- Core: saving a sourceFile onto itself no longer truncates it.
- Android: refuse to launch while another activity result is outstanding;
  stop reporting INITIAL_DIRECTORY, which only the URI hint honours.
- iOS: convert extension filters to legacy UTIs before iOS 14; copy picked
  documents off the main thread.
- JavaScript: report a dismissed picker as cancelled; a save too large for
  the heap still answers the callback.
- Linux/Windows: deliver results on the EDT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: address the second review round

- Core: a content writer still runs when the destination is the source
  file; the default implementation no longer advertises INITIAL_DIRECTORY.
- JavaSE: filtered saves (and filtered opens on Windows, where AWT's
  FilenameFilter does nothing) use the Swing chooser, which confirms the
  overwrite of the name with the extension added.
- Android: picks are checked against extension filters the MIME query could
  not express; a picked folder is copied to the cache so the result is a
  path FileSystemStorage can use.
- macOS: filters given as UTIs reach allowedFileTypes.
- iOS: close the staged export stream in a finally (SpotBugs DLS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: address the third review round

- Windows: an IFileDialogEvents sink keeps the save dialog's default
  extension on the selected filter, so switching type no longer yields
  report.pdf.png.
- Core: the fallback save form runs on the EDT when called from another
  thread, and the open fallback delivers on the EDT.
- JavaSE: drop a preview render that finishes after the selection moved;
  parse file:/ and drive-letter URLs for the starting folder; saves that
  must not confirm an overwrite use the Swing chooser.
- iOS: watchOS and tvOS use the Codename One fallback; a picker requested
  while another controller is presented answers cancelled instead of
  hanging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: address the fourth review round

- Windows: the events sink sets the default share-violation and overwrite
  responses instead of leaving them indeterminate.
- Core: drop the WEB_ID and WEB_START_IN hints; the browser port uses a
  download and a file input, neither of which reads them.
- iOS: escape '%' and newline in picker paths before joining them, and
  unescape in fileDialogResult.
- Android: siblings with the same display name in a copied folder get
  distinct local names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: address the fifth review round

- macOS: escape '%' and the record separator in every result field, since
  a Mac file name may contain the separator; macFileDialogResult unescapes.
- JavaSE: requests with a custom accept label use the Swing chooser, the
  only one that can set the button text.
- iOS: an import whose copy fails reports an error instead of silently
  dropping the item or reading as a cancellation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: fix the iOS warning census and fail mixed Android picks

- iOS: the pre-iOS 14 picker path uses the public.folder and public.item
  UTI strings instead of kUTTypeFolder/kUTTypeItem, which iOS 15
  deprecates; the Xcode 27 warning census rejected the new warning.
- Android: a multi-selection containing any file the filters reject fails
  whole with an error, instead of returning the accepted subset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: stage aliased saves, cap Linux items, clean iOS staging

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: clean failed Android imports, gate iOS 13 directory, wildcard filters

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: GTK wildcard, unbounded choices, final-path overwrite check; report fallback save controls

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: self-contained doc snippets, wildcard accept, iOS 11 multi-select, boolean hint default

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: wildcard default extension, iOS export name and folder gate, JavaSE URL dirs, Android partial-save cleanup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: Android save name extension, persist grant only after a successful write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: size GTK filter fields from the record

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: stage Android source saves, keep MIME family, iOS wildcard and coordinated copy, unchecked writer failures

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: unchecked writer failures on iOS and JS, Android launch failure, wildcard fallback accept

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: strict Windows save types, empty filters unconstrain the accept union

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: stage every save with rollback, convert only Windows separators

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Baselines: take #6059's repair of #5976's merged overlays

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* File dialogs: hint keys become FileDialogRequest.HINT_ constants; the fallback open dialog picks several files

FileDialogHints held nothing but the key names for FileDialogRequest.hint(),
so the constants now live beside the method that takes them.

The Codename One open dialog, used by ports without a native one, answered a
multi-select request with a single file. It now shows a file tree whose files
toggle a check mark and returns every checked file in the order it was checked,
and the fallback reports FileDialogFeatures.MULTI_SELECT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
…b packages, plugin stubs) (#6055)

* Dart transpiler: throw expressions, async*/await for, mixin application classes, redirecting constructors, function-typed params, mixin on-clauses

Real Flutter apps lean on these constructs (bloc's async* event handlers, `mixin X on State<W>`, `: this(...)` constructors), and each one used to fail the build with E01xx/E03xx.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dart transpiler: generator and generic closures, redirecting factories, super assignment, >>> operator

Also fixes two pre-existing emitter bugs real code hits: a factory in a
generic class referenced the class's type variable from a static method,
and a class declaring factory constructors could not be implemented
(the shape of every freezed model).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dart transpiler: dart:convert, dynamic dispatch, arrow factories, mixed list literals

dart:convert (json, utf8, ascii, latin1, base64, LineSplitter) in dart-runtime
with a stub, and a Dyn runtime that dispatches member reads, writes, calls and
indexing on dynamic receivers -- maps, lists, strings, numbers, functions, and
transpiled classes through generated DynamicObject members.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dart runtime: dart:io subset and fuller Streams

File, Directory and FileSystemEntity over FileSystemStorage (an in-memory file
system before Codename One starts), Platform from Display.getPlatformName(),
HttpClient/HttpClientRequest/HttpClientResponse over ConnectionRequest,
HttpHeaders, ContentType, HttpStatus and WebSocket over
com.codename1.io.WebSocket. Stream gains its factories, terminal operations,
derived streams and transform(); the dart:convert codecs are
StreamTransformers. Future.then types an untyped callback parameter from the
future's value type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: plugin stub packs, pub package import, and a pet-adoption acceptance app

Stub packs (flutter-runtime com.codename1.flutter.plugins.*, META-INF/dart/plugin_*.dart):
bloc/flutter_bloc, equatable, json_annotation, shared_preferences, path_provider, dio,
go_router (with MaterialApp.router) and cached_network_image, each with a headless
behavior test. The importer lists them as covered and transpiles other pure-Dart pub
packages from their sources.

Transpiler: stub extension methods, witness inference from a typed selector parameter
(context.select), explicit Java type arguments on generic stub calls, an empty {} read
as a Set where a Set is expected, Icons style-variant fallback, and javac-accurate
reachability after try/catch and if/else. Runtime: the full Material icon set,
FilledButton, Provider create blocks, DateTime.parse/toIso8601String.

scripts/flutter-apps/pet_adoption (bloc, go_router, dio, shared_preferences, equatable,
json_annotation, cached_network_image) imports, transpiles and compiles unmodified via
scripts/flutter-apps/Acceptance.java.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: plugin stub packs, PopScope/StreamBuilder, and an acceptance CI job

Plugin stub packs backed by Codename One APIs: cross_file, share_plus,
package_info_plus, device_info_plus, connectivity_plus, geolocator,
image_picker, app_links, flutter_local_notifications, firebase_core/auth/
analytics/messaging and google_maps_flutter. The importer marks them covered,
and the generated entry point forwards push, local-notification and deep-link
callbacks only when the app depends on the matching plugin.

Widget fidelity: PopScope and WillPopScope veto Navigator.maybePop and the
toolbar back command. StreamBuilder is new. FutureBuilder and StreamBuilder
builders are typed, and Dismissible callbacks are typed too.

Transpiler:
- A user enum or class that shares a stub's name wins.
- Explicit type arguments on non-generic Java methods are cast.
- Callback parameters take the receiver's type arguments, so a closure
  passed to stream.listen gets typed parameters.

A second acceptance app, field_notes (firebase, notifications, share,
connectivity, PopScope, StreamBuilder), joins pet_adoption.
scripts/flutter-apps/run-acceptance.sh runs both, and
flutter-acceptance.yml runs it in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: address review findings and fix the flutter-runtime test compile

- AsyncAndDependencyTest types its FutureBuilder builder (AsyncSnapshot<Object>).
- dart:io resolves relative paths against Directory.current.
- StreamIterator carries null events instead of dropping them.
- utf8.decode throws FormatException on malformed input unless allowMalformed.
- DateTime.parse truncates digits past microseconds, as the Dart VM does.
- Stream.fromFutures emits in completion order.
- Provider honours lazy: create runs on first lookup unless lazy is false.
- Equatable hashes through DartRuntime.hashOf, so 1 and 1.0 agree.
- The importer ignores import-like text inside triple-quoted strings.
- Geolocator shares one platform listener and removes it with the last subscriber.
- Local-notification payloads persist across process restarts.
- package_info_plus reports the pubspec build number from a resource the
  importer writes.
- CancelToken cancels every request it is attached to.
- AppLinks.getLatestLink returns the most recent link.
- FirebaseAuth drops change-stream controllers once they are cancelled.
- App classes extending runtime model classes such as Equatable get dynamic
  members; only widget, State, Element and RenderObject subclasses are skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: address second-round review findings

- Transpiler: fix gallery regressions (stub super calls, model-only dynamic
  members, implicit downcast of dynamic results).
- GoRouter: case-sensitive literal segments; async redirects awaited.
- dart:async/convert/io: cancel on collect failure, Dart equality in
  distinct/contains, range checks; strict UTF-8 and Base64 validation;
  HttpClientRequest.abort kills the in-flight request.
- Plugins: FCM opened flag, bloc released when explicit bloc dropped,
  dio ResponseType.stream returns a ResponseBody, PopScope notified once
  including WillPopScope vetoes, FirebaseAuth refreshes the ID token
  before account calls, zonedSchedule recurrence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: address third-round review findings

- Transpiler: dynamic dispatch applies declared defaults for omitted
  optional arguments (behavior case dart_dynamic_call_defaults).
- Streams: handleError emits what its handler throws; a throwing
  distinct(equals) errors one event and continues; cancelling a derived
  stream cancels its upstream and wakes a pending moveNext
  (behavior case dart_stream_transform_errors).
- dart:io: File/Directory.absolute resolve against Directory.current;
  File.create fails on a directory; HttpClientRequest enforces
  maxRedirects. Base64 strictness kept (matches the Dart VM), documented.
- Plugins: dio routes body-encoding failures through its future and
  detaches settled requests from a CancelToken; bloc reports failed async
  handlers to onError; a cold-launch notification tap is reported by
  getNotificationAppLaunchDetails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: fix native benchmark builds, push opt-in and an iterator race

- Dyn: hand-written sign; ParparVM's JavaAPI has no Math/Long.signum,
  so the Linux and Windows gallery builds failed to link.
- FirebaseMessaging no longer names com.codename1.push: any reference
  turns push on in an Android build, which then requires
  google-services.json even for apps without Firebase. The generated
  entry point supplies the push key only when firebase_messaging is used.
- StreamIterator: checking the queue and publishing the waiter is now
  atomic; an event pushed between the two from a timer thread was lost
  and an async* body hung (about 1 in 60 runs under load).
- Accept the gallery's JavaScript size growth for this PR
  (scripts/flutter-bench/baseline/pr/6055.json).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: fourth-round review fixes, a 20% native size regression, and a test-harness timeout

- Icons are static methods rather than 2,176 eagerly built fields, and dynamic
  dispatch switch cases are pruned to member names the program reaches through
  dynamic receivers, so ParparVM's dead-code removal can drop the rest.
- Derived streams (take/skip/expand/asyncMap...) forward source errors and stay
  subscribed; failed async GoRouter redirects show the error page; User.reload
  refreshes the account; getInitialMessage returns the cold-start push; bloc
  widgets rebind when the provided bloc changes; dynamic toInt/floor/ceil reject
  non-finite values; JSON numbers are ASCII digits; lastModified fails on a
  missing file.
- The behavior harness kills a generated program after a timeout instead of
  hanging the suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: fifth-round review fixes and the Linux size baseline

- GoRouter's initial route waits for an asynchronous redirect instead of
  mounting the guarded page; ChangeNotifierProvider disposes the notifier its
  create made; dynamic num.compareTo uses Dart's total order; byte codecs
  reject non-integer elements; ContentType keeps its parameters (multipart
  boundary); WebSocket.add after close throws StateError; periodicallyShow's
  first notification comes one interval after the call.
- Linux flutter-bench baseline calibrated for the remaining +0.15% after the
  Icons and dynamic-dispatch size fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: sixth-round review fixes

Dyn rejects extra arguments to built-in members; handleError forwards a
throwing test; asyncMap continues after a failed conversion; File.fromUri
decodes and validates; rename onto itself and into its own subtree are
handled; Dio refuses requests after close; dialog PopScope guards apply to
maybePop; GoRouter.canPop counts dialogs; async Bloc handler errors rethrow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: seventh-round review fixes

Directory create/rename reject files and non-empty targets; headless relative
paths resolve against Directory.current; HttpClient force-close aborts open
requests; Stream.fromIterable replays per listener; expand continues after a
failed element; dynamic built-ins take toList(growable:) and firstWhere(orElse:);
a vetoed maybePop answers true; Emitter.forEach/onEach route source errors to
onError; AppLinks settles the initial link on first start; FirebaseMessaging
getToken starts registration; CachedNetworkImage forwards httpHeaders; Dio
joins list-valued headers; the importer rejects every unimplemented dart:
library and drops a stale build-number resource.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: type WidgetsBinding.platformDispatcher so the native gallery starts

The stub left the dispatcher dynamic, so platformBrightness went through
Dyn.get, and the runtime's PlatformDispatcher is a plain Java object with no
dynamic members: the gallery threw NoSuchMethodError before its first frame on
every ParparVM desktop port, which the benchmark reported as cold start and
memory not measured. Reproduced on a local native macOS build; with the typed
stub it reaches BENCH:FIRSTFRAME in 172ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: eighth-round review fixes

Bloc reports async handler failures as uncaught and throws on unhandled
events; GoRouter treats an already-failed redirect as a navigation
failure; Geolocator honours timeLimit with a TimeoutException;
FirebaseAuth keeps per-app state; the UTF-8 stream decoder strips only
the leading BOM; the importer keeps edited files of a rejected package;
generated dynamic calls validate their arguments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: ninth-round review fixes

Reimport removes the build-number hints it wrote; Bloc widgets drop
cached state when their bloc changes; Dio request headers override base
headers case-insensitively; Firebase topics use Push; recursive mkdir
rejects file components; Stream.cast<R>() checks events; base64 stream
coding carries partial groups; openRead validates its range; Google Maps
reports onCameraMove during gestures; DateTime.tryParse returns null out
of range; pickMultiImage honours limit; pendingNotificationRequests
reports scheduled notifications.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: tenth-round review fixes

yield* forwards source errors and releases the source on cancel; Dio,
FirebaseAuth and HttpClient settle transport failures instead of
leaving the request pending; in-memory XFiles are written out before
sharing; jsonEncode lets toEncodable/toJson encode enums.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Android bench: prune unused Flutter plugin packs from the build

The whole flutter-runtime jar, all 19 plugin packs, was merged into every
app. The Android builder's class scan then saw geolocator/maps/firebase
classes and added play-services-location plus location, audio and boot
permissions to apps that use none of them (+762 KB dex on the gallery).
Executor.unzip now drops every pack nothing outside the plugin tree
references, keeping transitive pack dependencies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: eleventh-round review fixes

- Dyn: contains/startsWith/indexOf forward the optional offset.
- FileSystemEntity.uri escapes the path, so '#', '?' and '%' stay in names.
- Navigator: an explicit pop notifies PopScope (didPop true); maybePop
  reports only refusals, so a pop is never reported twice.
- GoRouter.go runs redirects even for the initial location.
- HttpClient gunzips gzip responses under autoUncompress; contentLength
  is the declared Content-Length (-1 if absent or decompressed).
- Derived streams (take/skip/asyncMap...) subscribe to the source inside
  listen(), so events right after listen are not lost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Android bench: prune Flutter plugin packs in the Android builder too

AndroidGradleBuilder overrides unzip, so the prune in Executor.unzip never
ran on Android: every plugin pack reached the permission scan, and
FirebaseMessaging's com/codename1/push reference switched FCM on, failing
the gallery build on a missing google-services.json.

Drop pr/6055.json: the latest run's JavaScript and Linux sizes are within
tolerance of the current rows (JavaScript once #5976's overlay is
re-based, on branch fix-5976-flutter-baseline), so nothing needs
rebaselining.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter bench: re-base #5976's JavaScript rebaseline on the folded row

#5976 merged after the nightly fold had already moved javascript
gallery/code_bytes to 13,304,997, so its overlay's 'from' (13,238,731)
no longer matched and every baseline read failed: master's Performance
baselines check and every PR's Flutter benchmark gate. Its measured
value (13,338,532) is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 2d83e24)

* Flutter bench: report an unreadable baseline without a KeyError

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e6b4a09)

* Firebase: keep push out of auth-only apps; users act through their own app

- FirebaseMessaging no longer names com.codename1.push: topic calls go
  through a topicSink hook the import-generated entry point installs,
  as tokenSource already did. Pruning keeps the whole firebase pack for
  an auth-only app, and that reference turned on FCM (and required
  google-services.json) on Android. NoPushReferenceTest guards it.
- User keeps the FirebaseAuth that created or restored it, so a
  secondary app's token refresh, profile update, reload and delete use
  that app's key and session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Baselines: drop #5976's stale ParparVM perf overlay, as #6059 does

Rows master had already moved made it unreadable; same repair as
3702c6c on parley-messaging, so the two branches merge cleanly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: adversarial-review fixes

Build time:
- Importer: a package importing an unsupported one is unsupported too
  ('depends on X'), so its files never reach the build.
- Generated $dcall/$dset convert arguments through DartRuntime.as
  (instanceof, Dart TypeError) instead of bare casts, which ParparVM does
  not check. Explicit setters and generic methods are now dispatched.
- Plugin pruning also reads library jars in libs/: a pack only a cn1lib
  calls is kept.

Runtime:
- AsyncStar.over is the shared transformer plumbing: LineSplitter and
  utf8/base64 bind subscribe inside listen() and forward source errors
  without ending the stream, as Stream.derive already did.
- Sink.onCancel and the cancel handler share one lock (a cancel between
  check and add left the hook unrun).
- Dyn join/padLeft/compareTo and base64.decode check their String casts.
- GoogleMap's camera poll stops after ~500 ms still and on unmount.
- ImagePicker's single-pick fallback propagates errors.
- HttpClientResponse.contentLength is -1 for any gzip body under
  autoUncompress, including one iOS already inflated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: adversarial round 2 fixes

Transpiler: a[i]++ through the index write (old value for postfix), dynamic
compound assignment evaluates receiver/key once, left operand pinned when the
right lifts statements, unary -/~ operator overloads, generic local functions
erased. Plugins: SharedPreferences mock values stay off Storage, held
cold-start pushes replayed to a late onMessageOpenedApp listener.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: adversarial round 3 fixes

bloc: close() completes live emitters (cancels forEach/onEach), a handler's
synchronous error goes to onError and is reported instead of thrown at add's
caller, on<E> handler and Emitter.forEach/onEach typed so block handlers and
emit.forEach bind statically. Transpiler: a block lambda with no value return
targeting a dynamic-returning function answers null. connectivity: events
delivered on the EDT, listener registered once Display is up. path_provider:
separate temp and cache subdirectories.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: adversarial round 4 fixes

A block lambda emitted with a null tail is value-shaped, so then()/catchError
pick the value SAM (block-bodied then callbacks failed to compile). Local
sync*/async* functions lowered like generator closures, with their declared
element type. await for over a stream of unknown element type reads it as
Stream<Object>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Flutter: select plugin packs at transpile time, not in the builders

The runtime jar no longer carries plugin pack classes. Packs ship as sources
under META-INF/dart/java and the transpiler copies in only those the generated
code or the app's own Java names (transitively), sweeping any it no longer
selects; the mojo also drops their stale classes. The Executor and
AndroidGradleBuilder class-scan prune is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 22, 2026
* Skirmish sample: deterministic shared rules module

A Clash Royale-style card battler sample. This first piece is the rules
module the app, the server and the replay viewer will all run: fixed
20 Hz ticks, integer-only arithmetic, a seeded SplitMix64 RNG, a data
driven card catalog, a practice bot, and replays as seed + decks +
command log. Tests pin determinism with a golden replay corpus that the
cross-platform check will replay on ParparVM and the JS port.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish sample: authoritative game backend

Accounts, decks, trophy matchmaking with a bot fallback, challenge links,
a lockstep match loop over /ws/game that runs the shared rules, replays,
a coin/gem shop with server-side store receipt validation and capped
rewarded ads, player reports and automatic flags, and audited admin
moderation. Flyway migrations for SQLite, PostgreSQL and MySQL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish sample: game client, engagement, admin console

The Codename One client: a com.codename1.gaming arena with CSS-styled
widgets around it (hand, elixir meter, name banner), practice against
the bot, online lockstep, challenge links, replays, deck builder, shop
with server-validated purchases, rewarded/interstitial/banner ads,
analytics, push, and the admin god-mode console. Simulator E2E tests
capture the developer-guide screenshots. Hash hex moves into the rules
module because Long.toHexString does not exist on device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* gpu: glTF scenes with skins and animation, AnimatedModel and ParticleEmitter

GltfLoader.loadScene reads every node, primitive, material, skin and clip;
AnimatedModel CPU-skins and cross-fades clips through dirty vertex buffers so
no backend changes; ParticleEmitter draws camera-facing additive or alpha
billboards in one call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: 3D battle with KayKit characters, towers and particle effects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: levels, daily quests, chests and achievements on the server

Progression keeps experience, chest slots, lifetime counters and three
daily quests per player in a new progress table (portable V4). A
finished match feeds it from Results; quests, chests and the training
battle pay out through /api/progress. Flags.auto opens its own
transaction so the demo seeding's flag is actually stored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: tutorial, card and hero art, home progression and reward popups

- A training battle walks a new player through elixir, deploying,
  defending and spells: a mentor in a speech bubble, time held still
  while she talks, and an animated finger on the card to pick and the
  spot to drag it to. It starts on a new player's first visit and is
  replayable from "How to play".
- Cards are framed renders of the battle's own 3D models (CardArt),
  with an elixir drop and a name ribbon, in the hand, the deck and the
  home strip; heroes in their victory pose on sign-in, home, results
  and reward popups. PortraitStudio also renders the Imp Den.
- Home shows the hero, level and XP bar, chest slots, daily quests
  with a claim button, and a trophy room of achievements; rewards,
  level-ups and unlocks pop up with the hero.
- Fields and buttons share one centred column width, so sign-in and
  register line up.
- Demo accounts are seeded with some progress; the dead 2D sprite
  code in Art and Viewport is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: finishing camera sweep, game-styled dialogs, reward popup and back arrow fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: native iOS build and a self-driving walkthrough; fix two iOS SoundPool crashes

The iOS sound pool's load shadowed its pool argument with POOL_BEGIN's
autorelease pool, and play dispatch_sync'ed to the main queue from the GPU
view's frame callback, which already runs there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: developer-guide chapters, demo page, Initializr template and CI

Adds the user's and implementor's guides, the /skirmish/ website page and
flagship card, the README, the Initializr template and the skirmish workflow.
Challenge links open the installed app through its skirmish: URL scheme
unless a hosted browser build is configured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: review round 2 - guide facts, portrait path, workflow paths

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CI: build a sample's rules module in the database server tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish CI: PMD, doc snippets, LanguageTool, Android licence key, silent sim audio

- Core gaming classes: foreach loops and documented NOPMD on the intentional
  identity checks and the per-frame scratch matrix; AnimatedModel and
  ParticleEmitter javadoc examples are complete runnable programs.
- Guide: Playground opt-out for sample code, the MCP link uses the chapter's
  generated id again (the explicit anchor broke the website's links),
  LanguageTool terms.
- Skirmish: placeholder android.licenseKey for its in-app purchases; Sfx only
  uses a native mixer, so a simulator without an audio device stays silent
  instead of starting a browser engine per sound.
- From #6059: perf-baseline overlay 5976 re-measured, starter-launchers macOS
  timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: MySQL replay column is LONGTEXT, the type the ORM validates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish CI: GltfScene indentation, flutter-bench baseline from #6059

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish Forge: content packs, custom arenas and missions in the rules, server packs, files and verified mission results

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish Forge: the in-app editor, mission play, moderation and the guide

- Forge home (official, popular, new, yours), pack screen with campaigns,
  stars, share, remix, rate and report; deep links open a pack.
- Editors for packs, cards (stats, bundled looks or an imported .glb with
  its clips mapped on a turntable), arenas (towers and obstacles on a grid,
  mirrored, any size and lane count), missions (goal, elixir, decks, waves,
  story lines, stars, rewards, test play) and campaigns.
- Missions play through BattleForm with a MissionDriver: story lines stop
  the clock, results go to the server, which plays them again.
- Battle view draws any arena, custom cards and uploaded models.
- Admin console Forge tab: reported packs, hide/restore/official, and the
  uploaded files to look at, approve or reject.
- Theme styles for the Forge, an e2e test that captures its screens, guide
  sections for players and implementors, template resync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish Forge: only APIs the device and compiled server have

- ContentPack's hash uses Match.hex, not Long.toHexString, which the device
  runtime lacks (bytecode compliance, Android and template builds).
- Forge splits the stored animation list with Lists.split; String.split is
  not in the compiled backend's runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: invite a friend, engagement through Codename One analytics and push, the admin Promote tab

- Invites: com.codename1.analytics.invite links carrying the player's
  referral code; the friend's app reads the attribution on start and
  claims it after signing in. The server keeps only the economy: codes,
  who joined through whom, and the rewards (refused for old accounts,
  own codes and second claims; inviter paid after the friend's first
  battle, at most ten friends). first_battle/first_win conversions.
- Engagement is read in the Codename One analytics console: user
  properties for level and trophy band, invite and push-open events,
  AppReview after a win.
- Promote tab: opens the analytics console, broadcasts Codename One push
  to a segment with a campaign the app reports on open (counted and
  confirmed, five a day), the home spotlight banner, campaign links.
- The console's tabs are a side bar on desktop and tablet; run-e2e.sh
  runs a second, desktop pass on Linux for PromoteTest.
- E2e.click taps components that are not Buttons (ForgeHome's pack rows
  are MultiButtons, which failed ForgeTest); ShopForm ignores a load
  that finishes after sign-out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: growth tutorial, Promote screenshots in the e2e, seeded spotlight, LanguageTool and template fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: transparent Forge/help labels, wrapping spotlight, scrolling admin tabs on phones, ForgeTest mission id, guide prose

The e2e screenshots showed white boxes behind every Forge and Promote
label, help text and the invite code: those UIIDs were missing from the
theme's transparent list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: Forge and engagement screenshots in the guides, ForgeTest's new-pack mission, remaining white icon and value boxes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish e2e: scroll a row into view before tapping it; guide screenshots from the restyled screens

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish guide: screenshots at full guide width

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish e2e: 1536m for the simulator, TutorialTest ran out of heap after the Forge tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish growth tutorial: the desktop console's Promote tab, push composer, confirmation and spotlight

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: desktop console with reports, query tool and engagement pipelines; one implementor guide

The admin console is a native-looking desktop tool (Desk widgets, aligned
label column, light palette, side bar) with charts of daily players,
battles, gems, the funnel, retention and the trophy ladder; a query tool
over player records; and pipelines that act on matching players hourly
with a per-player cool-down. Forge labels get room and margins. The
users' guide is folded into the implementor guide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: compiled-backend fix, console chart/condition alignment, guide section on reports, queries and pipelines

String.split is not in the compiled backend's runtime, so Audience splits by
hand. The two-series legend gets its own row, funnel labels are shorter, and
the condition rows share one joint-label width. The guide gains the console's
Reports, Query and Pipelines screenshots from CI, and LanguageTool's two
matches are reworded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish guide: reword the Count players sentence for LanguageTool

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Skirmish: the progress view never inserts the row, a legend row under two-series charts, refreshed console screenshots

On MySQL the first battle's result, recorded on the match ticker's thread, and
a progress read could both insert the player's progress row; the second insert
waited on the uncommitted row and failed with a duplicate key. Reading now
answers a fresh row without storing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant