Skip to content

Flutter port gaps: transpiler, runtime and Flutter API fixes from a real-world port - #6154

Open
shai-almog wants to merge 166 commits into
masterfrom
flutter-port-gaps
Open

shai-almog wants to merge 166 commits into
masterfrom
flutter-port-gaps

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Closes the gaps a real-world Flutter port into Codename One ran into: language features the transpiler mishandled, runtime crashes, missing Flutter API, stubs that were too shallow, dart:* gaps, and weak diagnostics. A clean-room acceptance app, scripts/flutter-apps/club_hub, follows the same shape as that port: it pulls in async, collection, hive, http, markdown, source_span, stream_channel, string_scanner, table_calendar, web_socket_channel and more, 699 Dart files in all. It now transpiles and compiles with zero errors. field_notes and pet_adoption are still accepted.

What changed

Transpiler (maven/dart-transpiler)

  • Generics:
    • type arguments are substituted from the receiver and the caller, for stub methods, named constructors, named factories and static generics
    • explicit type arguments are honoured on factories and on fold/map
    • covariant collection slots are cast
    • classes that are a Set, List or Iterable only through implements, beside a superclass, get live views, mixin forwarders and covariant-return pins
  • Closures:
    • capture boxing covers every body emitter, parameters (block and arrow bodies) and cascades
    • local functions can call themselves
    • lambda parameter types are inferred from a generic context
    • tear-offs: constructors, sinks, raw-bound casts and typedef void adapters
    • an immediately invoked closure takes its return type from its own returns
    • a list literal of closures with no context is typed by their function shape
  • Control flow:
    • a non-void body that ends in a Never call gets a closing throw
    • rethrow and guardless if-case count as leaving the method
  • Constructors and lookup:
    • constructor redirects to named constructors
    • overrides that widen a type variable to its bound
    • top-level lookup is import-scoped
    • an async main waits for running async* bodies
  • Strings: String.runes, and lone surrogates in literals are escaped.

Runtimes (maven/dart-runtime, maven/flutter-runtime)

  • An isolate event loop for timers and microtasks.
  • Lists record their element type, and dynamic downcasts are checked.
  • Stream/StreamTransformer variance fixes, and typed File.openRead.
  • Flutter API gaps closed: Matrix4's 16-argument constructor, generic TweenAnimationBuilder, AlignmentGeometry on Align/Stack/transitions, Scaffold.persistentFooterButtons, and a typed showDateRangePicker.

Tests

  • Every fix has a behaviour case whose expect.txt comes from a real dart run; Flutter-only fixes have flutter-runtime unit tests.
  • Behaviour cases this branch added are named for what they cover.
  • Nothing in the tests or fixtures comes from the original app.

Verification

  • install of dart-runtime, dart-transpiler and flutter-runtime with CN1_DART_TESTS_REQUIRED=1: 1,329 tests, 0 failures, 0 skipped, including 244 behaviour cases.
  • Acceptance: club_hub, field_notes and pet_adoption all ACCEPTED.
  • Other checks: EmbeddedStubDriftTest and FlutterProjectImporterTest (31) pass, and SpotBugs on build-engine reports 0 findings. The control-character, @author, @since, ASCII and copyright gates are clean.

Known limits

  • Generic type arguments are not reified at runtime: whereType<Relay<int>>() keeps a Relay<String> that Dart would drop.
  • async* bodies still run on their own thread; a CPS state-machine lowering is separate work.
  • Function.apply with named arguments is unsupported.

🤖 Generated with Claude Code

shai-almog and others added 30 commits November 1, 2026 04:03
…tializer cascades, crash guards, super ==, symbols, shared case variables; dart:core members
…ews, converters and chunked sinks, Uri resolve, Symbol, regex named groups
… extensions and mixins, do-while, Symbol, object patterns on core types, clearer diagnostics
…dows, text decorations, dialog/sheet arguments, button variants, lifecycle observers
…tion, last-wins mixin members, read-only unmodifiable maps; Uint8List is a List<int>
… sheet handle/shape, forms/navigation/table widgets, intl compact formats, google_fonts families; club_hub covers the UI packages
… masks, blur filters, real date/time/range pickers, safe-area dialogs
…aces, private accessors, mixin on-type interfaces, multi-variable for loops, bare getters in extensions
…er, switcher, align, positioned, rotation, slide, text style, TweenAnimationBuilder); font variations, Cupertino dynamic colors, icon theme getters
…neric extensions with typed callbacks, exact extension selection
…edSize, switcher builders, overlay styles, TextInputType keyboards, path transforms
…arameters in function types, typed constructor tear-offs, empty records
…ent headers, overlap handles, draggable sheets, button/slider/bottom-nav themes, Float64List matrix storage; fix IconData tests
…every tear-off adapter; generic type-parameter binding at call sites
… const fromEnvironment, Uri.encodeFull/splitQueryString, interface getters from mixins
…king pinned/floating headers, overlay autocomplete, textScaler, horizontal grids; resync embedded material stub
…rs, FontFeature, MediaQuery text scaling fallback, SelectionChangedCause
…per parameters typed by position, named constructors on abstract classes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… handoff, RawAutocomplete with arrow and enter keys

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reads, inherited interface getter bridges, discard temp only for fully parenthesized statements

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…omplete field and options view builders, key handling tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…comprehensions, switch pattern promotion, generic stub extensions; Autocomplete builder stubs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…redicates, int stores into Float64List, Codec

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…is! exits, this in interpolation, conditional common supertypes, generic stub mixin getters

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shai-almog and others added 17 commits November 3, 2026 07:19
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…red case bodies and awaiting collection elements

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ic calls and loop variables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nds, return context for awaiting collections

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t inference, Null runtime type; timer deadline after Display check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd Null constructor witnesses, record runtimeType; nanosecond timer deadlines

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ests and witnesses, dart:core Record

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… structural record casts, num operator dispatch

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t names for renamed classes, pattern assignment, enum statics

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ambda inference, exact num compare, canonical const widgets

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

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sures, function-type interning

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…edef type args, record function fields

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

shai-almog commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 210 screenshots: 210 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 48ms / native 3ms = 16.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 59.000 ms
Base64 CN1 decode 70.000 ms
Base64 SIMD encode 77.000 ms
Base64 encode ratio (SIMD/CN1) 1.305x (30.5% 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) 5.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.400x (60.0% faster)
Image applyMask (SIMD off) 16.000 ms
Image applyMask (SIMD on) 20.000 ms
Image applyMask ratio (SIMD on/off) 1.250x (25.0% slower)
Image modifyAlpha (SIMD off) 17.000 ms
Image modifyAlpha (SIMD on) 13.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.765x (23.5% faster)
Image modifyAlpha removeColor (SIMD off) 15.000 ms
Image modifyAlpha removeColor (SIMD on) 9.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.600x (40.0% 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.06x (base 1.11x, -4.4%) 0.71x (base 0.75x, -6.0%) ok
translator (self) 4 0.86x (base 0.84x, +2.8%) 0.47x (base 0.51x, -7.6%) ok
intArithmetic 4 1.04x (base 1.04x, -0.1%) 0.06x (base 0.06x, +2.9%) ok
longArithmetic 4 0.79x (base 0.80x, -0.0%) 0.06x (base 0.06x, +3.1%) ok
mathTranscendental 4 0.70x (base 0.72x, -3.2%) 0.07x (base 0.06x, +1.7%) ok
arraySequential 4 0.38x (base 0.46x, -16.2%) 0.39x (base 0.39x, +0.1%) ok
arrayRandom 4 0.94x (base 0.94x, +0.0%) 0.23x (base 0.23x, +0.2%) ok
objectAllocation 4 1.84x (base 1.82x, +0.9%) 0.40x (base 0.43x, -6.7%) ok
valueEscape 4 0.76x (base 0.76x, +0.0%) 0.05x (base 0.05x, +3.5%) ok
hashMapChurn 4 1.00x (base 0.98x, +1.1%) 0.12x (base 0.12x, +0.7%) ok
stringBuilding 4 1.53x (base 1.43x, +7.1%) 0.27x (base 0.27x, -0.1%) ok
recursion 4 1.46x (base 1.46x, -0.4%) 0.07x (base 0.07x, +1.2%) ok
quicksort 4 1.01x (base 1.00x, +0.5%) 0.12x (base 0.12x, +0.6%) ok

Result: no regression

shai-almog and others added 12 commits November 3, 2026 21:42
…e values, generic closure fields, generator element types

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

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…listener removal, canonical static views

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, signed casts; mixin super keys

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ped literals and named-param typedefs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nction bounds across nullability

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er static function view, Function-typed named calls

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…onstructor and instantiated-generic tear-off identity

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f type args from context

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