Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Oct 23, 2026
mrousavy
force-pushed
the
mrousavy/v1-kotlin-variant-cases
branch
from
October 23, 2026 17:34
1d637c3 to
1143302
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-erased-ulong
branch
from
October 23, 2026 17:34
dbb3032 to
ad1f1e3
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-variant-cases
branch
from
October 23, 2026 17:36
1143302 to
e180990
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-erased-ulong
branch
from
October 23, 2026 17:36
ad1f1e3 to
d961a25
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-erased-ulong
branch
from
October 23, 2026 17:42
d961a25 to
6a9e366
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-variant-cases
branch
from
October 23, 2026 17:51
e180990 to
771aed0
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-erased-ulong
branch
from
October 23, 2026 17:51
6a9e366 to
f0525bb
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-erased-ulong
branch
from
October 23, 2026 18:13
f0525bb to
be7dd57
Compare
This was referenced Oct 23, 2026
Kotlin exposed UInt64[] as Array<ULong> while JNI carries a long[], so every crossing copied the array and boxed each element. Generated structs copied it again each time C++ read the field. UInt64[] is now ULongArray, a value class over LongArray, and the bridge converts it with asLongArray() and asULongArray(), which reuse the same array. Struct fields hold the long[] that JNI reads directly. UInt64[][] becomes Array<ULongArray>, so only the outer array is mapped. The mapToLongArray helpers in nitro-core have no callers left and are removed. ULongArray still requires opting in to ExperimentalUnsignedTypes, and Kotlin warns without it. The generated +autolinking.gradle opts each Nitro module in, which covers generated code and the module's own spec implementations. ULongArray boxes compare by identity, so generated structs compare these fields through their long[]. New TestObject methods pass UInt64 arrays as parameters, nested and optional arrays, Promise results and callback values.
Kotlin variant case classes stored the type JNI uses instead of the public Kotlin type. A UInt64 case held a Long, so values above 2^63 read back negative and X.First(5uL) did not compile. A UInt64[] case held a LongArray, and a callback case held the generated Callback_* class, so constructing that case meant typing a Nitrogen specialization name. Each case now holds its public type, e.g. ULong, ULongArray or Callback<...>, and fromCpp_<n> converts from the JNI value. JNI reads the value field directly when it already has the JNI representation, as for ULong and ULongArray. Otherwise it calls a private getValue_cxx() accessor, like structs do. A callback case converts with Callback_*.fromKotlin(), which returns a callback that came from C++ unchanged. JNI calls these accessors and the struct get<Field>_cxx() getters with getNonvirtualMethod. Both are private and final, like the hybrid object _cxx bridges that already use it. New TestObject methods bounce UInt64 | string and UInt64[] | string variants. The Kotlin fixture rebuilds the ULong case with its constructor.
…rectly Record<string, UInt64> crossed JNI as a Map<String, Long>, so Kotlin copied the map with mapValues on every crossing. Promise<UInt64> and Promise<UInt64[]> results went through a second Promise that converted the value. Map values and Promise results are erased generics, so Kotlin can keep them as kotlin.ULong and kotlin.ULongArray boxes. JNI cannot name those classes, since R8 may rename them in release builds without keep rules, so it sees them as an Object. It creates and reads the boxes itself with AllocObject and field access, using the classes and value fields that ULongBox, a @keep helper in nitro-core, gives it once. ULongBox finds the fields by type, and also boxes and unboxes in Kotlin so R8 keeps the fields and does not assume their default value. UInt64? parameters and fields, and arrays of optional UInt64, still cross as Long. Their JVM signatures name kotlin.ULong, so they would need keep rules for Kotlin stdlib classes, which Nitro does not ship. New TestObject methods pass UInt64 and UInt64[] records and Promise<UInt64>, and call UInt64 callbacks with callAsync.
mrousavy
force-pushed
the
mrousavy/v1-kotlin-variant-cases
branch
from
October 28, 2026 10:58
771aed0 to
56adfa9
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-erased-ulong
branch
from
October 28, 2026 10:58
be7dd57 to
0891153
Compare
mrousavy
force-pushed
the
mrousavy/v1-kotlin-variant-cases
branch
from
October 28, 2026 11:22
56adfa9 to
5e44d44
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Folded into #1997. Direct boxed unsigned handling now covers maps and Promise results alongside arrays, with the regression cases preserved.
The replacement stack is #2017 → #1997 → #2009.