GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |
GeezerVison is showing github.com — feat(swift-interop): modules, generics, protocols, Observation and SwiftUI (3/7) by NathanWalker · Pull Request #520 · NativeScript/ios Conversation
|
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews: auto_review: drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Several Swift modules can now be generated as one unit (ABI 8), via --swift-unit with a --swift-symbolgraph-dir per module. The unit is merged into one IR. Every symbol keeps its own module, so declarations can name another module's types, and extensions of those types become their members. A unit has one thunk file, with shared support code and one type table, and one `.d.ts` per module that imports the others' types. At runtime, each ns_swift_register_<Module> symbol registers the whole unit, and every module maps to it. Each isolate builds the unit's templates once and gives every module its own ns:swift/<Module> namespace, so a type has one JS class wherever it appears. Types and members register with their module. Module-level overloads group per module. A module that is an implementation detail of another (SwiftUICore of SwiftUI) can't be imported. With --swift-reexport, which is implied for that pair, its declarations join the module that re-exports it. As a unit, SwiftUI and SwiftUICore verify and type-check with 2547 callables, against 873 for SwiftUI alone. The fixture gains a SwiftDemoKit module, which SwiftDemo uses and extends. It is built as its own static library target for TestRunner.
A generic type is now bridged through every concrete instantiation that the unit's declarations spell: signatures and public typealiases (for example `Measurement<UnitTemperature>` in WeatherKit). Instantiations found inside other instantiations' members are followed two levels deep. Before classification, instantiateGenerics adds a synthetic non-generic type for each instantiation. It copies the generic type's members, each with a substitution map for the generic parameters. Members whose same-type requirements contradict the arguments are left out, such as a `where UnitType == UnitMass` extension or a synthesized `Self == Style<T>` member. The classifier, thunks and probes then treat instantiations like any other type, and the compiler verifies every instantiated member. Typealiases now bridge as the type they name. Instantiations of one generic type share one JS class. They share a module and a JS name, and the runtime groups them into a family: one template and one member group per name. The constructor resolves among every instantiation's initializers, and instance members only consider the receiver's own instantiation. TypeScript declares the generic class once from template capabilities (`class Pair<First, Second>`), names instantiations with their arguments, and declares typealiases. Fix: the compiler log is removed before each verification run. LLVM's redirect doesn't truncate it, so a shorter second run kept the previous run's errors. At SDK scale, Foundation goes from 3038 to 3486 callables (74 instantiations) and WeatherKit from 267 to 379 (23). The WeatherKit and Foundation unit has 3968 callables. All of them type-check.
A parameter typed by a module protocol (`any P`, or a bare `P`) now accepts a Swift value that conforms to it, or a JS object implementing it (ABI 9). A protocol is adoptable when: - its requirements are instance methods and properties that bridge; - it has no associated types or `Self` requirements; - it has no static, async or main-actor requirements; - it refines at most one module protocol. For each adoptable protocol, the thunks get an __NSAdapter class conforming to it. Each requirement calls the JS object's member of the same name through new object-call entries and reads the returned value. A failure makes a throwing requirement throw. Otherwise the requirement returns its type's zero value, or traps when the type has none. Results come back as the JS object they started as, as their own registered class or struct, or boxed as the protocol, whose JS class carries the protocol's members. The runtime checks that a JS implementation provides every requirement, and builds each protocol's requirement table: the refined protocol's requirements, then its own. A requirement called from another thread runs on the isolate's thread while the Swift caller waits. A JS exception raised during a JS call takes precedence over the error a thunk reports. Callback handles generalize to JS object handles. TypeScript declares protocols as interfaces. The fixture covers JS and Swift conformers, throwing requirements, refinement, implementations Swift holds, and calls from a background task.
5efedd7 to
63b3a51
Compare
b951726 to
39dac9d
Compare
`ns:swift` gains track(read, onChange) and observe(read, onChange) (ABI 10). - track is Swift's withObservationTracking. It runs `read`, and the getter thunks `read` reaches run inside the tracking scope, so the observable properties it touches are recorded. `onChange` runs once, when one of them is about to change. - observe re-arms after every change, calls `onChange` after the change is made, and returns a stop function. Every generated unit carries the tracker and registers it. The runtime uses any loaded unit's tracker and throws what `read` throws. A change made on another thread reaches JS on its thread.
Results typed AsyncStream<T>, AsyncThrowingStream<T, E> or `some AsyncSequence<T, E>` now return JS async iterators, so `for await` works over them (ABI 11). The signature code is ~<element>. The thunk wraps the sequence in a type-erased __NSAsyncIterator. Its step runs the iterator's next() in a Task and reports the element as a one-element array, or an empty array at the end, through the existing async collection path. The runtime hands the iterator to a step function. A small factory compiled once per isolate makes that function an async iterator whose next() calls run one at a time. The step function's weak handle releases the Swift iterator when collected. A pending async result now keeps its own result code and name instead of a member pointer, since an iterator step's member can be collected before the step settles. Opaque results bind without naming their type.
A bridged struct that conforms to SwiftUI.View gains a synthesized hostingController() member. It returns a UIHostingController showing a copy of the view, as an ordinary NativeScript UIViewController that can go into a NativeScript layout. The thunk runs on the main actor and refuses other threads. The compiler verifies it like every other thunk, and the unit imports SwiftUI and UIKit when it hosts views.
39dac9d to
83c8aff
Compare
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.