-
-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript-ify entrypoint scripts #428
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export class SwiftRuntime { | ||
setInstance(instance: WebAssembly.Instance): void; | ||
readonly wasmImports: ImportedFunctions; | ||
} | ||
export type SwiftRuntimeConstructor = typeof SwiftRuntime; | ||
export interface ImportedFunctions { } |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,15 +13,17 @@ | |
// limitations under the License. | ||
|
||
import { WasmRunner } from "./common.js"; | ||
import type { SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JavaScriptKitはユーザが配布する想定で、実装はcarton側ではバンドルしません。 |
||
|
||
const startWasiTask = async () => { | ||
// Fetch our Wasm File | ||
const response = await fetch("REPLACE_THIS_WITH_THE_MAIN_WEBASSEMBLY_MODULE"); | ||
const responseArrayBuffer = await response.arrayBuffer(); | ||
|
||
let runtimeConstructor; | ||
let runtimeConstructor: SwiftRuntimeConstructor | undefined = undefined; | ||
try { | ||
const { SwiftRuntime } = await import( | ||
// @ts-ignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TypeScriptが下記のパスを検証して、ファイルが存在しない事のエラーを出しますが、 なお、 |
||
"./JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs" | ||
); | ||
runtimeConstructor = SwiftRuntime; | ||
|
@@ -36,7 +38,7 @@ const startWasiTask = async () => { | |
await wasmRunner.run(wasmBytes); | ||
}; | ||
|
||
function handleError(e) { | ||
function handleError(e: any) { | ||
console.error(e); | ||
if (e instanceof WebAssembly.RuntimeError) { | ||
console.log(e.stack); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,23 +15,34 @@ | |
import { WASI } from "@wasmer/wasi"; | ||
import { WasmFs } from "@wasmer/wasmfs"; | ||
import * as path from "path-browserify"; | ||
import type { SwiftRuntime, SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; | ||
|
||
export const WasmRunner = (rawOptions, SwiftRuntime) => { | ||
const options = defaultRunnerOptions(rawOptions); | ||
export type Options = { | ||
args?: string[]; | ||
onStdout?: (text: string) => void; | ||
onStderr?: (text: string) => void; | ||
}; | ||
|
||
export type WasmRunner = { | ||
run(wasmBytes: ArrayBufferLike, extraWasmImports?: WebAssembly.Imports): Promise<void> | ||
}; | ||
|
||
export const WasmRunner = (rawOptions: Options | false, SwiftRuntime: SwiftRuntimeConstructor | undefined): WasmRunner => { | ||
const options: Options = defaultRunnerOptions(rawOptions); | ||
|
||
let swift; | ||
let swift: SwiftRuntime; | ||
if (SwiftRuntime) { | ||
swift = new SwiftRuntime(); | ||
} | ||
|
||
const wasmFs = createWasmFS( | ||
(stdout) => { | ||
console.log(stdout); | ||
options.onStdout(stdout); | ||
options.onStdout?.call(undefined, stdout); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}, | ||
(stderr) => { | ||
console.error(stderr); | ||
options.onStderr(stderr); | ||
options.onStderr?.call(undefined, stderr); | ||
} | ||
); | ||
|
||
|
@@ -50,13 +61,16 @@ export const WasmRunner = (rawOptions, SwiftRuntime) => { | |
}, | ||
}); | ||
|
||
const createWasmImportObject = (extraWasmImports, wasmModule) => { | ||
const importObject = { | ||
const createWasmImportObject = ( | ||
extraWasmImports: WebAssembly.Imports, | ||
wasmModule: WebAssembly.Module | ||
): WebAssembly.Imports => { | ||
const importObject: WebAssembly.Imports = { | ||
wasi_snapshot_preview1: wrapWASI(wasi, wasmModule), | ||
}; | ||
|
||
if (swift) { | ||
importObject.javascript_kit = swift.wasmImports; | ||
importObject.javascript_kit = swift.wasmImports as unknown as WebAssembly.ModuleImports; | ||
} | ||
|
||
if (extraWasmImports) { | ||
|
@@ -70,7 +84,7 @@ export const WasmRunner = (rawOptions, SwiftRuntime) => { | |
}; | ||
|
||
return { | ||
async run(wasmBytes, extraWasmImports) { | ||
async run(wasmBytes: ArrayBufferLike, extraWasmImports?: WebAssembly.Imports) { | ||
if (!extraWasmImports) { | ||
extraWasmImports = {}; | ||
} | ||
|
@@ -91,7 +105,7 @@ export const WasmRunner = (rawOptions, SwiftRuntime) => { | |
wasi.start(instance); | ||
|
||
// Initialize and start Reactor | ||
if (instance.exports._initialize) { | ||
if (typeof instance.exports._initialize == "function") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ifの先で関数呼び出しをするために型チェックが必要です。 |
||
instance.exports._initialize(); | ||
if (typeof instance.exports.main === "function") { | ||
instance.exports.main(); | ||
|
@@ -104,7 +118,7 @@ export const WasmRunner = (rawOptions, SwiftRuntime) => { | |
}; | ||
}; | ||
|
||
const defaultRunnerOptions = (options) => { | ||
const defaultRunnerOptions = (options: Options | false): Options => { | ||
if (!options) return defaultRunnerOptions({}); | ||
if (!options.onStdout) { | ||
options.onStdout = () => { }; | ||
|
@@ -118,13 +132,19 @@ const defaultRunnerOptions = (options) => { | |
return options; | ||
}; | ||
|
||
const createWasmFS = (onStdout, onStderr) => { | ||
const createWasmFS = ( | ||
onStdout: (text: string) => void, | ||
onStderr: (text: string) => void | ||
): WasmFs => { | ||
// Instantiate a new WASI Instance | ||
const wasmFs = new WasmFs(); | ||
|
||
// Output stdout and stderr to console | ||
const originalWriteSync = wasmFs.fs.writeSync; | ||
wasmFs.fs.writeSync = (fd, buffer, offset, length, position) => { | ||
(wasmFs.fs as any).writeSync = ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メソッドのインターフェースであり、差し替えられるようになってないので、 |
||
fd: number, buffer: Buffer | Uint8Array, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここの |
||
offset?: number, length?: number, position?: number | ||
): number => { | ||
const text = new TextDecoder("utf-8").decode(buffer); | ||
if (text !== "\n") { | ||
switch (fd) { | ||
|
@@ -142,7 +162,7 @@ const createWasmFS = (onStdout, onStderr) => { | |
return wasmFs; | ||
}; | ||
|
||
const wrapWASI = (wasiObject, wasmModule) => { | ||
const wrapWASI = (wasiObject: WASI, wasmModule: WebAssembly.Module): WebAssembly.ModuleImports => { | ||
// PATCH: @wasmer-js/wasi@0.x forgets to call `refreshMemory` in `clock_res_get`, | ||
// which writes its result to memory view. Without the refresh the memory view, | ||
// it accesses a detached array buffer if the memory is grown by malloc. | ||
|
@@ -154,7 +174,7 @@ const wrapWASI = (wasiObject, wasmModule) => { | |
// Reference: https://github.com/wasmerio/wasmer-js/blob/55fa8c17c56348c312a8bd23c69054b1aa633891/packages/wasi/src/index.ts#L557 | ||
const original_clock_res_get = wasiObject.wasiImport["clock_res_get"]; | ||
|
||
wasiObject.wasiImport["clock_res_get"] = (clockId, resolution) => { | ||
wasiObject.wasiImport["clock_res_get"] = (clockId: number, resolution: number) => { | ||
wasiObject.refreshMemory(); | ||
return original_clock_res_get(clockId, resolution); | ||
}; | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,11 +20,14 @@ | |
}, | ||
"homepage": "https://github.com/swiftwasm/carton#readme", | ||
"devDependencies": { | ||
"@types/node": "^20.12.7", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
"@types/path-browserify": "^1.0.2", | ||
"@wasmer/wasi": "^0.12.0", | ||
"@wasmer/wasmfs": "^0.12.0", | ||
"path-browserify": "^1.0.1", | ||
"esbuild": "^0.14.38", | ||
"npm-run-all": "^4.1.5", | ||
"reconnecting-websocket": "^4.4.0" | ||
"path-browserify": "^1.0.1", | ||
"reconnecting-websocket": "^4.4.0", | ||
"typescript": "^5.4.5" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ローカルで |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JavaScriptKitの
index.mjs
があると想定されている場所に、index.d.ts
を置いて型付けします。cartonはJavaScriptKitをユーザが用意する事を想定しているため、
ここで利用するJavaScriptKitのバージョンがcartonに対して固定されません。
そのためここでの型定義は、他のコードと相互作用するために必要な最小限の定義にします。