Skip to content

Commit ac7d6f0

Browse files
author
Taois
committed
feat: 发布新版本
1 parent f07f372 commit ac7d6f0

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed

libs_drpy/qjs-wasm.js

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
const kWasmModule = Symbol('kWasmModule');
2+
const kWasmModuleRef = Symbol('kWasmModuleRef');
3+
const kWasmExports = Symbol('kWasmExports');
4+
const kWasmInstance = Symbol('kWasmInstance');
5+
const kWasmInstances = Symbol('kWasmInstances');
6+
const kWasiLinked = Symbol('kWasiLinked');
7+
const kWasiStarted = Symbol('kWasiStarted');
8+
const kWasiOptions = Symbol('kWasiOptions');
9+
10+
11+
class CompileError extends Error {
12+
constructor(...args) {
13+
super(...args);
14+
this.name = 'CompileError';
15+
}
16+
}
17+
18+
class LinkError extends Error {
19+
constructor(...args) {
20+
super(...args);
21+
this.name = 'LinkError';
22+
}
23+
}
24+
25+
class RuntimeError extends Error {
26+
constructor(...args) {
27+
super(...args);
28+
this.name = 'RuntimeError';
29+
}
30+
}
31+
32+
33+
function getWasmError(e) {
34+
switch (e.wasmError) {
35+
case 'CompileError':
36+
return new CompileError(e.message);
37+
case 'LinkError':
38+
return new LinkError(e.message);
39+
case 'RuntimeError':
40+
return new RuntimeError(e.message);
41+
default:
42+
return new TypeError(`Invalid WASM error: ${e.wasmError}`);
43+
}
44+
}
45+
46+
function callWasmFunction(name, ...args) {
47+
const instance = this;
48+
49+
try {
50+
return instance.callFunction(name, ...args);
51+
} catch (e) {
52+
if (e.wasmError) {
53+
throw getWasmError(e);
54+
} else {
55+
throw e;
56+
}
57+
}
58+
}
59+
60+
function buildInstance(mod) {
61+
try {
62+
return wasm.buildInstance(mod);
63+
} catch (e) {
64+
if (e.wasmError) {
65+
throw getWasmError(e);
66+
} else {
67+
throw e;
68+
}
69+
}
70+
}
71+
72+
function linkWasi(instance) {
73+
try {
74+
instance.linkWasi();
75+
} catch (e) {
76+
if (e.wasmError) {
77+
throw getWasmError(e);
78+
} else {
79+
throw e;
80+
}
81+
}
82+
}
83+
84+
function parseModule(buf) {
85+
try {
86+
return wasm.parseModule(buf);
87+
} catch (e) {
88+
if (e.wasmError) {
89+
throw getWasmError(e);
90+
} else {
91+
throw e;
92+
}
93+
}
94+
}
95+
96+
class Module {
97+
constructor(buf) {
98+
this[kWasmModule] = parseModule(buf);
99+
}
100+
101+
static exports(module) {
102+
return wasm.moduleExports(module[kWasmModule]);
103+
}
104+
105+
// eslint-disable-next-line no-unused-vars
106+
static imports(module) {
107+
// TODO.
108+
return {};
109+
}
110+
}
111+
112+
class Instance {
113+
constructor(module, importObject = {}) {
114+
const instance = buildInstance(module[kWasmModule]);
115+
116+
if (importObject.wasi_unstable) {
117+
linkWasi(instance);
118+
this[kWasiLinked] = true;
119+
}
120+
121+
const _exports = Module.exports(module);
122+
const exports = Object.create(null);
123+
124+
for (const item of _exports) {
125+
if (item.kind === 'function') {
126+
exports[item.name] = callWasmFunction.bind(instance, item.name);
127+
}
128+
}
129+
130+
this[kWasmInstance] = instance;
131+
this[kWasmExports] = Object.freeze(exports);
132+
this[kWasmModuleRef] = module;
133+
globalThis.WebAssembly[kWasmInstances].push(this);
134+
}
135+
136+
get exports() {
137+
return this[kWasmExports];
138+
}
139+
}
140+
141+
class WASI {
142+
wasiImport = 'w4s1'; // Doesn't matter right now.
143+
144+
constructor(options = {args: [], env: {}, preopens: {}}) {
145+
this[kWasiStarted] = false;
146+
147+
if (options === null || typeof options !== 'object') {
148+
throw new TypeError('options must be an object');
149+
}
150+
151+
this[kWasiOptions] = JSON.parse(JSON.stringify(options));
152+
}
153+
154+
start(instance) {
155+
if (this[kWasiStarted]) {
156+
throw new Error('WASI instance has already started');
157+
}
158+
159+
if (!instance[kWasiLinked]) {
160+
throw new Error('WASM instance doesn\'t have WASI linked');
161+
}
162+
163+
if (!instance.exports._start) {
164+
throw new TypeError('WASI entrypoint not found');
165+
}
166+
167+
this[kWasiStarted] = true;
168+
instance.exports._start(...(this[kWasiOptions].args ?? []));
169+
}
170+
}
171+
172+
class WebAssembly {
173+
Module = Module;
174+
Instance = Instance;
175+
CompileError = CompileError;
176+
LinkError = LinkError;
177+
RuntimeError = RuntimeError;
178+
WASI = WASI;
179+
180+
constructor() {
181+
this[kWasmInstances] = [];
182+
}
183+
184+
async compile(src) {
185+
return new Module(src);
186+
}
187+
188+
async instantiate(src, importObject) {
189+
const module = await this.compile(src);
190+
const instance = new Instance(module, importObject);
191+
192+
return {module, instance};
193+
}
194+
}
195+
196+
197+
Object.defineProperty(globalThis, 'WebAssembly', {
198+
enumerable: true, configurable: true, writable: true, value: new WebAssembly()
199+
});

0 commit comments

Comments
 (0)