porffor 0.60.7 → 0.60.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/compiler/2c.js +2 -2
- package/compiler/assemble.js +16 -3
- package/compiler/builtins/regexp.ts +180 -36
- package/compiler/builtins.js +348 -6
- package/compiler/builtins_precompiled.js +1099 -1099
- package/compiler/codegen.js +78 -12
- package/compiler/cyclone.js +2 -2
- package/compiler/disassemble.js +2 -2
- package/compiler/encoding.js +22 -4
- package/compiler/expression.js +0 -25
- package/compiler/opt.js +15 -15
- package/compiler/precompile.js +3 -3
- package/compiler/wrap.js +4 -1
- package/package.json +2 -2
- package/runtime/index.js +1 -1
- package/AGENTS.md +0 -20
- package/compiler/allocator.js +0 -65
- package/compiler/builtins_objects.js +0 -349
@@ -1,349 +0,0 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
2
|
-
import { TYPES } from './types.js';
|
3
|
-
import { number } from './encoding.js';
|
4
|
-
|
5
|
-
export default function ({ builtinFuncs }, Prefs) {
|
6
|
-
const makePrefix = name => (name.startsWith('__') ? '' : '__') + name + '_';
|
7
|
-
|
8
|
-
const done = new Set();
|
9
|
-
const object = (name, props) => {
|
10
|
-
done.add(name);
|
11
|
-
const prefix = name === 'globalThis' ? '' : makePrefix(name);
|
12
|
-
|
13
|
-
// already a func
|
14
|
-
const existingFunc = builtinFuncs[name];
|
15
|
-
|
16
|
-
builtinFuncs['#get_' + name] = {
|
17
|
-
params: [],
|
18
|
-
locals: [ Valtype.i32 ],
|
19
|
-
returns: [ Valtype.i32 ],
|
20
|
-
returnType: TYPES.object,
|
21
|
-
wasm: (scope, { allocPage, makeString, generate, getNodeType, builtin, funcRef, glbl }) => {
|
22
|
-
if (globalThis.precompile) return [ [ 'get object', name ] ];
|
23
|
-
|
24
|
-
// todo/perf: precompute bytes here instead of calling real funcs if we really care about perf later
|
25
|
-
|
26
|
-
let ptr;
|
27
|
-
if (existingFunc) {
|
28
|
-
ptr = funcRef(name)[0][1];
|
29
|
-
} else {
|
30
|
-
ptr = allocPage(scope, `builtin object: ${name}`);
|
31
|
-
}
|
32
|
-
|
33
|
-
const getPtr = glbl(Opcodes.global_get, `getptr_${name}`, Valtype.i32)[0];
|
34
|
-
const out = [
|
35
|
-
// check if already made/cached
|
36
|
-
getPtr,
|
37
|
-
[ Opcodes.if, Blocktype.void ],
|
38
|
-
getPtr,
|
39
|
-
[ Opcodes.return ],
|
40
|
-
[ Opcodes.end ],
|
41
|
-
|
42
|
-
// set cache & ptr for use
|
43
|
-
number(ptr, Valtype.i32),
|
44
|
-
[ Opcodes.local_tee, 0 ],
|
45
|
-
glbl(Opcodes.global_set, `getptr_${name}`, Valtype.i32)[0],
|
46
|
-
|
47
|
-
[ Opcodes.local_get, 0 ],
|
48
|
-
Opcodes.i32_from_u,
|
49
|
-
number(existingFunc ? TYPES.function : TYPES.object, Valtype.i32),
|
50
|
-
[ Opcodes.call, builtin('__Porffor_object_underlying') ],
|
51
|
-
[ Opcodes.drop ],
|
52
|
-
[ Opcodes.local_set, 0 ]
|
53
|
-
];
|
54
|
-
|
55
|
-
for (const x in props) {
|
56
|
-
let value = {
|
57
|
-
type: 'Identifier',
|
58
|
-
name: prefix + x
|
59
|
-
};
|
60
|
-
|
61
|
-
if (x === '__proto__') {
|
62
|
-
out.push(
|
63
|
-
[ Opcodes.local_get, 0 ],
|
64
|
-
number(TYPES.object, Valtype.i32),
|
65
|
-
|
66
|
-
...generate(scope, value),
|
67
|
-
Opcodes.i32_to_u,
|
68
|
-
...getNodeType(scope, value),
|
69
|
-
|
70
|
-
[ Opcodes.call, builtin('__Porffor_object_setPrototype') ]
|
71
|
-
);
|
72
|
-
continue;
|
73
|
-
}
|
74
|
-
|
75
|
-
let add = true;
|
76
|
-
if (existingFunc && (x === 'prototype' || x === 'constructor')) add = false;
|
77
|
-
|
78
|
-
let flags = 0b0000;
|
79
|
-
const d = props[x];
|
80
|
-
if (d.configurable) flags |= 0b0010;
|
81
|
-
if (d.enumerable) flags |= 0b0100;
|
82
|
-
if (d.writable) flags |= 0b1000;
|
83
|
-
|
84
|
-
out.push(
|
85
|
-
[ Opcodes.local_get, 0 ],
|
86
|
-
number(TYPES.object, Valtype.i32),
|
87
|
-
|
88
|
-
...makeString(scope, x),
|
89
|
-
Opcodes.i32_to_u,
|
90
|
-
number(TYPES.bytestring, Valtype.i32),
|
91
|
-
|
92
|
-
...generate(scope, value),
|
93
|
-
...getNodeType(scope, value),
|
94
|
-
|
95
|
-
number(flags, Valtype.i32),
|
96
|
-
number(TYPES.number, Valtype.i32),
|
97
|
-
|
98
|
-
[ Opcodes.call, builtin(add ? '__Porffor_object_fastAdd' : '__Porffor_object_define') ]
|
99
|
-
);
|
100
|
-
}
|
101
|
-
|
102
|
-
// return ptr
|
103
|
-
out.push(getPtr);
|
104
|
-
return out;
|
105
|
-
}
|
106
|
-
};
|
107
|
-
|
108
|
-
this[name] = (scope, { builtin }) => [
|
109
|
-
[ Opcodes.call, builtin('#get_' + name) ],
|
110
|
-
Opcodes.i32_from_u
|
111
|
-
];
|
112
|
-
this[name].type = existingFunc ? TYPES.function : TYPES.object;
|
113
|
-
|
114
|
-
for (const x in props) {
|
115
|
-
const d = props[x];
|
116
|
-
const k = prefix + x;
|
117
|
-
|
118
|
-
if (Object.hasOwn(d, 'value') && !Object.hasOwn(builtinFuncs, k) && !Object.hasOwn(this, k)) {
|
119
|
-
if (Array.isArray(d.value) || typeof d.value === 'function') {
|
120
|
-
this[k] = d.value;
|
121
|
-
continue;
|
122
|
-
}
|
123
|
-
|
124
|
-
if (typeof d.value === 'number') {
|
125
|
-
this[k] = [ number(d.value) ];
|
126
|
-
this[k].type = TYPES.number;
|
127
|
-
continue;
|
128
|
-
}
|
129
|
-
|
130
|
-
if (typeof d.value === 'string') {
|
131
|
-
this[k] = (scope, { makeString }) => makeString(scope, d.value);
|
132
|
-
this[k].type = TYPES.bytestring;
|
133
|
-
continue;
|
134
|
-
}
|
135
|
-
|
136
|
-
if (d.value === null) {
|
137
|
-
this[k] = this.null;
|
138
|
-
continue;
|
139
|
-
}
|
140
|
-
|
141
|
-
throw new Error(`unsupported value type (${typeof d.value})`);
|
142
|
-
}
|
143
|
-
}
|
144
|
-
};
|
145
|
-
|
146
|
-
const props = (base, vals) => {
|
147
|
-
const out = {};
|
148
|
-
|
149
|
-
if (Array.isArray(vals)) {
|
150
|
-
// array of keys with no value
|
151
|
-
for (const x of vals) {
|
152
|
-
out[x] = {
|
153
|
-
...base
|
154
|
-
};
|
155
|
-
}
|
156
|
-
} else for (const x in vals) {
|
157
|
-
// object of key values
|
158
|
-
out[x] = {
|
159
|
-
...base,
|
160
|
-
value: vals[x]
|
161
|
-
};
|
162
|
-
}
|
163
|
-
|
164
|
-
return out;
|
165
|
-
};
|
166
|
-
|
167
|
-
const builtinFuncKeys = Object.keys(builtinFuncs);
|
168
|
-
const autoFuncKeys = name => {
|
169
|
-
const prefix = makePrefix(name);
|
170
|
-
return builtinFuncKeys.filter(x => x.startsWith(prefix)).map(x => x.slice(prefix.length)).filter(x => !x.startsWith('prototype_'));
|
171
|
-
};
|
172
|
-
const autoFuncs = name => ({
|
173
|
-
...props({
|
174
|
-
writable: true,
|
175
|
-
enumerable: false,
|
176
|
-
configurable: true
|
177
|
-
}, autoFuncKeys(name)),
|
178
|
-
...(this[`__${name}_prototype`] ? {
|
179
|
-
prototype: {
|
180
|
-
writable: false,
|
181
|
-
enumerable: false,
|
182
|
-
configurable: false
|
183
|
-
}
|
184
|
-
} : {})
|
185
|
-
});
|
186
|
-
|
187
|
-
object('Math', {
|
188
|
-
...props({
|
189
|
-
writable: false,
|
190
|
-
enumerable: false,
|
191
|
-
configurable: false
|
192
|
-
}, {
|
193
|
-
E: Math.E,
|
194
|
-
LN10: Math.LN10,
|
195
|
-
LN2: Math.LN2,
|
196
|
-
LOG10E: Math.LOG10E,
|
197
|
-
LOG2E: Math.LOG2E,
|
198
|
-
PI: Math.PI,
|
199
|
-
SQRT1_2: Math.SQRT1_2,
|
200
|
-
SQRT2: Math.SQRT2,
|
201
|
-
|
202
|
-
// https://github.com/rwaldron/proposal-math-extensions/issues/10
|
203
|
-
RAD_PER_DEG: Math.PI / 180,
|
204
|
-
DEG_PER_RAD: 180 / Math.PI
|
205
|
-
}),
|
206
|
-
|
207
|
-
...autoFuncs('Math')
|
208
|
-
});
|
209
|
-
|
210
|
-
// automatically generate objects for prototypes
|
211
|
-
for (const x of builtinFuncKeys.reduce((acc, x) => {
|
212
|
-
const ind = x.indexOf('_prototype_');
|
213
|
-
if (ind === -1) return acc;
|
214
|
-
|
215
|
-
acc.add(x.slice(0, ind + 10));
|
216
|
-
return acc;
|
217
|
-
}, new Set())) {
|
218
|
-
const props = autoFuncs(x);
|
219
|
-
|
220
|
-
// special case: Object.prototype.__proto__ = null
|
221
|
-
if (x === '__Object_prototype') {
|
222
|
-
Object.defineProperty(props, '__proto__', { value: { value: null, configurable: true }, enumerable: true });
|
223
|
-
}
|
224
|
-
|
225
|
-
// special case: Function.prototype.length = 0
|
226
|
-
// special case: Function.prototype.name = ''
|
227
|
-
if (x === '__Function_prototype') {
|
228
|
-
props.length = { value: 0, configurable: true };
|
229
|
-
props.name = { value: '', configurable: true };
|
230
|
-
}
|
231
|
-
|
232
|
-
// add constructor for constructors
|
233
|
-
const name = x.slice(2, x.indexOf('_', 2));
|
234
|
-
if (builtinFuncs[name]?.constr) {
|
235
|
-
const value = (scope, { funcRef }) => funcRef(name);
|
236
|
-
value.type = TYPES.function;
|
237
|
-
|
238
|
-
props.constructor = {
|
239
|
-
value,
|
240
|
-
writable: true,
|
241
|
-
enumerable: false,
|
242
|
-
configurable: true
|
243
|
-
};
|
244
|
-
}
|
245
|
-
|
246
|
-
object(x, props);
|
247
|
-
}
|
248
|
-
|
249
|
-
|
250
|
-
object('Number', {
|
251
|
-
...props({
|
252
|
-
writable: false,
|
253
|
-
enumerable: false,
|
254
|
-
configurable: false
|
255
|
-
}, {
|
256
|
-
NaN: NaN,
|
257
|
-
POSITIVE_INFINITY: Infinity,
|
258
|
-
NEGATIVE_INFINITY: -Infinity,
|
259
|
-
MAX_VALUE: valtype === 'i32' ? 2147483647 : 1.7976931348623157e+308,
|
260
|
-
MIN_VALUE: valtype === 'i32' ? -2147483648 : 5e-324,
|
261
|
-
MAX_SAFE_INTEGER: valtype === 'i32' ? 2147483647 : 9007199254740991,
|
262
|
-
MIN_SAFE_INTEGER: valtype === 'i32' ? -2147483648 : -9007199254740991,
|
263
|
-
EPSILON: 2.220446049250313e-16
|
264
|
-
}),
|
265
|
-
|
266
|
-
...autoFuncs('Number')
|
267
|
-
});
|
268
|
-
|
269
|
-
// these technically not spec compliant as it should be classes or non-enumerable but eh
|
270
|
-
object('navigator', {
|
271
|
-
...props({
|
272
|
-
writable: false,
|
273
|
-
enumerable: true,
|
274
|
-
configurable: false
|
275
|
-
}, {
|
276
|
-
userAgent: `Porffor/${globalThis.version}`
|
277
|
-
})
|
278
|
-
});
|
279
|
-
|
280
|
-
for (const x of [
|
281
|
-
'console',
|
282
|
-
'crypto',
|
283
|
-
'performance',
|
284
|
-
]) {
|
285
|
-
object(x, props({
|
286
|
-
writable: true,
|
287
|
-
enumerable: true,
|
288
|
-
configurable: true
|
289
|
-
}, autoFuncKeys(x).slice(0, 12)));
|
290
|
-
}
|
291
|
-
|
292
|
-
for (const x of [ 'Array', 'ArrayBuffer', 'Atomics', 'Date', 'Error', 'JSON', 'Object', 'Promise', 'Reflect', 'String', 'Symbol', 'Uint8Array', 'Int8Array', 'Uint8ClampedArray', 'Uint16Array', 'Int16Array', 'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array', 'BigInt64Array', 'BigUint64Array', 'SharedArrayBuffer', 'BigInt', 'Boolean', 'DataView', 'AggregateError', 'TypeError', 'ReferenceError', 'SyntaxError', 'RangeError', 'EvalError', 'URIError', 'Function', 'Map', 'RegExp', 'Set', 'WeakMap', 'WeakRef', 'WeakSet' ]) {
|
293
|
-
object(x, autoFuncs(x));
|
294
|
-
}
|
295
|
-
|
296
|
-
const enumerableGlobals = [ 'atob', 'btoa', 'performance', 'crypto', 'navigator' ];
|
297
|
-
object('globalThis', {
|
298
|
-
// 19.1 Value Properties of the Global Object
|
299
|
-
// https://tc39.es/ecma262/#sec-value-properties-of-the-global-object
|
300
|
-
// 19.1.1 globalThis
|
301
|
-
globalThis: {
|
302
|
-
writable: true,
|
303
|
-
enumerable: false,
|
304
|
-
configurable: true
|
305
|
-
},
|
306
|
-
|
307
|
-
// 19.1.2 Infinity
|
308
|
-
// 19.1.3 NaN
|
309
|
-
// 19.1.4 undefined
|
310
|
-
...props({
|
311
|
-
writable: false,
|
312
|
-
enumerable: false,
|
313
|
-
configurable: false
|
314
|
-
}, [ 'Infinity', 'NaN', 'undefined' ]),
|
315
|
-
|
316
|
-
// 19.2 Function Properties of the Global Object
|
317
|
-
// https://tc39.es/ecma262/#sec-function-properties-of-the-global-object
|
318
|
-
// 19.3 Constructor Properties of the Global Object
|
319
|
-
// https://tc39.es/ecma262/#sec-constructor-properties-of-the-global-object
|
320
|
-
...props({
|
321
|
-
writable: true,
|
322
|
-
enumerable: false,
|
323
|
-
configurable: true
|
324
|
-
}, builtinFuncKeys.filter(x => !x.startsWith('__') && !enumerableGlobals.includes(x) && !x.startsWith('f64') && !x.startsWith('i32'))),
|
325
|
-
|
326
|
-
...props({
|
327
|
-
writable: true,
|
328
|
-
enumerable: true,
|
329
|
-
configurable: true
|
330
|
-
}, enumerableGlobals)
|
331
|
-
});
|
332
|
-
|
333
|
-
if (Prefs.logMissingObjects) for (const x of Object.keys(builtinFuncs).concat(Object.keys(this))) {
|
334
|
-
if (!x.startsWith('__')) continue;
|
335
|
-
const name = x.split('_').slice(2, -1).join('_');
|
336
|
-
|
337
|
-
let t = globalThis;
|
338
|
-
for (const x of name.split('_')) {
|
339
|
-
t = t[x];
|
340
|
-
if (!t) break;
|
341
|
-
}
|
342
|
-
if (!t) continue;
|
343
|
-
|
344
|
-
if (!done.has(name) && !done.has('__' + name)) {
|
345
|
-
console.log(name, !!builtinFuncs[name]);
|
346
|
-
done.add(name);
|
347
|
-
}
|
348
|
-
}
|
349
|
-
};
|