Skip to content

Add push V3 client framework and migration guide - #5440

Merged
shai-almog merged 27 commits into
masterfrom
push-v3-client-framework
Jul 27, 2026
Merged

Add push V3 client framework and migration guide#5440
shai-almog merged 27 commits into
masterfrom
push-v3-client-framework

Conversation

@shai-almog

@shai-almog shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add the builder-based Push V3 client API, typed messages, registration sink, listeners, errors, subscriptions, and pluggable low-level PushTransport
  • connect native delivery seams on Android, iOS, and JavaScript
  • integrate push dispatch with Surfaces and Live Activities/widgets
  • preserve the classic API while directing new classic sends to BuildCloud's compatibility endpoint
  • replace the developer guide chapter with a V3-only guide, explicit listener lifecycle and custom-server contracts, and remove the obsolete chapter and assets
  • add deterministic low-stack push tests and run the real JavaScript service worker contract in PR CI

Why

The existing callback-only API cannot express modern push lifecycle, typed schema-3 payloads, custom native push transports, registration state, or system surfaces cleanly. The new API provides those bindings while retaining compatibility for existing applications during the server cutover.

Testing strategy

CI does not pretend to provide physical-device end-to-end delivery:

  • Java tests drive the actual PushClient.dispatch() native seam and cover registration, unregistration, foreground/background delivery, cold-start replay, custom transports, and Surfaces
  • the JavaScript contract loads the real service-worker source with mocked browser clients and notification APIs
  • optional staging/device scripts remain diagnostics, not CI or nightly gates
  • backend provider and durable-queue tests live independently in the private BuildCloud repository

Companion services

This PR is designed to ship with BuildCloud PR #115 and BuildDaemon PR #156. BuildCloud preserves /push/push compatibility so the standalone PushServer can be retired; BuildDaemon detects Push V3 usage and generates the corresponding native FCM, APNs, Huawei, and callback bindings.

BuildCloud includes WNS provider delivery for explicit Windows targets. This client PR intentionally does not modify or revive the unsupported UWP port.

Validation

  • PushTest: 12 tests
  • PushMessageTest: 5 tests
  • PushClientTransportTest: 11 tests
  • real service-worker contract: pass
  • 624 include-backed developer-guide snippets validated
  • full AsciiDoctor developer-guide render
  • Vale: zero errors
  • changed-file copyright headers
  • focused PMD, Checkstyle, and SpotBugs reports
  • git diff --check

Copilot AI review requested due to automatic review settings July 23, 2026 04:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new Push V3 client framework to Codename One, adding a typed push envelope model and an explicit client binding (PushClient) while preserving the legacy push API via a compatibility endpoint and a deprecated documentation chapter.

Changes:

  • Added the Push V3 client API (typed PushMessage, PushSubscription, PushTransport, listeners/sinks, and dispatch wiring).
  • Updated native seams across Android/iOS/JavaScript/UWP to route typed envelopes and to support managed vs. legacy behavior.
  • Added deterministic push contract tests (including a real JavaScript service-worker contract) and updated the developer guide to V3-first with a deprecated legacy chapter.

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/push-e2e/service-worker-contract.mjs Executes the real JS service worker in a mocked environment to validate v3 push delivery behavior.
tests/push-e2e/scenarios.json Defines end-to-end diagnostic scenarios for optional/staging push verification.
tests/push-e2e/README.md Documents the push testing strategy and boundaries (CI vs. optional diagnostics).
scripts/run-push-e2e.sh Operator-run script to exercise BuildCloud push admission + receipt polling against real devices/providers.
Ports/UWP/VSProjectTemplate/UWPApp/src/com/codename1/impl/SilverlightImplementation.cs Routes WNS registration/delivery through PushClient when active; falls back to legacy behavior otherwise.
Ports/JavaScriptPort/src/main/webapp/sw.js Adds v3 push detection, delivery semantics, and deep-link handling in notification clicks.
Ports/JavaScriptPort/src/main/webapp/js/push.js Extends web push registration to optionally emit a typed subscription envelope for v3.
Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Push.java Bridges HTML5 push registration and message delivery into PushClient when active.
Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Implementation.java Ensures explicit push callback binding is respected before registering push on HTML5.
Ports/iOSPort/src/com/codename1/impl/ios/IOSImplementation.java Avoids legacy server registration when PushClient owns registration; forwards APNs token to active callback.
Ports/iOSPort/nativeSources/CodenameOne_GLAppDelegate.m Routes managed typed envelope (cn1 dictionary) intact to Java push dispatch before legacy decoding.
Ports/Android/src/com/codename1/impl/android/StubUtil.java Exposes stub helpers publicly for generated services to query app state/stub class.
Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java Adds Android v3 push handling path, plus Huawei transport accommodations for register/deregister.
maven/core-unittests/src/test/java/com/codename1/push/PushTest.java Updates legacy push URL to the BuildCloud compatibility endpoint.
maven/core-unittests/src/test/java/com/codename1/push/PushMessageTest.java Adds unit tests for typed envelope JSON roundtrip, schema validation, and immutability.
maven/core-unittests/src/test/java/com/codename1/push/PushClientTransportTest.java Adds tests for transport seam behavior, registration sinks, dispatch, and surface replay.
maven/codenameone-maven-plugin/src/main/resources/com/codename1/builders/CN1FirebaseMessagingService7.javas Generated FCM service routes typed envelope payloads into Android v3 handler when present.
maven/codenameone-maven-plugin/src/main/resources/com/codename1/builders/CN1FirebaseMessagingService.javas Same as above for the non-“7” template.
maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java Adds Huawei Push Kit support and updates generated push callback routing to use explicit callback getter.
docs/developer-guide/Push-Notifications.asciidoc Replaces push chapter with V3-first guidance (typed envelopes, client binding, managed/custom transports).
docs/developer-guide/developer-guide.asciidoc Includes the new deprecated push chapter under historical reference.
docs/developer-guide/Deprecated-Push-Notifications.asciidoc Restores legacy push docs as an explicitly deprecated chapter for migration reference.
CodenameOne/src/com/codename1/surfaces/Surfaces.java Adds push-facing entry point to publish remote widget timelines.
CodenameOne/src/com/codename1/surfaces/LiveActivity.java Adds push-facing entry points to update/end live activities by id.
CodenameOne/src/com/codename1/push/PushTransport.java Introduces pluggable low-level native transport interface for custom push stacks.
CodenameOne/src/com/codename1/push/PushSubscription.java Adds immutable model for transport-produced registration material and capabilities.
CodenameOne/src/com/codename1/push/PushRegistrationSink.java Adds application-owned server sink interface for storing/removing subscriptions.
CodenameOne/src/com/codename1/push/PushMessage.java Adds immutable typed v3 push envelope model + builder + JSON parse/serialize helpers.
CodenameOne/src/com/codename1/push/PushListener.java Adds listener interface for registration/message/error callbacks on EDT.
CodenameOne/src/com/codename1/push/PushError.java Adds structured error model for transport/registration/delivery failures.
CodenameOne/src/com/codename1/push/PushClient.java Adds the core v3 client binding, managed registration/unregistration, and native dispatch entry points.
CodenameOne/src/com/codename1/push/Push.java Points legacy server sends at BuildCloud compatibility endpoint.
CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java Adds getPushCallback() accessor for ports/generated code to retrieve explicit callback binding.
.github/workflows/pr.yml Runs the JS service-worker contract test in PR CI (Node) after core unit tests on Java 8.
Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CodenameOne/src/com/codename1/push/PushClient.java
Comment thread CodenameOne/src/com/codename1/push/PushMessage.java
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • Tests: 411 total, 0 failed, 14 skipped

Benchmark Results

  • Execution Time: 23341 ms

  • Hotspots (Top 20 sampled methods):

    • 21.40% java.util.ArrayList.indexOf (410 samples)
    • 7.46% com.codename1.tools.translator.BytecodeMethod.addToConstantPool (143 samples)
    • 4.18% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (80 samples)
    • 3.55% com.codename1.tools.translator.Parser.cn1EnsureSubclassIndex (68 samples)
    • 3.29% java.lang.StringBuilder.append (63 samples)
    • 2.66% org.objectweb.asm.tree.analysis.Analyzer.findSubroutine (51 samples)
    • 1.98% com.codename1.tools.translator.Parser.classIndex (38 samples)
    • 1.93% org.objectweb.asm.tree.analysis.Analyzer.analyze (37 samples)
    • 1.62% com.codename1.tools.translator.Parser.generateClassAndMethodIndexHeader (31 samples)
    • 1.51% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (29 samples)
    • 1.36% com.codename1.tools.translator.BytecodeMethod.appendCMethodPrefix (26 samples)
    • 1.20% java.util.HashMap.hash (23 samples)
    • 1.15% java.lang.String.equals (22 samples)
    • 1.15% com.codename1.tools.translator.BytecodeMethod.optimize (22 samples)
    • 1.15% com.codename1.tools.translator.bytecodes.Invoke.findMethodUp (22 samples)
    • 1.15% java.lang.StringCoding.encode (22 samples)
    • 1.10% org.objectweb.asm.ClassReader.readCode (21 samples)
    • 1.04% com.codename1.tools.translator.BytecodeMethod.addInstruction (20 samples)
    • 0.99% java.util.HashMap.putVal (19 samples)
    • 0.94% java.util.TreeMap.getEntry (18 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 151 screenshots: 151 matched.

Native Android coverage

  • 📊 Line coverage: 8.37% (7322/87435 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.26% (38206/462263), branch 3.02% (1310/43428), complexity 3.29% (1571/47783), method 4.94% (1275/25820), class 10.04% (349/3475)
    • 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)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 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)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/551 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 8.37% (7322/87435 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 8.26% (38206/462263), branch 3.02% (1310/43428), complexity 3.29% (1571/47783), method 4.94% (1275/25820), class 10.04% (349/3475)
    • 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)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 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)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/551 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 114ms / native 212ms = 0.5x speedup
SIMD float-mul (64K x300) java 145ms / native 75ms = 1.9x 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 70.000 ms
Base64 CN1 decode 79.000 ms
Base64 native encode 570.000 ms
Base64 encode ratio (CN1/native) 0.123x (87.7% faster)
Base64 native decode 391.000 ms
Base64 decode ratio (CN1/native) 0.202x (79.8% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

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

Copilot AI review requested due to automatic review settings July 23, 2026 05:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 37 out of 38 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file
Comments suppressed due to low confidence (2)

tests/push-e2e/service-worker-contract.mjs:1

  • This test can produce misleading results if the service worker fails to register a push event handler or doesn’t call event.waitUntil(): handlers.push may be undefined (throwing), or completion may remain undefined and await completion will resolve immediately without validating any async work. Add an assertion that handlers.push is a function and that waitUntil() was called with a thenable/Promise before awaiting, so failures reliably indicate a broken service-worker contract.
    scripts/run-push-e2e.sh:1
  • If the targets file is missing a provider key, jq -r will yield null and the script will attempt to send a request with "token":"null", which can mask configuration mistakes and create hard-to-triage failures. Add an explicit check that target is non-empty and not "null" before constructing/sending the request, and fail the scenario/provider with a clear error message.

Comment thread CodenameOne/src/com/codename1/push/PushMessage.java
Comment thread docs/demos/common/src/main/snippets/developer-guide/push-notifications.sh Outdated
@github-actions

github-actions Bot commented Jul 23, 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)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 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 Jul 23, 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)

Copilot AI review requested due to automatic review settings July 23, 2026 06:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 37 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

Comment thread CodenameOne/src/com/codename1/push/PushClient.java
Copilot AI review requested due to automatic review settings July 23, 2026 11:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 41 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file
Comments suppressed due to low confidence (1)

scripts/run-push-e2e.sh:1

  • Bash exit codes are limited to 0-255; returning the raw failure count will wrap modulo 256 for larger values (and can mistakenly report success if it wraps to 0). Consider exiting with 0 when failures==0 and 1 otherwise (while still printing the total failure count to stderr/stdout).

Comment thread CodenameOne/src/com/codename1/push/PushClient.java Outdated
Comment thread CodenameOne/src/com/codename1/surfaces/LiveActivity.java
Copilot AI review requested due to automatic review settings July 23, 2026 12:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 41 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file
Comments suppressed due to low confidence (2)

CodenameOne/src/com/codename1/push/PushClient.java:72

  • register() sets the global active client and installs the compatibility PushCallback before checking whether a custom transport is supported. If transport.isSupported() is false, this leaves the PushClient active and overwrites any existing callback even though registration cannot proceed, which can break legacy push behavior and misroute future native events.
    public void register() {
        active = this;
        CodenameOneImplementation.setPushCallback(compatibilityCallback);
        if (transport == null) {
            Display.getInstance().registerPush();
        } else if (!transport.isSupported()) {
            fireError(new PushError("unsupported_transport", transport.getId() + " is unavailable", false));
        } else {
            transport.register(new TransportCallback());
        }

Ports/JavaScriptPort/src/main/webapp/sw.js:143

  • notificationclick opens data.deepLink directly for v3 messages and then always posts the push payload to the window. This (1) allows a push payload to open arbitrary URLs (open-redirect/phishing risk) and (2) can duplicate delivery when the push was already posted to an existing client during the original push event. Validate deep links to same-origin destinations and skip posting when the message ID was already delivered.

Comment thread Ports/JavaScriptPort/src/main/webapp/sw.js Outdated
@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 54ms / native 3ms = 18.0x speedup
SIMD float-mul (64K x300) java 54ms / native 3ms = 18.0x 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 151.000 ms
Base64 CN1 decode 113.000 ms
Base64 native encode 451.000 ms
Base64 encode ratio (CN1/native) 0.335x (66.5% faster)
Base64 native decode 187.000 ms
Base64 decode ratio (CN1/native) 0.604x (39.6% faster)
Base64 SIMD encode 46.000 ms
Base64 encode ratio (SIMD/CN1) 0.305x (69.5% faster)
Base64 SIMD decode 43.000 ms
Base64 decode ratio (SIMD/CN1) 0.381x (61.9% faster)
Base64 encode ratio (SIMD/native) 0.102x (89.8% faster)
Base64 decode ratio (SIMD/native) 0.230x (77.0% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 7.000 ms
Image createMask (SIMD on) 1.000 ms
Image createMask ratio (SIMD on/off) 0.143x (85.7% faster)
Image applyMask (SIMD off) 38.000 ms
Image applyMask (SIMD on) 30.000 ms
Image applyMask ratio (SIMD on/off) 0.789x (21.1% faster)
Image modifyAlpha (SIMD off) 31.000 ms
Image modifyAlpha (SIMD on) 28.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.903x (9.7% faster)
Image modifyAlpha removeColor (SIMD off) 34.000 ms
Image modifyAlpha removeColor (SIMD on) 28.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.824x (17.6% faster)

@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

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

@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 100000 ms
Simulator Boot (Run) 2000 ms
App Install 23000 ms
App Launch 5000 ms
Test Execution 1167000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 105ms / native 7ms = 15.0x speedup
SIMD float-mul (64K x300) java 128ms / native 6ms = 21.3x 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 231.000 ms
Base64 CN1 decode 171.000 ms
Base64 native encode 697.000 ms
Base64 encode ratio (CN1/native) 0.331x (66.9% faster)
Base64 native decode 367.000 ms
Base64 decode ratio (CN1/native) 0.466x (53.4% faster)
Base64 SIMD encode 79.000 ms
Base64 encode ratio (SIMD/CN1) 0.342x (65.8% faster)
Base64 SIMD decode 79.000 ms
Base64 decode ratio (SIMD/CN1) 0.462x (53.8% faster)
Base64 encode ratio (SIMD/native) 0.113x (88.7% faster)
Base64 decode ratio (SIMD/native) 0.215x (78.5% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 22.000 ms
Image createMask (SIMD on) 6.000 ms
Image createMask ratio (SIMD on/off) 0.273x (72.7% faster)
Image applyMask (SIMD off) 172.000 ms
Image applyMask (SIMD on) 96.000 ms
Image applyMask ratio (SIMD on/off) 0.558x (44.2% faster)
Image modifyAlpha (SIMD off) 99.000 ms
Image modifyAlpha (SIMD on) 124.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.253x (25.3% slower)
Image modifyAlpha removeColor (SIMD off) 209.000 ms
Image modifyAlpha removeColor (SIMD on) 433.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 2.072x (107.2% slower)

@shai-almog

shai-almog commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 143 screenshots: 143 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 75000 ms
Simulator Boot (Run) 1000 ms
App Install 15000 ms
App Launch 1000 ms
Test Execution 951000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 62ms / native 3ms = 20.6x speedup
SIMD float-mul (64K x300) java 69ms / native 3ms = 23.0x 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 338.000 ms
Base64 CN1 decode 207.000 ms
Base64 native encode 739.000 ms
Base64 encode ratio (CN1/native) 0.457x (54.3% faster)
Base64 native decode 518.000 ms
Base64 decode ratio (CN1/native) 0.400x (60.0% faster)
Base64 SIMD encode 74.000 ms
Base64 encode ratio (SIMD/CN1) 0.219x (78.1% faster)
Base64 SIMD decode 98.000 ms
Base64 decode ratio (SIMD/CN1) 0.473x (52.7% faster)
Base64 encode ratio (SIMD/native) 0.100x (90.0% faster)
Base64 decode ratio (SIMD/native) 0.189x (81.1% 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) 68.000 ms
Image applyMask (SIMD on) 57.000 ms
Image applyMask ratio (SIMD on/off) 0.838x (16.2% faster)
Image modifyAlpha (SIMD off) 126.000 ms
Image modifyAlpha (SIMD on) 85.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.675x (32.5% faster)
Image modifyAlpha removeColor (SIMD off) 57.000 ms
Image modifyAlpha removeColor (SIMD on) 43.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.754x (24.6% faster)

Copilot AI review requested due to automatic review settings July 23, 2026 14:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 41 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

Comment thread CodenameOne/src/com/codename1/push/PushMessage.java
Comment thread CodenameOne/src/com/codename1/push/PushClient.java
Copilot AI review requested due to automatic review settings July 26, 2026 19:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 72 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

Copilot AI review requested due to automatic review settings July 26, 2026 22:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 72 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file
Comments suppressed due to low confidence (2)

maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java:1

  • The generated FirebaseMessagingService is marked android:exported=\"true\", which can allow other apps to start the service (depending on the OS/version/intent characteristics). Prefer android:exported=\"false\" for messaging services, and if delivery requires it, gate externally-started intents with the appropriate permission rather than exporting broadly.
    scripts/run-push-e2e.sh:1
  • Bash exit codes are limited to 0-255; if failures exceeds 255 the exit status will wrap. For a diagnostic runner this can be misleading in automation. Consider exiting with 0 when no failures, otherwise 1 (or clamp to 255) while still printing the full failure count.

Comment thread CodenameOne/src/com/codename1/push/PushSubscription.java
Copilot AI review requested due to automatic review settings July 27, 2026 00:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 72 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

Copilot AI review requested due to automatic review settings July 27, 2026 06:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 72 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

Copilot AI review requested due to automatic review settings July 27, 2026 07:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 72 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file
Comments suppressed due to low confidence (1)

maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java:1

  • The generated replay snippet references PushClient.dispatch(value) without qualifying it. Since this is string-generated source, it can fail compilation if the generated class doesn’t import com.codename1.push.PushClient. Use the fully-qualified call (e.g., com.codename1.push.PushClient.dispatch(value)) to make the generated code independent of imports.

Comment thread CodenameOne/src/com/codename1/surfaces/LiveActivity.java
Copilot AI review requested due to automatic review settings July 27, 2026 08:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 37 out of 73 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file

Comment thread Ports/JavaScriptPort/src/main/webapp/js/push.js Outdated
Copilot AI review requested due to automatic review settings July 27, 2026 09:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 37 out of 73 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • Ports/JavaScriptPort/src/main/webapp/sw.js: Generated file
Comments suppressed due to low confidence (3)

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Push.java:173

  • The typed push callback is captured in a local variable and then invoked later inside an asynchronous callSerially() runnable. If the PushClient unregisters (or a different PushClient becomes active) before this runnable executes, this can deliver a registration event to a stale callback after it is no longer active. Guard the invocation by checking that PushClient.getActiveCallback() is still the same callback before calling it; otherwise drop the event (or re-route it explicitly).
                        if (typedEnvelope) {
                            typedCallback.registeredForPush(id);
                        } else {
                            HTML5Implementation.getInstance()._registerServerPush(id);
                        }

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Push.java:186

  • In typed-envelope mode, this code calls the captured typedCallback directly. Because this is invoked from JavaScript/native event delivery, it can fire after the PushClient has been unregistered or replaced, causing late push delivery to a stale listener. Check that PushClient.getActiveCallback() is still the same callback before forwarding the message.
                if (typedEnvelope) {
                    typedCallback.push(stringify(data));
                    return;
                }

Ports/JavaScriptPort/src/main/java/com/codename1/impl/html5/HTML5Push.java:276

  • In typed-envelope mode this uses the captured typedCallback for registration errors. If the PushClient is unregistered/replaced before this runnable executes, the error can be delivered to a stale callback. Guard delivery by confirming the active callback still matches the captured callback before invoking it.
                        if (typedEnvelope) {
                            typedCallback.pushRegistrationError(message, -1);
                        } else {
                            HTML5Implementation.getInstance()
                                    ._sendPushRegistrationError(message, -1);
                        }

@shai-almog
shai-almog merged commit dba24da into master Jul 27, 2026
52 of 53 checks passed
@shai-almog
shai-almog deleted the push-v3-client-framework branch July 27, 2026 13:46
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.

2 participants