ReviewOS

also looking at this

craft-native/craft

fix(native): preserve workspace sources and native overlay lifecycle

#384
Merged chris wants to merge codex/windows-zig-cache-diagnostics into main
20 files +500 -227

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/android/fixtures/native-navigation/NativeNavigationTest.ktmodified+18-0
Changes to packages/android/fixtures/native-navigation/NativeNavigationTest.kt
@@ -1500,6 +1500,18 @@ class NativeNavigationTest {
15001500 var nullableSwitchInfo: AccessibilityNodeInfo? = null
15011501 instrumentation.runOnMainSync { nullableSwitchInfo = nullableSwitch.createAccessibilityNodeInfo() }
15021502 assertTrue("native checked state should remain accessible without accessibilityState", nullableSwitchInfo?.isChecked == true)
1503 instrumentation.runOnMainSync { nullableSwitch.performClick() }
1504 awaitText(activity, "nullable-switch-status", "nullable switch off")
1505 assertFalse("nullable switch should reconcile its native change", nullableSwitch.isChecked)
1506 instrumentation.runOnMainSync { nullableSwitch.performClick() }
1507 awaitText(activity, "nullable-switch-status", "nullable switch on")
1508 assertTrue("nullable switch should restore checked through its change handler", nullableSwitch.isChecked)
1509 instrumentation.runOnMainSync { precedenceSwitch.performClick() }
1510 awaitText(activity, "switch-precedence-status", "precedence switch on")
1511 assertTrue("switch value should reconcile its native change", precedenceSwitch.isChecked)
1512 instrumentation.runOnMainSync { precedenceSwitch.performClick() }
1513 awaitText(activity, "switch-precedence-status", "precedence switch off")
1514 assertFalse("switch value should still take precedence after reconciliation", precedenceSwitch.isChecked)
15031515 click(activity, "toggle-invalid-switch-colors")
15041516 awaitText(activity, "invalid-control-style-status", "invalid switch colors on")
15051517 assertTrue("uncontrolled switch should survive reconciliation", uncontrolledSwitch.isChecked)
@@ -1574,6 +1586,12 @@ class NativeNavigationTest {
15741586 assertTrue("indeterminate checkbox should become checked on first toggle", indeterminateCheckbox.isChecked)
15751587 val precedenceCheckbox = awaitView(activity, "checkbox-checked-precedence") as CheckBox
15761588 assertTrue("checked should take precedence over value", !precedenceCheckbox.isChecked)
1589 instrumentation.runOnMainSync { precedenceCheckbox.performClick() }
1590 awaitText(activity, "checkbox-precedence-status", "precedence checkbox on")
1591 assertTrue("checkbox checked should reconcile its native change", precedenceCheckbox.isChecked)
1592 instrumentation.runOnMainSync { precedenceCheckbox.performClick() }
1593 awaitText(activity, "checkbox-precedence-status", "precedence checkbox off")
1594 assertFalse("checkbox checked should still take precedence after reconciliation", precedenceCheckbox.isChecked)
15771595 val styledIndicator = awaitView(activity, "native-indicator") as ProgressBar
15781596 assertTrue("authored activity-indicator color should be applied", styledIndicator.indeterminateTintList != null)
15791597 click(activity, "toggle-invalid-control-colors")
packages/ios/fixtures/native-navigation/Home.stxmodified+9-3
Changes to packages/ios/fixtures/native-navigation/Home.stx
@@ -17,6 +17,9 @@ const panelAccessibilityDisabled = state(false)
1717const longPressStatus = state('')
1818const longPressAccessibilityDisabled = state(false)
1919const switchValue = state(false)
20const nullableSwitchChecked = state(true)
21const precedenceSwitchValue = state(false)
22const precedenceCheckboxChecked = state(false)
2023const invalidSwitchColors = state(false)
2124const pickerValue = state('one')
2225const itemsPickerValue = state('one')
@@ -845,8 +848,10 @@ function openDetailsThenUpdateBackground() {
845848 <Switch testID="native-switch" value={switchValue} accessibilityState={switchAccessibilityState()} trackColor={switchTrackColor()} thumbColor={switchThumbColor()} ios_backgroundColor="#475569" @value-change="toggleSwitch($event)" />
846849 <Switch testID="uncontrolled-switch" />
847850 <Button testID="toggle-invalid-switch-colors" @click="toggleInvalidSwitchColors()">Toggle invalid switch colors</Button>
848 <Switch testID="nullable-switch" :value="null" :checked="true" />
849 <Switch testID="switch-value-precedence" :value="false" :checked="true" />
851 <Switch testID="nullable-switch" :value="null" :checked="nullableSwitchChecked" @value-change="nullableSwitchChecked.set($event.value)" />
852 <Text testID="nullable-switch-status" :text="nullableSwitchChecked ? 'nullable switch on' : 'nullable switch off'" />
853 <Switch testID="switch-value-precedence" :value="precedenceSwitchValue" :checked="true" @value-change="precedenceSwitchValue.set($event.value)" />
854 <Text testID="switch-precedence-status" :text="precedenceSwitchValue ? 'precedence switch on' : 'precedence switch off'" />
850855 <select testID="native-picker" :value="pickerValue" @change="choosePicker($event)">
851856 <option value="one">One</option>
852857 <option value="two">Two</option>
@@ -864,7 +869,8 @@ function openDetailsThenUpdateBackground() {
864869 <Checkbox testID="native-checkbox" label="Accept terms" :value="checkboxValue" :color="invalidControlColors ? 'not-a-color' : '#22c55e'" @value-change="chooseCheckbox($event)" />
865870 <Text testID="checkbox-status" :text="checkboxStatus" />
866871 <Checkbox testID="native-checkbox-indeterminate" label="Mixed terms" indeterminate />
867 <Checkbox testID="checkbox-checked-precedence" :checked="false" :value="true" />
872 <Checkbox testID="checkbox-checked-precedence" :checked="precedenceCheckboxChecked" :value="true" @value-change="precedenceCheckboxChecked.set($event.value)" />
873 <Text testID="checkbox-precedence-status" :text="precedenceCheckboxChecked ? 'precedence checkbox on' : 'precedence checkbox off'" />
868874 <Button testID="toggle-invalid-control-colors" @click="toggleInvalidControlColors()">Toggle invalid control colors</Button>
869875 <Text testID="invalid-control-style-status" :text="invalidControlStyleStatus" />
870876 <Text testID="date-event-status" :text="dateEventStatus" />
packages/ios/fixtures/native-navigation/NativeNavigationUITests.swiftmodified+22-0
Changes to packages/ios/fixtures/native-navigation/NativeNavigationUITests.swift
@@ -746,6 +746,14 @@ final class NativeNavigationUITests: XCTestCase {
746746 let uncheckedCheckbox = app.buttons["checkbox-checked-precedence"]
747747 XCTAssertFalse(uncheckedCheckbox.isSelected)
748748 XCTAssertEqual(uncheckedCheckbox.value as? String, "unchecked")
749 uncheckedCheckbox.tap()
750 XCTAssertTrue(waitForLabel(app.staticTexts["checkbox-precedence-status"], "precedence checkbox on"))
751 XCTAssertTrue(uncheckedCheckbox.isSelected)
752 XCTAssertEqual(uncheckedCheckbox.value as? String, "checked")
753 uncheckedCheckbox.tap()
754 XCTAssertTrue(waitForLabel(app.staticTexts["checkbox-precedence-status"], "precedence checkbox off"))
755 XCTAssertFalse(uncheckedCheckbox.isSelected)
756 XCTAssertEqual(uncheckedCheckbox.value as? String, "unchecked")
749757 XCTAssertTrue(app.buttons["disabled-button"].waitForExistence(timeout: 5))
750758 XCTAssertFalse(app.buttons["disabled-button"].isEnabled)
751759 XCTAssertEqual(image.label, "Native pixel")
@@ -989,6 +997,20 @@ final class NativeNavigationUITests: XCTestCase {
989997 XCTAssertTrue(toggle.isEnabled)
990998 XCTAssertEqual(app.switches["nullable-switch"].value as? String, "1")
991999 XCTAssertEqual(app.switches["switch-value-precedence"].value as? String, "0")
1000 let nullableSwitch = app.switches["nullable-switch"]
1001 nullableSwitch.tap()
1002 XCTAssertTrue(waitForLabel(app.staticTexts["nullable-switch-status"], "nullable switch off"))
1003 XCTAssertEqual(nullableSwitch.value as? String, "0")
1004 nullableSwitch.tap()
1005 XCTAssertTrue(waitForLabel(app.staticTexts["nullable-switch-status"], "nullable switch on"))
1006 XCTAssertEqual(nullableSwitch.value as? String, "1")
1007 let precedenceSwitch = app.switches["switch-value-precedence"]
1008 precedenceSwitch.tap()
1009 XCTAssertTrue(waitForLabel(app.staticTexts["switch-precedence-status"], "precedence switch on"))
1010 XCTAssertEqual(precedenceSwitch.value as? String, "1")
1011 precedenceSwitch.tap()
1012 XCTAssertTrue(waitForLabel(app.staticTexts["switch-precedence-status"], "precedence switch off"))
1013 XCTAssertEqual(precedenceSwitch.value as? String, "0")
9921014 toggle.tap()
9931015 XCTAssertTrue(app.staticTexts["switch on"].waitForExistence(timeout: 5))
9941016 XCTAssertEqual(toggle.value as? String, "1")
scripts/native-renderer-contract.test.tsmodified+2-2
Changes to scripts/native-renderer-contract.test.ts
@@ -263,7 +263,7 @@ describe('native renderer component contract', () => {
263263 expect(android).toContain('else if (requestedChecked is Boolean)')
264264 expect(guide).toContain('`checked` is a compatibility alias')
265265 expect(guide).toContain('`value` is null, and `value` takes precedence')
266 expect(navigationHome).toContain('<Switch testID="switch-value-precedence" :value="false" :checked="true" />')
266 expect(navigationHome).toContain('<Switch testID="switch-value-precedence" :value="precedenceSwitchValue" :checked="true" @value-change="precedenceSwitchValue.set($event.value)" />')
267267 expect(navigationHome).toContain('<Switch testID="uncontrolled-switch" />')
268268 expect(androidNavigationTest).toContain('non-null switch value should take precedence over checked')
269269 expect(androidNavigationTest).toContain('uncontrolled switch should keep its native toggle')
@@ -274,7 +274,7 @@ describe('native renderer component contract', () => {
274274 expect(componentTypes).toContain('checked?: boolean')
275275 expect(ios).toContain('props["checked"] as? Bool) ?? (props["value"] as? Bool) ?? false')
276276 expect(android).toContain('checkboxChecked is Boolean -> checkboxChecked')
277 expect(navigationHome).toContain('<Checkbox testID="checkbox-checked-precedence" :checked="false" :value="true" />')
277 expect(navigationHome).toContain('<Checkbox testID="checkbox-checked-precedence" :checked="precedenceCheckboxChecked" :value="true" @value-change="precedenceCheckboxChecked.set($event.value)" />')
278278 expect(androidNavigationTest).toContain('checked should take precedence over value')
279279 expect(iosNavigationTest).toContain('let uncheckedCheckbox = app.buttons["checkbox-checked-precedence"]')
280280 expect(iosNavigationTest).toContain('XCTAssertFalse(uncheckedCheckbox.isSelected)')