Skip to content

Commit 1e699cd

Browse files
Support JSKit demo and update initial sample
1 parent 8e58dee commit 1e699cd

File tree

6 files changed

+56
-28
lines changed

6 files changed

+56
-28
lines changed

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
"build:prod": "webpack --mode production",
2020
"start": "webpack-dev-server"
2121
},
22-
"dependencies": {},
22+
"dependencies": {
23+
"javascript-kit-swift": "^0.15.0"
24+
},
2325
"devDependencies": {
2426
"@types/codemirror": "5.60.5",
2527
"@wasmer/wasi": "^0.12.0",
2.26 MB
Binary file not shown.

src/demo.swift

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import Glibc
2-
31
print("Hello, 🌐!")
42

53
// we can try loops and arithmetic:
@@ -37,13 +35,12 @@ func fib(n: Int) -> Int {
3735
print("The 10th Fibonacci number is \(fib(n: 10))")
3836

3937
// we can also run JavaScript from Swift.
40-
41-
@_silgen_name("executeScript")
42-
func executeScript(script: UnsafePointer<UInt8>, length: Int32)
43-
44-
// Here's a string holding JavaScript code, with some string interpolation:
45-
var scriptSrc = "alert('Hello from Swift! The 11th Fibonacci number is \(fib(n: 11))');"
46-
// and we can execute it.
47-
scriptSrc.withUTF8 { bufferPtr in
48-
executeScript(script: bufferPtr.baseAddress!, length: Int32(bufferPtr.count))
38+
import JavaScriptKit
39+
40+
let reply = JSObject.global.prompt!("Please input number here")
41+
let alert = JSObject.global.alert!
42+
if let n = Int(reply.string!) {
43+
alert("The \(n)th Fibonacci number is \(fib(n: n))")
44+
} else {
45+
alert("\(reply) is not a number :(")
4946
}

src/index.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import CodeMirror from "codemirror";
22

33
import "codemirror/mode/swift/swift";
44
import "codemirror/lib/codemirror.css";
5+
import { SwiftRuntime } from "javascript-kit-swift";
56
import kDefaultDemoScript from './demo.swift?raw';
67

78
const kCompileApi = "https://swiftwasm-compiler-api-mgv5x4syda-uc.a.run.app";
@@ -111,6 +112,25 @@ async function compileCode(code: string): Promise<CompilationResult> {
111112
}
112113
}
113114

115+
export const wrapWASI = (wasiObject: any) => {
116+
// PATCH: @wasmer-js/wasi@0.x forgets to call `refreshMemory` in `clock_res_get`,
117+
// which writes its result to memory view. Without the refresh the memory view,
118+
// it accesses a detached array buffer if the memory is grown by malloc.
119+
// But they wasmer team discarded the 0.x codebase at all and replaced it with
120+
// a new implementation written in Rust. The new version 1.x is really unstable
121+
// and not production-ready as far as katei investigated in Apr 2022.
122+
// So override the broken implementation of `clock_res_get` here instead of
123+
// fixing the wasi polyfill.
124+
// Reference: https://github.com/wasmerio/wasmer-js/blob/55fa8c17c56348c312a8bd23c69054b1aa633891/packages/wasi/src/index.ts#L557
125+
const original_clock_res_get = wasiObject.wasiImport["clock_res_get"];
126+
127+
wasiObject.wasiImport["clock_res_get"] = function() {
128+
wasiObject.refreshMemory();
129+
return Reflect.apply(original_clock_res_get, this, arguments);
130+
};
131+
return wasiObject.wasiImport;
132+
};
133+
114134
async function runWasm(wasmBuffer: ArrayBuffer) {
115135
writeOutputArea("Running WebAssembly...\n");
116136
const { WasmFs } = await import("@wasmer/wasmfs");
@@ -137,28 +157,20 @@ async function runWasm(wasmBuffer: ArrayBuffer) {
137157
fs: wasmFs.fs,
138158
},
139159
});
140-
141-
let _instance: WebAssembly.Instance;
142-
const importObject = {
143-
env: {
144-
executeScript: (ptr: number, len: number) => {
145-
const uint8Memory = new Uint8Array(
146-
(_instance.exports.memory as any).buffer
147-
);
148-
const script = decoder.decode(uint8Memory.subarray(ptr, ptr + len));
149-
new Function(script)();
150-
},
151-
},
152-
};
160+
const swift = new SwiftRuntime();
153161

154162
const { instance } = await WebAssembly.instantiate(wasmBuffer, {
155163
wasi_snapshot_preview1: wasi.wasiImport,
156164
wasi_unstable: wasi.wasiImport,
157-
...importObject,
165+
javascript_kit: swift.wasmImports as any,
158166
});
159167

160-
_instance = instance;
161-
wasi.start(instance);
168+
wasi.setMemory(instance.exports.memory as any);
169+
(instance.exports._initialize as any)();
170+
if (instance.exports.swjs_library_version) {
171+
swift.setInstance(instance);
172+
}
173+
(instance.exports.main as any)();
162174
}
163175

164176
function populateResultsArea(compileResult: CompilationResult) {

update-demo-wasm.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
curl 'https://swiftwasm-compiler-api-mgv5x4syda-uc.a.run.app/' \
2+
-o ./public/demo_compiled/program.wasm.txt \
3+
-H 'content-type: application/json' \
4+
--data-raw "$(jq -n --arg data "$(cat ./src/demo.swift)" '{"mainCode":$data,"action":"emitExecutable"}')"

0 commit comments

Comments
 (0)