diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 486f7b6bf..174b873ef 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -67,3 +67,18 @@ jobs:
- run: swift build
env:
DEVELOPER_DIR: /Applications/${{ matrix.xcode }}.app/Contents/Developer/
+
+ format:
+ runs-on: ubuntu-latest
+ container:
+ image: swift:6.0.3
+ steps:
+ - uses: actions/checkout@v4
+ - run: ./Utilities/format.swift
+ - name: Check for formatting changes
+ run: |
+ git config --global --add safe.directory "$GITHUB_WORKSPACE"
+ git diff --exit-code || {
+ echo "::error::The formatting changed some files. Please run \`./Utilities/format.swift\` and commit the changes."
+ exit 1
+ }
diff --git a/.swift-format b/.swift-format
new file mode 100644
index 000000000..22ce671e7
--- /dev/null
+++ b/.swift-format
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "lineLength": 120,
+ "indentation": {
+ "spaces": 4
+ },
+ "lineBreakBeforeEachArgument": true,
+ "indentConditionalCompilationBlocks": false,
+ "prioritizeKeepingFunctionOutputTogether": true,
+ "rules": {
+ "AlwaysUseLowerCamelCase": false
+ }
+}
diff --git a/Examples/ActorOnWebWorker/Package.swift b/Examples/ActorOnWebWorker/Package.swift
index 711bf6461..82e87dfdc 100644
--- a/Examples/ActorOnWebWorker/Package.swift
+++ b/Examples/ActorOnWebWorker/Package.swift
@@ -6,7 +6,7 @@ let package = Package(
name: "Example",
platforms: [.macOS("15"), .iOS("18"), .watchOS("11"), .tvOS("18"), .visionOS("2")],
dependencies: [
- .package(path: "../../"),
+ .package(path: "../../")
],
targets: [
.executableTarget(
@@ -15,6 +15,6 @@ let package = Package(
.product(name: "JavaScriptKit", package: "JavaScriptKit"),
.product(name: "JavaScriptEventLoop", package: "JavaScriptKit"),
]
- ),
+ )
]
)
diff --git a/Examples/ActorOnWebWorker/Sources/MyApp.swift b/Examples/ActorOnWebWorker/Sources/MyApp.swift
index 7d362d13e..42a2caeb4 100644
--- a/Examples/ActorOnWebWorker/Sources/MyApp.swift
+++ b/Examples/ActorOnWebWorker/Sources/MyApp.swift
@@ -144,17 +144,21 @@ final class App {
}
private func setupEventHandlers() {
- indexButton.onclick = .object(JSClosure { [weak self] _ in
- guard let self else { return .undefined }
- self.performIndex()
- return .undefined
- })
-
- searchButton.onclick = .object(JSClosure { [weak self] _ in
- guard let self else { return .undefined }
- self.performSearch()
- return .undefined
- })
+ indexButton.onclick = .object(
+ JSClosure { [weak self] _ in
+ guard let self else { return .undefined }
+ self.performIndex()
+ return .undefined
+ }
+ )
+
+ searchButton.onclick = .object(
+ JSClosure { [weak self] _ in
+ guard let self else { return .undefined }
+ self.performSearch()
+ return .undefined
+ }
+ )
}
private func performIndex() {
@@ -221,7 +225,8 @@ final class App {
"padding: 10px; margin: 5px 0; background: #f5f5f5; border-left: 3px solid blue;"
)
resultItem.innerHTML = .string(
- "Result \(index + 1): \(result.context)")
+ "Result \(index + 1): \(result.context)"
+ )
_ = resultsElement.appendChild(resultItem)
}
}
@@ -245,18 +250,18 @@ final class App {
}
#if canImport(wasi_pthread)
- import wasi_pthread
- import WASILibc
-
- /// Trick to avoid blocking the main thread. pthread_mutex_lock function is used by
- /// the Swift concurrency runtime.
- @_cdecl("pthread_mutex_lock")
- func pthread_mutex_lock(_ mutex: UnsafeMutablePointer) -> Int32 {
- // DO NOT BLOCK MAIN THREAD
- var ret: Int32
- repeat {
- ret = pthread_mutex_trylock(mutex)
- } while ret == EBUSY
- return ret
- }
+import wasi_pthread
+import WASILibc
+
+/// Trick to avoid blocking the main thread. pthread_mutex_lock function is used by
+/// the Swift concurrency runtime.
+@_cdecl("pthread_mutex_lock")
+func pthread_mutex_lock(_ mutex: UnsafeMutablePointer) -> Int32 {
+ // DO NOT BLOCK MAIN THREAD
+ var ret: Int32
+ repeat {
+ ret = pthread_mutex_trylock(mutex)
+ } while ret == EBUSY
+ return ret
+}
#endif
diff --git a/Examples/Basic/Package.swift b/Examples/Basic/Package.swift
index f1a80aaaa..6c729741c 100644
--- a/Examples/Basic/Package.swift
+++ b/Examples/Basic/Package.swift
@@ -13,7 +13,7 @@ let package = Package(
name: "Basic",
dependencies: [
"JavaScriptKit",
- .product(name: "JavaScriptEventLoop", package: "JavaScriptKit")
+ .product(name: "JavaScriptEventLoop", package: "JavaScriptKit"),
]
)
],
diff --git a/Examples/Basic/Sources/main.swift b/Examples/Basic/Sources/main.swift
index 98b8a6bb5..8fa9c956c 100644
--- a/Examples/Basic/Sources/main.swift
+++ b/Examples/Basic/Sources/main.swift
@@ -1,5 +1,5 @@
-import JavaScriptKit
import JavaScriptEventLoop
+import JavaScriptKit
let alert = JSObject.global.alert.function!
let document = JSObject.global.document
@@ -10,10 +10,12 @@ _ = document.body.appendChild(divElement)
var buttonElement = document.createElement("button")
buttonElement.innerText = "Alert demo"
-buttonElement.onclick = .object(JSClosure { _ in
- alert("Swift is running on browser!")
- return .undefined
-})
+buttonElement.onclick = .object(
+ JSClosure { _ in
+ alert("Swift is running on browser!")
+ return .undefined
+ }
+)
_ = document.body.appendChild(buttonElement)
@@ -30,19 +32,21 @@ struct Response: Decodable {
var asyncButtonElement = document.createElement("button")
asyncButtonElement.innerText = "Fetch UUID demo"
-asyncButtonElement.onclick = .object(JSClosure { _ in
- Task {
- do {
- let response = try await fetch("https://httpbin.org/uuid").value
- let json = try await JSPromise(response.json().object!)!.value
- let parsedResponse = try JSValueDecoder().decode(Response.self, from: json)
- alert(parsedResponse.uuid)
- } catch {
- print(error)
+asyncButtonElement.onclick = .object(
+ JSClosure { _ in
+ Task {
+ do {
+ let response = try await fetch("https://httpbin.org/uuid").value
+ let json = try await JSPromise(response.json().object!)!.value
+ let parsedResponse = try JSValueDecoder().decode(Response.self, from: json)
+ alert(parsedResponse.uuid)
+ } catch {
+ print(error)
+ }
}
- }
- return .undefined
-})
+ return .undefined
+ }
+)
_ = document.body.appendChild(asyncButtonElement)
diff --git a/Examples/Embedded/Package.swift b/Examples/Embedded/Package.swift
index f97638cc8..5ae19adc6 100644
--- a/Examples/Embedded/Package.swift
+++ b/Examples/Embedded/Package.swift
@@ -6,14 +6,14 @@ let package = Package(
name: "Embedded",
dependencies: [
.package(name: "JavaScriptKit", path: "../../"),
- .package(url: "https://github.com/swiftwasm/swift-dlmalloc", branch: "0.1.0")
+ .package(url: "https://github.com/swiftwasm/swift-dlmalloc", branch: "0.1.0"),
],
targets: [
.executableTarget(
name: "EmbeddedApp",
dependencies: [
"JavaScriptKit",
- .product(name: "dlmalloc", package: "swift-dlmalloc")
+ .product(name: "dlmalloc", package: "swift-dlmalloc"),
],
cSettings: [.unsafeFlags(["-fdeclspec"])],
swiftSettings: [
@@ -28,7 +28,7 @@ let package = Package(
.unsafeFlags([
"-Xclang-linker", "-nostdlib",
"-Xlinker", "--no-entry",
- "-Xlinker", "--export-if-defined=__main_argc_argv"
+ "-Xlinker", "--export-if-defined=__main_argc_argv",
])
]
)
diff --git a/Examples/Embedded/Sources/EmbeddedApp/main.swift b/Examples/Embedded/Sources/EmbeddedApp/main.swift
index 2ba81dc63..3f8c18ca6 100644
--- a/Examples/Embedded/Sources/EmbeddedApp/main.swift
+++ b/Examples/Embedded/Sources/EmbeddedApp/main.swift
@@ -13,11 +13,13 @@ _ = document.body.appendChild(divElement)
var buttonElement = document.createElement("button")
buttonElement.innerText = "Click me"
-buttonElement.onclick = JSValue.object(JSClosure { _ in
- count += 1
- divElement.innerText = .string("Count \(count)")
- return .undefined
-})
+buttonElement.onclick = JSValue.object(
+ JSClosure { _ in
+ count += 1
+ divElement.innerText = .string("Count \(count)")
+ return .undefined
+ }
+)
_ = document.body.appendChild(buttonElement)
diff --git a/Examples/Multithreading/Package.swift b/Examples/Multithreading/Package.swift
index 211f359a6..4d1ebde70 100644
--- a/Examples/Multithreading/Package.swift
+++ b/Examples/Multithreading/Package.swift
@@ -7,7 +7,10 @@ let package = Package(
platforms: [.macOS("15"), .iOS("18"), .watchOS("11"), .tvOS("18"), .visionOS("2")],
dependencies: [
.package(path: "../../"),
- .package(url: "https://github.com/kateinoigakukun/chibi-ray", revision: "c8cab621a3338dd2f8e817d3785362409d3b8cf1"),
+ .package(
+ url: "https://github.com/kateinoigakukun/chibi-ray",
+ revision: "c8cab621a3338dd2f8e817d3785362409d3b8cf1"
+ ),
],
targets: [
.executableTarget(
@@ -17,6 +20,6 @@ let package = Package(
.product(name: "JavaScriptEventLoop", package: "JavaScriptKit"),
.product(name: "ChibiRay", package: "chibi-ray"),
]
- ),
+ )
]
)
diff --git a/Examples/Multithreading/Sources/MyApp/Scene.swift b/Examples/Multithreading/Sources/MyApp/Scene.swift
index 5f6d467c5..bddde1715 100644
--- a/Examples/Multithreading/Sources/MyApp/Scene.swift
+++ b/Examples/Multithreading/Sources/MyApp/Scene.swift
@@ -60,7 +60,7 @@ func createDemoScene(size: Int) -> Scene {
surface: .diffuse
)
)
- )
+ ),
],
lights: [
.spherical(
@@ -83,7 +83,7 @@ func createDemoScene(size: Int) -> Scene {
color: Color(red: 0.8, green: 0.8, blue: 0.8),
intensity: 0.2
)
- )
+ ),
],
shadowBias: 1e-13,
maxRecursionDepth: 10
diff --git a/Examples/Multithreading/Sources/MyApp/main.swift b/Examples/Multithreading/Sources/MyApp/main.swift
index 29cb89f2f..9a1e09bb4 100644
--- a/Examples/Multithreading/Sources/MyApp/main.swift
+++ b/Examples/Multithreading/Sources/MyApp/main.swift
@@ -1,6 +1,6 @@
import ChibiRay
-import JavaScriptKit
import JavaScriptEventLoop
+import JavaScriptKit
JavaScriptEventLoop.installGlobalExecutor()
WebWorkerTaskExecutor.installGlobalExecutor()
@@ -8,12 +8,12 @@ WebWorkerTaskExecutor.installGlobalExecutor()
func renderInCanvas(ctx: JSObject, image: ImageView) {
let imageData = ctx.createImageData!(image.width, image.height).object!
let data = imageData.data.object!
-
+
for y in 0...allocate(capacity: scene.width * scene.height)
// Initialize the buffer with black color
@@ -73,12 +79,15 @@ func render(scene: Scene, ctx: JSObject, renderTimeElement: JSObject, concurrenc
}
var checkTimer: JSValue?
- checkTimer = JSObject.global.setInterval!(JSClosure { _ in
- print("Checking thread work...")
- renderInCanvas(ctx: ctx, image: imageView)
- updateRenderTime()
- return .undefined
- }, 250)
+ checkTimer = JSObject.global.setInterval!(
+ JSClosure { _ in
+ print("Checking thread work...")
+ renderInCanvas(ctx: ctx, image: imageView)
+ updateRenderTime()
+ return .undefined
+ },
+ 250
+ )
await withTaskGroup(of: Void.self) { group in
let yStride = scene.height / concurrency
@@ -117,10 +126,16 @@ func onClick() async throws {
let scene = createDemoScene(size: size)
let executor = background ? try await WebWorkerTaskExecutor(numberOfThreads: concurrency) : nil
- canvasElement.width = .number(Double(scene.width))
+ canvasElement.width = .number(Double(scene.width))
canvasElement.height = .number(Double(scene.height))
- await render(scene: scene, ctx: ctx, renderTimeElement: renderTimeElement, concurrency: concurrency, executor: executor)
+ await render(
+ scene: scene,
+ ctx: ctx,
+ renderTimeElement: renderTimeElement,
+ concurrency: concurrency,
+ executor: executor
+ )
executor?.terminate()
print("Render done")
}
@@ -130,19 +145,21 @@ func main() async throws {
let concurrencyElement = JSObject.global.document.getElementById("concurrency").object!
concurrencyElement.value = JSObject.global.navigator.hardwareConcurrency
- _ = renderButtonElement.addEventListener!("click", JSClosure { _ in
- Task {
- try await onClick()
+ _ = renderButtonElement.addEventListener!(
+ "click",
+ JSClosure { _ in
+ Task {
+ try await onClick()
+ }
+ return JSValue.undefined
}
- return JSValue.undefined
- })
+ )
}
Task {
try await main()
}
-
#if canImport(wasi_pthread)
import wasi_pthread
import WASILibc
diff --git a/Examples/OffscrenCanvas/Package.swift b/Examples/OffscrenCanvas/Package.swift
index 7fc45ad1b..ca6d7357f 100644
--- a/Examples/OffscrenCanvas/Package.swift
+++ b/Examples/OffscrenCanvas/Package.swift
@@ -6,7 +6,7 @@ let package = Package(
name: "Example",
platforms: [.macOS("15"), .iOS("18"), .watchOS("11"), .tvOS("18"), .visionOS("2")],
dependencies: [
- .package(path: "../../"),
+ .package(path: "../../")
],
targets: [
.executableTarget(
@@ -15,6 +15,6 @@ let package = Package(
.product(name: "JavaScriptKit", package: "JavaScriptKit"),
.product(name: "JavaScriptEventLoop", package: "JavaScriptKit"),
]
- ),
+ )
]
)
diff --git a/Examples/OffscrenCanvas/Sources/MyApp/main.swift b/Examples/OffscrenCanvas/Sources/MyApp/main.swift
index 67e087122..a2a6e2aac 100644
--- a/Examples/OffscrenCanvas/Sources/MyApp/main.swift
+++ b/Examples/OffscrenCanvas/Sources/MyApp/main.swift
@@ -56,7 +56,8 @@ func startFPSMonitor() {
JSClosure { _ in
countFrame()
return .undefined
- })
+ }
+ )
}
// Start counting
@@ -107,14 +108,16 @@ func main() async throws {
try await onClick(renderer: renderer)
}
return JSValue.undefined
- })
+ }
+ )
_ = cancelButtonElement.addEventListener!(
"click",
JSClosure { _ in
renderingTask?.cancel()
return JSValue.undefined
- })
+ }
+ )
}
Task {
@@ -122,18 +125,18 @@ Task {
}
#if canImport(wasi_pthread)
- import wasi_pthread
- import WASILibc
-
- /// Trick to avoid blocking the main thread. pthread_mutex_lock function is used by
- /// the Swift concurrency runtime.
- @_cdecl("pthread_mutex_lock")
- func pthread_mutex_lock(_ mutex: UnsafeMutablePointer) -> Int32 {
- // DO NOT BLOCK MAIN THREAD
- var ret: Int32
- repeat {
- ret = pthread_mutex_trylock(mutex)
- } while ret == EBUSY
- return ret
- }
+import wasi_pthread
+import WASILibc
+
+/// Trick to avoid blocking the main thread. pthread_mutex_lock function is used by
+/// the Swift concurrency runtime.
+@_cdecl("pthread_mutex_lock")
+func pthread_mutex_lock(_ mutex: UnsafeMutablePointer) -> Int32 {
+ // DO NOT BLOCK MAIN THREAD
+ var ret: Int32
+ repeat {
+ ret = pthread_mutex_trylock(mutex)
+ } while ret == EBUSY
+ return ret
+}
#endif
diff --git a/Examples/OffscrenCanvas/Sources/MyApp/render.swift b/Examples/OffscrenCanvas/Sources/MyApp/render.swift
index 714cac184..6a9d057a9 100644
--- a/Examples/OffscrenCanvas/Sources/MyApp/render.swift
+++ b/Examples/OffscrenCanvas/Sources/MyApp/render.swift
@@ -8,12 +8,17 @@ func sleepOnThread(milliseconds: Int, isolation: isolated (any Actor)? = #isolat
JSOneshotClosure { _ in
continuation.resume()
return JSValue.undefined
- }, milliseconds
+ },
+ milliseconds
)
}
}
-func renderAnimation(canvas: JSObject, size: Int, isolation: isolated (any Actor)? = #isolation)
+func renderAnimation(
+ canvas: JSObject,
+ size: Int,
+ isolation: isolated (any Actor)? = #isolation
+)
async throws
{
let ctx = canvas.getContext!("2d").object!
diff --git a/Examples/Testing/Package.swift b/Examples/Testing/Package.swift
index d9d1719f0..2a81bfa7a 100644
--- a/Examples/Testing/Package.swift
+++ b/Examples/Testing/Package.swift
@@ -7,7 +7,8 @@ let package = Package(
products: [
.library(
name: "Counter",
- targets: ["Counter"]),
+ targets: ["Counter"]
+ )
],
dependencies: [.package(name: "JavaScriptKit", path: "../../")],
targets: [
@@ -15,13 +16,14 @@ let package = Package(
name: "Counter",
dependencies: [
.product(name: "JavaScriptKit", package: "JavaScriptKit")
- ]),
+ ]
+ ),
.testTarget(
name: "CounterTests",
dependencies: [
"Counter",
// This is needed to run the tests in the JavaScript event loop
- .product(name: "JavaScriptEventLoopTestSupport", package: "JavaScriptKit")
+ .product(name: "JavaScriptEventLoopTestSupport", package: "JavaScriptKit"),
]
),
]
diff --git a/Examples/Testing/Tests/CounterTests/CounterTests.swift b/Examples/Testing/Tests/CounterTests/CounterTests.swift
index 4421c1223..ec92cd14c 100644
--- a/Examples/Testing/Tests/CounterTests/CounterTests.swift
+++ b/Examples/Testing/Tests/CounterTests/CounterTests.swift
@@ -1,3 +1,5 @@
+import XCTest
+
@testable import Counter
#if canImport(Testing)
@@ -18,8 +20,6 @@ import Testing
#endif
-import XCTest
-
class CounterTests: XCTestCase {
func testIncrement() async {
var counter = Counter()
diff --git a/IntegrationTests/TestSuites/Package.swift b/IntegrationTests/TestSuites/Package.swift
index 3d583d082..1ae22dfa5 100644
--- a/IntegrationTests/TestSuites/Package.swift
+++ b/IntegrationTests/TestSuites/Package.swift
@@ -8,12 +8,13 @@ let package = Package(
// This package doesn't work on macOS host, but should be able to be built for it
// for developing on Xcode. This minimum version requirement is to prevent availability
// errors for Concurrency API, whose runtime support is shipped from macOS 12.0
- .macOS("12.0"),
+ .macOS("12.0")
],
products: [
.executable(
- name: "BenchmarkTests", targets: ["BenchmarkTests"]
- ),
+ name: "BenchmarkTests",
+ targets: ["BenchmarkTests"]
+ )
],
dependencies: [.package(name: "JavaScriptKit", path: "../../")],
targets: [
diff --git a/IntegrationTests/TestSuites/Sources/BenchmarkTests/main.swift b/IntegrationTests/TestSuites/Sources/BenchmarkTests/main.swift
index 2803f0137..6bd10835b 100644
--- a/IntegrationTests/TestSuites/Sources/BenchmarkTests/main.swift
+++ b/IntegrationTests/TestSuites/Sources/BenchmarkTests/main.swift
@@ -1,24 +1,24 @@
-import JavaScriptKit
import CHelpers
+import JavaScriptKit
let serialization = Benchmark("Serialization")
let noopFunction = JSObject.global.noopFunction.function!
serialization.testSuite("JavaScript function call through Wasm import") { n in
- for _ in 0 ..< n {
+ for _ in 0.. Void = { _, _ in }
) -> TaskKey {
let taskKey = TaskKey(id: output.description)
@@ -118,12 +121,20 @@ struct MiniMake {
return try encoder.encode($0)
}
let info = TaskInfo(
- wants: inputTasks, inputs: inputFiles, output: output, attributes: attributes,
+ wants: inputTasks,
+ inputs: inputFiles,
+ output: output,
+ attributes: attributes,
salt: saltData
)
self.tasks[taskKey] = Task(
- info: info, wants: Set(inputTasks), attributes: Set(attributes),
- key: taskKey, build: build, isDone: false)
+ info: info,
+ wants: Set(inputTasks),
+ attributes: Set(attributes),
+ key: taskKey,
+ build: build,
+ isDone: false
+ )
return taskKey
}
@@ -234,7 +245,9 @@ struct MiniMake {
// Ignore directory modification times
var isDirectory: ObjCBool = false
let fileExists = FileManager.default.fileExists(
- atPath: inputURL.path, isDirectory: &isDirectory)
+ atPath: inputURL.path,
+ isDirectory: &isDirectory
+ )
if fileExists && isDirectory.boolValue {
return false
}
diff --git a/Plugins/PackageToJS/Sources/PackageToJS.swift b/Plugins/PackageToJS/Sources/PackageToJS.swift
index 80ad9b805..5f66a28ab 100644
--- a/Plugins/PackageToJS/Sources/PackageToJS.swift
+++ b/Plugins/PackageToJS/Sources/PackageToJS.swift
@@ -73,7 +73,10 @@ struct PackageToJS {
testLibraryArguments.append("--list-tests")
}
if let prelude = testOptions.prelude {
- let preludeURL = URL(fileURLWithPath: prelude, relativeTo: URL(fileURLWithPath: FileManager.default.currentDirectoryPath))
+ let preludeURL = URL(
+ fileURLWithPath: prelude,
+ relativeTo: URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
+ )
testJsArguments.append("--prelude")
testJsArguments.append(preludeURL.path)
}
@@ -97,9 +100,11 @@ struct PackageToJS {
extraArguments.append(contentsOf: testOptions.filter)
try PackageToJS.runSingleTestingLibrary(
- testRunner: testRunner, currentDirectoryURL: currentDirectoryURL,
+ testRunner: testRunner,
+ currentDirectoryURL: currentDirectoryURL,
extraArguments: extraArguments,
- testParser: testOptions.packageOptions.verbose ? nil : FancyTestsParser(write: { print($0, terminator: "") }),
+ testParser: testOptions.packageOptions.verbose
+ ? nil : FancyTestsParser(write: { print($0, terminator: "") }),
testOptions: testOptions
)
}
@@ -120,14 +125,17 @@ struct PackageToJS {
}
try PackageToJS.runSingleTestingLibrary(
- testRunner: testRunner, currentDirectoryURL: currentDirectoryURL,
+ testRunner: testRunner,
+ currentDirectoryURL: currentDirectoryURL,
extraArguments: extraArguments,
testOptions: testOptions
)
}
if testOptions.packageOptions.enableCodeCoverage {
- let profrawFiles = [xctestCoverageFile.path, swiftTestingCoverageFile.path].filter { FileManager.default.fileExists(atPath: $0) }
+ let profrawFiles = [xctestCoverageFile.path, swiftTestingCoverageFile.path].filter {
+ FileManager.default.fileExists(atPath: $0)
+ }
do {
try PackageToJS.postProcessCoverageFiles(outputDir: outputDir, profrawFiles: profrawFiles)
} catch {
@@ -254,7 +262,9 @@ extension PackagingSystem {
func createDirectory(atPath: String) throws {
guard !FileManager.default.fileExists(atPath: atPath) else { return }
try FileManager.default.createDirectory(
- atPath: atPath, withIntermediateDirectories: true, attributes: nil
+ atPath: atPath,
+ withIntermediateDirectories: true,
+ attributes: nil
)
}
@@ -264,7 +274,8 @@ extension PackagingSystem {
}
try FileManager.default.copyItem(atPath: from, toPath: to)
try FileManager.default.setAttributes(
- [.modificationDate: Date()], ofItemAtPath: to
+ [.modificationDate: Date()],
+ ofItemAtPath: to
)
}
@@ -316,9 +327,9 @@ internal func which(_ executable: String) throws -> URL {
}
let pathSeparator: Character
#if os(Windows)
- pathSeparator = ";"
+ pathSeparator = ";"
#else
- pathSeparator = ":"
+ pathSeparator = ":"
#endif
let paths = ProcessInfo.processInfo.environment["PATH"]!.split(separator: pathSeparator)
for path in paths {
@@ -401,10 +412,14 @@ struct PackagingPlanner {
buildOptions: PackageToJS.BuildOptions
) throws -> MiniMake.TaskKey {
let (allTasks, _, _, _) = try planBuildInternal(
- make: &make, noOptimize: buildOptions.noOptimize, debugInfoFormat: buildOptions.debugInfoFormat
+ make: &make,
+ noOptimize: buildOptions.noOptimize,
+ debugInfoFormat: buildOptions.debugInfoFormat
)
return make.addTask(
- inputTasks: allTasks, output: BuildPath(phony: "all"), attributes: [.phony, .silent]
+ inputTasks: allTasks,
+ output: BuildPath(phony: "all"),
+ attributes: [.phony, .silent]
)
}
@@ -420,7 +435,9 @@ struct PackagingPlanner {
) {
// Prepare output directory
let outputDirTask = make.addTask(
- inputFiles: [selfPath], output: outputDir, attributes: [.silent]
+ inputFiles: [selfPath],
+ output: outputDir,
+ attributes: [.silent]
) {
try system.createDirectory(atPath: $1.resolve(path: $0.output).path)
}
@@ -438,7 +455,9 @@ struct PackagingPlanner {
}
let intermediatesDirTask = make.addTask(
- inputFiles: [selfPath], output: intermediatesDir, attributes: [.silent]
+ inputFiles: [selfPath],
+ output: intermediatesDir,
+ attributes: [.silent]
) {
try system.createDirectory(atPath: $1.resolve(path: $0.output).path)
}
@@ -458,35 +477,50 @@ struct PackagingPlanner {
wasmOptInputFile = intermediatesDir.appending(path: wasmFilename + ".no-dwarf")
// First, strip DWARF sections as their existence enables DWARF preserving mode in wasm-opt
wasmOptInputTask = make.addTask(
- inputFiles: [selfPath, wasmProductArtifact], inputTasks: [outputDirTask, intermediatesDirTask],
+ inputFiles: [selfPath, wasmProductArtifact],
+ inputTasks: [outputDirTask, intermediatesDirTask],
output: wasmOptInputFile
) {
print("Stripping DWARF debug info...")
- try system.wasmOpt(["--strip-dwarf", "--debuginfo"], input: $1.resolve(path: wasmProductArtifact).path, output: $1.resolve(path: $0.output).path)
+ try system.wasmOpt(
+ ["--strip-dwarf", "--debuginfo"],
+ input: $1.resolve(path: wasmProductArtifact).path,
+ output: $1.resolve(path: $0.output).path
+ )
}
}
// Then, run wasm-opt with all optimizations
wasm = make.addTask(
- inputFiles: [selfPath, wasmOptInputFile], inputTasks: [outputDirTask] + (wasmOptInputTask.map { [$0] } ?? []),
+ inputFiles: [selfPath, wasmOptInputFile],
+ inputTasks: [outputDirTask] + (wasmOptInputTask.map { [$0] } ?? []),
output: finalWasmPath
) {
print("Optimizing the wasm file...")
- try system.wasmOpt(["-Os"] + (debugInfoFormat != .none ? ["--debuginfo"] : []), input: $1.resolve(path: wasmOptInputFile).path, output: $1.resolve(path: $0.output).path)
+ try system.wasmOpt(
+ ["-Os"] + (debugInfoFormat != .none ? ["--debuginfo"] : []),
+ input: $1.resolve(path: wasmOptInputFile).path,
+ output: $1.resolve(path: $0.output).path
+ )
}
} else {
// Copy the wasm product artifact
wasm = make.addTask(
- inputFiles: [selfPath, wasmProductArtifact], inputTasks: [outputDirTask],
+ inputFiles: [selfPath, wasmProductArtifact],
+ inputTasks: [outputDirTask],
output: finalWasmPath
) {
- try system.syncFile(from: $1.resolve(path: wasmProductArtifact).path, to: $1.resolve(path: $0.output).path)
+ try system.syncFile(
+ from: $1.resolve(path: wasmProductArtifact).path,
+ to: $1.resolve(path: $0.output).path
+ )
}
}
packageInputs.append(wasm)
let wasmImportsPath = intermediatesDir.appending(path: "wasm-imports.json")
let wasmImportsTask = make.addTask(
- inputFiles: [selfPath, finalWasmPath], inputTasks: [outputDirTask, intermediatesDirTask, wasm],
+ inputFiles: [selfPath, finalWasmPath],
+ inputTasks: [outputDirTask, intermediatesDirTask, wasm],
output: wasmImportsPath
) {
let metadata = try parseImports(
@@ -502,14 +536,20 @@ struct PackagingPlanner {
let platformsDir = outputDir.appending(path: "platforms")
let platformsDirTask = make.addTask(
- inputFiles: [selfPath], output: platformsDir, attributes: [.silent]
+ inputFiles: [selfPath],
+ output: platformsDir,
+ attributes: [.silent]
) {
try system.createDirectory(atPath: $1.resolve(path: $0.output).path)
}
let packageJsonTask = planCopyTemplateFile(
- make: &make, file: "Plugins/PackageToJS/Templates/package.json", output: "package.json", outputDirTask: outputDirTask,
- inputFiles: [], inputTasks: []
+ make: &make,
+ file: "Plugins/PackageToJS/Templates/package.json",
+ output: "package.json",
+ outputDirTask: outputDirTask,
+ inputFiles: [],
+ inputTasks: []
)
packageInputs.append(packageJsonTask)
@@ -526,11 +566,17 @@ struct PackagingPlanner {
("Plugins/PackageToJS/Templates/platforms/node.d.ts", "platforms/node.d.ts"),
("Sources/JavaScriptKit/Runtime/index.mjs", "runtime.js"),
] {
- packageInputs.append(planCopyTemplateFile(
- make: &make, file: file, output: output, outputDirTask: outputDirTask,
- inputFiles: [wasmImportsPath], inputTasks: [platformsDirTask, wasmImportsTask],
- wasmImportsPath: wasmImportsPath
- ))
+ packageInputs.append(
+ planCopyTemplateFile(
+ make: &make,
+ file: file,
+ output: output,
+ outputDirTask: outputDirTask,
+ inputFiles: [wasmImportsPath],
+ inputTasks: [platformsDirTask, wasmImportsTask],
+ wasmImportsPath: wasmImportsPath
+ )
+ )
}
return (packageInputs, outputDirTask, intermediatesDirTask, packageJsonTask)
}
@@ -540,24 +586,30 @@ struct PackagingPlanner {
make: inout MiniMake
) throws -> (rootTask: MiniMake.TaskKey, binDir: BuildPath) {
var (allTasks, outputDirTask, intermediatesDirTask, packageJsonTask) = try planBuildInternal(
- make: &make, noOptimize: false, debugInfoFormat: .dwarf
+ make: &make,
+ noOptimize: false,
+ debugInfoFormat: .dwarf
)
// Install npm dependencies used in the test harness
- allTasks.append(make.addTask(
- inputFiles: [
- selfPath,
- outputDir.appending(path: "package.json"),
- ], inputTasks: [intermediatesDirTask, packageJsonTask],
- output: intermediatesDir.appending(path: "npm-install.stamp")
- ) {
- try system.npmInstall(packageDir: $1.resolve(path: outputDir).path)
- try system.writeFile(atPath: $1.resolve(path: $0.output).path, content: Data())
- })
+ allTasks.append(
+ make.addTask(
+ inputFiles: [
+ selfPath,
+ outputDir.appending(path: "package.json"),
+ ],
+ inputTasks: [intermediatesDirTask, packageJsonTask],
+ output: intermediatesDir.appending(path: "npm-install.stamp")
+ ) {
+ try system.npmInstall(packageDir: $1.resolve(path: outputDir).path)
+ try system.writeFile(atPath: $1.resolve(path: $0.output).path, content: Data())
+ }
+ )
let binDir = outputDir.appending(path: "bin")
let binDirTask = make.addTask(
- inputFiles: [selfPath], inputTasks: [outputDirTask],
+ inputFiles: [selfPath],
+ inputTasks: [outputDirTask],
output: binDir
) {
try system.createDirectory(atPath: $1.resolve(path: $0.output).path)
@@ -571,13 +623,21 @@ struct PackagingPlanner {
("Plugins/PackageToJS/Templates/test.browser.html", "test.browser.html"),
("Plugins/PackageToJS/Templates/bin/test.js", "bin/test.js"),
] {
- allTasks.append(planCopyTemplateFile(
- make: &make, file: file, output: output, outputDirTask: outputDirTask,
- inputFiles: [], inputTasks: [binDirTask]
- ))
+ allTasks.append(
+ planCopyTemplateFile(
+ make: &make,
+ file: file,
+ output: output,
+ outputDirTask: outputDirTask,
+ inputFiles: [],
+ inputTasks: [binDirTask]
+ )
+ )
}
let rootTask = make.addTask(
- inputTasks: allTasks, output: BuildPath(phony: "all"), attributes: [.phony, .silent]
+ inputTasks: allTasks,
+ output: BuildPath(phony: "all"),
+ attributes: [.phony, .silent]
)
return (rootTask, binDir)
}
@@ -610,14 +670,19 @@ struct PackagingPlanner {
let salt = Salt(conditions: conditions, substitutions: constantSubstitutions)
return make.addTask(
- inputFiles: [selfPath, inputPath] + inputFiles, inputTasks: [outputDirTask] + inputTasks,
- output: outputDir.appending(path: output), salt: salt
+ inputFiles: [selfPath, inputPath] + inputFiles,
+ inputTasks: [outputDirTask] + inputTasks,
+ output: outputDir.appending(path: output),
+ salt: salt
) {
var substitutions = constantSubstitutions
if let wasmImportsPath = wasmImportsPath {
let wasmImportsPath = $1.resolve(path: wasmImportsPath)
- let importEntries = try JSONDecoder().decode([ImportEntry].self, from: Data(contentsOf: wasmImportsPath))
+ let importEntries = try JSONDecoder().decode(
+ [ImportEntry].self,
+ from: Data(contentsOf: wasmImportsPath)
+ )
let memoryImport = importEntries.first {
$0.module == "env" && $0.name == "memory"
}
diff --git a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift
index 62e7dc16e..5f257079a 100644
--- a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift
+++ b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift
@@ -20,8 +20,8 @@ struct PackageToJSPlugin: CommandPlugin {
// In case user misses the `--swift-sdk` option
{ build, arguments in
guard
- build.logText.contains("ld.gold: --export-if-defined=__main_argc_argv: unknown option") ||
- build.logText.contains("-static-stdlib is no longer supported for Apple platforms")
+ build.logText.contains("ld.gold: --export-if-defined=__main_argc_argv: unknown option")
+ || build.logText.contains("-static-stdlib is no longer supported for Apple platforms")
else { return nil }
let didYouMean =
[
@@ -57,7 +57,11 @@ struct PackageToJSPlugin: CommandPlugin {
(
// In case selected toolchain is a Xcode toolchain, not OSS toolchain
{ build, arguments in
- guard build.logText.contains("No available targets are compatible with triple \"wasm32-unknown-wasi\"") else {
+ guard
+ build.logText.contains(
+ "No available targets are compatible with triple \"wasm32-unknown-wasi\""
+ )
+ else {
return nil
}
return """
@@ -74,7 +78,8 @@ struct PackageToJSPlugin: CommandPlugin {
}
private func reportBuildFailure(
- _ build: PackageManager.BuildResult, _ arguments: [String]
+ _ build: PackageManager.BuildResult,
+ _ arguments: [String]
) {
for diagnostic in Self.friendlyBuildDiagnostics {
if let message = diagnostic(build, arguments) {
@@ -100,11 +105,12 @@ struct PackageToJSPlugin: CommandPlugin {
if filePath.hasPrefix(packageDir.path) {
// Emit hint for --allow-writing-to-package-directory if the destination path
// is under the package directory
- let didYouMean = [
- "swift", "package", "--swift-sdk", "wasm32-unknown-wasi",
- "plugin", "--allow-writing-to-package-directory",
- "js",
- ] + arguments
+ let didYouMean =
+ [
+ "swift", "package", "--swift-sdk", "wasm32-unknown-wasi",
+ "plugin", "--allow-writing-to-package-directory",
+ "js",
+ ] + arguments
emitHintMessage(
"""
Please pass `--allow-writing-to-package-directory` to "swift package".
@@ -116,11 +122,12 @@ struct PackageToJSPlugin: CommandPlugin {
} else {
// Emit hint for --allow-writing-to-directory
// if the destination path is outside the package directory
- let didYouMean = [
- "swift", "package", "--swift-sdk", "wasm32-unknown-wasi",
- "plugin", "--allow-writing-to-directory", "\(filePath)",
- "js",
- ] + arguments
+ let didYouMean =
+ [
+ "swift", "package", "--swift-sdk", "wasm32-unknown-wasi",
+ "plugin", "--allow-writing-to-directory", "\(filePath)",
+ "js",
+ ] + arguments
emitHintMessage(
"""
Please pass `--allow-writing-to-directory ` to "swift package".
@@ -147,7 +154,8 @@ struct PackageToJSPlugin: CommandPlugin {
if extractor.remainingArguments.count > 0 {
printStderr(
- "Unexpected arguments: \(extractor.remainingArguments.joined(separator: " "))")
+ "Unexpected arguments: \(extractor.remainingArguments.joined(separator: " "))"
+ )
printStderr(PackageToJS.BuildOptions.help())
exit(1)
}
@@ -155,7 +163,8 @@ struct PackageToJSPlugin: CommandPlugin {
// Build products
let productName = try buildOptions.product ?? deriveDefaultProduct(package: context.package)
let build = try buildWasm(
- productName: productName, context: context,
+ productName: productName,
+ context: context,
options: buildOptions.packageOptions
)
guard build.succeeded else {
@@ -171,7 +180,9 @@ struct PackageToJSPlugin: CommandPlugin {
}
guard
let selfPackage = findPackageInDependencies(
- package: context.package, id: Self.JAVASCRIPTKIT_PACKAGE_ID)
+ package: context.package,
+ id: Self.JAVASCRIPTKIT_PACKAGE_ID
+ )
else {
throw PackageToJSError("Failed to find JavaScriptKit in dependencies!?")
}
@@ -180,12 +191,17 @@ struct PackageToJSPlugin: CommandPlugin {
printProgress: self.printProgress
)
let planner = PackagingPlanner(
- options: buildOptions.packageOptions, context: context, selfPackage: selfPackage,
- outputDir: outputDir, wasmProductArtifact: productArtifact,
+ options: buildOptions.packageOptions,
+ context: context,
+ selfPackage: selfPackage,
+ outputDir: outputDir,
+ wasmProductArtifact: productArtifact,
wasmFilename: productArtifact.lastPathComponent
)
let rootTask = try planner.planBuild(
- make: &make, buildOptions: buildOptions)
+ make: &make,
+ buildOptions: buildOptions
+ )
cleanIfBuildGraphChanged(root: rootTask, make: make, context: context)
print("Packaging...")
let scope = MiniMake.VariableScope(variables: [:])
@@ -204,14 +220,16 @@ struct PackageToJSPlugin: CommandPlugin {
if extractor.remainingArguments.count > 0 {
printStderr(
- "Unexpected arguments: \(extractor.remainingArguments.joined(separator: " "))")
+ "Unexpected arguments: \(extractor.remainingArguments.joined(separator: " "))"
+ )
printStderr(PackageToJS.TestOptions.help())
exit(1)
}
let productName = "\(context.package.displayName)PackageTests"
let build = try buildWasm(
- productName: productName, context: context,
+ productName: productName,
+ context: context,
options: testOptions.packageOptions
)
guard build.succeeded else {
@@ -237,7 +255,8 @@ struct PackageToJSPlugin: CommandPlugin {
}
guard let productArtifact = productArtifact else {
throw PackageToJSError(
- "Failed to find '\(productName).wasm' or '\(productName).xctest'")
+ "Failed to find '\(productName).wasm' or '\(productName).xctest'"
+ )
}
let outputDir =
if let outputPath = testOptions.packageOptions.outputPath {
@@ -247,7 +266,9 @@ struct PackageToJSPlugin: CommandPlugin {
}
guard
let selfPackage = findPackageInDependencies(
- package: context.package, id: Self.JAVASCRIPTKIT_PACKAGE_ID)
+ package: context.package,
+ id: Self.JAVASCRIPTKIT_PACKAGE_ID
+ )
else {
throw PackageToJSError("Failed to find JavaScriptKit in dependencies!?")
}
@@ -256,8 +277,11 @@ struct PackageToJSPlugin: CommandPlugin {
printProgress: self.printProgress
)
let planner = PackagingPlanner(
- options: testOptions.packageOptions, context: context, selfPackage: selfPackage,
- outputDir: outputDir, wasmProductArtifact: productArtifact,
+ options: testOptions.packageOptions,
+ context: context,
+ selfPackage: selfPackage,
+ outputDir: outputDir,
+ wasmProductArtifact: productArtifact,
// If the product artifact doesn't have a .wasm extension, add it
// to deliver it with the correct MIME type when serving the test
// files for browser tests.
@@ -266,7 +290,8 @@ struct PackageToJSPlugin: CommandPlugin {
: productArtifact.lastPathComponent + ".wasm"
)
let (rootTask, binDir) = try planner.planTestBuild(
- make: &make)
+ make: &make
+ )
cleanIfBuildGraphChanged(root: rootTask, make: make, context: context)
print("Packaging tests...")
let scope = MiniMake.VariableScope(variables: [:])
@@ -284,7 +309,11 @@ struct PackageToJSPlugin: CommandPlugin {
}
}
- private func buildWasm(productName: String, context: PluginContext, options: PackageToJS.PackageOptions) throws
+ private func buildWasm(
+ productName: String,
+ context: PluginContext,
+ options: PackageToJS.PackageOptions
+ ) throws
-> PackageManager.BuildResult
{
var parameters = PackageManager.BuildParameters(
@@ -295,7 +324,8 @@ struct PackageToJSPlugin: CommandPlugin {
parameters.otherSwiftcFlags = ["-color-diagnostics"]
let buildingForEmbedded =
ProcessInfo.processInfo.environment["JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM"].flatMap(
- Bool.init) ?? false
+ Bool.init
+ ) ?? false
if !buildingForEmbedded {
// NOTE: We only support static linking for now, and the new SwiftDriver
// does not infer `-static-stdlib` for WebAssembly targets intentionally
@@ -323,7 +353,8 @@ struct PackageToJSPlugin: CommandPlugin {
/// path.
private func cleanIfBuildGraphChanged(
root: MiniMake.TaskKey,
- make: MiniMake, context: PluginContext
+ make: MiniMake,
+ context: PluginContext
) {
let buildFingerprint = context.pluginWorkDirectoryURL.appending(path: "minimake.json")
let lastBuildFingerprint = try? Data(contentsOf: buildFingerprint)
@@ -338,7 +369,8 @@ struct PackageToJSPlugin: CommandPlugin {
private func printProgress(context: MiniMake.ProgressPrinter.Context, message: String) {
let buildCwd = FileManager.default.currentDirectoryPath
let outputPath = context.scope.resolve(path: context.subject.output).path
- let displayName = outputPath.hasPrefix(buildCwd + "/")
+ let displayName =
+ outputPath.hasPrefix(buildCwd + "/")
? String(outputPath.dropFirst(buildCwd.count + 1)) : outputPath
printStderr("[\(context.built + 1)/\(context.total)] \(displayName): \(message)")
}
@@ -359,7 +391,12 @@ extension PackageToJS.PackageOptions {
let verbose = extractor.extractFlag(named: "verbose")
let enableCodeCoverage = extractor.extractFlag(named: "enable-code-coverage")
return PackageToJS.PackageOptions(
- outputPath: outputPath, packageName: packageName, explain: explain != 0, verbose: verbose != 0, useCDN: useCDN != 0, enableCodeCoverage: enableCodeCoverage != 0
+ outputPath: outputPath,
+ packageName: packageName,
+ explain: explain != 0,
+ verbose: verbose != 0,
+ useCDN: useCDN != 0,
+ enableCodeCoverage: enableCodeCoverage != 0
)
}
}
@@ -372,12 +409,19 @@ extension PackageToJS.BuildOptions {
var debugInfoFormat: PackageToJS.DebugInfoFormat = .none
if let rawDebugInfoFormat = rawDebugInfoFormat {
guard let format = PackageToJS.DebugInfoFormat(rawValue: rawDebugInfoFormat) else {
- fatalError("Invalid debug info format: \(rawDebugInfoFormat), expected one of \(PackageToJS.DebugInfoFormat.allCases.map(\.rawValue).joined(separator: ", "))")
+ fatalError(
+ "Invalid debug info format: \(rawDebugInfoFormat), expected one of \(PackageToJS.DebugInfoFormat.allCases.map(\.rawValue).joined(separator: ", "))"
+ )
}
debugInfoFormat = format
}
let packageOptions = PackageToJS.PackageOptions.parse(from: &extractor)
- return PackageToJS.BuildOptions(product: product, noOptimize: noOptimize != 0, debugInfoFormat: debugInfoFormat, packageOptions: packageOptions)
+ return PackageToJS.BuildOptions(
+ product: product,
+ noOptimize: noOptimize != 0,
+ debugInfoFormat: debugInfoFormat,
+ packageOptions: packageOptions
+ )
}
static func help() -> String {
@@ -424,8 +468,12 @@ extension PackageToJS.TestOptions {
let extraNodeArguments = extractor.extractSingleDashOption(named: "Xnode")
let packageOptions = PackageToJS.PackageOptions.parse(from: &extractor)
var options = PackageToJS.TestOptions(
- buildOnly: buildOnly != 0, listTests: listTests != 0,
- filter: filter, prelude: prelude, environment: environment, inspect: inspect != 0,
+ buildOnly: buildOnly != 0,
+ listTests: listTests != 0,
+ filter: filter,
+ prelude: prelude,
+ environment: environment,
+ inspect: inspect != 0,
extraNodeArguments: extraNodeArguments,
packageOptions: packageOptions
)
@@ -467,36 +515,34 @@ extension PackageToJS.TestOptions {
// MARK: - PackagePlugin helpers
extension ArgumentExtractor {
- fileprivate mutating func extractSingleDashOption(named name: String) -> [String] {
- let parts = remainingArguments.split(separator: "--", maxSplits: 1, omittingEmptySubsequences: false)
- var args = Array(parts[0])
- let literals = Array(parts.count == 2 ? parts[1] : [])
-
- var values: [String] = []
- var idx = 0
- while idx < args.count {
- var arg = args[idx]
- if arg == "-\(name)" {
- args.remove(at: idx)
- if idx < args.count {
- let val = args[idx]
- values.append(val)
- args.remove(at: idx)
+ fileprivate mutating func extractSingleDashOption(named name: String) -> [String] {
+ let parts = remainingArguments.split(separator: "--", maxSplits: 1, omittingEmptySubsequences: false)
+ var args = Array(parts[0])
+ let literals = Array(parts.count == 2 ? parts[1] : [])
+
+ var values: [String] = []
+ var idx = 0
+ while idx < args.count {
+ var arg = args[idx]
+ if arg == "-\(name)" {
+ args.remove(at: idx)
+ if idx < args.count {
+ let val = args[idx]
+ values.append(val)
+ args.remove(at: idx)
+ }
+ } else if arg.starts(with: "-\(name)=") {
+ args.remove(at: idx)
+ arg.removeFirst(2 + name.count)
+ values.append(arg)
+ } else {
+ idx += 1
+ }
}
- }
- else if arg.starts(with: "-\(name)=") {
- args.remove(at: idx)
- arg.removeFirst(2 + name.count)
- values.append(arg)
- }
- else {
- idx += 1
- }
- }
- self = ArgumentExtractor(args + literals)
- return values
- }
+ self = ArgumentExtractor(args + literals)
+ return values
+ }
}
/// Derive default product from the package
@@ -506,7 +552,8 @@ internal func deriveDefaultProduct(package: Package) throws -> String {
let executableProducts = package.products(ofType: ExecutableProduct.self)
guard !executableProducts.isEmpty else {
throw PackageToJSError(
- "Make sure there's at least one executable product in your Package.swift")
+ "Make sure there's at least one executable product in your Package.swift"
+ )
}
guard executableProducts.count == 1 else {
throw PackageToJSError(
@@ -568,7 +615,9 @@ extension PackagingPlanner {
self.init(
options: options,
packageId: context.package.id,
- intermediatesDir: BuildPath(absolute: context.pluginWorkDirectoryURL.appending(path: outputBaseName + ".tmp").path),
+ intermediatesDir: BuildPath(
+ absolute: context.pluginWorkDirectoryURL.appending(path: outputBaseName + ".tmp").path
+ ),
selfPackageDir: BuildPath(absolute: selfPackage.directoryURL.path),
outputDir: BuildPath(absolute: outputDir.path),
wasmProductArtifact: BuildPath(absolute: wasmProductArtifact.path),
diff --git a/Plugins/PackageToJS/Sources/ParseWasm.swift b/Plugins/PackageToJS/Sources/ParseWasm.swift
index 8cfb6c66c..4372b32c5 100644
--- a/Plugins/PackageToJS/Sources/ParseWasm.swift
+++ b/Plugins/PackageToJS/Sources/ParseWasm.swift
@@ -199,7 +199,8 @@ func parseImports(moduleBytes: Data) throws -> [ImportEntry] {
case 0x02: // Memory
let limits = try parseLimits(parseState)
imports.append(
- ImportEntry(module: module, name: name, kind: .memory(type: limits)))
+ ImportEntry(module: module, name: name, kind: .memory(type: limits))
+ )
case 0x03: // Global
_ = try parseGlobalType(parseState)
diff --git a/Plugins/PackageToJS/Sources/Preprocess.swift b/Plugins/PackageToJS/Sources/Preprocess.swift
index 835dd31a6..bafa2aae5 100644
--- a/Plugins/PackageToJS/Sources/Preprocess.swift
+++ b/Plugins/PackageToJS/Sources/Preprocess.swift
@@ -66,7 +66,10 @@ private struct Preprocessor {
}
/// Get the 1-indexed line and column
- private static func computeLineAndColumn(from index: String.Index, in source: String) -> (line: Int, column: Int) {
+ private static func computeLineAndColumn(
+ from index: String.Index,
+ in source: String
+ ) -> (line: Int, column: Int) {
var line = 1
var column = 1
for char in source[.. PreprocessorError {
+ func unexpectedCharacterError(
+ expected: CustomStringConvertible,
+ character: Character,
+ at index: String.Index
+ ) -> PreprocessorError {
return PreprocessorError(
file: file,
- message: "Expected \(expected) but got \(character)", source: source, index: index)
+ message: "Expected \(expected) but got \(character)",
+ source: source,
+ index: index
+ )
}
func unexpectedDirectiveError(at index: String.Index) -> PreprocessorError {
return PreprocessorError(
file: file,
- message: "Unexpected directive", source: source, index: index)
+ message: "Unexpected directive",
+ source: source,
+ index: index
+ )
}
func eofError(at index: String.Index) -> PreprocessorError {
return PreprocessorError(
file: file,
- message: "Unexpected end of input", source: source, index: index)
+ message: "Unexpected end of input",
+ source: source,
+ index: index
+ )
}
func undefinedVariableError(name: String, at index: String.Index) -> PreprocessorError {
return PreprocessorError(
file: file,
- message: "Undefined variable \(name)", source: source, index: index)
+ message: "Undefined variable \(name)",
+ source: source,
+ index: index
+ )
}
func tokenize() throws -> [TokenInfo] {
@@ -188,7 +210,10 @@ private struct Preprocessor {
func expect(_ expected: String) throws {
guard
let endIndex = source.index(
- cursor, offsetBy: expected.count, limitedBy: source.endIndex)
+ cursor,
+ offsetBy: expected.count,
+ limitedBy: source.endIndex
+ )
else {
throw eofError(at: cursor)
}
@@ -281,7 +306,11 @@ private struct Preprocessor {
enum ParseResult {
case block(String)
indirect case `if`(
- condition: String, then: [ParseResult], else: [ParseResult], position: String.Index)
+ condition: String,
+ then: [ParseResult],
+ else: [ParseResult],
+ position: String.Index
+ )
}
func parse(tokens: [TokenInfo]) throws -> [ParseResult] {
@@ -314,13 +343,19 @@ private struct Preprocessor {
}
guard case .endif = tokens[cursor].token else {
throw unexpectedTokenError(
- expected: .endif, token: tokens[cursor].token, at: tokens[cursor].position)
+ expected: .endif,
+ token: tokens[cursor].token,
+ at: tokens[cursor].position
+ )
}
consume()
return .if(condition: condition, then: then, else: `else`, position: ifPosition)
case .else, .endif:
throw unexpectedTokenError(
- expected: nil, token: tokens[cursor].token, at: tokens[cursor].position)
+ expected: nil,
+ token: tokens[cursor].token,
+ at: tokens[cursor].position
+ )
}
}
var results: [ParseResult] = []
@@ -338,9 +373,13 @@ private struct Preprocessor {
var substitutedContent = content
for (key, value) in options.substitutions {
substitutedContent = substitutedContent.replacingOccurrences(
- of: "@" + key + "@", with: value)
+ of: "@" + key + "@",
+ with: value
+ )
substitutedContent = substitutedContent.replacingOccurrences(
- of: "import.meta." + key, with: value)
+ of: "import.meta." + key,
+ with: value
+ )
}
result.append(substitutedContent)
}
diff --git a/Plugins/PackageToJS/Sources/TestsParser.swift b/Plugins/PackageToJS/Sources/TestsParser.swift
index 61d417521..72afd6b07 100644
--- a/Plugins/PackageToJS/Sources/TestsParser.swift
+++ b/Plugins/PackageToJS/Sources/TestsParser.swift
@@ -186,7 +186,8 @@ class FancyTestsParser {
write("\n")
func formatCategory(
- label: String, statuses: [Status]
+ label: String,
+ statuses: [Status]
) -> String {
var passed = 0
var skipped = 0
@@ -220,7 +221,8 @@ class FancyTestsParser {
let suitesWithCases = suites.filter { $0.cases.count > 0 }
write(
formatCategory(
- label: "Test Suites:", statuses: suitesWithCases.map(\.status)
+ label: "Test Suites:",
+ statuses: suitesWithCases.map(\.status)
)
)
let allCaseStatuses = suitesWithCases.flatMap {
@@ -228,7 +230,8 @@ class FancyTestsParser {
}
write(
formatCategory(
- label: "Tests: ", statuses: allCaseStatuses
+ label: "Tests: ",
+ statuses: allCaseStatuses
)
)
diff --git a/Plugins/PackageToJS/Tests/ExampleTests.swift b/Plugins/PackageToJS/Tests/ExampleTests.swift
index 508062297..304878692 100644
--- a/Plugins/PackageToJS/Tests/ExampleTests.swift
+++ b/Plugins/PackageToJS/Tests/ExampleTests.swift
@@ -54,7 +54,10 @@ extension Trait where Self == ConditionTrait {
static func copyRepository(to destination: URL) throws {
try FileManager.default.createDirectory(
- atPath: destination.path, withIntermediateDirectories: true, attributes: nil)
+ atPath: destination.path,
+ withIntermediateDirectories: true,
+ attributes: nil
+ )
let ignore = [
".git",
".vscode",
@@ -81,7 +84,9 @@ extension Trait where Self == ConditionTrait {
do {
try FileManager.default.createDirectory(
at: destinationPath.deletingLastPathComponent(),
- withIntermediateDirectories: true, attributes: nil)
+ withIntermediateDirectories: true,
+ attributes: nil
+ )
try FileManager.default.copyItem(at: sourcePath, to: destinationPath)
} catch {
print("Failed to copy \(sourcePath) to \(destinationPath): \(error)")
@@ -101,7 +106,9 @@ extension Trait where Self == ConditionTrait {
process.executableURL = URL(
fileURLWithPath: "swift",
relativeTo: URL(
- fileURLWithPath: try #require(Self.getSwiftPath())))
+ fileURLWithPath: try #require(Self.getSwiftPath())
+ )
+ )
process.arguments = args
process.currentDirectoryURL = destination.appending(path: path)
process.environment = ProcessInfo.processInfo.environment.merging(env) { _, new in
@@ -141,7 +148,10 @@ extension Trait where Self == ConditionTrait {
try runSwift(["package", "--swift-sdk", swiftSDKID, "js"], [:])
try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "--debug-info-format", "dwarf"], [:])
try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "--debug-info-format", "name"], [:])
- try runSwift(["package", "--swift-sdk", swiftSDKID, "-Xswiftc", "-DJAVASCRIPTKIT_WITHOUT_WEAKREFS", "js"], [:])
+ try runSwift(
+ ["package", "--swift-sdk", swiftSDKID, "-Xswiftc", "-DJAVASCRIPTKIT_WITHOUT_WEAKREFS", "js"],
+ [:]
+ )
}
}
@@ -152,17 +162,23 @@ extension Trait where Self == ConditionTrait {
try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "test"], [:])
try withTemporaryDirectory(body: { tempDir, _ in
let scriptContent = """
- const fs = require('fs');
- const path = require('path');
- const scriptPath = path.join(__dirname, 'test.txt');
- fs.writeFileSync(scriptPath, 'Hello, world!');
- """
+ const fs = require('fs');
+ const path = require('path');
+ const scriptPath = path.join(__dirname, 'test.txt');
+ fs.writeFileSync(scriptPath, 'Hello, world!');
+ """
try scriptContent.write(to: tempDir.appending(path: "script.js"), atomically: true, encoding: .utf8)
let scriptPath = tempDir.appending(path: "script.js")
- try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "test", "-Xnode=--require=\(scriptPath.path)"], [:])
+ try runSwift(
+ ["package", "--swift-sdk", swiftSDKID, "js", "test", "-Xnode=--require=\(scriptPath.path)"],
+ [:]
+ )
let testPath = tempDir.appending(path: "test.txt")
try #require(FileManager.default.fileExists(atPath: testPath.path), "test.txt should exist")
- try #require(try String(contentsOf: testPath, encoding: .utf8) == "Hello, world!", "test.txt should be created by the script")
+ try #require(
+ try String(contentsOf: testPath, encoding: .utf8) == "Hello, world!",
+ "test.txt should be created by the script"
+ )
})
try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser"], [:])
}
@@ -174,15 +190,22 @@ extension Trait where Self == ConditionTrait {
let swiftSDKID = try #require(Self.getSwiftSDKID())
let swiftPath = try #require(Self.getSwiftPath())
try withPackage(at: "Examples/Testing") { packageDir, runSwift in
- try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "test", "--enable-code-coverage"], [
- "LLVM_PROFDATA_PATH": URL(fileURLWithPath: swiftPath).appending(path: "llvm-profdata").path
- ])
+ try runSwift(
+ ["package", "--swift-sdk", swiftSDKID, "js", "test", "--enable-code-coverage"],
+ [
+ "LLVM_PROFDATA_PATH": URL(fileURLWithPath: swiftPath).appending(path: "llvm-profdata").path
+ ]
+ )
do {
let llvmCov = try which("llvm-cov")
let process = Process()
process.executableURL = llvmCov
- let profdata = packageDir.appending(path: ".build/plugins/PackageToJS/outputs/PackageTests/default.profdata")
- let wasm = packageDir.appending(path: ".build/plugins/PackageToJS/outputs/PackageTests/TestingPackageTests.wasm")
+ let profdata = packageDir.appending(
+ path: ".build/plugins/PackageToJS/outputs/PackageTests/default.profdata"
+ )
+ let wasm = packageDir.appending(
+ path: ".build/plugins/PackageToJS/outputs/PackageTests/TestingPackageTests.wasm"
+ )
process.arguments = ["report", "-instr-profile", profdata.path, wasm.path]
process.standardOutput = FileHandle.nullDevice
try process.run()
diff --git a/Plugins/PackageToJS/Tests/MiniMakeTests.swift b/Plugins/PackageToJS/Tests/MiniMakeTests.swift
index b15a87607..c0bba29c7 100644
--- a/Plugins/PackageToJS/Tests/MiniMakeTests.swift
+++ b/Plugins/PackageToJS/Tests/MiniMakeTests.swift
@@ -14,9 +14,12 @@ import Testing
try "Hello".write(toFile: $1.resolve(path: $0.output).path, atomically: true, encoding: .utf8)
}
- try make.build(output: task, scope: MiniMake.VariableScope(variables: [
- "OUTPUT": tempDir.path,
- ]))
+ try make.build(
+ output: task,
+ scope: MiniMake.VariableScope(variables: [
+ "OUTPUT": tempDir.path
+ ])
+ )
let content = try String(contentsOfFile: tempDir.appendingPathComponent("output.txt").path, encoding: .utf8)
#expect(content == "Hello")
}
@@ -28,7 +31,7 @@ import Testing
var make = MiniMake(printProgress: { _, _ in })
let prefix = BuildPath(prefix: "PREFIX")
let scope = MiniMake.VariableScope(variables: [
- "PREFIX": tempDir.path,
+ "PREFIX": tempDir.path
])
let input = prefix.appending(path: "input.txt")
let intermediate = prefix.appending(path: "intermediate.txt")
@@ -39,15 +42,23 @@ import Testing
let intermediateTask = make.addTask(inputFiles: [input], output: intermediate) { task, outputURL in
let content = try String(contentsOfFile: scope.resolve(path: task.inputs[0]).path, encoding: .utf8)
try (content + " processed").write(
- toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8)
+ toFile: scope.resolve(path: task.output).path,
+ atomically: true,
+ encoding: .utf8
+ )
}
let finalTask = make.addTask(
- inputFiles: [intermediate], inputTasks: [intermediateTask], output: output
+ inputFiles: [intermediate],
+ inputTasks: [intermediateTask],
+ output: output
) { task, scope in
let content = try String(contentsOfFile: scope.resolve(path: task.inputs[0]).path, encoding: .utf8)
try (content + " final").write(
- toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8)
+ toFile: scope.resolve(path: task.output).path,
+ atomically: true,
+ encoding: .utf8
+ )
}
try make.build(output: finalTask, scope: scope)
@@ -67,11 +78,15 @@ import Testing
let task = make.addTask(output: outputPath, attributes: [.phony]) { task, scope in
buildCount += 1
- try String(buildCount).write(toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8)
+ try String(buildCount).write(
+ toFile: scope.resolve(path: task.output).path,
+ atomically: true,
+ encoding: .utf8
+ )
}
let scope = MiniMake.VariableScope(variables: [
- "OUTPUT": tempDir.path,
+ "OUTPUT": tempDir.path
])
try make.build(output: task, scope: scope)
try make.build(output: task, scope: scope)
@@ -102,7 +117,7 @@ import Testing
var make = MiniMake(printProgress: { _, _ in })
let prefix = BuildPath(prefix: "PREFIX")
let scope = MiniMake.VariableScope(variables: [
- "PREFIX": tempDir.path,
+ "PREFIX": tempDir.path
])
let input = prefix.appending(path: "input.txt")
let output = prefix.appending(path: "output.txt")
@@ -142,7 +157,7 @@ import Testing
)
let prefix = BuildPath(prefix: "PREFIX")
let scope = MiniMake.VariableScope(variables: [
- "PREFIX": tempDir.path,
+ "PREFIX": tempDir.path
])
let silentOutputPath = prefix.appending(path: "silent.txt")
let silentTask = make.addTask(output: silentOutputPath, attributes: [.silent]) { task, scope in
@@ -150,14 +165,21 @@ import Testing
}
let finalOutputPath = prefix.appending(path: "output.txt")
let task = make.addTask(
- inputTasks: [silentTask], output: finalOutputPath
+ inputTasks: [silentTask],
+ output: finalOutputPath
) { task, scope in
try "Hello".write(toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8)
}
try make.build(output: task, scope: scope)
- #expect(FileManager.default.fileExists(atPath: scope.resolve(path: silentOutputPath).path), "Silent task should still create output file")
- #expect(FileManager.default.fileExists(atPath: scope.resolve(path: finalOutputPath).path), "Final task should create output file")
+ #expect(
+ FileManager.default.fileExists(atPath: scope.resolve(path: silentOutputPath).path),
+ "Silent task should still create output file"
+ )
+ #expect(
+ FileManager.default.fileExists(atPath: scope.resolve(path: finalOutputPath).path),
+ "Final task should create output file"
+ )
try #require(messages.count == 1, "Should print progress for the final task")
#expect(messages[0] == ("$PREFIX/output.txt", 1, 0, "\u{1B}[32mbuilding\u{1B}[0m"))
}
@@ -170,7 +192,7 @@ import Testing
var make = MiniMake(printProgress: { _, _ in })
let prefix = BuildPath(prefix: "PREFIX")
let scope = MiniMake.VariableScope(variables: [
- "PREFIX": tempDir.path,
+ "PREFIX": tempDir.path
])
let output = prefix.appending(path: "error.txt")
@@ -190,7 +212,7 @@ import Testing
var make = MiniMake(printProgress: { _, _ in })
let prefix = BuildPath(prefix: "PREFIX")
let scope = MiniMake.VariableScope(variables: [
- "PREFIX": tempDir.path,
+ "PREFIX": tempDir.path
])
let outputs = [
prefix.appending(path: "clean1.txt"),
@@ -200,7 +222,11 @@ import Testing
// Create tasks and build them
let tasks = outputs.map { output in
make.addTask(output: output) { task, scope in
- try "Content".write(toFile: scope.resolve(path: task.output).path, atomically: true, encoding: .utf8)
+ try "Content".write(
+ toFile: scope.resolve(path: task.output).path,
+ atomically: true,
+ encoding: .utf8
+ )
}
}
@@ -212,7 +238,8 @@ import Testing
for output in outputs {
#expect(
FileManager.default.fileExists(atPath: scope.resolve(path: output).path),
- "Output file should exist before cleanup")
+ "Output file should exist before cleanup"
+ )
}
// Clean everything
@@ -222,7 +249,8 @@ import Testing
for output in outputs {
#expect(
!FileManager.default.fileExists(atPath: scope.resolve(path: output).path),
- "Output file should not exist after cleanup")
+ "Output file should not exist after cleanup"
+ )
}
}
}
diff --git a/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift b/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift
index 6392ca664..c69dcb66f 100644
--- a/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift
+++ b/Plugins/PackageToJS/Tests/PackagingPlannerTests.swift
@@ -15,12 +15,15 @@ import Testing
func wasmOpt(_ arguments: [String], input: String, output: String) throws {
try FileManager.default.copyItem(
- at: URL(fileURLWithPath: input), to: URL(fileURLWithPath: output))
+ at: URL(fileURLWithPath: input),
+ to: URL(fileURLWithPath: output)
+ )
}
}
func snapshotBuildPlan(
- filePath: String = #filePath, function: String = #function,
+ filePath: String = #filePath,
+ function: String = #function,
sourceLocation: SourceLocation = #_sourceLocation,
variant: String? = nil,
body: (inout MiniMake) throws -> MiniMake.TaskKey
@@ -29,8 +32,11 @@ import Testing
let rootKey = try body(&make)
let fingerprint = try make.computeFingerprint(root: rootKey, prettyPrint: true)
try assertSnapshot(
- filePath: filePath, function: function, sourceLocation: sourceLocation,
- variant: variant, input: fingerprint
+ filePath: filePath,
+ function: function,
+ sourceLocation: sourceLocation,
+ variant: variant,
+ input: fingerprint
)
}
@@ -39,11 +45,19 @@ import Testing
@Test(arguments: [
(variant: "debug", configuration: "debug", noOptimize: false, debugInfoFormat: DebugInfoFormat.none),
(variant: "release", configuration: "release", noOptimize: false, debugInfoFormat: DebugInfoFormat.none),
- (variant: "release_no_optimize", configuration: "release", noOptimize: true, debugInfoFormat: DebugInfoFormat.none),
+ (
+ variant: "release_no_optimize", configuration: "release", noOptimize: true,
+ debugInfoFormat: DebugInfoFormat.none
+ ),
(variant: "release_dwarf", configuration: "release", noOptimize: false, debugInfoFormat: DebugInfoFormat.dwarf),
(variant: "release_name", configuration: "release", noOptimize: false, debugInfoFormat: DebugInfoFormat.name),
])
- func planBuild(variant: String, configuration: String, noOptimize: Bool, debugInfoFormat: PackageToJS.DebugInfoFormat) throws {
+ func planBuild(
+ variant: String,
+ configuration: String,
+ noOptimize: Bool,
+ debugInfoFormat: PackageToJS.DebugInfoFormat
+ ) throws {
let options = PackageToJS.PackageOptions()
let system = TestPackagingSystem()
let planner = PackagingPlanner(
@@ -88,7 +102,7 @@ import Testing
selfPath: BuildPath(prefix: "PLANNER_SOURCE_PATH"),
system: system
)
- try snapshotBuildPlan() { make in
+ try snapshotBuildPlan { make in
let (root, binDir) = try planner.planTestBuild(make: &make)
#expect(binDir.description == "$OUTPUT/bin")
return root
diff --git a/Plugins/PackageToJS/Tests/PreprocessTests.swift b/Plugins/PackageToJS/Tests/PreprocessTests.swift
index 9ebb7a161..6e7e4a1b9 100644
--- a/Plugins/PackageToJS/Tests/PreprocessTests.swift
+++ b/Plugins/PackageToJS/Tests/PreprocessTests.swift
@@ -1,15 +1,16 @@
import Testing
+
@testable import PackageToJS
@Suite struct PreprocessTests {
@Test func thenBlock() throws {
let source = """
- /* #if FOO */
- console.log("FOO");
- /* #else */
- console.log("BAR");
- /* #endif */
- """
+ /* #if FOO */
+ console.log("FOO");
+ /* #else */
+ console.log("BAR");
+ /* #endif */
+ """
let options = PreprocessOptions(conditions: ["FOO": true])
let result = try preprocess(source: source, options: options)
#expect(result == "console.log(\"FOO\");\n")
@@ -17,12 +18,12 @@ import Testing
@Test func elseBlock() throws {
let source = """
- /* #if FOO */
- console.log("FOO");
- /* #else */
- console.log("BAR");
- /* #endif */
- """
+ /* #if FOO */
+ console.log("FOO");
+ /* #else */
+ console.log("BAR");
+ /* #endif */
+ """
let options = PreprocessOptions(conditions: ["FOO": false])
let result = try preprocess(source: source, options: options)
#expect(result == "console.log(\"BAR\");\n")
@@ -30,8 +31,8 @@ import Testing
@Test func onelineIf() throws {
let source = """
- /* #if FOO */console.log("FOO");/* #endif */
- """
+ /* #if FOO */console.log("FOO");/* #endif */
+ """
let options = PreprocessOptions(conditions: ["FOO": true])
let result = try preprocess(source: source, options: options)
#expect(result == "console.log(\"FOO\");")
@@ -39,9 +40,9 @@ import Testing
@Test func undefinedVariable() throws {
let source = """
- /* #if FOO */
- /* #endif */
- """
+ /* #if FOO */
+ /* #endif */
+ """
let options = PreprocessOptions(conditions: [:])
#expect(throws: Error.self) {
try preprocess(source: source, options: options)
@@ -57,8 +58,8 @@ import Testing
@Test func missingEndOfDirective() throws {
let source = """
- /* #if FOO
- """
+ /* #if FOO
+ """
#expect(throws: Error.self) {
try preprocess(source: source, options: PreprocessOptions())
}
@@ -72,17 +73,17 @@ import Testing
])
func nestedIfDirectives(foo: Bool, bar: Bool, expected: String) throws {
let source = """
- /* #if FOO */
- console.log("FOO");
- /* #if BAR */
- console.log("FOO & BAR");
- /* #else */
- console.log("FOO & !BAR");
- /* #endif */
- /* #else */
- console.log("!FOO");
- /* #endif */
- """
+ /* #if FOO */
+ console.log("FOO");
+ /* #if BAR */
+ console.log("FOO & BAR");
+ /* #else */
+ console.log("FOO & !BAR");
+ /* #endif */
+ /* #else */
+ console.log("!FOO");
+ /* #endif */
+ """
let options = PreprocessOptions(conditions: ["FOO": foo, "BAR": bar])
let result = try preprocess(source: source, options: options)
#expect(result == expected)
@@ -90,26 +91,28 @@ import Testing
@Test func multipleSubstitutions() throws {
let source = """
- const name = "@NAME@";
- const version = "@VERSION@";
- """
+ const name = "@NAME@";
+ const version = "@VERSION@";
+ """
let options = PreprocessOptions(substitutions: [
"NAME": "MyApp",
- "VERSION": "1.0.0"
+ "VERSION": "1.0.0",
])
let result = try preprocess(source: source, options: options)
- #expect(result == """
- const name = "MyApp";
- const version = "1.0.0";
- """)
+ #expect(
+ result == """
+ const name = "MyApp";
+ const version = "1.0.0";
+ """
+ )
}
@Test func invalidVariableName() throws {
let source = """
- /* #if invalid-name */
- console.log("error");
- /* #endif */
- """
+ /* #if invalid-name */
+ console.log("error");
+ /* #endif */
+ """
#expect(throws: Error.self) {
try preprocess(source: source, options: PreprocessOptions())
}
@@ -117,10 +120,10 @@ import Testing
@Test func emptyBlocks() throws {
let source = """
- /* #if FOO */
- /* #else */
- /* #endif */
- """
+ /* #if FOO */
+ /* #else */
+ /* #endif */
+ """
let options = PreprocessOptions(conditions: ["FOO": true])
let result = try preprocess(source: source, options: options)
#expect(result == "")
@@ -128,9 +131,9 @@ import Testing
@Test func ignoreNonDirectiveComments() throws {
let source = """
- /* Normal comment */
- /** Doc comment */
- """
+ /* Normal comment */
+ /** Doc comment */
+ """
let result = try preprocess(source: source, options: PreprocessOptions())
#expect(result == source)
}
diff --git a/Plugins/PackageToJS/Tests/SnapshotTesting.swift b/Plugins/PackageToJS/Tests/SnapshotTesting.swift
index 4732cfce8..e900954ff 100644
--- a/Plugins/PackageToJS/Tests/SnapshotTesting.swift
+++ b/Plugins/PackageToJS/Tests/SnapshotTesting.swift
@@ -1,11 +1,13 @@
-import Testing
import Foundation
+import Testing
func assertSnapshot(
- filePath: String = #filePath, function: String = #function,
+ filePath: String = #filePath,
+ function: String = #function,
sourceLocation: SourceLocation = #_sourceLocation,
variant: String? = nil,
- input: Data, fileExtension: String = "json"
+ input: Data,
+ fileExtension: String = "json"
) throws {
let testFileName = URL(fileURLWithPath: filePath).deletingPathExtension().lastPathComponent
let snapshotDir = URL(fileURLWithPath: filePath)
@@ -13,7 +15,8 @@ func assertSnapshot(
.appendingPathComponent("__Snapshots__")
.appendingPathComponent(testFileName)
try FileManager.default.createDirectory(at: snapshotDir, withIntermediateDirectories: true)
- let snapshotFileName: String = "\(function[..=6.1) && _runtime(_multithreaded)
- return $0.ownerTid
+ return $0.ownerTid
#else
- _ = $0
- // On single-threaded runtime, source and destination threads are always the main thread (TID = -1).
- return -1
+ _ = $0
+ // On single-threaded runtime, source and destination threads are always the main thread (TID = -1).
+ return -1
#endif
},
transferring: transferring
@@ -226,7 +226,11 @@ extension JSSending {
/// - Returns: The received object of type `T`.
/// - Throws: `JSSendingError` if the sending operation fails, or `JSException` if a JavaScript error occurs.
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
- public func receive(isolation: isolated (any Actor)? = #isolation, file: StaticString = #file, line: UInt = #line) async throws -> T {
+ public func receive(
+ isolation: isolated (any Actor)? = #isolation,
+ file: StaticString = #file,
+ line: UInt = #line
+ ) async throws -> T {
#if compiler(>=6.1) && _runtime(_multithreaded)
let idInDestination = try await withCheckedThrowingContinuation { continuation in
let context = _JSSendingContext(continuation: continuation)
@@ -281,7 +285,9 @@ extension JSSending {
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public static func receive(
_ sendings: repeat JSSending,
- isolation: isolated (any Actor)? = #isolation, file: StaticString = #file, line: UInt = #line
+ isolation: isolated (any Actor)? = #isolation,
+ file: StaticString = #file,
+ line: UInt = #line
) async throws -> (repeat each U) where T == (repeat each U) {
#if compiler(>=6.1) && _runtime(_multithreaded)
var sendingObjects: [JavaScriptObjectRef] = []
@@ -329,11 +335,11 @@ extension JSSending {
return try await (repeat (each sendings).receive())
#endif
}
- #endif // compiler(>=6.1)
+ #endif // compiler(>=6.1)
}
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
-fileprivate final class _JSSendingContext: Sendable {
+private final class _JSSendingContext: Sendable {
let continuation: CheckedContinuation
init(continuation: CheckedContinuation) {
@@ -361,6 +367,7 @@ public struct JSSendingError: Error, CustomStringConvertible {
/// - Parameters:
/// - object: The `JSObject` to be received.
/// - contextPtr: A pointer to the `_JSSendingContext` instance.
+// swift-format-ignore
#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+
@_expose(wasm, "swjs_receive_response")
@_cdecl("swjs_receive_response")
@@ -380,6 +387,7 @@ func _swjs_receive_response(_ object: JavaScriptObjectRef, _ contextPtr: UnsafeR
/// - Parameters:
/// - error: The error to be received.
/// - contextPtr: A pointer to the `_JSSendingContext` instance.
+// swift-format-ignore
#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+
@_expose(wasm, "swjs_receive_error")
@_cdecl("swjs_receive_error")
diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift
index ce4fb1047..6cd8de171 100644
--- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift
+++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift
@@ -6,35 +6,34 @@ import _CJavaScriptKit
#if compiler(>=5.5)
-/** Singleton type responsible for integrating JavaScript event loop as a Swift concurrency executor, conforming to
-`SerialExecutor` protocol from the standard library. To utilize it:
-
-1. Make sure that your target depends on `JavaScriptEventLoop` in your `Packages.swift`:
-
-```swift
-.target(
- name: "JavaScriptKitExample",
- dependencies: [
- "JavaScriptKit",
- .product(name: "JavaScriptEventLoop", package: "JavaScriptKit")
- ]
-)
-```
-
-2. Add an explicit import in the code that executes **before* you start using `await` and/or `Task`
-APIs (most likely in `main.swift`):
-
-```swift
-import JavaScriptEventLoop
-```
-
-3. Run this function **before* you start using `await` and/or `Task` APIs (again, most likely in
-`main.swift`):
-
-```swift
-JavaScriptEventLoop.installGlobalExecutor()
-```
-*/
+/// Singleton type responsible for integrating JavaScript event loop as a Swift concurrency executor, conforming to
+/// `SerialExecutor` protocol from the standard library. To utilize it:
+///
+/// 1. Make sure that your target depends on `JavaScriptEventLoop` in your `Packages.swift`:
+///
+/// ```swift
+/// .target(
+/// name: "JavaScriptKitExample",
+/// dependencies: [
+/// "JavaScriptKit",
+/// .product(name: "JavaScriptEventLoop", package: "JavaScriptKit")
+/// ]
+/// )
+/// ```
+///
+/// 2. Add an explicit import in the code that executes **before* you start using `await` and/or `Task`
+/// APIs (most likely in `main.swift`):
+///
+/// ```swift
+/// import JavaScriptEventLoop
+/// ```
+///
+/// 3. Run this function **before* you start using `await` and/or `Task` APIs (again, most likely in
+/// `main.swift`):
+///
+/// ```swift
+/// JavaScriptEventLoop.installGlobalExecutor()
+/// ```
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
@@ -93,10 +92,13 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
}
},
setTimeout: { delay, job in
- setTimeout(JSOneshotClosure { _ in
- job()
- return JSValue.undefined
- }, delay)
+ setTimeout(
+ JSOneshotClosure { _ in
+ job()
+ return JSValue.undefined
+ },
+ delay
+ )
}
)
return eventLoop
@@ -107,7 +109,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
/// Set JavaScript event loop based executor to be the global executor
/// Note that this should be called before any of the jobs are created.
/// This installation step will be unnecessary after custom executor are
- /// introduced officially. See also [a draft proposal for custom
+ /// introduced officially. See also [a draft proposal for custom
/// executors](https://github.com/rjmccall/swift-evolution/blob/custom-executors/proposals/0000-custom-executors.md#the-default-global-concurrent-executor)
public static func installGlobalExecutor() {
MainActor.assumeIsolated {
@@ -119,51 +121,88 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
guard !didInstallGlobalExecutor else { return }
#if compiler(>=5.9)
- typealias swift_task_asyncMainDrainQueue_hook_Fn = @convention(thin) (swift_task_asyncMainDrainQueue_original, swift_task_asyncMainDrainQueue_override) -> Void
+ typealias swift_task_asyncMainDrainQueue_hook_Fn = @convention(thin) (
+ swift_task_asyncMainDrainQueue_original, swift_task_asyncMainDrainQueue_override
+ ) -> Void
let swift_task_asyncMainDrainQueue_hook_impl: swift_task_asyncMainDrainQueue_hook_Fn = { _, _ in
swjs_unsafe_event_loop_yield()
}
- swift_task_asyncMainDrainQueue_hook = unsafeBitCast(swift_task_asyncMainDrainQueue_hook_impl, to: UnsafeMutableRawPointer?.self)
+ swift_task_asyncMainDrainQueue_hook = unsafeBitCast(
+ swift_task_asyncMainDrainQueue_hook_impl,
+ to: UnsafeMutableRawPointer?.self
+ )
#endif
- typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original) -> Void
+ typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original)
+ -> Void
let swift_task_enqueueGlobal_hook_impl: swift_task_enqueueGlobal_hook_Fn = { job, original in
JavaScriptEventLoop.shared.unsafeEnqueue(job)
}
- swift_task_enqueueGlobal_hook = unsafeBitCast(swift_task_enqueueGlobal_hook_impl, to: UnsafeMutableRawPointer?.self)
+ swift_task_enqueueGlobal_hook = unsafeBitCast(
+ swift_task_enqueueGlobal_hook_impl,
+ to: UnsafeMutableRawPointer?.self
+ )
- typealias swift_task_enqueueGlobalWithDelay_hook_Fn = @convention(thin) (UInt64, UnownedJob, swift_task_enqueueGlobalWithDelay_original) -> Void
- let swift_task_enqueueGlobalWithDelay_hook_impl: swift_task_enqueueGlobalWithDelay_hook_Fn = { delay, job, original in
+ typealias swift_task_enqueueGlobalWithDelay_hook_Fn = @convention(thin) (
+ UInt64, UnownedJob, swift_task_enqueueGlobalWithDelay_original
+ ) -> Void
+ let swift_task_enqueueGlobalWithDelay_hook_impl: swift_task_enqueueGlobalWithDelay_hook_Fn = {
+ delay,
+ job,
+ original in
JavaScriptEventLoop.shared.enqueue(job, withDelay: delay)
}
- swift_task_enqueueGlobalWithDelay_hook = unsafeBitCast(swift_task_enqueueGlobalWithDelay_hook_impl, to: UnsafeMutableRawPointer?.self)
+ swift_task_enqueueGlobalWithDelay_hook = unsafeBitCast(
+ swift_task_enqueueGlobalWithDelay_hook_impl,
+ to: UnsafeMutableRawPointer?.self
+ )
#if compiler(>=5.7)
- typealias swift_task_enqueueGlobalWithDeadline_hook_Fn = @convention(thin) (Int64, Int64, Int64, Int64, Int32, UnownedJob, swift_task_enqueueGlobalWithDelay_original) -> Void
- let swift_task_enqueueGlobalWithDeadline_hook_impl: swift_task_enqueueGlobalWithDeadline_hook_Fn = { sec, nsec, tsec, tnsec, clock, job, original in
+ typealias swift_task_enqueueGlobalWithDeadline_hook_Fn = @convention(thin) (
+ Int64, Int64, Int64, Int64, Int32, UnownedJob, swift_task_enqueueGlobalWithDelay_original
+ ) -> Void
+ let swift_task_enqueueGlobalWithDeadline_hook_impl: swift_task_enqueueGlobalWithDeadline_hook_Fn = {
+ sec,
+ nsec,
+ tsec,
+ tnsec,
+ clock,
+ job,
+ original in
JavaScriptEventLoop.shared.enqueue(job, withDelay: sec, nsec, tsec, tnsec, clock)
}
- swift_task_enqueueGlobalWithDeadline_hook = unsafeBitCast(swift_task_enqueueGlobalWithDeadline_hook_impl, to: UnsafeMutableRawPointer?.self)
+ swift_task_enqueueGlobalWithDeadline_hook = unsafeBitCast(
+ swift_task_enqueueGlobalWithDeadline_hook_impl,
+ to: UnsafeMutableRawPointer?.self
+ )
#endif
- typealias swift_task_enqueueMainExecutor_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueMainExecutor_original) -> Void
+ typealias swift_task_enqueueMainExecutor_hook_Fn = @convention(thin) (
+ UnownedJob, swift_task_enqueueMainExecutor_original
+ ) -> Void
let swift_task_enqueueMainExecutor_hook_impl: swift_task_enqueueMainExecutor_hook_Fn = { job, original in
JavaScriptEventLoop.shared.unsafeEnqueue(job)
}
- swift_task_enqueueMainExecutor_hook = unsafeBitCast(swift_task_enqueueMainExecutor_hook_impl, to: UnsafeMutableRawPointer?.self)
+ swift_task_enqueueMainExecutor_hook = unsafeBitCast(
+ swift_task_enqueueMainExecutor_hook_impl,
+ to: UnsafeMutableRawPointer?.self
+ )
didInstallGlobalExecutor = true
}
private func enqueue(_ job: UnownedJob, withDelay nanoseconds: UInt64) {
let milliseconds = nanoseconds / 1_000_000
- setTimeout(Double(milliseconds), {
- #if compiler(>=5.9)
- job.runSynchronously(on: self.asUnownedSerialExecutor())
- #else
- job._runSynchronously(on: self.asUnownedSerialExecutor())
- #endif
- })
+ setTimeout(
+ Double(milliseconds),
+ {
+ #if compiler(>=5.9)
+ job.runSynchronously(on: self.asUnownedSerialExecutor())
+ #else
+ job._runSynchronously(on: self.asUnownedSerialExecutor())
+ #endif
+ }
+ )
}
private func unsafeEnqueue(_ job: UnownedJob) {
@@ -192,15 +231,19 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
/// Taken from https://github.com/apple/swift/blob/d375c972f12128ec6055ed5f5337bfcae3ec67d8/stdlib/public/Concurrency/Clock.swift#L84-L88
@_silgen_name("swift_get_time")
internal func swift_get_time(
- _ seconds: UnsafeMutablePointer,
- _ nanoseconds: UnsafeMutablePointer,
- _ clock: CInt)
+ _ seconds: UnsafeMutablePointer,
+ _ nanoseconds: UnsafeMutablePointer,
+ _ clock: CInt
+)
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
extension JavaScriptEventLoop {
fileprivate func enqueue(
- _ job: UnownedJob, withDelay seconds: Int64, _ nanoseconds: Int64,
- _ toleranceSec: Int64, _ toleranceNSec: Int64,
+ _ job: UnownedJob,
+ withDelay seconds: Int64,
+ _ nanoseconds: Int64,
+ _ toleranceSec: Int64,
+ _ toleranceNSec: Int64,
_ clock: Int32
) {
var nowSec: Int64 = 0
@@ -213,9 +256,9 @@ extension JavaScriptEventLoop {
#endif
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
-public extension JSPromise {
+extension JSPromise {
/// Wait for the promise to complete, returning (or throwing) its result.
- var value: JSValue {
+ public var value: JSValue {
get async throws {
try await withUnsafeThrowingContinuation { [self] continuation in
self.then(
@@ -235,7 +278,7 @@ public extension JSPromise {
/// Wait for the promise to complete, returning its result or exception as a Result.
///
/// - Note: Calling this function does not switch from the caller's isolation domain.
- func value(isolation: isolated (any Actor)? = #isolation) async throws -> JSValue {
+ public func value(isolation: isolated (any Actor)? = #isolation) async throws -> JSValue {
try await withUnsafeThrowingContinuation(isolation: isolation) { [self] continuation in
self.then(
success: {
@@ -251,7 +294,7 @@ public extension JSPromise {
}
/// Wait for the promise to complete, returning its result or exception as a Result.
- var result: JSPromise.Result {
+ public var result: JSPromise.Result {
get async {
await withUnsafeContinuation { [self] continuation in
self.then(
diff --git a/Sources/JavaScriptEventLoop/JobQueue.swift b/Sources/JavaScriptEventLoop/JobQueue.swift
index 5ad71f0a0..cb583dae3 100644
--- a/Sources/JavaScriptEventLoop/JobQueue.swift
+++ b/Sources/JavaScriptEventLoop/JobQueue.swift
@@ -63,18 +63,18 @@ extension JavaScriptEventLoop {
}
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
-fileprivate extension UnownedJob {
+extension UnownedJob {
private func asImpl() -> UnsafeMutablePointer<_CJavaScriptEventLoop.Job> {
unsafeBitCast(self, to: UnsafeMutablePointer<_CJavaScriptEventLoop.Job>.self)
}
- var flags: JobFlags {
+ fileprivate var flags: JobFlags {
JobFlags(bits: asImpl().pointee.Flags)
}
- var rawPriority: UInt32 { flags.priority }
+ fileprivate var rawPriority: UInt32 { flags.priority }
- func nextInQueue() -> UnsafeMutablePointer {
+ fileprivate func nextInQueue() -> UnsafeMutablePointer {
return withUnsafeMutablePointer(to: &asImpl().pointee.SchedulerPrivate.0) { rawNextJobPtr in
let nextJobPtr = UnsafeMutableRawPointer(rawNextJobPtr).bindMemory(to: UnownedJob?.self, capacity: 1)
return nextJobPtr
@@ -83,13 +83,11 @@ fileprivate extension UnownedJob {
}
-fileprivate struct JobFlags {
- var bits: UInt32 = 0
+private struct JobFlags {
+ var bits: UInt32 = 0
- var priority: UInt32 {
- get {
- (bits & 0xFF00) >> 8
+ var priority: UInt32 {
+ (bits & 0xFF00) >> 8
}
- }
}
#endif
diff --git a/Sources/JavaScriptEventLoop/WebWorkerDedicatedExecutor.swift b/Sources/JavaScriptEventLoop/WebWorkerDedicatedExecutor.swift
index 695eb9c61..eecaf93c5 100644
--- a/Sources/JavaScriptEventLoop/WebWorkerDedicatedExecutor.swift
+++ b/Sources/JavaScriptEventLoop/WebWorkerDedicatedExecutor.swift
@@ -2,11 +2,11 @@ import JavaScriptKit
import _CJavaScriptEventLoop
#if canImport(Synchronization)
- import Synchronization
+import Synchronization
#endif
#if canImport(wasi_pthread)
- import wasi_pthread
- import WASILibc
+import wasi_pthread
+import WASILibc
#endif
/// A serial executor that runs on a dedicated web worker thread.
@@ -42,7 +42,9 @@ public final class WebWorkerDedicatedExecutor: SerialExecutor {
/// - Throws: An error if any worker thread fails to initialize within the timeout period.
public init(timeout: Duration = .seconds(3), checkInterval: Duration = .microseconds(5)) async throws {
let underlying = try await WebWorkerTaskExecutor(
- numberOfThreads: 1, timeout: timeout, checkInterval: checkInterval
+ numberOfThreads: 1,
+ timeout: timeout,
+ checkInterval: checkInterval
)
self.underlying = underlying
}
diff --git a/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift b/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift
index 7373b9604..f47cb1b9c 100644
--- a/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift
+++ b/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift
@@ -1,15 +1,15 @@
-#if compiler(>=6.0) // `TaskExecutor` is available since Swift 6.0
+#if compiler(>=6.0) // `TaskExecutor` is available since Swift 6.0
import JavaScriptKit
import _CJavaScriptKit
import _CJavaScriptEventLoop
#if canImport(Synchronization)
- import Synchronization
+import Synchronization
#endif
#if canImport(wasi_pthread)
- import wasi_pthread
- import WASILibc
+import wasi_pthread
+import WASILibc
#endif
// MARK: - Web Worker Task Executor
@@ -23,13 +23,13 @@ import _CJavaScriptEventLoop
///
/// ## Multithreading Model
///
-/// Each task submitted to the executor runs on one of the available worker threads. By default,
+/// Each task submitted to the executor runs on one of the available worker threads. By default,
/// child tasks created within a worker thread continue to run on the same worker thread,
/// maintaining thread locality and avoiding excessive context switching.
///
/// ## Object Sharing Between Threads
///
-/// When working with JavaScript objects across threads, you must use the `JSSending` API to
+/// When working with JavaScript objects across threads, you must use the `JSSending` API to
/// explicitly transfer or clone objects:
///
/// ```swift
@@ -80,7 +80,7 @@ import _CJavaScriptEventLoop
/// return fibonacci(i)
/// }
/// }
-///
+///
/// for await result in group {
/// // Process results as they complete
/// }
@@ -106,8 +106,8 @@ import _CJavaScriptEventLoop
/// // Back to the main thread.
/// }
/// ````
-///
-@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) // For `Atomic` and `TaskExecutor` types
+///
+@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) // For `Atomic` and `TaskExecutor` types
public final class WebWorkerTaskExecutor: TaskExecutor {
/// A job worker dedicated to a single Web Worker thread.
@@ -199,10 +199,12 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
// like `setTimeout` or `addEventListener`.
// We can run the job and subsequently spawned jobs immediately.
// JSPromise.resolve(JSValue.undefined).then { _ in
- _ = JSObject.global.queueMicrotask!(JSOneshotClosure { _ in
- self.run()
- return JSValue.undefined
- })
+ _ = JSObject.global.queueMicrotask!(
+ JSOneshotClosure { _ in
+ self.run()
+ return JSValue.undefined
+ }
+ )
} else {
let tid = self.tid.load(ordering: .sequentiallyConsistent)
swjs_wake_up_worker_thread(tid)
@@ -220,10 +222,12 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
}
func scheduleNextRun() {
- _ = JSObject.global.queueMicrotask!(JSOneshotClosure { _ in
- self.run()
- return JSValue.undefined
- })
+ _ = JSObject.global.queueMicrotask!(
+ JSOneshotClosure { _ in
+ self.run()
+ return JSValue.undefined
+ }
+ )
}
/// Run the worker
@@ -277,18 +281,22 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
return job
}
// No more jobs to run now. Wait for a new job to be enqueued.
- let (exchanged, original) = state.compareExchange(expected: .running, desired: .idle, ordering: .sequentiallyConsistent)
+ let (exchanged, original) = state.compareExchange(
+ expected: .running,
+ desired: .idle,
+ ordering: .sequentiallyConsistent
+ )
switch (exchanged, original) {
case (true, _):
trace("Worker.run exited \(original) -> idle")
- return nil // Regular case
+ return nil // Regular case
case (false, .idle):
preconditionFailure("unreachable: Worker/run running in multiple threads!?")
case (false, .running):
preconditionFailure("unreachable: running -> idle should return exchanged=true")
case (false, .terminated):
- return nil // The worker is terminated, exit the loop.
+ return nil // The worker is terminated, exit the loop.
}
}
guard let job else { return }
@@ -347,16 +355,21 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
// immediately. The context must be retained until the thread is started.
let context = Context(executor: self, worker: worker)
let ptr = Unmanaged.passRetained(context).toOpaque()
- let ret = pthread_create(nil, nil, { ptr in
- // Cast to a optional pointer to absorb nullability variations between platforms.
- let ptr: UnsafeMutableRawPointer? = ptr
- let context = Unmanaged.fromOpaque(ptr!).takeRetainedValue()
- context.worker.start(executor: context.executor)
- // The worker is started. Throw JS exception to unwind the call stack without
- // reaching the `pthread_exit`, which is called immediately after this block.
- swjs_unsafe_event_loop_yield()
- return nil
- }, ptr)
+ let ret = pthread_create(
+ nil,
+ nil,
+ { ptr in
+ // Cast to a optional pointer to absorb nullability variations between platforms.
+ let ptr: UnsafeMutableRawPointer? = ptr
+ let context = Unmanaged.fromOpaque(ptr!).takeRetainedValue()
+ context.worker.start(executor: context.executor)
+ // The worker is started. Throw JS exception to unwind the call stack without
+ // reaching the `pthread_exit`, which is called immediately after this block.
+ swjs_unsafe_event_loop_yield()
+ return nil
+ },
+ ptr
+ )
precondition(ret == 0, "Failed to create a thread")
}
// Wait until all worker threads are started and wire up messaging channels
@@ -432,15 +445,19 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
/// - timeout: The maximum time to wait for all worker threads to be started. Default is 3 seconds.
/// - checkInterval: The interval to check if all worker threads are started. Default is 5 microseconds.
/// - Throws: An error if any worker thread fails to initialize within the timeout period.
- public init(numberOfThreads: Int, timeout: Duration = .seconds(3), checkInterval: Duration = .microseconds(5)) async throws {
+ public init(
+ numberOfThreads: Int,
+ timeout: Duration = .seconds(3),
+ checkInterval: Duration = .microseconds(5)
+ ) async throws {
self.executor = Executor(numberOfThreads: numberOfThreads)
try await self.executor.start(timeout: timeout, checkInterval: checkInterval)
}
/// Terminates all worker threads managed by this executor.
///
- /// This method should be called when the executor is no longer needed to free up
- /// resources. After calling this method, any tasks enqueued to this executor will
+ /// This method should be called when the executor is no longer needed to free up
+ /// resources. After calling this method, any tasks enqueued to this executor will
/// be ignored and may never complete.
///
/// It's recommended to use a `defer` statement immediately after creating the executor
@@ -533,7 +550,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
/// Installs a global executor that forwards jobs from Web Worker threads to the main thread.
///
/// This method sets up the necessary hooks to ensure proper task scheduling between
- /// the main thread and worker threads. It must be called once (typically at application
+ /// the main thread and worker threads. It must be called once (typically at application
/// startup) before using any `WebWorkerTaskExecutor` instances.
///
/// ## Example
@@ -564,14 +581,18 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
_swift_task_enqueueGlobal_hook_original = swift_task_enqueueGlobal_hook
- typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original) -> Void
+ typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original)
+ -> Void
let swift_task_enqueueGlobal_hook_impl: swift_task_enqueueGlobal_hook_Fn = { job, base in
WebWorkerTaskExecutor.traceStatsIncrement(\.enqueueGlobal)
// Enter this block only if the current Task has no executor preference.
if pthread_equal(pthread_self(), WebWorkerTaskExecutor._mainThread) != 0 {
// If the current thread is the main thread, delegate the job
// execution to the original hook of JavaScriptEventLoop.
- let original = unsafeBitCast(WebWorkerTaskExecutor._swift_task_enqueueGlobal_hook_original, to: swift_task_enqueueGlobal_hook_Fn.self)
+ let original = unsafeBitCast(
+ WebWorkerTaskExecutor._swift_task_enqueueGlobal_hook_original,
+ to: swift_task_enqueueGlobal_hook_Fn.self
+ )
original(job, base)
} else {
// Notify the main thread to execute the job when a job is
@@ -583,7 +604,10 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
swjs_send_job_to_main_thread(jobBitPattern)
}
}
- swift_task_enqueueGlobal_hook = unsafeBitCast(swift_task_enqueueGlobal_hook_impl, to: UnsafeMutableRawPointer?.self)
+ swift_task_enqueueGlobal_hook = unsafeBitCast(
+ swift_task_enqueueGlobal_hook_impl,
+ to: UnsafeMutableRawPointer?.self
+ )
#else
fatalError("Unsupported platform")
#endif
@@ -593,7 +617,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor {
/// Enqueue a job scheduled from a Web Worker thread to the main thread.
/// This function is called when a job is enqueued from a Web Worker thread.
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
-#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+
+#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+
@_expose(wasm, "swjs_enqueue_main_job_from_worker")
#endif
func _swjs_enqueue_main_job_from_worker(_ job: UnownedJob) {
@@ -604,17 +628,17 @@ func _swjs_enqueue_main_job_from_worker(_ job: UnownedJob) {
/// Wake up the worker thread.
/// This function is called when a job is enqueued from the main thread to a worker thread.
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
-#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+
+#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+
@_expose(wasm, "swjs_wake_worker_thread")
#endif
func _swjs_wake_worker_thread() {
WebWorkerTaskExecutor.Worker.currentThread!.run()
}
-fileprivate func trace(_ message: String) {
-#if JAVASCRIPTKIT_TRACE
+private func trace(_ message: String) {
+ #if JAVASCRIPTKIT_TRACE
JSObject.global.process.stdout.write("[trace tid=\(swjs_get_worker_thread_id())] \(message)\n")
-#endif
+ #endif
}
-#endif // compiler(>=6.0)
+#endif // compiler(>=6.0)
diff --git a/Sources/JavaScriptKit/BasicObjects/JSArray.swift b/Sources/JavaScriptKit/BasicObjects/JSArray.swift
index 56345d085..fad602465 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSArray.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSArray.swift
@@ -98,8 +98,8 @@ private func getObjectValuesLength(_ object: JSObject) -> Int {
return Int(values.length.number!)
}
-public extension JSValue {
- var array: JSArray? {
+extension JSValue {
+ public var array: JSArray? {
object.flatMap(JSArray.init)
}
}
diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift
index c8a6623a1..9157796bc 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift
@@ -1,11 +1,10 @@
-/** A wrapper around the [JavaScript `Date`
- class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) that
- exposes its properties in a type-safe way. This doesn't 100% match the JS API, for example
- `getMonth`/`setMonth` etc accessor methods are converted to properties, but the rest of it matches
- in the naming. Parts of the JavaScript `Date` API that are not consistent across browsers and JS
- implementations are not exposed in a type-safe manner, you should access the underlying `jsObject`
- property if you need those.
- */
+/// A wrapper around the [JavaScript `Date`
+/// class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) that
+/// exposes its properties in a type-safe way. This doesn't 100% match the JS API, for example
+/// `getMonth`/`setMonth` etc accessor methods are converted to properties, but the rest of it matches
+/// in the naming. Parts of the JavaScript `Date` API that are not consistent across browsers and JS
+/// implementations are not exposed in a type-safe manner, you should access the underlying `jsObject`
+/// property if you need those.
public final class JSDate: JSBridgedClass {
/// The constructor function used to create new `Date` objects.
public static var constructor: JSFunction? { _constructor.wrappedValue }
diff --git a/Sources/JavaScriptKit/BasicObjects/JSError.swift b/Sources/JavaScriptKit/BasicObjects/JSError.swift
index 0f87d3c67..38accb97b 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSError.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSError.swift
@@ -1,7 +1,6 @@
-/** A wrapper around [the JavaScript `Error`
- class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) that
- exposes its properties in a type-safe way.
- */
+/// A wrapper around [the JavaScript `Error`
+/// class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) that
+/// exposes its properties in a type-safe way.
public final class JSError: JSBridgedClass {
/// The constructor function used to create new JavaScript `Error` objects.
public static var constructor: JSFunction? { _constructor.wrappedValue }
diff --git a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift
index cfe32d515..7502bb5f1 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSPromise.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSPromise.swift
@@ -27,7 +27,7 @@ public final class JSPromise: JSBridgedClass {
/// is not an object and is not an instance of JavaScript `Promise`, this function will
/// return `nil`.
public static func construct(from value: JSValue) -> Self? {
- guard case let .object(jsObject) = value else { return nil }
+ guard case .object(let jsObject) = value else { return nil }
return Self(jsObject)
}
@@ -55,9 +55,9 @@ public final class JSPromise: JSBridgedClass {
resolver {
switch $0 {
- case let .success(success):
+ case .success(let success):
resolve(success)
- case let .failure(error):
+ case .failure(let error):
reject(error)
}
}
@@ -66,7 +66,7 @@ public final class JSPromise: JSBridgedClass {
self.init(unsafelyWrapping: Self.constructor!.new(closure))
}
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
public static func resolve(_ value: ConvertibleToJSValue) -> JSPromise {
self.init(unsafelyWrapping: Self.constructor!.resolve!(value).object!)
}
@@ -74,7 +74,7 @@ public final class JSPromise: JSBridgedClass {
public static func reject(_ reason: ConvertibleToJSValue) -> JSPromise {
self.init(unsafelyWrapping: Self.constructor!.reject!(reason).object!)
}
-#else
+ #else
public static func resolve(_ value: some ConvertibleToJSValue) -> JSPromise {
self.init(unsafelyWrapping: constructor!.resolve!(value).object!)
}
@@ -82,9 +82,9 @@ public final class JSPromise: JSBridgedClass {
public static func reject(_ reason: some ConvertibleToJSValue) -> JSPromise {
self.init(unsafelyWrapping: constructor!.reject!(reason).object!)
}
-#endif
+ #endif
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
/// Schedules the `success` closure to be invoked on successful completion of `self`.
@discardableResult
public func then(success: @escaping (JSValue) -> ConvertibleToJSValue) -> JSPromise {
@@ -95,15 +95,15 @@ public final class JSPromise: JSBridgedClass {
}
#if compiler(>=5.5)
- /// Schedules the `success` closure to be invoked on successful completion of `self`.
- @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
- @discardableResult
- public func then(success: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue) -> JSPromise {
- let closure = JSOneshotClosure.async {
- try await success($0[0]).jsValue
- }
- return JSPromise(unsafelyWrapping: jsObject.then!(closure).object!)
+ /// Schedules the `success` closure to be invoked on successful completion of `self`.
+ @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
+ @discardableResult
+ public func then(success: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue) -> JSPromise {
+ let closure = JSOneshotClosure.async {
+ try await success($0[0]).jsValue
}
+ return JSPromise(unsafelyWrapping: jsObject.then!(closure).object!)
+ }
#endif
/// Schedules the `success` closure to be invoked on successful completion of `self`.
@@ -122,20 +122,21 @@ public final class JSPromise: JSBridgedClass {
}
#if compiler(>=5.5)
- /// Schedules the `success` closure to be invoked on successful completion of `self`.
- @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
- @discardableResult
- public func then(success: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue,
- failure: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue) -> JSPromise
- {
- let successClosure = JSOneshotClosure.async {
- try await success($0[0]).jsValue
- }
- let failureClosure = JSOneshotClosure.async {
- try await failure($0[0]).jsValue
- }
- return JSPromise(unsafelyWrapping: jsObject.then!(successClosure, failureClosure).object!)
+ /// Schedules the `success` closure to be invoked on successful completion of `self`.
+ @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
+ @discardableResult
+ public func then(
+ success: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue,
+ failure: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue
+ ) -> JSPromise {
+ let successClosure = JSOneshotClosure.async {
+ try await success($0[0]).jsValue
+ }
+ let failureClosure = JSOneshotClosure.async {
+ try await failure($0[0]).jsValue
}
+ return JSPromise(unsafelyWrapping: jsObject.then!(successClosure, failureClosure).object!)
+ }
#endif
/// Schedules the `failure` closure to be invoked on rejected completion of `self`.
@@ -148,15 +149,16 @@ public final class JSPromise: JSBridgedClass {
}
#if compiler(>=5.5)
- /// Schedules the `failure` closure to be invoked on rejected completion of `self`.
- @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
- @discardableResult
- public func `catch`(failure: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue) -> JSPromise {
- let closure = JSOneshotClosure.async {
- try await failure($0[0]).jsValue
- }
- return .init(unsafelyWrapping: jsObject.catch!(closure).object!)
+ /// Schedules the `failure` closure to be invoked on rejected completion of `self`.
+ @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
+ @discardableResult
+ public func `catch`(failure: sending @escaping (sending JSValue) async throws -> ConvertibleToJSValue) -> JSPromise
+ {
+ let closure = JSOneshotClosure.async {
+ try await failure($0[0]).jsValue
}
+ return .init(unsafelyWrapping: jsObject.catch!(closure).object!)
+ }
#endif
/// Schedules the `failure` closure to be invoked on either successful or rejected
@@ -169,5 +171,5 @@ public final class JSPromise: JSBridgedClass {
}
return .init(unsafelyWrapping: jsObject.finally!(closure).object!)
}
-#endif
+ #endif
}
diff --git a/Sources/JavaScriptKit/BasicObjects/JSTimer.swift b/Sources/JavaScriptKit/BasicObjects/JSTimer.swift
index 231792a84..3655a185c 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSTimer.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSTimer.swift
@@ -1,15 +1,14 @@
-/** This timer is an abstraction over [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval)
-/ [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval) and
-[`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
-/ [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
-JavaScript functions. It intentionally doesn't match the JavaScript API, as a special care is
-needed to hold a reference to the timer closure and to call `JSClosure.release()` on it when the
-timer is deallocated. As a user, you have to hold a reference to a `JSTimer` instance for it to stay
-valid. The `JSTimer` API is also intentionally trivial, the timer is started right away, and the
-only way to invalidate the timer is to bring the reference count of the `JSTimer` instance to zero.
-For invalidation you should either store the timer in an optional property and assign `nil` to it,
-or deallocate the object that owns the timer.
-*/
+/// This timer is an abstraction over [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval)
+/// / [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval) and
+/// [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
+/// / [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
+/// JavaScript functions. It intentionally doesn't match the JavaScript API, as a special care is
+/// needed to hold a reference to the timer closure and to call `JSClosure.release()` on it when the
+/// timer is deallocated. As a user, you have to hold a reference to a `JSTimer` instance for it to stay
+/// valid. The `JSTimer` API is also intentionally trivial, the timer is started right away, and the
+/// only way to invalidate the timer is to bring the reference count of the `JSTimer` instance to zero.
+/// For invalidation you should either store the timer in an optional property and assign `nil` to it,
+/// or deallocate the object that owns the timer.
public final class JSTimer {
enum ClosureStorage {
case oneshot(JSOneshotClosure)
@@ -27,11 +26,11 @@ public final class JSTimer {
case .oneshot(let closure):
closure.release()
case .repeating(let closure):
-#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
+ #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
closure.release()
-#else
+ #else
break // no-op
-#endif
+ #endif
}
}
}
@@ -58,17 +57,21 @@ public final class JSTimer {
`millisecondsDelay` intervals indefinitely until the timer is deallocated.
- callback: the closure to be executed after a given `millisecondsDelay` interval.
*/
- public init(millisecondsDelay: Double, isRepeating: Bool = false, callback: @escaping () -> ()) {
+ public init(millisecondsDelay: Double, isRepeating: Bool = false, callback: @escaping () -> Void) {
if isRepeating {
- closure = .repeating(JSClosure { _ in
- callback()
- return .undefined
- })
+ closure = .repeating(
+ JSClosure { _ in
+ callback()
+ return .undefined
+ }
+ )
} else {
- closure = .oneshot(JSOneshotClosure { _ in
- callback()
- return .undefined
- })
+ closure = .oneshot(
+ JSOneshotClosure { _ in
+ callback()
+ return .undefined
+ }
+ )
}
self.isRepeating = isRepeating
if isRepeating {
diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
index dec834bbd..19602a314 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
@@ -97,35 +97,35 @@ public class JSTypedArray: JSBridgedClass, ExpressibleByArrayLiteral wh
}
#if compiler(>=5.5)
- /// Calls the given async closure with a pointer to a copy of the underlying bytes of the
- /// array's storage.
- ///
- /// - Note: The pointer passed as an argument to `body` is valid only for the
- /// lifetime of the closure. Do not escape it from the async closure for later
- /// use.
- ///
- /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter
- /// that points to the contiguous storage for the array.
- /// If `body` has a return value, that value is also
- /// used as the return value for the `withUnsafeBytes(_:)` method. The
- /// argument is valid only for the duration of the closure's execution.
- /// - Returns: The return value, if any, of the `body`async closure parameter.
- @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
- public func withUnsafeBytesAsync(_ body: (UnsafeBufferPointer) async throws -> R) async rethrows -> R {
- let bytesLength = lengthInBytes
- let rawBuffer = UnsafeMutableBufferPointer.allocate(capacity: bytesLength)
- defer { rawBuffer.deallocate() }
- let baseAddress = rawBuffer.baseAddress!
- swjs_load_typed_array(jsObject.id, baseAddress)
- let length = bytesLength / MemoryLayout.size
- let rawBaseAddress = UnsafeRawPointer(baseAddress)
- let bufferPtr = UnsafeBufferPointer(
- start: rawBaseAddress.assumingMemoryBound(to: Element.self),
- count: length
- )
- let result = try await body(bufferPtr)
- return result
- }
+ /// Calls the given async closure with a pointer to a copy of the underlying bytes of the
+ /// array's storage.
+ ///
+ /// - Note: The pointer passed as an argument to `body` is valid only for the
+ /// lifetime of the closure. Do not escape it from the async closure for later
+ /// use.
+ ///
+ /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter
+ /// that points to the contiguous storage for the array.
+ /// If `body` has a return value, that value is also
+ /// used as the return value for the `withUnsafeBytes(_:)` method. The
+ /// argument is valid only for the duration of the closure's execution.
+ /// - Returns: The return value, if any, of the `body`async closure parameter.
+ @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
+ public func withUnsafeBytesAsync(_ body: (UnsafeBufferPointer) async throws -> R) async rethrows -> R {
+ let bytesLength = lengthInBytes
+ let rawBuffer = UnsafeMutableBufferPointer.allocate(capacity: bytesLength)
+ defer { rawBuffer.deallocate() }
+ let baseAddress = rawBuffer.baseAddress!
+ swjs_load_typed_array(jsObject.id, baseAddress)
+ let length = bytesLength / MemoryLayout.size
+ let rawBaseAddress = UnsafeRawPointer(baseAddress)
+ let bufferPtr = UnsafeBufferPointer(
+ start: rawBaseAddress.assumingMemoryBound(to: Element.self),
+ count: length
+ )
+ let result = try await body(bufferPtr)
+ return result
+ }
#endif
}
@@ -138,7 +138,9 @@ func valueForBitWidth(typeName: String, bitWidth: Int, when32: T) -> T {
} else if bitWidth == 64 {
fatalError("64-bit \(typeName)s are not yet supported in JSTypedArray")
} else {
- fatalError("Unsupported bit width for type \(typeName): \(bitWidth) (hint: stick to fixed-size \(typeName)s to avoid this issue)")
+ fatalError(
+ "Unsupported bit width for type \(typeName): \(bitWidth) (hint: stick to fixed-size \(typeName)s to avoid this issue)"
+ )
}
}
diff --git a/Sources/JavaScriptKit/ConstructibleFromJSValue.swift b/Sources/JavaScriptKit/ConstructibleFromJSValue.swift
index f0e0ad431..d4a5921cd 100644
--- a/Sources/JavaScriptKit/ConstructibleFromJSValue.swift
+++ b/Sources/JavaScriptKit/ConstructibleFromJSValue.swift
@@ -68,11 +68,11 @@ extension SignedInteger where Self: ConstructibleFromJSValue {
if let number = value.number {
return Self(exactly: number.rounded(.towardZero))
}
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
if let bigInt = value.bigInt as? JSBigIntExtended {
return Self(exactly: bigInt)
}
-#endif
+ #endif
return nil
}
}
@@ -116,11 +116,11 @@ extension UnsignedInteger where Self: ConstructibleFromJSValue {
if let number = value.number {
return Self(exactly: number.rounded(.towardZero))
}
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
if let bigInt = value.bigInt as? JSBigIntExtended {
return Self(exactly: bigInt)
}
-#endif
+ #endif
return nil
}
}
diff --git a/Sources/JavaScriptKit/ConvertibleToJSValue.swift b/Sources/JavaScriptKit/ConvertibleToJSValue.swift
index a7f7da8b6..805ee74d5 100644
--- a/Sources/JavaScriptKit/ConvertibleToJSValue.swift
+++ b/Sources/JavaScriptKit/ConvertibleToJSValue.swift
@@ -63,7 +63,6 @@ extension UInt32: ConvertibleToJSValue {
public var jsValue: JSValue { .number(Double(self)) }
}
-
extension Int8: ConvertibleToJSValue {
public var jsValue: JSValue { .number(Double(self)) }
}
@@ -147,7 +146,7 @@ extension Optional: ConvertibleToJSValue where Wrapped: ConvertibleToJSValue {
public var jsValue: JSValue {
switch self {
case .none: return .null
- case let .some(wrapped): return wrapped.jsValue
+ case .some(let wrapped): return wrapped.jsValue
}
}
}
@@ -185,7 +184,7 @@ extension Array: ConstructibleFromJSValue where Element: ConstructibleFromJSValu
var array = [Element]()
array.reserveCapacity(count)
- for i in 0 ..< count {
+ for i in 0.. T
+ _ values: Self,
+ _ index: Int,
+ _ results: inout [RawJSValue],
+ _ body: ([RawJSValue]) -> T
) -> T {
if index == values.count { return body(results) }
return values[index].jsValue.withRawJSValue { (rawValue) -> T in
@@ -285,8 +286,10 @@ extension Array where Element == ConvertibleToJSValue {
guard self.count != 0 else { return body([]) }
func _withRawJSValues(
- _ values: [ConvertibleToJSValue], _ index: Int,
- _ results: inout [RawJSValue], _ body: ([RawJSValue]) -> T
+ _ values: [ConvertibleToJSValue],
+ _ index: Int,
+ _ results: inout [RawJSValue],
+ _ body: ([RawJSValue]) -> T
) -> T {
if index == values.count { return body(results) }
return values[index].jsValue.withRawJSValue { (rawValue) -> T in
diff --git a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift
index 156ac0540..a528e65b1 100644
--- a/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift
+++ b/Sources/JavaScriptKit/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-2-1-main-swift.swift
@@ -3,4 +3,4 @@ import JavaScriptKit
let document = JSObject.global.document
var div = document.createElement("div")
div.innerText = "Hello from Swift!"
-document.body.appendChild(div)
+document.body.appendChild(div)
diff --git a/Sources/JavaScriptKit/Features.swift b/Sources/JavaScriptKit/Features.swift
index db6e00f26..313edab40 100644
--- a/Sources/JavaScriptKit/Features.swift
+++ b/Sources/JavaScriptKit/Features.swift
@@ -5,9 +5,9 @@ enum LibraryFeatures {
@_cdecl("_library_features")
func _library_features() -> Int32 {
var features: Int32 = 0
-#if !JAVASCRIPTKIT_WITHOUT_WEAKREFS
+ #if !JAVASCRIPTKIT_WITHOUT_WEAKREFS
features |= LibraryFeatures.weakRefs
-#endif
+ #endif
return features
}
@@ -15,4 +15,4 @@ func _library_features() -> Int32 {
// cdecls currently don't work in embedded, and expose for wasm only works >=6.0
@_expose(wasm, "swjs_library_features")
public func _swjs_library_features() -> Int32 { _library_features() }
-#endif
\ No newline at end of file
+#endif
diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift b/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift
index a8867f95c..3f0c2632b 100644
--- a/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift
+++ b/Sources/JavaScriptKit/FundamentalObjects/JSBigInt.swift
@@ -10,18 +10,18 @@ public final class JSBigInt: JSObject {
override public init(id: JavaScriptObjectRef) {
super.init(id: id)
}
-
+
/// Instantiate a new `JSBigInt` with given Int64 value in a slow path
/// This doesn't require [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature.
public init(_slowBridge value: Int64) {
let value = UInt64(bitPattern: value)
- super.init(id: swjs_i64_to_bigint_slow(UInt32(value & 0xffffffff), UInt32(value >> 32), true))
+ super.init(id: swjs_i64_to_bigint_slow(UInt32(value & 0xffff_ffff), UInt32(value >> 32), true))
}
/// Instantiate a new `JSBigInt` with given UInt64 value in a slow path
/// This doesn't require [JS-BigInt-integration](https://github.com/WebAssembly/JS-BigInt-integration) feature.
public init(_slowBridge value: UInt64) {
- super.init(id: swjs_i64_to_bigint_slow(UInt32(value & 0xffffffff), UInt32(value >> 32), false))
+ super.init(id: swjs_i64_to_bigint_slow(UInt32(value & 0xffff_ffff), UInt32(value >> 32), false))
}
override public var jsValue: JSValue {
diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift
index 828cb40f2..66ce009bf 100644
--- a/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift
+++ b/Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift
@@ -26,15 +26,19 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol {
}
// 3. Retain the given body in static storage by `funcRef`.
- JSClosure.sharedClosures.wrappedValue[hostFuncRef] = (self, {
- defer { self.release() }
- return body($0)
- })
+ JSClosure.sharedClosures.wrappedValue[hostFuncRef] = (
+ self,
+ {
+ defer { self.release() }
+ return body($0)
+ }
+ )
}
#if compiler(>=5.5) && !hasFeature(Embedded)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
- public static func async(_ body: sending @escaping (sending [JSValue]) async throws -> JSValue) -> JSOneshotClosure {
+ public static func async(_ body: sending @escaping (sending [JSValue]) async throws -> JSValue) -> JSOneshotClosure
+ {
JSOneshotClosure(makeAsyncClosure(body))
}
#endif
@@ -90,9 +94,14 @@ public class JSClosure: JSFunction, JSClosureProtocol {
private var isReleased: Bool = false
#endif
- @available(*, deprecated, message: "This initializer will be removed in the next minor version update. Please use `init(_ body: @escaping ([JSValue]) -> JSValue)` and add `return .undefined` to the end of your closure")
+ @available(
+ *,
+ deprecated,
+ message:
+ "This initializer will be removed in the next minor version update. Please use `init(_ body: @escaping ([JSValue]) -> JSValue)` and add `return .undefined` to the end of your closure"
+ )
@_disfavoredOverload
- public convenience init(_ body: @escaping ([JSValue]) -> ()) {
+ public convenience init(_ body: @escaping ([JSValue]) -> Void) {
self.init({
body($0)
return .undefined
@@ -200,7 +209,8 @@ private func makeAsyncClosure(
@_cdecl("_call_host_function_impl")
func _call_host_function_impl(
_ hostFuncRef: JavaScriptHostFuncRef,
- _ argv: UnsafePointer, _ argc: Int32,
+ _ argv: UnsafePointer,
+ _ argc: Int32,
_ callbackFuncRef: JavaScriptObjectRef
) -> Bool {
guard let (_, hostFunc) = JSClosure.sharedClosures.wrappedValue[hostFuncRef] else {
@@ -216,7 +226,6 @@ func _call_host_function_impl(
return false
}
-
/// [WeakRefs](https://github.com/tc39/proposal-weakrefs) are already Stage 4,
/// but was added recently enough that older browser versions don’t support it.
/// Build with `-Xswiftc -DJAVASCRIPTKIT_WITHOUT_WEAKREFS` to disable the relevant behavior.
@@ -231,7 +240,6 @@ extension JSClosure {
}
}
-
@_cdecl("_free_host_function_impl")
func _free_host_function_impl(_ hostFuncRef: JavaScriptHostFuncRef) {}
@@ -254,11 +262,13 @@ func _free_host_function_impl(_ hostFuncRef: JavaScriptHostFuncRef) {
// cdecls currently don't work in embedded, and expose for wasm only works >=6.0
@_expose(wasm, "swjs_call_host_function")
public func _swjs_call_host_function(
- _ hostFuncRef: JavaScriptHostFuncRef,
- _ argv: UnsafePointer, _ argc: Int32,
- _ callbackFuncRef: JavaScriptObjectRef) -> Bool {
+ _ hostFuncRef: JavaScriptHostFuncRef,
+ _ argv: UnsafePointer,
+ _ argc: Int32,
+ _ callbackFuncRef: JavaScriptObjectRef
+) -> Bool {
- _call_host_function_impl(hostFuncRef, argv, argc, callbackFuncRef)
+ _call_host_function_impl(hostFuncRef, argv, argc, callbackFuncRef)
}
@_expose(wasm, "swjs_free_host_function")
diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift
index 498bbc3ea..172483612 100644
--- a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift
+++ b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift
@@ -11,7 +11,7 @@ import _CJavaScriptKit
/// ```
///
public class JSFunction: JSObject {
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
/// Call this function with given `arguments` and binding given `this` as context.
/// - Parameters:
/// - this: The value to be passed as the `this` parameter to this function.
@@ -84,7 +84,7 @@ public class JSFunction: JSObject {
public var `throws`: JSThrowingFunction {
JSThrowingFunction(self)
}
-#endif
+ #endif
@discardableResult
public func callAsFunction(arguments: [JSValue]) -> JSValue {
@@ -116,7 +116,7 @@ public class JSFunction: JSObject {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) }
}
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue]) -> RawJSValue {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0) }
}
@@ -124,7 +124,7 @@ public class JSFunction: JSObject {
final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue], this: JSObject) -> RawJSValue {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) }
}
-#endif
+ #endif
final private func invokeNonThrowingJSFunction(rawValues: [RawJSValue]) -> RawJSValue {
rawValues.withUnsafeBufferPointer { [id] bufferPointer in
@@ -133,8 +133,11 @@ public class JSFunction: JSObject {
var payload1 = JavaScriptPayload1()
var payload2 = JavaScriptPayload2()
let resultBitPattern = swjs_call_function_no_catch(
- id, argv, Int32(argc),
- &payload1, &payload2
+ id,
+ argv,
+ Int32(argc),
+ &payload1,
+ &payload2
)
let kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
assert(!kindAndFlags.isException)
@@ -149,9 +152,13 @@ public class JSFunction: JSObject {
let argc = bufferPointer.count
var payload1 = JavaScriptPayload1()
var payload2 = JavaScriptPayload2()
- let resultBitPattern = swjs_call_function_with_this_no_catch(this.id,
- id, argv, Int32(argc),
- &payload1, &payload2
+ let resultBitPattern = swjs_call_function_with_this_no_catch(
+ this.id,
+ id,
+ argv,
+ Int32(argc),
+ &payload1,
+ &payload2
)
let kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
#if !hasFeature(Embedded)
@@ -172,20 +179,20 @@ public class JSFunction: JSObject {
//
// Once Embedded Swift supports parameter packs/variadic generics, we can
// replace all variants with a single method each that takes a generic pack.
-public extension JSFunction {
+extension JSFunction {
@discardableResult
- func callAsFunction(this: JSObject) -> JSValue {
+ public func callAsFunction(this: JSObject) -> JSValue {
invokeNonThrowingJSFunction(arguments: [], this: this).jsValue
}
@discardableResult
- func callAsFunction(this: JSObject, _ arg0: some ConvertibleToJSValue) -> JSValue {
+ public func callAsFunction(this: JSObject, _ arg0: some ConvertibleToJSValue) -> JSValue {
invokeNonThrowingJSFunction(arguments: [arg0.jsValue], this: this).jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue
@@ -194,7 +201,7 @@ public extension JSFunction {
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
@@ -204,18 +211,19 @@ public extension JSFunction {
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
_ arg3: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue], this: this).jsValue
+ invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue], this: this)
+ .jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
@@ -223,11 +231,14 @@ public extension JSFunction {
_ arg3: some ConvertibleToJSValue,
_ arg4: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue], this: this).jsValue
+ invokeNonThrowingJSFunction(
+ arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue],
+ this: this
+ ).jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
@@ -236,11 +247,14 @@ public extension JSFunction {
_ arg4: some ConvertibleToJSValue,
_ arg5: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue], this: this).jsValue
+ invokeNonThrowingJSFunction(
+ arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue],
+ this: this
+ ).jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
@@ -250,26 +264,31 @@ public extension JSFunction {
_ arg5: some ConvertibleToJSValue,
_ arg6: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue], this: this).jsValue
+ invokeNonThrowingJSFunction(
+ arguments: [
+ arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue,
+ ],
+ this: this
+ ).jsValue
}
@discardableResult
- func callAsFunction(this: JSObject, arguments: [JSValue]) -> JSValue {
+ public func callAsFunction(this: JSObject, arguments: [JSValue]) -> JSValue {
invokeNonThrowingJSFunction(arguments: arguments, this: this).jsValue
}
@discardableResult
- func callAsFunction() -> JSValue {
+ public func callAsFunction() -> JSValue {
invokeNonThrowingJSFunction(arguments: []).jsValue
}
@discardableResult
- func callAsFunction(_ arg0: some ConvertibleToJSValue) -> JSValue {
+ public func callAsFunction(_ arg0: some ConvertibleToJSValue) -> JSValue {
invokeNonThrowingJSFunction(arguments: [arg0.jsValue]).jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue
) -> JSValue {
@@ -277,7 +296,7 @@ public extension JSFunction {
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue
@@ -286,7 +305,7 @@ public extension JSFunction {
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -296,18 +315,19 @@ public extension JSFunction {
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
_ arg3: some ConvertibleToJSValue,
_ arg4: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue]).jsValue
+ invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue])
+ .jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -315,11 +335,13 @@ public extension JSFunction {
_ arg4: some ConvertibleToJSValue,
_ arg5: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue]).jsValue
+ invokeNonThrowingJSFunction(arguments: [
+ arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue,
+ ]).jsValue
}
@discardableResult
- func callAsFunction(
+ public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -328,25 +350,27 @@ public extension JSFunction {
_ arg5: some ConvertibleToJSValue,
_ arg6: some ConvertibleToJSValue
) -> JSValue {
- invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue]).jsValue
+ invokeNonThrowingJSFunction(arguments: [
+ arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue,
+ ]).jsValue
}
- func new() -> JSObject {
+ public func new() -> JSObject {
new(arguments: [])
}
- func new(_ arg0: some ConvertibleToJSValue) -> JSObject {
+ public func new(_ arg0: some ConvertibleToJSValue) -> JSObject {
new(arguments: [arg0.jsValue])
}
- func new(
+ public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue
) -> JSObject {
new(arguments: [arg0.jsValue, arg1.jsValue])
}
- func new(
+ public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue
@@ -354,7 +378,7 @@ public extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue])
}
- func new(
+ public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -363,7 +387,7 @@ public extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue])
}
- func new(
+ public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -373,7 +397,7 @@ public extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue])
}
- func new(
+ public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -384,7 +408,7 @@ public extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue])
}
- func new(
+ public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
@@ -393,7 +417,9 @@ public extension JSFunction {
_ arg5: some ConvertibleToJSValue,
_ arg6: some ConvertibleToJSValue
) -> JSObject {
- new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue])
+ new(arguments: [
+ arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue,
+ ])
}
}
#endif
diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift
index 9006ec7b7..33a20f3b5 100644
--- a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift
+++ b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift
@@ -22,9 +22,9 @@ public class JSObject: Equatable {
@usableFromInline
internal var _id: JavaScriptObjectRef
-#if compiler(>=6.1) && _runtime(_multithreaded)
+ #if compiler(>=6.1) && _runtime(_multithreaded)
package let ownerTid: Int32
-#endif
+ #endif
@_spi(JSObject_id)
@inlinable
@@ -33,9 +33,9 @@ public class JSObject: Equatable {
@_spi(JSObject_id)
public init(id: JavaScriptObjectRef) {
self._id = id
-#if compiler(>=6.1) && _runtime(_multithreaded)
+ #if compiler(>=6.1) && _runtime(_multithreaded)
self.ownerTid = swjs_get_worker_thread_id_cached()
-#endif
+ #endif
}
/// Asserts that the object is being accessed from the owner thread.
@@ -47,18 +47,24 @@ public class JSObject: Equatable {
/// object spaces are not shared across threads backed by Web Workers.
private func assertOnOwnerThread(hint: @autoclosure () -> String) {
#if compiler(>=6.1) && _runtime(_multithreaded)
- precondition(ownerTid == swjs_get_worker_thread_id_cached(), "JSObject is being accessed from a thread other than the owner thread: \(hint())")
+ precondition(
+ ownerTid == swjs_get_worker_thread_id_cached(),
+ "JSObject is being accessed from a thread other than the owner thread: \(hint())"
+ )
#endif
}
/// Asserts that the two objects being compared are owned by the same thread.
private static func assertSameOwnerThread(lhs: JSObject, rhs: JSObject, hint: @autoclosure () -> String) {
#if compiler(>=6.1) && _runtime(_multithreaded)
- precondition(lhs.ownerTid == rhs.ownerTid, "JSObject is being accessed from a thread other than the owner thread: \(hint())")
+ precondition(
+ lhs.ownerTid == rhs.ownerTid,
+ "JSObject is being accessed from a thread other than the owner thread: \(hint())"
+ )
#endif
}
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
/// Returns the `name` member method binding this object as `this` context.
///
/// e.g.
@@ -101,7 +107,7 @@ public class JSObject: Equatable {
public subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue)? {
self[name]
}
-#endif
+ #endif
/// A convenience method of `subscript(_ name: String) -> JSValue`
/// to access the member through Dynamic Member Lookup.
@@ -166,7 +172,7 @@ public class JSObject: Equatable {
}
}
-#if !hasFeature(Embedded)
+ #if !hasFeature(Embedded)
/// A modifier to call methods as throwing methods capturing `this`
///
///
@@ -187,7 +193,7 @@ public class JSObject: Equatable {
public var throwing: JSThrowingObject {
JSThrowingObject(self)
}
-#endif
+ #endif
/// Return `true` if this value is an instance of the passed `constructor` function.
/// - Parameter constructor: The constructor function to check.
@@ -230,10 +236,11 @@ public class JSObject: Equatable {
public static func construct(from value: JSValue) -> Self? {
switch value {
case .boolean,
- .string,
- .number,
- .null,
- .undefined: return nil
+ .string,
+ .number,
+ .null,
+ .undefined:
+ return nil
case .object(let object):
return object as? Self
case .function(let function):
@@ -295,7 +302,6 @@ public class JSThrowingObject {
}
#endif
-
#if hasFeature(Embedded)
// Overloads of `JSObject.subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)?`
// for 0 through 7 arguments for Embedded Swift.
@@ -305,33 +311,33 @@ public class JSThrowingObject {
//
// NOTE: Once Embedded Swift supports parameter packs/variadic generics, we can
// replace all of these with a single method that takes a generic pack.
-public extension JSObject {
+extension JSObject {
@_disfavoredOverload
- subscript(dynamicMember name: String) -> (() -> JSValue)? {
- self[name].function.map { function in
+ public subscript(dynamicMember name: String) -> (() -> JSValue)? {
+ self[name].function.map { function in
{ function(this: self) }
}
}
@_disfavoredOverload
- subscript(dynamicMember name: String) -> ((A0) -> JSValue)? {
- self[name].function.map { function in
+ public subscript(dynamicMember name: String) -> ((A0) -> JSValue)? {
+ self[name].function.map { function in
{ function(this: self, $0) }
}
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue
>(dynamicMember name: String) -> ((A0, A1) -> JSValue)? {
- self[name].function.map { function in
+ self[name].function.map { function in
{ function(this: self, $0, $1) }
}
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue
@@ -342,7 +348,7 @@ public extension JSObject {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
@@ -354,7 +360,7 @@ public extension JSObject {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
@@ -367,7 +373,7 @@ public extension JSObject {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
@@ -381,7 +387,7 @@ public extension JSObject {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSString.swift b/Sources/JavaScriptKit/FundamentalObjects/JSString.swift
index 686d1ba11..cd88a5302 100644
--- a/Sources/JavaScriptKit/FundamentalObjects/JSString.swift
+++ b/Sources/JavaScriptKit/FundamentalObjects/JSString.swift
@@ -66,7 +66,7 @@ public struct JSString: LosslessStringConvertible, Equatable {
public init(_ stringValue: String) {
self.guts = Guts(from: stringValue)
}
-
+
/// A Swift representation of this `JSString`.
/// Note that this accessor may copy the JS string value into Swift side memory.
public var description: String { guts.buffer }
@@ -87,7 +87,6 @@ extension JSString: ExpressibleByStringLiteral {
}
}
-
// MARK: - Internal Helpers
extension JSString {
@@ -97,7 +96,9 @@ extension JSString {
func withRawJSValue(_ body: (RawJSValue) -> T) -> T {
let rawValue = RawJSValue(
- kind: .string, payload1: guts.jsRef, payload2: 0
+ kind: .string,
+ payload1: guts.jsRef,
+ payload2: 0
)
return body(rawValue)
}
diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift
index 17b61090f..aee17fd69 100644
--- a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift
+++ b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift
@@ -1,7 +1,6 @@
#if !hasFeature(Embedded)
import _CJavaScriptKit
-
/// A `JSFunction` wrapper that enables throwing function calls.
/// Exceptions produced by JavaScript functions will be thrown as `JSValue`.
public class JSThrowingFunction {
@@ -46,12 +45,20 @@ public class JSThrowingFunction {
var exceptionPayload1 = JavaScriptPayload1()
var exceptionPayload2 = JavaScriptPayload2()
let resultObj = swjs_call_throwing_new(
- self.base.id, argv, Int32(argc),
- &exceptionRawKind, &exceptionPayload1, &exceptionPayload2
+ self.base.id,
+ argv,
+ Int32(argc),
+ &exceptionRawKind,
+ &exceptionPayload1,
+ &exceptionPayload2
)
let exceptionKind = JavaScriptValueKindAndFlags(bitPattern: exceptionRawKind)
if exceptionKind.isException {
- let exception = RawJSValue(kind: exceptionKind.kind, payload1: exceptionPayload1, payload2: exceptionPayload2)
+ let exception = RawJSValue(
+ kind: exceptionKind.kind,
+ payload1: exceptionPayload1,
+ payload2: exceptionPayload2
+ )
return .failure(JSException(exception.jsValue))
}
return .success(JSObject(id: resultObj))
@@ -65,7 +72,11 @@ public class JSThrowingFunction {
}
}
-private func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) throws -> JSValue {
+private func invokeJSFunction(
+ _ jsFunc: JSFunction,
+ arguments: [ConvertibleToJSValue],
+ this: JSObject?
+) throws -> JSValue {
let id = jsFunc.id
let (result, isException) = arguments.withRawJSValues { rawValues in
rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in
@@ -76,14 +87,21 @@ private func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSV
var payload2 = JavaScriptPayload2()
if let thisId = this?.id {
let resultBitPattern = swjs_call_function_with_this(
- thisId, id, argv, Int32(argc),
- &payload1, &payload2
+ thisId,
+ id,
+ argv,
+ Int32(argc),
+ &payload1,
+ &payload2
)
kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
} else {
let resultBitPattern = swjs_call_function(
- id, argv, Int32(argc),
- &payload1, &payload2
+ id,
+ argv,
+ Int32(argc),
+ &payload1,
+ &payload2
)
kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
}
diff --git a/Sources/JavaScriptKit/JSBridgedType.swift b/Sources/JavaScriptKit/JSBridgedType.swift
index dcc0a3857..92739079e 100644
--- a/Sources/JavaScriptKit/JSBridgedType.swift
+++ b/Sources/JavaScriptKit/JSBridgedType.swift
@@ -5,12 +5,12 @@ public protocol JSBridgedType: JSValueCompatible, CustomStringConvertible {
init?(from value: JSValue)
}
-public extension JSBridgedType {
- static func construct(from value: JSValue) -> Self? {
+extension JSBridgedType {
+ public static func construct(from value: JSValue) -> Self? {
Self(from: value)
}
- var description: String { jsValue.description }
+ public var description: String { jsValue.description }
}
/// Conform to this protocol when your Swift class wraps a JavaScript class.
@@ -27,15 +27,15 @@ public protocol JSBridgedClass: JSBridgedType {
init(unsafelyWrapping jsObject: JSObject)
}
-public extension JSBridgedClass {
- var jsValue: JSValue { jsObject.jsValue }
+extension JSBridgedClass {
+ public var jsValue: JSValue { jsObject.jsValue }
- init?(from value: JSValue) {
+ public init?(from value: JSValue) {
guard let object = value.object else { return nil }
self.init(from: object)
}
- init?(from object: JSObject) {
+ public init?(from object: JSObject) {
guard let constructor = Self.constructor, object.isInstanceOf(constructor) else { return nil }
self.init(unsafelyWrapping: object)
}
diff --git a/Sources/JavaScriptKit/JSException.swift b/Sources/JavaScriptKit/JSException.swift
index 393ae9615..8783d808b 100644
--- a/Sources/JavaScriptKit/JSException.swift
+++ b/Sources/JavaScriptKit/JSException.swift
@@ -16,7 +16,7 @@ public struct JSException: Error, Equatable {
/// The value thrown from JavaScript.
/// This can be any JavaScript value (error object, string, number, etc.).
public var thrownValue: JSValue {
- return _thrownValue
+ return _thrownValue
}
/// The actual JavaScript value that was thrown.
diff --git a/Sources/JavaScriptKit/JSValue.swift b/Sources/JavaScriptKit/JSValue.swift
index 2562daac8..8c605530f 100644
--- a/Sources/JavaScriptKit/JSValue.swift
+++ b/Sources/JavaScriptKit/JSValue.swift
@@ -17,7 +17,7 @@ public enum JSValue: Equatable {
/// If not, returns `nil`.
public var boolean: Bool? {
switch self {
- case let .boolean(boolean): return boolean
+ case .boolean(let boolean): return boolean
default: return nil
}
}
@@ -37,7 +37,7 @@ public enum JSValue: Equatable {
///
public var jsString: JSString? {
switch self {
- case let .string(string): return string
+ case .string(let string): return string
default: return nil
}
}
@@ -46,7 +46,7 @@ public enum JSValue: Equatable {
/// If not, returns `nil`.
public var number: Double? {
switch self {
- case let .number(number): return number
+ case .number(let number): return number
default: return nil
}
}
@@ -55,7 +55,7 @@ public enum JSValue: Equatable {
/// If not, returns `nil`.
public var object: JSObject? {
switch self {
- case let .object(object): return object
+ case .object(let object): return object
default: return nil
}
}
@@ -64,7 +64,7 @@ public enum JSValue: Equatable {
/// If not, returns `nil`.
public var function: JSFunction? {
switch self {
- case let .function(function): return function
+ case .function(let function): return function
default: return nil
}
}
@@ -73,7 +73,7 @@ public enum JSValue: Equatable {
/// If not, returns `nil`.
public var symbol: JSSymbol? {
switch self {
- case let .symbol(symbol): return symbol
+ case .symbol(let symbol): return symbol
default: return nil
}
}
@@ -82,7 +82,7 @@ public enum JSValue: Equatable {
/// If not, returns `nil`.
public var bigInt: JSBigInt? {
switch self {
- case let .bigInt(bigInt): return bigInt
+ case .bigInt(let bigInt): return bigInt
default: return nil
}
}
@@ -107,38 +107,38 @@ public enum JSValue: Equatable {
@available(*, unavailable)
extension JSValue: Sendable {}
-public extension JSValue {
-#if !hasFeature(Embedded)
+extension JSValue {
+ #if !hasFeature(Embedded)
/// An unsafe convenience method of `JSObject.subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)?`
/// - Precondition: `self` must be a JavaScript Object and specified member should be a callable object.
- subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue) {
+ public subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue) {
object![dynamicMember: name]!
}
-#endif
+ #endif
/// An unsafe convenience method of `JSObject.subscript(_ index: Int) -> JSValue`
/// - Precondition: `self` must be a JavaScript Object.
- subscript(dynamicMember name: String) -> JSValue {
+ public subscript(dynamicMember name: String) -> JSValue {
get { self.object![name] }
set { self.object![name] = newValue }
}
/// An unsafe convenience method of `JSObject.subscript(_ index: Int) -> JSValue`
/// - Precondition: `self` must be a JavaScript Object.
- subscript(_ index: Int) -> JSValue {
+ public subscript(_ index: Int) -> JSValue {
get { object![index] }
set { object![index] = newValue }
}
}
-public extension JSValue {
- func fromJSValue() -> Type? where Type: ConstructibleFromJSValue {
+extension JSValue {
+ public func fromJSValue() -> Type? where Type: ConstructibleFromJSValue {
return Type.construct(from: self)
}
}
-public extension JSValue {
- static func string(_ value: String) -> JSValue {
+extension JSValue {
+ public static func string(_ value: String) -> JSValue {
.string(JSString(value))
}
@@ -167,12 +167,17 @@ public extension JSValue {
/// eventListener.release()
/// ```
@available(*, deprecated, message: "Please create JSClosure directly and manage its lifetime manually.")
- static func function(_ body: @escaping ([JSValue]) -> JSValue) -> JSValue {
+ public static func function(_ body: @escaping ([JSValue]) -> JSValue) -> JSValue {
.object(JSClosure(body))
}
- @available(*, deprecated, renamed: "object", message: "JSClosure is no longer a subclass of JSFunction. Use .object(closure) instead.")
- static func function(_ closure: JSClosure) -> JSValue {
+ @available(
+ *,
+ deprecated,
+ renamed: "object",
+ message: "JSClosure is no longer a subclass of JSFunction. Use .object(closure) instead."
+ )
+ public static func function(_ closure: JSClosure) -> JSValue {
.object(closure)
}
}
@@ -204,8 +209,10 @@ extension JSValue: ExpressibleByNilLiteral {
public func getJSValue(this: JSObject, name: JSString) -> JSValue {
var rawValue = RawJSValue()
let rawBitPattern = swjs_get_prop(
- this.id, name.asInternalJSRef(),
- &rawValue.payload1, &rawValue.payload2
+ this.id,
+ name.asInternalJSRef(),
+ &rawValue.payload1,
+ &rawValue.payload2
)
rawValue.kind = unsafeBitCast(rawBitPattern, to: JavaScriptValueKind.self)
return rawValue.jsValue
@@ -220,8 +227,10 @@ public func setJSValue(this: JSObject, name: JSString, value: JSValue) {
public func getJSValue(this: JSObject, index: Int32) -> JSValue {
var rawValue = RawJSValue()
let rawBitPattern = swjs_get_subscript(
- this.id, index,
- &rawValue.payload1, &rawValue.payload2
+ this.id,
+ index,
+ &rawValue.payload1,
+ &rawValue.payload2
)
rawValue.kind = unsafeBitCast(rawBitPattern, to: JavaScriptValueKind.self)
return rawValue.jsValue
@@ -229,17 +238,23 @@ public func getJSValue(this: JSObject, index: Int32) -> JSValue {
public func setJSValue(this: JSObject, index: Int32, value: JSValue) {
value.withRawJSValue { rawValue in
- swjs_set_subscript(this.id, index,
- rawValue.kind,
- rawValue.payload1, rawValue.payload2)
+ swjs_set_subscript(
+ this.id,
+ index,
+ rawValue.kind,
+ rawValue.payload1,
+ rawValue.payload2
+ )
}
}
public func getJSValue(this: JSObject, symbol: JSSymbol) -> JSValue {
var rawValue = RawJSValue()
let rawBitPattern = swjs_get_prop(
- this.id, symbol.id,
- &rawValue.payload1, &rawValue.payload2
+ this.id,
+ symbol.id,
+ &rawValue.payload1,
+ &rawValue.payload2
)
rawValue.kind = unsafeBitCast(rawBitPattern, to: JavaScriptValueKind.self)
return rawValue.jsValue
@@ -251,18 +266,18 @@ public func setJSValue(this: JSObject, symbol: JSSymbol, value: JSValue) {
}
}
-public extension JSValue {
+extension JSValue {
/// Return `true` if this value is an instance of the passed `constructor` function.
/// Returns `false` for everything except objects and functions.
/// - Parameter constructor: The constructor function to check.
/// - Returns: The result of `instanceof` in the JavaScript environment.
- func isInstanceOf(_ constructor: JSFunction) -> Bool {
+ public func isInstanceOf(_ constructor: JSFunction) -> Bool {
switch self {
case .boolean, .string, .number, .null, .undefined, .symbol, .bigInt:
return false
- case let .object(ref):
+ case .object(let ref):
return ref.isInstanceOf(constructor)
- case let .function(ref):
+ case .function(let ref):
return ref.isInstanceOf(constructor)
}
}
@@ -285,19 +300,19 @@ extension JSValue: CustomStringConvertible {
//
// Note: Once Embedded Swift supports parameter packs/variadic generics, we can
// replace all of these with a single method that takes a generic pack.
-public extension JSValue {
+extension JSValue {
@_disfavoredOverload
- subscript(dynamicMember name: String) -> (() -> JSValue) {
+ public subscript(dynamicMember name: String) -> (() -> JSValue) {
object![dynamicMember: name]!
}
@_disfavoredOverload
- subscript(dynamicMember name: String) -> ((A0) -> JSValue) {
+ public subscript(dynamicMember name: String) -> ((A0) -> JSValue) {
object![dynamicMember: name]!
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue
>(dynamicMember name: String) -> ((A0, A1) -> JSValue) {
@@ -305,7 +320,7 @@ public extension JSValue {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue
@@ -314,7 +329,7 @@ public extension JSValue {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
@@ -324,7 +339,7 @@ public extension JSValue {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
@@ -335,7 +350,7 @@ public extension JSValue {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
@@ -347,7 +362,7 @@ public extension JSValue {
}
@_disfavoredOverload
- subscript<
+ public subscript<
A0: ConvertibleToJSValue,
A1: ConvertibleToJSValue,
A2: ConvertibleToJSValue,
diff --git a/Sources/JavaScriptKit/JSValueDecoder.swift b/Sources/JavaScriptKit/JSValueDecoder.swift
index b2cf7b2a3..08e29915c 100644
--- a/Sources/JavaScriptKit/JSValueDecoder.swift
+++ b/Sources/JavaScriptKit/JSValueDecoder.swift
@@ -121,7 +121,10 @@ private struct _KeyedDecodingContainer: KeyedDecodingContainerPr
return try T(from: _decoder(forKey: key))
}
- func nestedContainer(keyedBy _: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer where NestedKey: CodingKey {
+ func nestedContainer(
+ keyedBy _: NestedKey.Type,
+ forKey key: Key
+ ) throws -> KeyedDecodingContainer where NestedKey: CodingKey {
try _decoder(forKey: key).container(keyedBy: NestedKey.self)
}
@@ -185,7 +188,8 @@ private struct _UnkeyedDecodingContainer: UnkeyedDecodingContainer {
return try T(from: _decoder())
}
- mutating func nestedContainer(keyedBy _: NestedKey.Type) throws -> KeyedDecodingContainer where NestedKey: CodingKey {
+ mutating func nestedContainer(keyedBy _: NestedKey.Type) throws -> KeyedDecodingContainer
+ where NestedKey: CodingKey {
return try _decoder().container(keyedBy: NestedKey.self)
}
diff --git a/Sources/JavaScriptKit/ThreadLocal.swift b/Sources/JavaScriptKit/ThreadLocal.swift
index 9f5751c96..e92ca32ac 100644
--- a/Sources/JavaScriptKit/ThreadLocal.swift
+++ b/Sources/JavaScriptKit/ThreadLocal.swift
@@ -15,7 +15,7 @@ import Glibc
/// The value is stored in a thread-local variable, which is a separate copy for each thread.
@propertyWrapper
final class ThreadLocal: Sendable {
-#if compiler(>=6.1) && _runtime(_multithreaded)
+ #if compiler(>=6.1) && _runtime(_multithreaded)
/// The wrapped value stored in the thread-local storage.
/// The initial value is `nil` for each thread.
var wrappedValue: Value? {
@@ -76,7 +76,7 @@ final class ThreadLocal: Sendable {
}
self.release = { Unmanaged.fromOpaque($0).release() }
}
-#else
+ #else
// Fallback implementation for platforms that don't support pthread
private class SendableBox: @unchecked Sendable {
var value: Value? = nil
@@ -93,7 +93,7 @@ final class ThreadLocal: Sendable {
init(boxing _: Void) {
wrappedValue = nil
}
-#endif
+ #endif
deinit {
preconditionFailure("ThreadLocal can only be used as an immortal storage, cannot be deallocated")
diff --git a/Tests/JavaScriptBigIntSupportTests/JavaScriptBigIntSupportTests.swift b/Tests/JavaScriptBigIntSupportTests/JavaScriptBigIntSupportTests.swift
index e1fb8a96f..73aacf1bb 100644
--- a/Tests/JavaScriptBigIntSupportTests/JavaScriptBigIntSupportTests.swift
+++ b/Tests/JavaScriptBigIntSupportTests/JavaScriptBigIntSupportTests.swift
@@ -1,6 +1,6 @@
-import XCTest
import JavaScriptBigIntSupport
import JavaScriptKit
+import XCTest
class JavaScriptBigIntSupportTests: XCTestCase {
func testBigIntSupport() {
@@ -11,7 +11,7 @@ class JavaScriptBigIntSupportTests: XCTestCase {
let bigInt2 = JSBigInt(_slowBridge: value)
XCTAssertEqual(bigInt2.description, value.description, file: file, line: line)
}
-
+
// Test unsigned values
func testUnsignedValue(_ value: UInt64, file: StaticString = #filePath, line: UInt = #line) {
let bigInt = JSBigInt(unsigned: value)
@@ -19,21 +19,21 @@ class JavaScriptBigIntSupportTests: XCTestCase {
let bigInt2 = JSBigInt(_slowBridge: value)
XCTAssertEqual(bigInt2.description, value.description, file: file, line: line)
}
-
+
// Test specific signed values
testSignedValue(0)
testSignedValue(1 << 62)
testSignedValue(-2305)
-
+
// Test random signed values
for _ in 0..<100 {
testSignedValue(.random(in: .min ... .max))
}
-
+
// Test edge signed values
testSignedValue(.min)
testSignedValue(.max)
-
+
// Test specific unsigned values
testUnsignedValue(0)
testUnsignedValue(1 << 62)
@@ -41,7 +41,7 @@ class JavaScriptBigIntSupportTests: XCTestCase {
testUnsignedValue(.min)
testUnsignedValue(.max)
testUnsignedValue(~0)
-
+
// Test random unsigned values
for _ in 0..<100 {
testUnsignedValue(.random(in: .min ... .max))
diff --git a/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift b/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift
index cca303a09..d2b776304 100644
--- a/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift
+++ b/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift
@@ -1,5 +1,5 @@
-import XCTest
import JavaScriptKit
+import XCTest
final class JavaScriptEventLoopTestSupportTests: XCTestCase {
func testAwaitMicrotask() async {
diff --git a/Tests/JavaScriptEventLoopTests/JSPromiseTests.swift b/Tests/JavaScriptEventLoopTests/JSPromiseTests.swift
index e19d356e5..962b04421 100644
--- a/Tests/JavaScriptEventLoopTests/JSPromiseTests.swift
+++ b/Tests/JavaScriptEventLoopTests/JSPromiseTests.swift
@@ -1,4 +1,5 @@
import XCTest
+
@testable import JavaScriptKit
final class JSPromiseTests: XCTestCase {
diff --git a/Tests/JavaScriptEventLoopTests/JavaScriptEventLoopTests.swift b/Tests/JavaScriptEventLoopTests/JavaScriptEventLoopTests.swift
index 1cd628338..1da56e680 100644
--- a/Tests/JavaScriptEventLoopTests/JavaScriptEventLoopTests.swift
+++ b/Tests/JavaScriptEventLoopTests/JavaScriptEventLoopTests.swift
@@ -18,7 +18,9 @@ final class JavaScriptEventLoopTests: XCTestCase {
}
func expectAsyncThrow(
- _ body: @autoclosure () async throws -> T, file: StaticString = #file, line: UInt = #line,
+ _ body: @autoclosure () async throws -> T,
+ file: StaticString = #file,
+ line: UInt = #line,
column: UInt = #column
) async throws -> Error {
do {
@@ -241,20 +243,20 @@ final class JavaScriptEventLoopTests: XCTestCase {
// MARK: - Clock Tests
#if compiler(>=5.7)
- func testClockSleep() async throws {
- // Test ContinuousClock.sleep
- let continuousClockDiff = try await measureTime {
- let c = ContinuousClock()
- try await c.sleep(until: .now + .milliseconds(100))
- }
- XCTAssertGreaterThanOrEqual(continuousClockDiff, 50)
+ func testClockSleep() async throws {
+ // Test ContinuousClock.sleep
+ let continuousClockDiff = try await measureTime {
+ let c = ContinuousClock()
+ try await c.sleep(until: .now + .milliseconds(100))
+ }
+ XCTAssertGreaterThanOrEqual(continuousClockDiff, 50)
- // Test SuspendingClock.sleep
- let suspendingClockDiff = try await measureTime {
- let c = SuspendingClock()
- try await c.sleep(until: .now + .milliseconds(100))
- }
- XCTAssertGreaterThanOrEqual(suspendingClockDiff, 50)
+ // Test SuspendingClock.sleep
+ let suspendingClockDiff = try await measureTime {
+ let c = SuspendingClock()
+ try await c.sleep(until: .now + .milliseconds(100))
}
+ XCTAssertGreaterThanOrEqual(suspendingClockDiff, 50)
+ }
#endif
}
diff --git a/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift b/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift
index 1696224df..8a45aead5 100644
--- a/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift
+++ b/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift
@@ -1,6 +1,6 @@
#if compiler(>=6.1) && _runtime(_multithreaded)
import XCTest
-import _CJavaScriptKit // For swjs_get_worker_thread_id
+import _CJavaScriptKit // For swjs_get_worker_thread_id
@testable import JavaScriptKit
@testable import JavaScriptEventLoop
@@ -226,17 +226,17 @@ final class WebWorkerTaskExecutorTests: XCTestCase {
func decodeJob() throws {
let json = """
- {
- "prop_1": {
- "nested_prop": 42
- },
- "prop_2": 100,
- "prop_3": true,
- "prop_7": 3.14,
- "prop_8": "Hello, World!",
- "prop_9": ["a", "b", "c"]
- }
- """
+ {
+ "prop_1": {
+ "nested_prop": 42
+ },
+ "prop_2": 100,
+ "prop_3": true,
+ "prop_7": 3.14,
+ "prop_8": "Hello, World!",
+ "prop_9": ["a", "b", "c"]
+ }
+ """
let object = JSObject.global.JSON.parse(json)
let decoder = JSValueDecoder()
let result = try decoder.decode(DecodeMe.self, from: object)
@@ -444,18 +444,18 @@ final class WebWorkerTaskExecutorTests: XCTestCase {
XCTAssertEqual(object["test"].string!, "Hello, World!")
}
-/*
- func testDeinitJSObjectOnDifferentThread() async throws {
- let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
+ /*
+ func testDeinitJSObjectOnDifferentThread() async throws {
+ let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
- var object: JSObject? = JSObject.global.Object.function!.new()
- let task = Task(executorPreference: executor) {
- object = nil
- _ = object
+ var object: JSObject? = JSObject.global.Object.function!.new()
+ let task = Task(executorPreference: executor) {
+ object = nil
+ _ = object
+ }
+ await task.value
+ executor.terminate()
}
- await task.value
- executor.terminate()
- }
-*/
+ */
}
#endif
diff --git a/Tests/JavaScriptKitTests/JavaScriptKitTests.swift b/Tests/JavaScriptKitTests/JavaScriptKitTests.swift
index 6c90afead..d7911feb9 100644
--- a/Tests/JavaScriptKitTests/JavaScriptKitTests.swift
+++ b/Tests/JavaScriptKitTests/JavaScriptKitTests.swift
@@ -1,5 +1,5 @@
-import XCTest
import JavaScriptKit
+import XCTest
class JavaScriptKitTests: XCTestCase {
func testLiteralConversion() {
@@ -22,7 +22,7 @@ class JavaScriptKitTests: XCTestCase {
setJSValue(this: global, name: prop, value: input)
let got = getJSValue(this: global, name: prop)
switch (got, input) {
- case let (.number(lhs), .number(rhs)):
+ case (.number(let lhs), .number(let rhs)):
// Compare bitPattern because nan == nan is always false
XCTAssertEqual(lhs.bitPattern, rhs.bitPattern)
default:
@@ -30,7 +30,7 @@ class JavaScriptKitTests: XCTestCase {
}
}
}
-
+
func testObjectConversion() {
// Notes: globalObject1 is defined in JavaScript environment
//
@@ -47,7 +47,7 @@ class JavaScriptKitTests: XCTestCase {
// ...
// }
// ```
-
+
let globalObject1 = getJSValue(this: .global, name: "globalObject1")
let globalObject1Ref = try! XCTUnwrap(globalObject1.object)
let prop_1 = getJSValue(this: globalObject1Ref, name: "prop_1")
@@ -67,10 +67,10 @@ class JavaScriptKitTests: XCTestCase {
let actualElement = getJSValue(this: prop_4Array, index: Int32(index))
XCTAssertEqual(actualElement, expectedElement)
}
-
+
XCTAssertEqual(getJSValue(this: globalObject1Ref, name: "undefined_prop"), .undefined)
}
-
+
func testValueConstruction() {
let globalObject1 = getJSValue(this: .global, name: "globalObject1")
let globalObject1Ref = try! XCTUnwrap(globalObject1.object)
@@ -81,10 +81,10 @@ class JavaScriptKitTests: XCTestCase {
let prop_7 = getJSValue(this: globalObject1Ref, name: "prop_7")
XCTAssertEqual(Double.construct(from: prop_7), 3.14)
XCTAssertEqual(Float.construct(from: prop_7), 3.14)
-
+
for source: JSValue in [
.number(.infinity), .number(.nan),
- .number(Double(UInt64.max).nextUp), .number(Double(Int64.min).nextDown)
+ .number(Double(UInt64.max).nextUp), .number(Double(Int64.min).nextDown),
] {
XCTAssertNil(Int.construct(from: source))
XCTAssertNil(Int8.construct(from: source))
@@ -98,7 +98,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertNil(UInt64.construct(from: source))
}
}
-
+
func testArrayIterator() {
let globalObject1 = getJSValue(this: .global, name: "globalObject1")
let globalObject1Ref = try! XCTUnwrap(globalObject1.object)
@@ -108,14 +108,14 @@ class JavaScriptKitTests: XCTestCase {
.number(3), .number(4), .string("str_elm_1"), .null, .undefined, .number(5),
]
XCTAssertEqual(Array(array1), expectedProp_4)
-
+
// Ensure that iterator skips empty hole as JavaScript does.
let prop_8 = getJSValue(this: globalObject1Ref, name: "prop_8")
let array2 = try! XCTUnwrap(prop_8.array)
let expectedProp_8: [JSValue] = [0, 2, 3, 6]
XCTAssertEqual(Array(array2), expectedProp_8)
}
-
+
func testArrayRandomAccessCollection() {
let globalObject1 = getJSValue(this: .global, name: "globalObject1")
let globalObject1Ref = try! XCTUnwrap(globalObject1.object)
@@ -125,22 +125,22 @@ class JavaScriptKitTests: XCTestCase {
.number(3), .number(4), .string("str_elm_1"), .null, .undefined, .number(5),
]
XCTAssertEqual([array1[0], array1[1], array1[2], array1[3], array1[4], array1[5]], expectedProp_4)
-
+
// Ensure that subscript can access empty hole
let prop_8 = getJSValue(this: globalObject1Ref, name: "prop_8")
let array2 = try! XCTUnwrap(prop_8.array)
let expectedProp_8: [JSValue] = [
- 0, .undefined, 2, 3, .undefined, .undefined, 6
+ 0, .undefined, 2, 3, .undefined, .undefined, 6,
]
XCTAssertEqual([array2[0], array2[1], array2[2], array2[3], array2[4], array2[5], array2[6]], expectedProp_8)
}
-
+
func testValueDecoder() {
struct GlobalObject1: Codable {
struct Prop1: Codable {
let nested_prop: Int
}
-
+
let prop_1: Prop1
let prop_2: Int
let prop_3: Bool
@@ -154,7 +154,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(globalObject1.prop_3, true)
XCTAssertEqual(globalObject1.prop_7, 3.14)
}
-
+
func testFunctionCall() {
// Notes: globalObject1 is defined in JavaScript environment
//
@@ -174,12 +174,12 @@ class JavaScriptKitTests: XCTestCase {
// ...
// }
// ```
-
+
let globalObject1 = getJSValue(this: .global, name: "globalObject1")
let globalObject1Ref = try! XCTUnwrap(globalObject1.object)
let prop_5 = getJSValue(this: globalObject1Ref, name: "prop_5")
let prop_5Ref = try! XCTUnwrap(prop_5.object)
-
+
let func1 = try! XCTUnwrap(getJSValue(this: prop_5Ref, name: "func1").function)
XCTAssertEqual(func1(), .undefined)
let func2 = try! XCTUnwrap(getJSValue(this: prop_5Ref, name: "func2").function)
@@ -196,30 +196,30 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(func6(false, 1, 2), .number(2))
XCTAssertEqual(func6(true, "OK", 2), .string("OK"))
}
-
+
func testClosureLifetime() {
let evalClosure = JSObject.global.globalObject1.eval_closure.function!
-
+
do {
let c1 = JSClosure { arguments in
return arguments[0]
}
XCTAssertEqual(evalClosure(c1, JSValue.number(1.0)), .number(1.0))
-#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
+ #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
c1.release()
-#endif
+ #endif
}
-
+
do {
let array = JSObject.global.Array.function!.new()
let c1 = JSClosure { _ in .number(3) }
_ = array.push!(c1)
XCTAssertEqual(array[0].function!().number, 3.0)
-#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
+ #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
c1.release()
-#endif
+ #endif
}
-
+
do {
let c1 = JSClosure { _ in .undefined }
XCTAssertEqual(c1(), .undefined)
@@ -230,7 +230,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(c1(), .number(4))
}
}
-
+
func testHostFunctionRegistration() {
// ```js
// global.globalObject1 = {
@@ -246,24 +246,24 @@ class JavaScriptKitTests: XCTestCase {
let globalObject1Ref = try! XCTUnwrap(globalObject1.object)
let prop_6 = getJSValue(this: globalObject1Ref, name: "prop_6")
let prop_6Ref = try! XCTUnwrap(prop_6.object)
-
+
var isHostFunc1Called = false
let hostFunc1 = JSClosure { (_) -> JSValue in
isHostFunc1Called = true
return .number(1)
}
-
+
setJSValue(this: prop_6Ref, name: "host_func_1", value: .object(hostFunc1))
-
+
let call_host_1 = getJSValue(this: prop_6Ref, name: "call_host_1")
let call_host_1Func = try! XCTUnwrap(call_host_1.function)
XCTAssertEqual(call_host_1Func(), .number(1))
XCTAssertEqual(isHostFunc1Called, true)
-
-#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
+
+ #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
hostFunc1.release()
-#endif
-
+ #endif
+
let evalClosure = JSObject.global.globalObject1.eval_closure.function!
let hostFunc2 = JSClosure { (arguments) -> JSValue in
if let input = arguments[0].number {
@@ -272,15 +272,15 @@ class JavaScriptKitTests: XCTestCase {
return .string(String(describing: arguments[0]))
}
}
-
+
XCTAssertEqual(evalClosure(hostFunc2, 3), .number(6))
XCTAssertTrue(evalClosure(hostFunc2, true).string != nil)
-
-#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
+
+ #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
hostFunc2.release()
-#endif
+ #endif
}
-
+
func testNewObjectConstruction() {
// ```js
// global.Animal = function(name, age, isCat) {
@@ -299,14 +299,14 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(cat1.isInstanceOf(try! XCTUnwrap(getJSValue(this: .global, name: "Array").function)), false)
let cat1Bark = try! XCTUnwrap(getJSValue(this: cat1, name: "bark").function)
XCTAssertEqual(cat1Bark(), .string("nyan"))
-
+
let dog1 = objectConstructor.new("Pochi", 3, false)
let dog1Bark = try! XCTUnwrap(getJSValue(this: dog1, name: "bark").function)
XCTAssertEqual(dog1Bark(), .string("wan"))
}
-
+
func testObjectDecoding() {
- /*
+ /*
```js
global.objectDecodingTest = {
obj: {},
@@ -317,7 +317,7 @@ class JavaScriptKitTests: XCTestCase {
```
*/
let js: JSValue = JSObject.global.objectDecodingTest
-
+
// I can't use regular name like `js.object` here
// cz its conflicting with case name and DML.
// so I use abbreviated names
@@ -325,28 +325,28 @@ class JavaScriptKitTests: XCTestCase {
let function: JSValue = js.fn
let symbol: JSValue = js.sym
let bigInt: JSValue = js.bi
-
+
XCTAssertNotNil(JSObject.construct(from: object))
XCTAssertEqual(JSObject.construct(from: function).map { $0 is JSFunction }, .some(true))
XCTAssertEqual(JSObject.construct(from: symbol).map { $0 is JSSymbol }, .some(true))
XCTAssertEqual(JSObject.construct(from: bigInt).map { $0 is JSBigInt }, .some(true))
-
+
XCTAssertNil(JSFunction.construct(from: object))
XCTAssertNotNil(JSFunction.construct(from: function))
XCTAssertNil(JSFunction.construct(from: symbol))
XCTAssertNil(JSFunction.construct(from: bigInt))
-
+
XCTAssertNil(JSSymbol.construct(from: object))
XCTAssertNil(JSSymbol.construct(from: function))
XCTAssertNotNil(JSSymbol.construct(from: symbol))
XCTAssertNil(JSSymbol.construct(from: bigInt))
-
+
XCTAssertNil(JSBigInt.construct(from: object))
XCTAssertNil(JSBigInt.construct(from: function))
XCTAssertNil(JSBigInt.construct(from: symbol))
XCTAssertNotNil(JSBigInt.construct(from: bigInt))
}
-
+
func testCallFunctionWithThis() {
// ```js
// global.Animal = function(name, age, isCat) {
@@ -366,16 +366,16 @@ class JavaScriptKitTests: XCTestCase {
let cat1Value = JSValue.object(cat1)
let getIsCat = try! XCTUnwrap(getJSValue(this: cat1, name: "getIsCat").function)
let setName = try! XCTUnwrap(getJSValue(this: cat1, name: "setName").function)
-
+
// Direct call without this
XCTAssertThrowsError(try getIsCat.throws())
-
+
// Call with this
let gotIsCat = getIsCat(this: cat1)
XCTAssertEqual(gotIsCat, .boolean(true))
XCTAssertEqual(cat1.getIsCat!(), .boolean(true))
XCTAssertEqual(cat1Value.getIsCat(), .boolean(true))
-
+
// Call with this and argument
setName(this: cat1, JSValue.string("Shiro"))
XCTAssertEqual(getJSValue(this: cat1, name: "name"), .string("Shiro"))
@@ -384,7 +384,7 @@ class JavaScriptKitTests: XCTestCase {
_ = cat1Value.setName("Chibi")
XCTAssertEqual(getJSValue(this: cat1, name: "name"), .string("Chibi"))
}
-
+
func testJSObjectConversion() {
let array1 = [1, 2, 3]
let jsArray1 = array1.jsValue.object!
@@ -392,7 +392,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(jsArray1[0], .number(1))
XCTAssertEqual(jsArray1[1], .number(2))
XCTAssertEqual(jsArray1[2], .number(3))
-
+
let array2: [ConvertibleToJSValue] = [1, "str", false]
let jsArray2 = array2.jsValue.object!
XCTAssertEqual(jsArray2.length, .number(3))
@@ -402,9 +402,9 @@ class JavaScriptKitTests: XCTestCase {
_ = jsArray2.push!(5)
XCTAssertEqual(jsArray2.length, .number(4))
_ = jsArray2.push!(jsArray1)
-
+
XCTAssertEqual(jsArray2[4], .object(jsArray1))
-
+
let dict1: [String: JSValue] = [
"prop1": 1.jsValue,
"prop2": "foo".jsValue,
@@ -413,7 +413,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(jsDict1.prop1, .number(1))
XCTAssertEqual(jsDict1.prop2, .string("foo"))
}
-
+
func testObjectRefLifetime() {
// ```js
// global.globalObject1 = {
@@ -428,24 +428,24 @@ class JavaScriptKitTests: XCTestCase {
// ...
// }
// ```
-
+
let evalClosure = JSObject.global.globalObject1.eval_closure.function!
let identity = JSClosure { $0[0] }
let ref1 = getJSValue(this: .global, name: "globalObject1").object!
let ref2 = evalClosure(identity, ref1).object!
XCTAssertEqual(ref1.prop_2, .number(2))
XCTAssertEqual(ref2.prop_2, .number(2))
-
-#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
+
+ #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
identity.release()
-#endif
+ #endif
}
-
+
func testDate() {
let date1Milliseconds = JSDate.now()
let date1 = JSDate(millisecondsSinceEpoch: date1Milliseconds)
let date2 = JSDate(millisecondsSinceEpoch: date1.valueOf())
-
+
XCTAssertEqual(date1.valueOf(), date2.valueOf())
XCTAssertEqual(date1.fullYear, date2.fullYear)
XCTAssertEqual(date1.month, date2.month)
@@ -464,7 +464,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(date1.utcSeconds, date2.utcSeconds)
XCTAssertEqual(date1.utcMilliseconds, date2.utcMilliseconds)
XCTAssertEqual(date1, date2)
-
+
let date3 = JSDate(millisecondsSinceEpoch: 0)
XCTAssertEqual(date3.valueOf(), 0)
XCTAssertEqual(date3.utcFullYear, 1970)
@@ -477,10 +477,10 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(date3.utcSeconds, 0)
XCTAssertEqual(date3.utcMilliseconds, 0)
XCTAssertEqual(date3.toISOString(), "1970-01-01T00:00:00.000Z")
-
+
XCTAssertTrue(date3 < date1)
}
-
+
func testError() {
let message = "test error"
let expectedDescription = "Error: test error"
@@ -492,21 +492,21 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertNil(JSError(from: .string("error"))?.description)
XCTAssertEqual(JSError(from: .object(error.jsObject))?.description, expectedDescription)
}
-
+
func testJSValueAccessor() {
var globalObject1 = JSObject.global.globalObject1
XCTAssertEqual(globalObject1.prop_1.nested_prop, .number(1))
XCTAssertEqual(globalObject1.object!.prop_1.object!.nested_prop, .number(1))
-
+
XCTAssertEqual(globalObject1.prop_4[0], .number(3))
XCTAssertEqual(globalObject1.prop_4[1], .number(4))
-
+
let originalProp1 = globalObject1.prop_1.object!.nested_prop
globalObject1.prop_1.nested_prop = "bar"
XCTAssertEqual(globalObject1.prop_1.nested_prop, .string("bar"))
globalObject1.prop_1.nested_prop = originalProp1
}
-
+
func testException() {
// ```js
// global.globalObject1 = {
@@ -528,33 +528,33 @@ class JavaScriptKitTests: XCTestCase {
//
let globalObject1 = JSObject.global.globalObject1
let prop_9: JSValue = globalObject1.prop_9
-
+
// MARK: Throwing method calls
XCTAssertThrowsError(try prop_9.object!.throwing.func1!()) { error in
XCTAssertTrue(error is JSException)
let errorObject = JSError(from: (error as! JSException).thrownValue)
XCTAssertNotNil(errorObject)
}
-
+
XCTAssertThrowsError(try prop_9.object!.throwing.func2!()) { error in
XCTAssertTrue(error is JSException)
let thrownValue = (error as! JSException).thrownValue
XCTAssertEqual(thrownValue.string, "String Error")
}
-
+
XCTAssertThrowsError(try prop_9.object!.throwing.func3!()) { error in
XCTAssertTrue(error is JSException)
let thrownValue = (error as! JSException).thrownValue
XCTAssertEqual(thrownValue.number, 3.0)
}
-
+
// MARK: Simple function calls
XCTAssertThrowsError(try prop_9.func1.function!.throws()) { error in
XCTAssertTrue(error is JSException)
let errorObject = JSError(from: (error as! JSException).thrownValue)
XCTAssertNotNil(errorObject)
}
-
+
// MARK: Throwing constructor call
let Animal = JSObject.global.Animal.function!
XCTAssertNoThrow(try Animal.throws.new("Tama", 3, true))
@@ -564,16 +564,16 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertNotNil(errorObject)
}
}
-
+
func testSymbols() {
let symbol1 = JSSymbol("abc")
let symbol2 = JSSymbol("abc")
XCTAssertNotEqual(symbol1, symbol2)
XCTAssertEqual(symbol1.name, symbol2.name)
XCTAssertEqual(symbol1.name, "abc")
-
+
XCTAssertEqual(JSSymbol.iterator, JSSymbol.iterator)
-
+
// let hasInstanceClass = {
// prop: function () {}
// }.prop
@@ -584,35 +584,36 @@ class JavaScriptKitTests: XCTestCase {
let propertyDescriptor = JSObject.global.Object.function!.new()
propertyDescriptor.value = JSClosure { _ in .boolean(true) }.jsValue
_ = JSObject.global.Object.function!.defineProperty!(
- hasInstanceClass, JSSymbol.hasInstance,
+ hasInstanceClass,
+ JSSymbol.hasInstance,
propertyDescriptor
)
XCTAssertEqual(hasInstanceClass[JSSymbol.hasInstance].function!().boolean, true)
XCTAssertEqual(JSObject.global.Object.isInstanceOf(hasInstanceClass), true)
}
-
+
func testJSValueDecoder() {
struct AnimalStruct: Decodable {
let name: String
let age: Int
let isCat: Bool
}
-
+
let Animal = JSObject.global.Animal.function!
let tama = try! Animal.throws.new("Tama", 3, true)
let decoder = JSValueDecoder()
let decodedTama = try! decoder.decode(AnimalStruct.self, from: tama.jsValue)
-
+
XCTAssertEqual(decodedTama.name, tama.name.string)
XCTAssertEqual(decodedTama.name, "Tama")
-
+
XCTAssertEqual(decodedTama.age, tama.age.number.map(Int.init))
XCTAssertEqual(decodedTama.age, 3)
-
+
XCTAssertEqual(decodedTama.isCat, tama.isCat.boolean)
XCTAssertEqual(decodedTama.isCat, true)
}
-
+
func testConvertibleToJSValue() {
let array1 = [1, 2, 3]
let jsArray1 = array1.jsValue.object!
@@ -620,7 +621,7 @@ class JavaScriptKitTests: XCTestCase {
XCTAssertEqual(jsArray1[0], .number(1))
XCTAssertEqual(jsArray1[1], .number(2))
XCTAssertEqual(jsArray1[2], .number(3))
-
+
let array2: [ConvertibleToJSValue] = [1, "str", false]
let jsArray2 = array2.jsValue.object!
XCTAssertEqual(jsArray2.length, .number(3))
@@ -630,9 +631,9 @@ class JavaScriptKitTests: XCTestCase {
_ = jsArray2.push!(5)
XCTAssertEqual(jsArray2.length, .number(4))
_ = jsArray2.push!(jsArray1)
-
+
XCTAssertEqual(jsArray2[4], .object(jsArray1))
-
+
let dict1: [String: JSValue] = [
"prop1": 1.jsValue,
"prop2": "foo".jsValue,
diff --git a/Tests/JavaScriptKitTests/ThreadLocalTests.swift b/Tests/JavaScriptKitTests/ThreadLocalTests.swift
index 55fcdadb4..d1d736b8b 100644
--- a/Tests/JavaScriptKitTests/ThreadLocalTests.swift
+++ b/Tests/JavaScriptKitTests/ThreadLocalTests.swift
@@ -1,4 +1,5 @@
import XCTest
+
@testable import JavaScriptKit
final class ThreadLocalTests: XCTestCase {
diff --git a/Utilities/format.swift b/Utilities/format.swift
new file mode 100755
index 000000000..206ccfc39
--- /dev/null
+++ b/Utilities/format.swift
@@ -0,0 +1,89 @@
+#!/usr/bin/env swift
+
+import class Foundation.FileManager
+import class Foundation.Process
+import class Foundation.ProcessInfo
+import struct Foundation.URL
+import func Foundation.exit
+
+/// The root directory of the project.
+let projectRoot = URL(fileURLWithPath: #filePath).deletingLastPathComponent().deletingLastPathComponent()
+
+/// Returns the path to the executable if it is found in the PATH environment variable.
+func which(_ executable: String) -> String? {
+ let pathSeparator: Character
+ #if os(Windows)
+ pathSeparator = ";"
+ #else
+ pathSeparator = ":"
+ #endif
+ let paths = ProcessInfo.processInfo.environment["PATH"]!.split(separator: pathSeparator)
+ for path in paths {
+ let url = URL(fileURLWithPath: String(path)).appendingPathComponent(executable)
+ if FileManager.default.isExecutableFile(atPath: url.path) {
+ return url.path
+ }
+ }
+ return nil
+}
+
+/// Runs the `swift-format` command with the given arguments in the project root.
+func swiftFormat(_ arguments: [String]) throws {
+ guard let swiftFormat = which("swift-format") else {
+ print("swift-format not found in PATH")
+ exit(1)
+ }
+ let task = Process()
+ task.executableURL = URL(fileURLWithPath: swiftFormat)
+ task.arguments = arguments
+ task.currentDirectoryURL = projectRoot
+ try task.run()
+ task.waitUntilExit()
+ if task.terminationStatus != 0 {
+ print("swift-format failed with status \(task.terminationStatus)")
+ exit(1)
+ }
+}
+
+/// Patterns to exclude from formatting.
+let excluded: Set = [
+ ".git",
+ ".build",
+ ".index-build",
+ "node_modules",
+ "__Snapshots__",
+ // Exclude the script itself to avoid changing its file mode.
+ URL(fileURLWithPath: #filePath).lastPathComponent,
+]
+
+/// Returns a list of directories to format.
+func filesToFormat() -> [String] {
+ var files: [String] = []
+ let fileManager = FileManager.default
+ let enumerator = fileManager.enumerator(
+ at: projectRoot, includingPropertiesForKeys: nil
+ )!
+ for case let fileURL as URL in enumerator {
+ if excluded.contains(fileURL.lastPathComponent) {
+ if fileURL.hasDirectoryPath {
+ enumerator.skipDescendants()
+ }
+ continue
+ }
+ guard fileURL.pathExtension == "swift" else { continue }
+ files.append(fileURL.path)
+ }
+ return files
+}
+
+let arguments = CommandLine.arguments[1...]
+switch arguments.first {
+case "lint":
+ try swiftFormat(["lint", "--parallel", "--recursive"] + filesToFormat())
+case "format", nil:
+ try swiftFormat(["format", "--parallel", "--in-place", "--recursive"] + filesToFormat())
+case let subcommand?:
+ print("Unknown subcommand: \(subcommand)")
+ print("Usage: format.swift lint|format")
+ exit(1)
+}