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.
@@ -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
- };