1 Commits
v2.0.5 ... main

Author SHA1 Message Date
=
830c0a7586 update wfa.js,
reduce clobbering of global namespaces
2025-10-02 21:56:39 +00:00
3 changed files with 70 additions and 51 deletions

View File

@@ -1,11 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script src="dist/wfa.js" type="module"></script>
<script src="wfa.js" type="module"></script>
<script type="module">
import wfaInit from "./dist/wfa.js";
window.addEventListener("DOMContentLoaded", () => {
import wfaInit from "./wfa.js";
wfaInit("dist/wfa.wasm");
window.addEventListener("DOMContentLoaded", () => {
document.querySelector("#submit").addEventListener("click", () => {
a = document.querySelector("#a").value
b = document.querySelector("#b").value
@@ -15,8 +15,8 @@
o: 0,
e: 1
};
const { score, CIGAR } = global.wfAlign(a, b, penalties, true);
const alignment = global.DecodeCIGAR(CIGAR);
const { score, CIGAR } = global.wfa.wfAlign(a, b, penalties, true);
const alignment = global.wfa.DecodeCIGAR(CIGAR);
document.querySelector("#result").innerText = `${score}, ${CIGAR}, ${alignment}`;
})
});

View File

@@ -7,8 +7,8 @@ import (
func main() {
c := make(chan bool)
js.Global().Set("wfAlign", js.FuncOf(wfAlign))
js.Global().Set("DecodeCIGAR", js.FuncOf(DecodeCIGAR))
js.Global().Get("wfa").Set("wfAlign", js.FuncOf(wfAlign))
js.Global().Get("wfa").Set("DecodeCIGAR", js.FuncOf(DecodeCIGAR))
<-c
}

91
wfa.js
View File

@@ -1,5 +1,3 @@
// wasm_exec.js from tinygo
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -134,6 +132,7 @@
const decoder = new TextDecoder("utf-8");
let reinterpretBuf = new DataView(new ArrayBuffer(8));
var logLine = [];
const wasmExit = {}; // thrown to exit via proc_exit (not an error)
global.Go = class {
constructor() {
@@ -272,14 +271,11 @@
fd_close: () => 0, // dummy
fd_fdstat_get: () => 0, // dummy
fd_seek: () => 0, // dummy
"proc_exit": (code) => {
if (global.process) {
// Node.js
process.exit(code);
} else {
// Can't exit in a browser.
throw 'trying to exit with code ' + code;
}
proc_exit: (code) => {
this.exited = true;
this.exitCode = code;
this._resolveExitPromise();
throw wasmExit;
},
random_get: (bufPtr, bufLen) => {
crypto.getRandomValues(loadSlice(bufPtr, bufLen));
@@ -287,20 +283,30 @@
},
},
gojs: {
// func ticks() float64
// func ticks() int64
"runtime.ticks": () => {
return timeOrigin + performance.now();
return BigInt((timeOrigin + performance.now()) * 1e6);
},
// func sleepTicks(timeout float64)
// func sleepTicks(timeout int64)
"runtime.sleepTicks": (timeout) => {
// Do not sleep, only reactivate scheduler after the given timeout.
setTimeout(this._inst.exports.go_scheduler, timeout);
setTimeout(() => {
if (this.exited) return;
try {
this._inst.exports.go_scheduler();
} catch (e) {
if (e !== wasmExit) throw e;
}
}, Number(timeout)/1e6);
},
// func finalizeRef(v ref)
"syscall/js.finalizeRef": (v_ref) => {
const id = mem().getUint32(unboxValue(v_ref), true);
// Note: TinyGo does not support finalizers so this is only called
// for one specific case, by js.go:jsString. and can/might leak memory.
const id = v_ref & 0xffffffffn;
if (this._goRefCounts?.[id] !== undefined) {
this._goRefCounts[id]--;
if (this._goRefCounts[id] === 0) {
const v = this._values[id];
@@ -308,10 +314,14 @@
this._ids.delete(v);
this._idPool.push(id);
}
} else {
console.error("syscall/js.finalizeRef: unknown id", id);
}
},
// func stringVal(value string) ref
"syscall/js.stringVal": (value_ptr, value_len) => {
value_ptr >>>= 0;
const s = loadString(value_ptr, value_len);
return boxValue(s);
},
@@ -472,21 +482,25 @@
this._ids = new Map(); // mapping from JS values to reference ids
this._idPool = []; // unused ids that have been garbage collected
this.exited = false; // whether the Go program has exited
this.exitCode = 0;
while (true) {
const callbackPromise = new Promise((resolve) => {
this._resolveCallbackPromise = () => {
if (this.exited) {
throw new Error("bad callback: Go program has already exited");
}
setTimeout(resolve, 0); // make sure it is asynchronous
};
if (this._inst.exports._start) {
let exitPromise = new Promise((resolve, reject) => {
this._resolveExitPromise = resolve;
});
// Run program, but catch the wasmExit exception that's thrown
// to return back here.
try {
this._inst.exports._start();
if (this.exited) {
break;
} catch (e) {
if (e !== wasmExit) throw e;
}
await callbackPromise;
await exitPromise;
return this.exitCode;
} else {
this._inst.exports._initialize();
}
}
@@ -494,7 +508,11 @@
if (this.exited) {
throw new Error("Go program has already exited");
}
try {
this._inst.exports.resume();
} catch (e) {
if (e !== wasmExit) throw e;
}
if (this.exited) {
this._resolveExitPromise();
}
@@ -524,8 +542,9 @@
}
const go = new Go();
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
return go.run(result.instance);
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then(async (result) => {
let exitCode = await go.run(result.instance);
process.exit(exitCode);
}).catch((err) => {
console.error(err);
process.exit(1);
@@ -537,22 +556,22 @@
export default function init (path) {
return new Promise ((res) => {
const go = new Go();
var wasm;
if ('instantiateStreaming' in WebAssembly) {
WebAssembly.instantiateStreaming(fetch(path), go.importObject).then(function (obj) {
wasm = obj.instance;
const run = (obj) => {
const wasm = obj.instance;
global.wfa = wasm
go.run(wasm);
res()
}
if ('instantiateStreaming' in WebAssembly) {
WebAssembly.instantiateStreaming(fetch(path), go.importObject).then(function (obj) {
run(obj)
})
} else {
fetch(path).then(resp =>
resp.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {
wasm = obj.instance;
go.run(wasm);
res()
run(obj)
})
)
}