diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..0e720b4d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index d786c31e..a239a79c 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -1,5 +1,4 @@ // @ts-check -// @ts-ignore import { SwiftRuntime } from "./runtime.js" export const MODULE_PATH = "@PACKAGE_TO_JS_MODULE_PATH@"; diff --git a/Plugins/PackageToJS/Templates/platforms/browser.js b/Plugins/PackageToJS/Templates/platforms/browser.js index 672c274d..b1e469fb 100644 --- a/Plugins/PackageToJS/Templates/platforms/browser.js +++ b/Plugins/PackageToJS/Templates/platforms/browser.js @@ -2,8 +2,10 @@ import { MODULE_PATH /* #if USE_SHARED_MEMORY */, MEMORY_TYPE /* #endif */} from "../instantiate.js" /* #if IS_WASI */ /* #if USE_WASI_CDN */ +// @ts-ignore import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from 'https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.4.1/+esm'; /* #else */ +// @ts-ignore import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from '@bjorn3/browser_wasi_shim'; /* #endif */ /* #endif */ diff --git a/Plugins/PackageToJS/Templates/runtime.d.ts b/Plugins/PackageToJS/Templates/runtime.d.ts index aff6d1c8..98e1f1cc 100644 --- a/Plugins/PackageToJS/Templates/runtime.d.ts +++ b/Plugins/PackageToJS/Templates/runtime.d.ts @@ -18,58 +18,8 @@ declare class Memory { writeFloat64: (ptr: pointer, value: number) => void; } -declare const enum Kind { - Boolean = 0, - String = 1, - Number = 2, - Object = 3, - Null = 4, - Undefined = 5, - Function = 6, - Symbol = 7, - BigInt = 8 -} - type ref = number; type pointer = number; -type bool = number; -type JavaScriptValueKind = number; -type JavaScriptValueKindAndFlags = number; -interface ImportedFunctions { - swjs_set_prop(ref: number, name: number, kind: Kind, payload1: number, payload2: number): void; - swjs_get_prop(ref: number, name: number, payload1_ptr: pointer, payload2_ptr: pointer): JavaScriptValueKind; - swjs_set_subscript(ref: number, index: number, kind: Kind, payload1: number, payload2: number): void; - swjs_get_subscript(ref: number, index: number, payload1_ptr: pointer, payload2_ptr: pointer): JavaScriptValueKind; - swjs_encode_string(ref: number, bytes_ptr_result: pointer): number; - swjs_decode_string(bytes_ptr: pointer, length: number): number; - swjs_load_string(ref: number, buffer: pointer): void; - swjs_call_function(ref: number, argv: pointer, argc: number, payload1_ptr: pointer, payload2_ptr: pointer): JavaScriptValueKindAndFlags; - swjs_call_function_no_catch(ref: number, argv: pointer, argc: number, payload1_ptr: pointer, payload2_ptr: pointer): JavaScriptValueKindAndFlags; - swjs_call_function_with_this(obj_ref: ref, func_ref: ref, argv: pointer, argc: number, payload1_ptr: pointer, payload2_ptr: pointer): JavaScriptValueKindAndFlags; - swjs_call_function_with_this_no_catch(obj_ref: ref, func_ref: ref, argv: pointer, argc: number, payload1_ptr: pointer, payload2_ptr: pointer): JavaScriptValueKindAndFlags; - swjs_call_new(ref: number, argv: pointer, argc: number): number; - swjs_call_throwing_new(ref: number, argv: pointer, argc: number, exception_kind_ptr: pointer, exception_payload1_ptr: pointer, exception_payload2_ptr: pointer): number; - swjs_instanceof(obj_ref: ref, constructor_ref: ref): boolean; - swjs_value_equals(lhs_ref: ref, rhs_ref: ref): boolean; - swjs_create_function(host_func_id: number, line: number, file: ref): number; - swjs_create_typed_array(constructor_ref: ref, elementsPtr: pointer, length: number): number; - swjs_create_object(): number; - swjs_load_typed_array(ref: ref, buffer: pointer): void; - swjs_release(ref: number): void; - swjs_release_remote(tid: number, ref: number): void; - swjs_i64_to_bigint(value: bigint, signed: bool): ref; - swjs_bigint_to_i64(ref: ref, signed: bool): bigint; - swjs_i64_to_bigint_slow(lower: number, upper: number, signed: bool): ref; - swjs_unsafe_event_loop_yield: () => void; - swjs_send_job_to_main_thread: (unowned_job: number) => void; - swjs_listen_message_from_main_thread: () => void; - swjs_wake_up_worker_thread: (tid: number) => void; - swjs_listen_message_from_worker_thread: (tid: number) => void; - swjs_terminate_worker_thread: (tid: number) => void; - swjs_get_worker_thread_id: () => number; - swjs_request_sending_object: (sending_object: ref, transferring_objects: pointer, transferring_objects_count: number, object_source_tid: number, sending_context: pointer) => void; - swjs_request_sending_objects: (sending_objects: pointer, sending_objects_count: number, transferring_objects: pointer, transferring_objects_count: number, object_source_tid: number, sending_context: pointer) => void; -} /** * A thread channel is a set of functions that are used to communicate between @@ -254,11 +204,11 @@ declare class SwiftRuntime { private get closureDeallocator(); private callHostFunction; /** @deprecated Use `wasmImports` instead */ - importObjects: () => ImportedFunctions; - get wasmImports(): ImportedFunctions; + importObjects: () => WebAssembly.ModuleImports; + get wasmImports(): WebAssembly.ModuleImports; private postMessageToMainThread; private postMessageToWorkerThread; } export { SwiftRuntime }; -export type { SwiftRuntimeOptions }; +export type { SwiftRuntimeOptions, SwiftRuntimeThreadChannel }; diff --git a/Plugins/PackageToJS/Templates/tsconfig.json b/Plugins/PackageToJS/Templates/tsconfig.json new file mode 100644 index 00000000..ac3a2b01 --- /dev/null +++ b/Plugins/PackageToJS/Templates/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "noEmit": true, + "allowJs": true, + "skipLibCheck": true, + "moduleResolution": "node" + }, + "include": ["**/*.d.ts", "**/*.js"] +} diff --git a/Plugins/PackageToJS/Tests/TemplatesTests.swift b/Plugins/PackageToJS/Tests/TemplatesTests.swift new file mode 100644 index 00000000..e885eb08 --- /dev/null +++ b/Plugins/PackageToJS/Tests/TemplatesTests.swift @@ -0,0 +1,20 @@ +import Testing +import Foundation +@testable import PackageToJS + +@Suite struct TemplatesTests { + static let templatesPath = URL(fileURLWithPath: #filePath) + .deletingLastPathComponent() + .deletingLastPathComponent() + .appendingPathComponent("Templates") + + /// `npx tsc -p Templates/tsconfig.json` + @Test func tscCheck() throws { + let tsc = Process() + tsc.executableURL = try which("npx") + tsc.arguments = ["tsc", "-p", Self.templatesPath.appending(path: "tsconfig.json").path] + try tsc.run() + tsc.waitUntilExit() + #expect(tsc.terminationStatus == 0) + } +} diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 83d588ad..ee12e5be 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -5,13 +5,13 @@ import { ref, pointer, TypedArray, - ImportedFunctions, MAIN_THREAD_TID, } from "./types.js"; import * as JSValue from "./js-value.js"; import { Memory } from "./memory.js"; import { deserializeError, MainToWorkerMessage, MessageBroker, ResponseMessage, ITCInterface, serializeError, SwiftRuntimeThreadChannel, WorkerToMainMessage } from "./itc.js"; import { decodeObjectRefs } from "./js-value.js"; +export { SwiftRuntimeThreadChannel }; export type SwiftRuntimeOptions = { /** @@ -181,7 +181,7 @@ export class SwiftRuntime { /** @deprecated Use `wasmImports` instead */ importObjects = () => this.wasmImports; - get wasmImports(): ImportedFunctions { + get wasmImports(): WebAssembly.ModuleImports { let broker: MessageBroker | null = null; const getMessageBroker = (threadChannel: SwiftRuntimeThreadChannel) => { if (broker) return broker; @@ -575,7 +575,7 @@ export class SwiftRuntime { return BigInt.asIntN(64, object); } }, - swjs_i64_to_bigint_slow: (lower, upper, signed) => { + swjs_i64_to_bigint_slow: (lower: number, upper: number, signed: number) => { const value = BigInt.asUintN(32, BigInt(lower)) + (BigInt.asUintN(32, BigInt(upper)) << BigInt(32)); @@ -586,7 +586,7 @@ export class SwiftRuntime { swjs_unsafe_event_loop_yield: () => { throw new UnsafeEventLoopYield(); }, - swjs_send_job_to_main_thread: (unowned_job) => { + swjs_send_job_to_main_thread: (unowned_job: number) => { this.postMessageToMainThread({ type: "job", data: unowned_job }); }, swjs_listen_message_from_main_thread: () => { @@ -616,10 +616,10 @@ export class SwiftRuntime { } }); }, - swjs_wake_up_worker_thread: (tid) => { + swjs_wake_up_worker_thread: (tid: number) => { this.postMessageToWorkerThread(tid, { type: "wake" }); }, - swjs_listen_message_from_worker_thread: (tid) => { + swjs_listen_message_from_worker_thread: (tid: number) => { const threadChannel = this.options.threadChannel; if (!(threadChannel && "listenMessageFromWorkerThread" in threadChannel)) { throw new Error( @@ -648,7 +648,7 @@ export class SwiftRuntime { }, ); }, - swjs_terminate_worker_thread: (tid) => { + swjs_terminate_worker_thread: (tid: number) => { const threadChannel = this.options.threadChannel; if (threadChannel && "terminateWorkerThread" in threadChannel) { threadChannel.terminateWorkerThread?.(tid); diff --git a/Runtime/src/types.ts b/Runtime/src/types.ts index bb20bd95..a8872f80 100644 --- a/Runtime/src/types.ts +++ b/Runtime/src/types.ts @@ -1,5 +1,3 @@ -import * as JSValue from "./js-value.js"; - export type ref = number; export type pointer = number; export type bool = number; @@ -26,114 +24,6 @@ export interface ExportedFunctions { swjs_receive_error(error: ref, context: number): void; } -export interface ImportedFunctions { - swjs_set_prop( - ref: number, - name: number, - kind: JSValue.Kind, - payload1: number, - payload2: number - ): void; - swjs_get_prop( - ref: number, - name: number, - payload1_ptr: pointer, - payload2_ptr: pointer - ): JavaScriptValueKind; - swjs_set_subscript( - ref: number, - index: number, - kind: JSValue.Kind, - payload1: number, - payload2: number - ): void; - swjs_get_subscript( - ref: number, - index: number, - payload1_ptr: pointer, - payload2_ptr: pointer - ): JavaScriptValueKind; - swjs_encode_string(ref: number, bytes_ptr_result: pointer): number; - swjs_decode_string(bytes_ptr: pointer, length: number): number; - swjs_load_string(ref: number, buffer: pointer): void; - swjs_call_function( - ref: number, - argv: pointer, - argc: number, - payload1_ptr: pointer, - payload2_ptr: pointer - ): JavaScriptValueKindAndFlags; - swjs_call_function_no_catch( - ref: number, - argv: pointer, - argc: number, - payload1_ptr: pointer, - payload2_ptr: pointer - ): JavaScriptValueKindAndFlags; - swjs_call_function_with_this( - obj_ref: ref, - func_ref: ref, - argv: pointer, - argc: number, - payload1_ptr: pointer, - payload2_ptr: pointer - ): JavaScriptValueKindAndFlags; - swjs_call_function_with_this_no_catch( - obj_ref: ref, - func_ref: ref, - argv: pointer, - argc: number, - payload1_ptr: pointer, - payload2_ptr: pointer - ): JavaScriptValueKindAndFlags; - swjs_call_new(ref: number, argv: pointer, argc: number): number; - swjs_call_throwing_new( - ref: number, - argv: pointer, - argc: number, - exception_kind_ptr: pointer, - exception_payload1_ptr: pointer, - exception_payload2_ptr: pointer - ): number; - swjs_instanceof(obj_ref: ref, constructor_ref: ref): boolean; - swjs_value_equals(lhs_ref: ref, rhs_ref: ref): boolean; - swjs_create_function(host_func_id: number, line: number, file: ref): number; - swjs_create_typed_array( - constructor_ref: ref, - elementsPtr: pointer, - length: number - ): number; - swjs_create_object(): number; - swjs_load_typed_array(ref: ref, buffer: pointer): void; - swjs_release(ref: number): void; - swjs_release_remote(tid: number, ref: number): void; - swjs_i64_to_bigint(value: bigint, signed: bool): ref; - swjs_bigint_to_i64(ref: ref, signed: bool): bigint; - swjs_i64_to_bigint_slow(lower: number, upper: number, signed: bool): ref; - swjs_unsafe_event_loop_yield: () => void; - swjs_send_job_to_main_thread: (unowned_job: number) => void; - swjs_listen_message_from_main_thread: () => void; - swjs_wake_up_worker_thread: (tid: number) => void; - swjs_listen_message_from_worker_thread: (tid: number) => void; - swjs_terminate_worker_thread: (tid: number) => void; - swjs_get_worker_thread_id: () => number; - swjs_request_sending_object: ( - sending_object: ref, - transferring_objects: pointer, - transferring_objects_count: number, - object_source_tid: number, - sending_context: pointer, - ) => void; - swjs_request_sending_objects: ( - sending_objects: pointer, - sending_objects_count: number, - transferring_objects: pointer, - transferring_objects_count: number, - object_source_tid: number, - sending_context: pointer, - ) => void; -} - export const enum LibraryFeatures { WeakRefs = 1 << 0, } diff --git a/package-lock.json b/package-lock.json index ec5bd0a4..55981f7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,9 @@ "version": "0.0.0", "license": "MIT", "devDependencies": { + "@bjorn3/browser_wasi_shim": "^0.4.1", "@rollup/plugin-typescript": "^12.1.2", + "@types/node": "^22.13.14", "playwright": "^1.51.0", "prettier": "3.5.3", "rollup": "^4.37.0", @@ -42,6 +44,12 @@ "node": ">=6.9.0" } }, + "node_modules/@bjorn3/browser_wasi_shim": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@bjorn3/browser_wasi_shim/-/browser_wasi_shim-0.4.1.tgz", + "integrity": "sha512-54kpBQX69TZ8I1zyDC8sziv/zPT1zoIadv3CmdIZNZ5WDF1houMjAzRZ3dwWvhXObiEBjOxXyS8Ja7vA0EfGEQ==", + "dev": true + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -385,6 +393,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "dev": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -655,6 +672,12 @@ "engines": { "node": ">=14.17" } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true } } } diff --git a/package.json b/package.json index 0ff2d17a..867adb98 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,9 @@ "author": "swiftwasm", "license": "MIT", "devDependencies": { + "@bjorn3/browser_wasi_shim": "^0.4.1", "@rollup/plugin-typescript": "^12.1.2", + "@types/node": "^22.13.14", "playwright": "^1.51.0", "prettier": "3.5.3", "rollup": "^4.37.0",