also looking at this
fix(mobile): preserve native editing, navigation, and durable media requests
#369
36 files
+864
-185
| @@ -2,6 +2,34 @@ | ||
| 2 | 2 | import { test } from 'bun:test' |
| 3 | 3 | import { runKotlinFixture } from './testing' |
| 4 | 4 | |
| 5 | test('snaps authored padding to the nearest physical pixel at fractional density', async () => { | |
| 6 | const template = await Bun.file(new URL('../templates/MainActivityNative.kt.template', import.meta.url)).text() | |
| 7 | const padding = template.match(/internal fun craftNativePadding\([^]*?\n\}/)?.[0] | |
| 8 | const number = template.match(/private fun craftNativeNumber\([^]*?\n \?\.takeIf \{ it\.isFinite\(\) \}/)?.[0] | |
| 9 | if (!padding || !number) throw new Error('Native padding normalization is missing') | |
| 10 | await runKotlinFixture(` | |
| 11 | import kotlin.math.roundToInt | |
| 12 | ||
| 13 | class JSONObject(private val values: Map<String, Any?>) { | |
| 14 | fun opt(name: String): Any? = values[name] | |
| 15 | } | |
| 16 | ${number} | |
| 17 | ${padding} | |
| 18 | ||
| 19 | fun main() { | |
| 20 | val density = 2.625f | |
| 21 | check(craftNativePadding(JSONObject(mapOf("padding" to 4)), "padding", 0, density) == 11) | |
| 22 | check(craftNativePadding(JSONObject(mapOf("padding" to 8)), "padding", 0, density) == 21) | |
| 23 | check(craftNativePadding(JSONObject(mapOf("padding" to 4)), "padding", 0, 1f) == 4) | |
| 24 | for (invalid in listOf(null, -1, Double.NaN, Double.POSITIVE_INFINITY, true, "4")) { | |
| 25 | check(craftNativePadding(JSONObject(mapOf("padding" to invalid)), "padding", 7, density) == 7) | |
| 26 | } | |
| 27 | check(craftNativePadding(null, "padding", 7, density) == 7) | |
| 28 | println("PASS native padding rounds once to the nearest physical pixel and retains invalid-value defaults") | |
| 29 | } | |
| 30 | `) | |
| 31 | }, 180_000) | |
| 32 | ||
| 5 | 33 | test('sizes occupied and empty explicit grid rows after padding and fractional gaps', async () => { |
| 6 | 34 | const template = await Bun.file(new URL('../templates/MainActivityNative.kt.template', import.meta.url)).text() |
| 7 | 35 | const allocation = template.match(/ val rowHeights = if \(gridRows != null\) \{[\s\S]*?\n \} else naturalRowHeights/)?.[0] |
| @@ -34,3 +62,31 @@ fun main() { | ||
| 34 | 62 | } |
| 35 | 63 | `) |
| 36 | 64 | }, 180_000) |
| 65 | ||
| 66 | ||
| 67 | test('encodes shared grid counts as the unsigned integer fields in the native ABI', async () => { | |
| 68 | const template = await Bun.file(new URL('../templates/MainActivityNative.kt.template', import.meta.url)).text() | |
| 69 | const columns = template.match(/^[^\n]*put(?:Enum)?\(base, 29, node\.gridColumns[^\n]*$/m)?.[0] | |
| 70 | const rows = template.match(/^[^\n]*if \(explicitRowsAware\) put(?:Enum)?\(base, 34, [^\n]*$/m)?.[0] | |
| 71 | const directColumns = template.match(/^[^\n]*put(?:Enum)?\(base, 29, 1f?\)[^\n]*$/m)?.[0] | |
| 72 | if (!columns || !rows || !directColumns) throw new Error('Shared grid count serialization is missing') | |
| 73 | await runKotlinFixture(` | |
| 74 | data class GridNode(val gridColumns: Int, val gridRows: Int?) | |
| 75 | ||
| 76 | fun main() { | |
| 77 | val base = 0 | |
| 78 | val node = GridNode(2, 3) | |
| 79 | val explicitRowsAware = true | |
| 80 | val nodeData = FloatArray(35) { Float.NaN } | |
| 81 | fun put(base: Int, index: Int, value: Float) { nodeData[base + index] = value } | |
| 82 | fun putEnum(base: Int, index: Int, value: Int) { put(base, index, Float.fromBits(value)) } | |
| 83 | ${columns} | |
| 84 | ${rows} | |
| 85 | check(nodeData[29].toRawBits() == 2) { "grid_columns is not encoded as u32" } | |
| 86 | check(nodeData[34].toRawBits() == 3) { "grid_rows is not encoded as u32" } | |
| 87 | ${directColumns} | |
| 88 | check(nodeData[29].toRawBits() == 1) { "direct layout grid_columns default is not encoded as u32" } | |
| 89 | println("PASS native grid counts retain the integer bit patterns consumed by Zig") | |
| 90 | } | |
| 91 | `) | |
| 92 | }, 180_000) | |