Repository navigation
feat!: Navigator 的 push / pop 带上调用方 PageContext,pop 定为关闭调用方 - #47
Conversation
留在返回栈里的页面照常运行,页面也可能分在几个栈里,宿主只凭「栈顶」会弹错页、动错栈。 两个方法都加 from: PageContext(与 HostCapability、AnalyticsSink、LinkOpener 一致), 宿主经挂载时的 locals 认出调用方自己的条目;pop 关闭调用方并把结果交给它下面那一页, 非栈顶页面发起的 push 由宿主决定,通常忽略。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's Guide该 PR 让 Navigator 的 push/pop 携带框架注入的 PageContext,由 PageHost 自动传递调用方身份;宿主据此按具体挂载和导航栈执行操作,pop 关闭调用方并向下方页面传递结果,同时更新文档、测试和 ABI。 Sequence diagram for caller-aware navigationsequenceDiagram
participant Page as PageHost
participant Navigator
participant Stack as Host navigation stack
participant Below as PageHost below caller
Page->>Navigator: push(page, paramsJson, context)
Navigator->>Stack: from[NavEntryLocal]
alt caller is not topmost
Stack-->>Navigator: ignore or report push
else caller is topmost
Navigator->>Stack: push page
end
Page->>Navigator: pop(resultJson, context)
Navigator->>Stack: remove caller entry from[NavEntryLocal]
Stack->>Below: emit(navigation.result, resultJson)
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
There was a problem hiding this comment.
CodeSeer 审查
结论:批准
摘要
本次改动将 Navigator.push 和 Navigator.pop 的调用方 PageContext 传递到宿主,并在 PageHost 的导航 J4 分发处使用当前挂载的 context。ABI 快照、测试及 native-api.md 也同步了接口变化和新的 pop 语义。给出的代码中未发现由该增量引入的确定性逻辑或资源管理问题。
整个 PR 至 1d9e62b · gpt-5.6-terra
There was a problem hiding this comment.
Hey - I've found 3 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="compose/src/commonMain/kotlin/app/tinyui/PageHost.kt" line_range="441" />
<code_context>
"timer.cancel" -> a["cbId"]?.jsonPrimitive?.intOrNull?.let { timers.remove(it)?.cancel() }
- "navigation.push" -> host.navigator.push(a.str("page") ?: return, a["params"]?.toString() ?: "{}")
- "navigation.pop" -> host.navigator.pop(a["result"]?.toString())
+ "navigation.push" -> host.navigator.push(a.str("page") ?: return, a["params"]?.toString() ?: "{}", context)
+ "navigation.pop" -> host.navigator.pop(a["result"]?.toString(), context)
"store.set" -> { val key = a.str("key") ?: return; host.store.setJson(key, a.str("value") ?: "null") }
</code_context>
<issue_to_address>
**Deferred navigation targets the wrong entry**
When a host defers handling a navigation call while the same retained page is recomposed with a different entry in `locals`, `PageHost.send` passes a mutable `PageContext`; if a host defers handling until after `TinyUIPage` updates `context.locals`, `from[NavEntryLocal]` resolves the replacement entry and navigation acts on the wrong page or stack.
Have the host capture the entry from `from` synchronously before deferring navigation, or provide an immutable caller-context snapshot.
Also at `compose/src/commonMain/kotlin/app/tinyui/PageHost.kt:442`.
</issue_to_address>
### Comment 2
<location path="docs/native-api.md" line_range="67" />
<code_context>
+override fun pop(resultJson: String?, from: PageContext) {
+ val entry = from[NavEntryLocal] ?: return
+ val below = entry.stack.remove(entry) // 关的是调用方,哪怕它不在栈顶
+ if (resultJson != null) below?.pageHost?.emit("navigation.result", """{"result":$resultJson,"from":"${from.name}"}""")
+}
+```
</code_context>
<issue_to_address>
**Navigation results can be dropped**
When the recipient is still mounting when the host emits the result, or it closes before its queued emit runs, `PageHost.emit` only queues an entry; `PageHost.entry` silently returns when `entries` is still null, and scope cancellation also discards queued work. The host gets no indication to retry, so the page below the caller never receives `navigation.result`.
Buffer navigation results until the recipient is mounted and ensure delivery is serialized with closing it.
</issue_to_address>
### Comment 3
<location path="docs/native-api.md" line_range="66-67" />
<code_context>
+
+override fun pop(resultJson: String?, from: PageContext) {
+ val entry = from[NavEntryLocal] ?: return
+ val below = entry.stack.remove(entry) // 关的是调用方,哪怕它不在栈顶
+ if (resultJson != null) below?.pageHost?.emit("navigation.result", """{"result":$resultJson,"from":"${from.name}"}""")
+}
+```
</code_context>
<issue_to_address>
**Documented pop example does not compile**
When the host follows the documented example with a standard Kotlin mutable list for its stack, `entry.stack.remove(entry)` returns a Boolean, so `below?.pageHost` does not compile and hosts cannot deliver the result to the page below.
Remove the caller while retaining the entry below it, then emit the result through that entry's `PageHost`.
Also at `docs/native-api.md:69`.
</issue_to_address>Sourcery assessment
Approval pending. 3 findings to address first.
Blocking findings: compose/src/commonMain/kotlin/app/tinyui/PageHost.kt:441, docs/native-api.md:67, docs/native-api.md:67
- PageHost 的 entry() 遇到还没挂载的页面直接返回,宿主在页面被回收重建时 emit 的 navigation.result 会丢 (与 app-model.md「被回收重建后照样收到」不符);现在先等挂载结束,挂载失败或页面关闭才放弃 - native-api.md §3 的 pop 示例改成能编译的写法,并写明 from[local] 要在调用里同步取(locals 跟着最近一次组合) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mount 在 entries 赋值之后才抛时,先到的 emit 等挂载结束后仍会调失败页面的引擎(CodeSeer 审查意见)。 测试用桩里只认 probe topic 的 emit 回调 navigation.pop 作为可观察副作用:不修时 pop 到达 Navigator。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Navigator.push/pop原来不知道是哪一页在调用,宿主只能对栈顶操作。两种情况会出错:pop会弹掉盖在上面的那一页改动:
push(page, paramsJson, from: PageContext)/pop(resultJson, from: PageContext),PageHost传入自己的context。与HostCapability、AnalyticsSink、LinkOpener一致,调用方身份由框架带上,页面改不了pop= 关闭调用方自己(同 Androidfinish()、SwiftUIdismiss),结果交给它下面那一页;非栈顶页面发起的push由宿主决定,通常忽略并上报locals给页面一个指向自己导航条目的句柄,from[local]取回。写法见 native-api.md §3tinyui-native的 JS API 不变破坏性:实现了
Navigator的宿主要加参数。0.14.0 还没发布,随它一起出。测试:
PageHostTest.navigationTellsTheNavigatorWhichMountCalled:push / pop 到达 Navigator 时from是这次挂载,带着挂载时的 locals:compose:iosSimulatorArm64Test通过、apiCheck通过(ABI 文件已更新);本机 Android host test 缺宿主 JNI 库没跑起来,看 CI🤖 Generated with Claude Code
Summary by Sourcery
Make Navigator operations caller-aware so hosts can close the originating page and route results correctly across persistent and multiple navigation stacks.
New Features:
Bug Fixes:
Enhancements:
Documentation:
Tests:
Chores: