@swiftbrowser/cli 0.6.7 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -11
- package/dist/appSources.d.ts +116 -0
- package/dist/appSources.js +624 -0
- package/dist/appSources.js.map +1 -0
- package/dist/browser.d.ts +4 -0
- package/dist/browser.js +8 -0
- package/dist/browser.js.map +1 -0
- package/dist/build.d.ts +17 -2
- package/dist/build.js +38 -11
- package/dist/build.js.map +1 -1
- package/dist/cli.js +28 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.js +10 -7
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +38 -8
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +8 -4
- package/dist/commands/dev.js +25 -10
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.js +52 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/kit.d.ts +1 -0
- package/dist/commands/kit.js +20 -5
- package/dist/commands/kit.js.map +1 -1
- package/dist/commands/shared.d.ts +24 -6
- package/dist/commands/shared.js +92 -16
- package/dist/commands/shared.js.map +1 -1
- package/dist/commands/test.d.ts +4 -2
- package/dist/commands/test.js +25 -17
- package/dist/commands/test.js.map +1 -1
- package/dist/compat.d.ts +2 -30
- package/dist/compat.js +2 -44
- package/dist/compat.js.map +1 -1
- package/dist/compiler.d.ts +50 -0
- package/dist/compiler.js +94 -0
- package/dist/compiler.js.map +1 -0
- package/dist/config.d.ts +5 -2
- package/dist/config.js +7 -3
- package/dist/config.js.map +1 -1
- package/dist/frameworks.d.ts +30 -0
- package/dist/frameworks.js +48 -0
- package/dist/frameworks.js.map +1 -0
- package/dist/icu.d.ts +2 -4
- package/dist/icu.js +7 -36
- package/dist/icu.js.map +1 -1
- package/dist/kit.d.ts +62 -17
- package/dist/kit.js +183 -33
- package/dist/kit.js.map +1 -1
- package/dist/log.js +2 -1
- package/dist/log.js.map +1 -1
- package/dist/manifest.d.ts +73 -0
- package/dist/manifest.js +324 -0
- package/dist/manifest.js.map +1 -0
- package/dist/moduleCache.d.ts +20 -0
- package/dist/moduleCache.js +98 -0
- package/dist/moduleCache.js.map +1 -0
- package/dist/objc.js +1 -1
- package/dist/objc.js.map +1 -1
- package/dist/packages.d.ts +8 -1
- package/dist/packages.js +10 -2
- package/dist/packages.js.map +1 -1
- package/dist/registry.d.ts +46 -0
- package/dist/registry.js +184 -0
- package/dist/registry.js.map +1 -0
- package/dist/resolve.d.ts +80 -0
- package/dist/resolve.js +396 -0
- package/dist/resolve.js.map +1 -0
- package/dist/stage.d.ts +5 -144
- package/dist/stage.js +19 -516
- package/dist/stage.js.map +1 -1
- package/dist/testDiscovery.d.ts +44 -0
- package/dist/testDiscovery.js +111 -0
- package/dist/testDiscovery.js.map +1 -0
- package/dist/vendor.d.ts +41 -5
- package/dist/vendor.js +71 -31
- package/dist/vendor.js.map +1 -1
- package/dist/wasmCompiler.d.ts +160 -0
- package/dist/wasmCompiler.js +628 -0
- package/dist/wasmCompiler.js.map +1 -0
- package/dist/wasmFlags.d.ts +31 -0
- package/dist/wasmFlags.js +56 -0
- package/dist/wasmFlags.js.map +1 -0
- package/dist/wasmPackages.d.ts +163 -0
- package/dist/wasmPackages.js +466 -0
- package/dist/wasmPackages.js.map +1 -0
- package/dist/wasmSdk.d.ts +27 -0
- package/dist/wasmSdk.js +103 -0
- package/dist/wasmSdk.js.map +1 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -36,12 +36,15 @@ down), or a plain folder of Swift sources. Options for all of them:
|
|
|
36
36
|
(with Swift 6.4 and its Swift SDK for WebAssembly): every module of the shim,
|
|
37
37
|
and an archive of each module's objects, in a *kit* under
|
|
38
38
|
`~/.cache/swiftbrowser/kits/` (`SWIFTBROWSER_CACHE` moves the cache). A
|
|
39
|
-
released CLI comes with its kit, @swiftbrowser/kit (
|
|
40
|
-
the
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
released CLI comes with its kit, @swiftbrowser/kit (36 MB to download): the
|
|
40
|
+
first build copies it into the cache and checks that your toolchain reads its
|
|
41
|
+
modules. Its macros (`@Model`, `#Predicate`, `@Entry`) come built as
|
|
42
|
+
WebAssembly, the same files on every host: the toolchain runs them through a
|
|
43
|
+
small launcher in @swiftbrowser/wasm-compiler, under the Node that runs the
|
|
44
|
+
CLI. Where the kit cannot serve (Windows, where the compiler runs no
|
|
45
|
+
launcher script; a toolchain whose compiler reads only modules it wrote), or
|
|
46
|
+
in a checkout of this repository, the first build compiles the kit itself, in
|
|
47
|
+
a minute or two. A kit takes 83 MB: 50 MB of archives, 15 MB of
|
|
45
48
|
modules and the 18 MB macro executable; SwiftPM's scratch path for building
|
|
46
49
|
kits takes 325 MB more.
|
|
47
50
|
Every app built after that, in any project, compiles its own code and
|
|
@@ -55,7 +58,54 @@ the toolchain and the SDK, so a change to any of them (a newer
|
|
|
55
58
|
SwiftPM's scratch path for kits stays in the cache, so that rebuild compiles
|
|
56
59
|
only the modules the change touched, and the three most recent kits are kept.
|
|
57
60
|
`SWIFTBROWSER_KIT=0` builds the shim from its sources in the app's own build
|
|
58
|
-
instead, as before kits. `check` compiles
|
|
61
|
+
instead, as before kits. A native `check` compiles for the host against the
|
|
62
|
+
shim's sources and does not use the kit.
|
|
63
|
+
|
|
64
|
+
### The WebAssembly compiler
|
|
65
|
+
|
|
66
|
+
`--compiler` (or `SWIFTBROWSER_COMPILER`, which the flag overrides) picks
|
|
67
|
+
what compiles the app in `check`, `dev`, `build` and `test` (src/compiler.ts):
|
|
68
|
+
|
|
69
|
+
| Value | Builds with |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `auto` (the default) | the Swift toolchain when it is installed (it builds faster), else the WebAssembly compiler, saying why |
|
|
72
|
+
| `native` | the Swift toolchain and SwiftPM |
|
|
73
|
+
| `wasm` | the Swift compiler and linker built as WebAssembly (`@swiftbrowser/wasm-compiler`, the tools from `@swiftbrowser/wasm-tools` or `SWIFTBROWSER_WASM_TOOLS`): no Swift install |
|
|
74
|
+
|
|
75
|
+
So with Swift installed nothing changes, and without it `npx
|
|
76
|
+
@swiftbrowser/cli dev` builds with the npm packages alone, once
|
|
77
|
+
`swiftbrowser doctor --install` has downloaded the Swift SDK for
|
|
78
|
+
WebAssembly's files.
|
|
79
|
+
|
|
80
|
+
The WebAssembly compiler builds against the kit and needs only the Swift
|
|
81
|
+
SDK for WebAssembly's files: the toolchain's install, or, without a
|
|
82
|
+
toolchain, the CLI's own download (`swiftbrowser doctor --install`, 93 MB
|
|
83
|
+
into the cache; src/wasmSdk.ts). Without a toolchain it uses the released
|
|
84
|
+
kit (@swiftbrowser/kit, checked by type-checking an import of every module)
|
|
85
|
+
and cannot build one. It runs the kit's macros
|
|
86
|
+
built as WebAssembly: @swiftbrowser/kit has them, and a kit made here gets
|
|
87
|
+
them from `swiftbrowser kit --wasm-macros` or the first WebAssembly build
|
|
88
|
+
(with a toolchain; minutes the first time, swift-syntax compiling for
|
|
89
|
+
WebAssembly). `check` type-checks against the kit with it. Package
|
|
90
|
+
dependencies build with it too: without SwiftPM in charge (no toolchain, or
|
|
91
|
+
`--compiler wasm`), the CLI resolves them with git, honouring
|
|
92
|
+
`Package.resolved` (src/resolve.ts; registry packages from their
|
|
93
|
+
registry, src/registry.ts), and runs their manifests with the
|
|
94
|
+
WebAssembly tools (src/manifest.ts; @swiftbrowser/wasm-tools ships SwiftPM's
|
|
95
|
+
PackageDescription for this), caching both. C targets in packages compile
|
|
96
|
+
with clang built as WebAssembly, and package traits are followed; Ice Cubes
|
|
97
|
+
builds this way. A package's macro targets (TCA's) build as WebAssembly
|
|
98
|
+
plugins, swift-syntax compiled for them alone (minutes the first time, then
|
|
99
|
+
cached). The packages' compiled modules are cached too, keyed by their
|
|
100
|
+
inputs (src/moduleCache.ts): a rebuild compiles only what an edit reaches,
|
|
101
|
+
and apps share the modules of the packages they have in common. `test`
|
|
102
|
+
builds with it too: the app as a testable module, each test target against
|
|
103
|
+
it, and a runner like SwiftPM's (XCTest's tests listed from the test
|
|
104
|
+
module's symbol graph, Swift Testing's found as it runs; src/testDiscovery.ts),
|
|
105
|
+
with swift-testing's macros built as WebAssembly. In
|
|
106
|
+
`dev` it compiles unoptimized (`-Onone`, without a DEBUG define, so the app
|
|
107
|
+
behaves as it will in `build`) and keeps the compiled tools between
|
|
108
|
+
rebuilds: a save rebuilds Counter in about 5 s, as SwiftPM does.
|
|
59
109
|
|
|
60
110
|
Building several apps in a row (a CI job, a script) can compile the
|
|
61
111
|
SwiftBrowser package once for all of them: set `SWIFTBROWSER_BUILD_ROOT` to a
|
|
@@ -140,7 +190,8 @@ was released with).
|
|
|
140
190
|
rebuilds neither from scratch. Each unit-test target is a test target in it
|
|
141
191
|
that depends on the app's. Its files get the same adjustments, along with
|
|
142
192
|
the generated alias file, because a test module imports both Foundation and
|
|
143
|
-
the app. It links the SDK's whole ICU data rather than a trimmed copy.
|
|
193
|
+
the app. It links the SDK's whole ICU data rather than a trimmed copy. The
|
|
194
|
+
WebAssembly compiler builds the same staging without SwiftPM.
|
|
144
195
|
|
|
145
196
|
## Foundation
|
|
146
197
|
|
|
@@ -232,6 +283,7 @@ CI checks.
|
|
|
232
283
|
"corsProxy": "https://swiftbrowser-cors-proxy.you.workers.dev/",
|
|
233
284
|
"packages": [
|
|
234
285
|
{ "url": "https://github.com/twostraws/CodeScanner", "from": "2.5.2", "products": ["CodeScanner"] },
|
|
286
|
+
{ "id": "mona.LinkedList", "from": "1.2.0", "products": ["LinkedList"] },
|
|
235
287
|
{ "path": "../Shared", "products": ["SharedKit"] }
|
|
236
288
|
]
|
|
237
289
|
}
|
|
@@ -250,9 +302,14 @@ files) one by one.
|
|
|
250
302
|
|
|
251
303
|
`packages` adds Swift packages to the ones the Xcode target links: the only
|
|
252
304
|
way a plain folder of sources depends on one. Each has a `url` with one rule
|
|
253
|
-
(`from`: up to the next major version, `exact`, `branch` or `revision`),
|
|
254
|
-
|
|
255
|
-
|
|
305
|
+
(`from`: up to the next major version, `exact`, `branch` or `revision`), a
|
|
306
|
+
package registry's `id` (`scope.name`) with `from` or `exact`, or a local
|
|
307
|
+
`path` (relative to the project), and the `products` the app imports. They
|
|
308
|
+
are built as described in "Swift packages". Registries are configured as
|
|
309
|
+
SwiftPM configures them (`swift package-registry set`):
|
|
310
|
+
`.swiftpm/configuration/registries.json` in the app's folder, then in your
|
|
311
|
+
home folder, with credentials in `~/.netrc`; packages that depend on
|
|
312
|
+
registry packages (`.package(id:)`) find them the same way.
|
|
256
313
|
|
|
257
314
|
`corsProxy` (or `--cors-proxy <url>` on `dev` and `build`) names a CORS proxy:
|
|
258
315
|
the page retries a cross-origin GET or HEAD the browser refused (the server
|
|
@@ -413,6 +470,20 @@ git clone --depth 1 https://github.com/apple/sample-food-truck
|
|
|
413
470
|
npx @swiftbrowser/cli dev sample-food-truck --target "Food Truck"
|
|
414
471
|
```
|
|
415
472
|
|
|
473
|
+
[The Composable Architecture](https://github.com/pointfreeco/swift-composable-architecture)
|
|
474
|
+
builds as it is, with the packages it brings (swift-dependencies,
|
|
475
|
+
swift-navigation, swift-sharing, combine-schedulers and the rest): its
|
|
476
|
+
macros (`@Reducer`, `@ObservableState`, `@DependencyClient`) build as
|
|
477
|
+
plugins, and its packages are copied and built against the shim like any
|
|
478
|
+
other. swift-navigation's UIKit layer builds over the shim's UIKit, whose
|
|
479
|
+
views and view controllers are `NSObject`s with iOS 17's traits; the
|
|
480
|
+
Objective-C target it swizzles view controllers with is the shim's own
|
|
481
|
+
lifecycle hooks here. Code a package keeps for older systems
|
|
482
|
+
(`#if canImport(ObjectiveC)`, CoreFoundation imports, `-ObjC` link flags,
|
|
483
|
+
KVO overrides) is adjusted in its copy (src/appSources.ts, vendor.ts). The
|
|
484
|
+
TCACounter fixture (packages/cli/test/fixtures/apps) is a counter, with
|
|
485
|
+
the versions it was made with pinned in its Package.resolved.
|
|
486
|
+
|
|
416
487
|
A package SwiftBrowser has a patch for is built from its own sources with
|
|
417
488
|
a few passages replaced first: code that only works with the Objective-C
|
|
418
489
|
runtime and no general adjustment can take. Today that is
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export interface TransformResult {
|
|
2
|
+
text: string;
|
|
3
|
+
previewsStripped: number;
|
|
4
|
+
/** `import Foundation` lines rewritten. */
|
|
5
|
+
foundationRewrites: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function transformSource(text: string, options?: {
|
|
8
|
+
bridged?: boolean;
|
|
9
|
+
optionalRequirements?: ReadonlySet<string>;
|
|
10
|
+
}): TransformResult;
|
|
11
|
+
/**
|
|
12
|
+
* `configuration.delegateClass = SceneDelegate.self` →
|
|
13
|
+
* `configuration._setDelegateClass(SceneDelegate.self) { SceneDelegate() }`:
|
|
14
|
+
* UIKit makes the scene delegate through the Objective-C runtime, and Swift
|
|
15
|
+
* without it can only make an instance from a metatype through a `required`
|
|
16
|
+
* initializer (UIKit/SceneDelegates.swift). Same line, so diagnostics keep
|
|
17
|
+
* their places.
|
|
18
|
+
*/
|
|
19
|
+
export declare function sceneDelegateClasses(text: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* `as? AnyObject` → `as? _AnyObjectValue` where the file reads a number from
|
|
22
|
+
* the result: `(dict[key] as? AnyObject)?.doubleValue` looks the member up on
|
|
23
|
+
* any object through Objective-C (nil where there is none); FoundationBridge's
|
|
24
|
+
* `_AnyObjectValue` (Selector.swift) has those members, optional likewise, on
|
|
25
|
+
* the numbers, booleans and strings a dictionary of `Any` holds.
|
|
26
|
+
*/
|
|
27
|
+
export declare function numberCasts(text: string): string;
|
|
28
|
+
/** Whether a source uses the Objective-C runtime's selectors or attributes. */
|
|
29
|
+
export declare function usesObjC(text: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Whether a source calls POSIX mutex functions. WASI's libc module leaves
|
|
32
|
+
* `pthread.h` out, so a package that does is built from a copy: there
|
|
33
|
+
* `#if os(iOS)` holds (Darwin's `os_unfair_lock` branch) and FoundationBridge
|
|
34
|
+
* declares the mutex functions for the page's single thread (Locks.swift).
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* `unsafeBitCast(Selector(#function), to: UnsafeRawPointer.self)` →
|
|
38
|
+
* `Selector(#function)._uniquePointer`: the address that stands for the
|
|
39
|
+
* selector's name (FoundationBridge/Selector.swift), which on Apple
|
|
40
|
+
* platforms the bit cast gives, the selector being a uniqued pointer.
|
|
41
|
+
*/
|
|
42
|
+
export declare function selectorPointers(text: string): string;
|
|
43
|
+
/** Whether a source imports ObjectiveC, which the SDK does not have on WASI (transformSource). */
|
|
44
|
+
export declare function importsObjectiveC(text: string): boolean;
|
|
45
|
+
/** Whether a source imports Dispatch, which the SDK does not have on WASI (transformSource). */
|
|
46
|
+
export declare function importsDispatch(text: string): boolean;
|
|
47
|
+
/** CoreFoundation's headers need wasi-libc's signal and mman emulations (`WASI_EMULATION_FLAGS`). */
|
|
48
|
+
export declare function importsCoreFoundation(text: string): boolean;
|
|
49
|
+
/** What a Swift module that imports CoreFoundation is compiled with for WASI: the emulations its headers include (the link has their libraries). */
|
|
50
|
+
export declare const WASI_EMULATION_FLAGS: readonly string[];
|
|
51
|
+
export declare function usesPosixMutex(text: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Objective-C without its runtime (FoundationBridge/Selector.swift). The
|
|
54
|
+
* browser's Swift has no Objective-C interop, so `@objc` (and the Interface
|
|
55
|
+
* Builder attributes that imply it) is dropped, and `#selector(handle(_:))`
|
|
56
|
+
* becomes `Selector(Self.handle(_:), name: "handle(_:)")`: the method itself,
|
|
57
|
+
* which the target/selector APIs call on their target. A qualified method
|
|
58
|
+
* (`Type.method`) is used as it is; one of another object
|
|
59
|
+
* (`#selector(model.refresh)`) is called bound; `getter:`/`setter:`
|
|
60
|
+
* selectors only have a name, as does a method of three or more arguments
|
|
61
|
+
* (`navigationController(_:didShow:animated:)`), which target-action never
|
|
62
|
+
* sends (it passes the sender and the event at most) and code only compares
|
|
63
|
+
* or asks about (`responds(to:)`). A method the file declares `@MainActor` is
|
|
64
|
+
* bound to its target in a closure instead,
|
|
65
|
+
* `Selector(name: "tick", isolated: { (target: Self) in target.tick })`:
|
|
66
|
+
* Swift 6 rejects naming a main-actor method of a class that is not
|
|
67
|
+
* `Sendable` unapplied (Gifu's display link proxy).
|
|
68
|
+
*/
|
|
69
|
+
export declare function rewriteObjC(text: string): string;
|
|
70
|
+
/** Replaces every `#Preview …{ … }` block and `PreviewProvider` struct with blank lines of the same count. */
|
|
71
|
+
export declare function stripPreviews(text: string): {
|
|
72
|
+
text: string;
|
|
73
|
+
count: number;
|
|
74
|
+
};
|
|
75
|
+
/** Index of the `}` closing the `{` at `open`, skipping strings and comments; -1 when unbalanced. */
|
|
76
|
+
export declare function matchingBrace(text: string, open: number): number;
|
|
77
|
+
/** C-ABI entry points the browser renderer calls; the linker must keep them. */
|
|
78
|
+
export declare const WASM_EXPORTS: string[];
|
|
79
|
+
/** The reconciler recurses once per view; 8 MB of stack like a native thread. */
|
|
80
|
+
export declare const APP_STACK_SIZE: number;
|
|
81
|
+
/**
|
|
82
|
+
* Locale.current follows the host's choice (SB_LOCALE): the two functions
|
|
83
|
+
* that hard-code en_001 in swift-foundation are redirected to FoundationBridge.
|
|
84
|
+
*/
|
|
85
|
+
export declare const LOCALE_WRAPS: string[];
|
|
86
|
+
/** The linker flags of the app's target (the manifest's `wasmExports`, without `-Xlinker`). */
|
|
87
|
+
export declare function appLinkerFlags(): string[];
|
|
88
|
+
/** The shim's products the app links: the defaults, SwiftData and the frameworks it imports. */
|
|
89
|
+
export declare function linkedProducts(features: StageFeatures): string[];
|
|
90
|
+
/** What the app's sources use beyond the shim, which decides what the staging links. */
|
|
91
|
+
export interface StageFeatures {
|
|
92
|
+
/**
|
|
93
|
+
* Some file imports SwiftData: the app links the SwiftData product (and so
|
|
94
|
+
* builds its macros, against swift-syntax), and the generated file routes
|
|
95
|
+
* `#Predicate` to SwiftData's copy of the macro.
|
|
96
|
+
*/
|
|
97
|
+
swiftData: boolean;
|
|
98
|
+
/** The stand-in frameworks (StoreKit, CoreLocation, LocalAuthentication, CoreML, PhotosUI, CoreImage, UserNotifications, …) some file imports; each is linked. */
|
|
99
|
+
frameworks: readonly string[];
|
|
100
|
+
}
|
|
101
|
+
/** The features `sources` (their text) call for. */
|
|
102
|
+
export declare function featuresOf(sources: readonly string[]): StageFeatures;
|
|
103
|
+
/** The staged file that settles names declared by both the shim and Foundation. */
|
|
104
|
+
export declare const FULL_FOUNDATION_FILE = "_SwiftBrowserFoundation.swift";
|
|
105
|
+
/**
|
|
106
|
+
* The app imports both the shim and Foundation, and both declare a few names
|
|
107
|
+
* (a module does not shadow another's declarations, only the current module's
|
|
108
|
+
* do). A typealias in the app module does: these point the shared names at
|
|
109
|
+
* the shim's types (what its `frame(width:)` and friends take) and at
|
|
110
|
+
* FoundationBridge's `Timer` and `RunLoop`, which Foundation lacks on WASI
|
|
111
|
+
* (`RunLoop` is marked unavailable, its `Timer` needs CFRunLoop and does not
|
|
112
|
+
* link).
|
|
113
|
+
*/
|
|
114
|
+
export declare function fullFoundationSource(features?: StageFeatures, declared?: ReadonlySet<string>): string;
|
|
115
|
+
/** The type names a module's sources declare at the top level (lines that start with the declaration). */
|
|
116
|
+
export declare function declaredTypeNames(sources: readonly string[]): Set<string>;
|