navigation: federation — contracts, mount, and capabilities - #12569
Open
aurindam wants to merge 5 commits into
Open
navigation: federation — contracts, mount, and capabilities#12569aurindam wants to merge 5 commits into
aurindam wants to merge 5 commits into
Conversation
…rmance Re-implements the navigation-contract slice on master's redesigned interface model, where conformance is the body statement `implement I <=> self;` (the old `implements` header was removed). - grammar: `route` members (RouteDeclaration) with `@version`/`@uri` attributes on an `interface`, parsed unconditionally, gated at lowering. - object tree: an interface's routes collect into a side-car `Component.navigation_contract`, kept off the member lists so interface member projection never sees routes; `route` outside an interface is rejected. - conformance: `validate_navigation_contract_conformance` walks the self- implemented interfaces from master's `get_implemented_interfaces` and requires the component's navigator to cover every contract route by name. Test `navigation_contract_conformance` covers both the passing and the missing-route cases. Mount, `needs`, and external mount are later steps. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- needs: `needs Capability;` declares the interface's callbacks as unbound
members, bound by the integrator at the mount site
(get_needed_interfaces/apply_needs; verify_mount_capabilities).
- local mount: `Route.X: mount Impl via Contract { bindings }` desugars to a
direct instantiation, conformance-checked against the contract
(from_navigator_node + verify_federated_mount/resolve_mount_contract/
validate_mount_conformance).
- external mount: `mount extern via Contract { component-factory: … }` builds a
ComponentContainer the host fills at runtime (from_external_mount_node/
verify_external_mount); FederatedMount.impl_name is None for external.
- route-set fix: lower_navigator marks the route property set so a mounted
module's internal navigator isn't classified constant (would panic on navigate).
Tests: navigation_federated_mount (mount + unbound-capability + external), and
navigation_internal_route_is_writable (runtime navigate/back on an internal
route). 30 interpreter + 325 compiler tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- example: port examples/navigation-federated to the new conformance syntax (`implement <Contract> <=> self;` instead of the removed `implements` header); registered in the examples workspace. Builds end to end, including the external plugin mounted via `mount extern via` whose factory main.rs builds from interpreter-loaded source. - api: make `slint_interpreter::ComponentDefinition::create_embedded` public so a host can supply the factory for an external mount without internal API. - docs: add the Federated Navigation guide (contracts, implement/needs, mount, extern), registered in the sidebar after Navigation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…al route - tests/cases/navigation/mount.slint: a mounted feature (implement <=> self) driven through the outer navigator, in Rust/C++/JS/Python. - tests/cases/navigation/internal_route.slint: navigate()/back() on a non-root component's internal route (the mark_as_set regression). Green in the Rust driver (LLR codegen) and the interpreter driver. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Compress the wordier inline/doc comments added by the federation slices to match the repository convention (why, not what). No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0x6e
reviewed
Jul 21, 2026
|
|
||
| /// Resolve the `needs` specifiers on `node` to capability interfaces. | ||
| pub(super) fn get_needed_interfaces( | ||
| e: &Element, |
Collaborator
There was a problem hiding this comment.
Please spell out variable names in this file (e -> element, tr -> type_register) etc. Here an below.
| for NeededInterface { needs_specifier, interface, interface_name } in needed { | ||
| let mut members = Vec::new(); | ||
| for (name, prop_decl) in interface.borrow().property_declarations.iter().filter(|(_, d)| { | ||
| matches!(d.property_type, Type::Callback { .. } | Type::Function { .. }) |
Collaborator
There was a problem hiding this comment.
Can a capability provide a property? An interface can provide one, yet they are not applied.
| } | ||
|
|
||
| export component MediaFeature inherits Rectangle { | ||
| implement FeatureNav <=> self; |
Collaborator
There was a problem hiding this comment.
Note that once #12566 lands the interface must be fully implemented here. I haven't understood what that means for your @version and @uri yet.
| home => { root.go-home(); } | ||
| } | ||
| MediaRoute.Player: Player { | ||
| can-go-back: root.can-go-back; |
Collaborator
There was a problem hiding this comment.
Where does root.can-go-back come from? Or is root here no longer the MediaFeature?
| } | ||
| all_bound | ||
| } | ||
|
|
Collaborator
There was a problem hiding this comment.
I wonder if some of the stuff added to object_tree.rs and interfaces.rs should be moved to object_tree/navigation.rs?
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.
Adds the federation layer to the
navigator(built on #12554): an app can be assembled from independently-authored, independently-released parts, composed by an integration layer without editing any part's internals.This supersedes #12565, re-implemented on master's current
interface/implementmodel. The only user-visible change from that earlier draft: a part declares conformance with the body statementimplement <Contract> <=> self;instead of the removedimplementsheader. Contracts,needs, and both mount forms are unchanged.Multi-team composition
A navigation contract (an
interfaceofroutes) is the boundary. A part conforms withimplement Contract <=> self, declares the capabilities itneeds, and runs its own navigator; the integration shellmounts each part at a route and binds those needs.Runnable:
examples/navigation-federatedmodels this with separate owners.ui/contract.slintFeatureNavcontract +HostServicesui/media.slintMediaFeature,implement FeatureNav <=> self,needs HostServicesui/settings.slintSettingsFeature, same contractui/app.slintWhat's in it
interfacecarries a navigation contract; route attributes@version(n)/@uri("…")make it versioned and deep-linkable. Routes live in aside-car on the component, off the interface member lists, so interface member
projection never sees them.
implement Contract <=> selfrequires the component's navigator tocover every contract route by name (checked at build time).
needs Capability;declares the interface's callbacks as unboundmembers, bound by the integrator at the mount site; an unbound need is a compile error.
mount Impl via Contract { … }, a direct instantiation checkedagainst the contract.
mount extern via Contract { component-factory: … }viaComponentContainer+ComponentFactory, for parts shipped as their own binary.examples/navigation-federateddemonstrates it end to end: the host builds the pluginin
main.rsand passes it in as aslint::ComponentFactory.slint_interpreter::ComponentDefinition::create_embeddedis nowpublic (was
#[doc(hidden)]+#[cfg(feature = "internal")]), so a real app can supplythe factory for an external mount without reaching into internal API.
(
docs/…/guide/development/navigation-federation.mdx).Notes
SLINT_ENABLE_EXPERIMENTAL_FEATURES=1.navigatorconstruct #12554 (auri/upstream/nav-a5); the diff shows only the federation delta.binding, and the external factory seam; cross-language driver case
tests/cases/navigation/mount.slint(Rust/C++/JS/Python).through
navigate), cross-process capability binding over theexternseam,route param-type conformance, and
<=> childcontracts.