-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathloader.js
128 lines (116 loc) · 4.11 KB
/
loader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
;const eval = globalThis.eval;
const loadModules = async (bytecode) => {
if (typeof bytecode === "string") bytecode = new Uint8Array([...atob(bytecode)].map(e => e.charCodeAt()));
let memory = { buffer: null };
share: {
const TypedArray = Uint8Array.__proto__;
const decode = TextDecoder.prototype.decode;
TextDecoder.prototype.decode = function (buffer, ...a) {
if (!buffer) return '';
return decode.call(this, new Uint8Array(new Uint8Array(buffer)), ...a);
}
const send = WebSocket.prototype.send;
WebSocket.prototype.send = function (buffer) {
return send.call(this, new Uint8Array(new Uint8Array(buffer)));
}
const { get: getByteLength } = Object.getOwnPropertyDescriptor(TypedArray.prototype, 'byteLength');
Object.defineProperty(TypedArray.prototype, 'byteLength', {
get() {
if (this.byteOffset === 0 && getByteLength.call(this) === this.buffer.byteLength) {
if (this.buffer.constructor.name === 'SharedArrayBuffer' && this.buffer !== memory.buffer) {
return 0;
}
}
return getByteLength.call(this);
}
})
};
memory = await new Promise(res => {
WebAssembly.instantiateStreaming = async (r, i) => WebAssembly.instantiate(await (await r).arrayBuffer(), i);
WebAssembly.instantiate = ((inst) => {
const SEC_MEM = 5;
const read = (array, pos = 0) => ({
pos: pos,
array,
vu() {
let val = 0;
let i = 0;
do {
val |= (array[this.pos] & 0x7F) << i;
i += 7;
} while (array[this.pos++] & 0x80);
return val;
},
u8() {
return array[this.pos++];
},
left() {
return array.length - this.pos;
}
})
return async (buffer, imports) => {
if (!(buffer instanceof ArrayBuffer) && !(buffer instanceof Uint8Array)) return inst(buffer, imports);
let bytes = new Uint8Array(buffer);
const r = read(Array.from(bytes), 8);
while (r.left() >= 0) {
let secPos = r.pos;
const id = r.u8();
const len = r.vu();
if (id !== SEC_MEM) {
r.pos += len;
continue;
}
let memPos = r.pos;
r.u8();
if (r.array[r.pos] & 0b11) break;
r.array[r.pos++] |= 0b11; // 0b10=shared, 0b01=has max
r.vu();
let max = 65536;
do {
r.array.splice(r.pos, 0, max & 0x7F);
max >>= 7;
if (max) r.array[r.pos] |= 0x80;
r.pos += 1;
} while (max);
r.array[secPos + 1] = r.pos - memPos;
break;
}
bytes = new Uint8Array(r.array);
const wasm = await inst(bytes, imports);
res(Object.values(wasm.instance.exports).find((val) => val.buffer));
return wasm;
}
})(WebAssembly.instantiate);
});
let evalwithref = null;
const wmod = await WebAssembly.compile(bytecode);
// for evalling
const HEAPU8 = () => new Uint8Array(memory.buffer);
const HEAP32 = () => new Int32Array(memory.buffer);
const HEAP64 = () => new BigInt64Array(memory.buffer);
const HEAPF32 = () => new Float32Array(memory.buffer);
const HEAPF64 = () => new Float64Array(memory.buffer);
const decodeUTF8 = (charCodes) => new TextDecoder().decode(charCodes);
const decodeFromMemory = (addr) => decodeUTF8(HEAPU8().subarray(addr, HEAPU8().indexOf(0, addr)));
const wasm = await WebAssembly.instantiate(wmod, {
env: {
memory,
d: () => {debugger},
as: (addr) => top.alert(decodeFromMemory(addr)),
ls: (addr) => top.console.log(decodeFromMemory(addr)),
lf: (val) =>top.console.log(val),
li: (val) => top.console.log(val),
e: (...argv) => evalwithref(...argv)
}
});
// for evalling
const pop = wasm.exports.pop;
const push = wasm.exports.push;
const alloc = wasm.exports.alloc;
const free = wasm.exports.free;
// Link layer 1
evalwithref = (body, ref) => {
eval(decodeFromMemory(body))((data) => wasm.exports.call(ref, data));
}
if (wasm.exports.main) wasm.exports.main();
};