Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/core/wasi-js/src/runtime.ts
1067 views
1
import WASI from "./wasi";
2
import type { WASIConfig } from "./types";
3
import nodeBindings from "./bindings/node";
4
import fs from "fs";
5
import { readFile } from "fs/promises";
6
import debug from "debug";
7
const log = debug("wasi");
8
9
interface Options {
10
noWasi?: boolean; // if true, include wasi
11
env?: object; // functions to include in the environment
12
dir?: string | null; // WASI pre-opened directory; default is to preopen /, i.e., full filesystem; explicitly set as null to sandbox.
13
time?: boolean;
14
}
15
16
async function wasmImport(name: string, options: Options = {}): Promise<void> {
17
const pathToWasm = `${name}${name.endsWith(".wasm") ? "" : ".wasm"}`;
18
19
function getrandom(bufPtr, bufLen, _flags) {
20
// NOTE: returning 0 here (our default stub behavior)
21
// would result in Python hanging on startup! So critical to do this.
22
nodeBindings.randomFillSync(
23
// @ts-ignore
24
new Uint8Array(result.instance.exports.memory.buffer),
25
bufPtr,
26
bufLen
27
);
28
return bufLen;
29
}
30
31
const wasmOpts: any = {
32
env: new Proxy(
33
{ getrandom, ...options?.env },
34
{
35
get(target, key) {
36
if (key in target) {
37
return Reflect.get(target, key);
38
}
39
log("WARNING: creating stub for", key);
40
return (..._args) => {
41
return 0;
42
};
43
},
44
}
45
),
46
};
47
48
let wasi: any = undefined;
49
if (!options?.noWasi) {
50
const opts: WASIConfig = {
51
args: process.argv,
52
bindings: nodeBindings,
53
env: process.env,
54
};
55
if (options.dir === null) {
56
// sandbox -- don't give any fs access
57
} else {
58
opts.bindings = {
59
...nodeBindings,
60
fs,
61
};
62
// just give full access; security of fs access isn't
63
// really relevant for us at this point
64
if (!options.dir) {
65
opts.preopens = { "/": "/" };
66
} else {
67
opts.preopens = { [options.dir]: options.dir };
68
}
69
}
70
wasi = new WASI(opts);
71
wasmOpts.wasi_snapshot_preview1 = wasi.wasiImport;
72
}
73
74
//console.log(`reading ${pathToWasm}`);
75
const source = await readFile(pathToWasm);
76
const typedArray = new Uint8Array(source);
77
const result = await WebAssembly.instantiate(typedArray, wasmOpts);
78
if (wasi != null) {
79
wasi.start(result.instance);
80
}
81
}
82
83
export async function run(name: string, options: Options = {}): Promise<void> {
84
await wasmImport(name, options);
85
}
86
87