@swiftbrowser/cli 0.6.7 → 0.7.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.
Files changed (90) hide show
  1. package/README.md +73 -5
  2. package/dist/appSources.d.ts +116 -0
  3. package/dist/appSources.js +624 -0
  4. package/dist/appSources.js.map +1 -0
  5. package/dist/browser.d.ts +4 -0
  6. package/dist/browser.js +8 -0
  7. package/dist/browser.js.map +1 -0
  8. package/dist/build.d.ts +17 -2
  9. package/dist/build.js +38 -11
  10. package/dist/build.js.map +1 -1
  11. package/dist/cli.js +28 -4
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/build.js +10 -7
  14. package/dist/commands/build.js.map +1 -1
  15. package/dist/commands/check.js +38 -8
  16. package/dist/commands/check.js.map +1 -1
  17. package/dist/commands/dev.d.ts +8 -4
  18. package/dist/commands/dev.js +25 -10
  19. package/dist/commands/dev.js.map +1 -1
  20. package/dist/commands/doctor.d.ts +8 -0
  21. package/dist/commands/doctor.js +52 -4
  22. package/dist/commands/doctor.js.map +1 -1
  23. package/dist/commands/kit.d.ts +1 -0
  24. package/dist/commands/kit.js +20 -5
  25. package/dist/commands/kit.js.map +1 -1
  26. package/dist/commands/shared.d.ts +24 -6
  27. package/dist/commands/shared.js +92 -16
  28. package/dist/commands/shared.js.map +1 -1
  29. package/dist/commands/test.d.ts +4 -2
  30. package/dist/commands/test.js +25 -17
  31. package/dist/commands/test.js.map +1 -1
  32. package/dist/compat.d.ts +2 -30
  33. package/dist/compat.js +2 -44
  34. package/dist/compat.js.map +1 -1
  35. package/dist/compiler.d.ts +50 -0
  36. package/dist/compiler.js +94 -0
  37. package/dist/compiler.js.map +1 -0
  38. package/dist/config.d.ts +5 -2
  39. package/dist/config.js +7 -3
  40. package/dist/config.js.map +1 -1
  41. package/dist/frameworks.d.ts +30 -0
  42. package/dist/frameworks.js +48 -0
  43. package/dist/frameworks.js.map +1 -0
  44. package/dist/icu.d.ts +2 -4
  45. package/dist/icu.js +7 -36
  46. package/dist/icu.js.map +1 -1
  47. package/dist/kit.d.ts +44 -12
  48. package/dist/kit.js +149 -27
  49. package/dist/kit.js.map +1 -1
  50. package/dist/log.js +2 -1
  51. package/dist/log.js.map +1 -1
  52. package/dist/manifest.d.ts +73 -0
  53. package/dist/manifest.js +324 -0
  54. package/dist/manifest.js.map +1 -0
  55. package/dist/moduleCache.d.ts +20 -0
  56. package/dist/moduleCache.js +98 -0
  57. package/dist/moduleCache.js.map +1 -0
  58. package/dist/objc.js +1 -1
  59. package/dist/objc.js.map +1 -1
  60. package/dist/packages.d.ts +8 -1
  61. package/dist/packages.js +10 -2
  62. package/dist/packages.js.map +1 -1
  63. package/dist/registry.d.ts +46 -0
  64. package/dist/registry.js +184 -0
  65. package/dist/registry.js.map +1 -0
  66. package/dist/resolve.d.ts +80 -0
  67. package/dist/resolve.js +396 -0
  68. package/dist/resolve.js.map +1 -0
  69. package/dist/stage.d.ts +5 -144
  70. package/dist/stage.js +19 -516
  71. package/dist/stage.js.map +1 -1
  72. package/dist/testDiscovery.d.ts +44 -0
  73. package/dist/testDiscovery.js +111 -0
  74. package/dist/testDiscovery.js.map +1 -0
  75. package/dist/vendor.d.ts +41 -5
  76. package/dist/vendor.js +71 -31
  77. package/dist/vendor.js.map +1 -1
  78. package/dist/wasmCompiler.d.ts +160 -0
  79. package/dist/wasmCompiler.js +628 -0
  80. package/dist/wasmCompiler.js.map +1 -0
  81. package/dist/wasmFlags.d.ts +31 -0
  82. package/dist/wasmFlags.js +56 -0
  83. package/dist/wasmFlags.js.map +1 -0
  84. package/dist/wasmPackages.d.ts +163 -0
  85. package/dist/wasmPackages.js +466 -0
  86. package/dist/wasmPackages.js.map +1 -0
  87. package/dist/wasmSdk.d.ts +27 -0
  88. package/dist/wasmSdk.js +103 -0
  89. package/dist/wasmSdk.js.map +1 -0
  90. package/package.json +6 -5
package/README.md CHANGED
@@ -55,7 +55,54 @@ the toolchain and the SDK, so a change to any of them (a newer
55
55
  SwiftPM's scratch path for kits stays in the cache, so that rebuild compiles
56
56
  only the modules the change touched, and the three most recent kits are kept.
57
57
  `SWIFTBROWSER_KIT=0` builds the shim from its sources in the app's own build
58
- instead, as before kits. `check` compiles natively and does not use the kit.
58
+ instead, as before kits. A native `check` compiles for the host against the
59
+ shim's sources and does not use the kit.
60
+
61
+ ### The WebAssembly compiler
62
+
63
+ `--compiler` (or `SWIFTBROWSER_COMPILER`, which the flag overrides) picks
64
+ what compiles the app in `check`, `dev`, `build` and `test` (src/compiler.ts):
65
+
66
+ | Value | Builds with |
67
+ |---|---|
68
+ | `auto` (the default) | the Swift toolchain when it is installed (it builds faster), else the WebAssembly compiler, saying why |
69
+ | `native` | the Swift toolchain and SwiftPM |
70
+ | `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 |
71
+
72
+ So with Swift installed nothing changes, and without it `npx
73
+ @swiftbrowser/cli dev` builds with the npm packages alone, once
74
+ `swiftbrowser doctor --install` has downloaded the Swift SDK for
75
+ WebAssembly's files.
76
+
77
+ The WebAssembly compiler builds against the kit and needs only the Swift
78
+ SDK for WebAssembly's files: the toolchain's install, or, without a
79
+ toolchain, the CLI's own download (`swiftbrowser doctor --install`, 93 MB
80
+ into the cache; src/wasmSdk.ts). Without a toolchain it uses the released
81
+ kit (@swiftbrowser/kit, checked by type-checking an import of every module;
82
+ no host package needed) and cannot build one. It runs the kit's macros
83
+ built as WebAssembly: @swiftbrowser/kit has them, and a kit made here gets
84
+ them from `swiftbrowser kit --wasm-macros` or the first WebAssembly build
85
+ (with a toolchain; minutes the first time, swift-syntax compiling for
86
+ WebAssembly). `check` type-checks against the kit with it. Package
87
+ dependencies build with it too: without SwiftPM in charge (no toolchain, or
88
+ `--compiler wasm`), the CLI resolves them with git, honouring
89
+ `Package.resolved` (src/resolve.ts; registry packages from their
90
+ registry, src/registry.ts), and runs their manifests with the
91
+ WebAssembly tools (src/manifest.ts; @swiftbrowser/wasm-tools ships SwiftPM's
92
+ PackageDescription for this), caching both. C targets in packages compile
93
+ with clang built as WebAssembly, and package traits are followed; Ice Cubes
94
+ builds this way. A package's macro targets (TCA's) build as WebAssembly
95
+ plugins, swift-syntax compiled for them alone (minutes the first time, then
96
+ cached). The packages' compiled modules are cached too, keyed by their
97
+ inputs (src/moduleCache.ts): a rebuild compiles only what an edit reaches,
98
+ and apps share the modules of the packages they have in common. `test`
99
+ builds with it too: the app as a testable module, each test target against
100
+ it, and a runner like SwiftPM's (XCTest's tests listed from the test
101
+ module's symbol graph, Swift Testing's found as it runs; src/testDiscovery.ts),
102
+ with swift-testing's macros built as WebAssembly. In
103
+ `dev` it compiles unoptimized (`-Onone`, without a DEBUG define, so the app
104
+ behaves as it will in `build`) and keeps the compiled tools between
105
+ rebuilds: a save rebuilds Counter in about 5 s, as SwiftPM does.
59
106
 
60
107
  Building several apps in a row (a CI job, a script) can compile the
61
108
  SwiftBrowser package once for all of them: set `SWIFTBROWSER_BUILD_ROOT` to a
@@ -140,7 +187,8 @@ was released with).
140
187
  rebuilds neither from scratch. Each unit-test target is a test target in it
141
188
  that depends on the app's. Its files get the same adjustments, along with
142
189
  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.
190
+ the app. It links the SDK's whole ICU data rather than a trimmed copy. The
191
+ WebAssembly compiler builds the same staging without SwiftPM.
144
192
 
145
193
  ## Foundation
146
194
 
@@ -232,6 +280,7 @@ CI checks.
232
280
  "corsProxy": "https://swiftbrowser-cors-proxy.you.workers.dev/",
233
281
  "packages": [
234
282
  { "url": "https://github.com/twostraws/CodeScanner", "from": "2.5.2", "products": ["CodeScanner"] },
283
+ { "id": "mona.LinkedList", "from": "1.2.0", "products": ["LinkedList"] },
235
284
  { "path": "../Shared", "products": ["SharedKit"] }
236
285
  ]
237
286
  }
@@ -250,9 +299,14 @@ files) one by one.
250
299
 
251
300
  `packages` adds Swift packages to the ones the Xcode target links: the only
252
301
  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`), or
254
- a local `path` (relative to the project), and the `products` the app
255
- imports. They are built as described in "Swift packages".
302
+ (`from`: up to the next major version, `exact`, `branch` or `revision`), a
303
+ package registry's `id` (`scope.name`) with `from` or `exact`, or a local
304
+ `path` (relative to the project), and the `products` the app imports. They
305
+ are built as described in "Swift packages". Registries are configured as
306
+ SwiftPM configures them (`swift package-registry set`):
307
+ `.swiftpm/configuration/registries.json` in the app's folder, then in your
308
+ home folder, with credentials in `~/.netrc`; packages that depend on
309
+ registry packages (`.package(id:)`) find them the same way.
256
310
 
257
311
  `corsProxy` (or `--cors-proxy <url>` on `dev` and `build`) names a CORS proxy:
258
312
  the page retries a cross-origin GET or HEAD the browser refused (the server
@@ -413,6 +467,20 @@ git clone --depth 1 https://github.com/apple/sample-food-truck
413
467
  npx @swiftbrowser/cli dev sample-food-truck --target "Food Truck"
414
468
  ```
415
469
 
470
+ [The Composable Architecture](https://github.com/pointfreeco/swift-composable-architecture)
471
+ builds as it is, with the packages it brings (swift-dependencies,
472
+ swift-navigation, swift-sharing, combine-schedulers and the rest): its
473
+ macros (`@Reducer`, `@ObservableState`, `@DependencyClient`) build as
474
+ plugins, and its packages are copied and built against the shim like any
475
+ other. swift-navigation's UIKit layer builds over the shim's UIKit, whose
476
+ views and view controllers are `NSObject`s with iOS 17's traits; the
477
+ Objective-C target it swizzles view controllers with is the shim's own
478
+ lifecycle hooks here. Code a package keeps for older systems
479
+ (`#if canImport(ObjectiveC)`, CoreFoundation imports, `-ObjC` link flags,
480
+ KVO overrides) is adjusted in its copy (src/appSources.ts, vendor.ts). The
481
+ TCACounter fixture (packages/cli/test/fixtures/apps) is a counter, with
482
+ the versions it was made with pinned in its Package.resolved.
483
+
416
484
  A package SwiftBrowser has a patch for is built from its own sources with
417
485
  a few passages replaced first: code that only works with the Objective-C
418
486
  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>;