porffor 0.57.19 → 0.57.21
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/compiler/assemble.js +382 -324
- package/compiler/codegen.js +2 -3
- package/compiler/encoding.js +22 -0
- package/compiler/wrap.js +5 -41
- package/foo.js +17 -1
- package/package.json +1 -1
- package/r.js +243 -0
- package/runtime/index.js +1 -1
package/compiler/assemble.js
CHANGED
@@ -1,61 +1,10 @@
|
|
1
1
|
import { Valtype, FuncType, ExportDesc, Section, Magic, Opcodes, PageSize, Reftype } from './wasmSpec.js';
|
2
|
-
import {
|
2
|
+
import { unsignedLEB128_length, signedLEB128_length } from './encoding.js';
|
3
3
|
import { importedFuncs } from './builtins.js';
|
4
4
|
import { log } from './log.js';
|
5
5
|
import './prefs.js';
|
6
6
|
|
7
|
-
const createSection = (type, data) => [
|
8
|
-
type,
|
9
|
-
...encodeVector(data)
|
10
|
-
];
|
11
|
-
|
12
|
-
const customSection = (name, data) => createSection(
|
13
|
-
Section.custom,
|
14
|
-
[ ...encodeString(name), ...data ]
|
15
|
-
);
|
16
|
-
|
17
|
-
const encodeNames = funcs => {
|
18
|
-
const encodeSection = (id, section) => [
|
19
|
-
id,
|
20
|
-
...unsignedLEB128(section.length),
|
21
|
-
...section
|
22
|
-
];
|
23
|
-
|
24
|
-
const moduleSection = encodeString('js'); // TODO: filename?
|
25
|
-
const functionsSection = encodeVector(
|
26
|
-
funcs.map(x => unsignedLEB128(x.asmIndex).concat(encodeString(x.name))),
|
27
|
-
);
|
28
|
-
const localsSection = encodeVector(
|
29
|
-
funcs.map(x => unsignedLEB128(x.asmIndex).concat(encodeVector(
|
30
|
-
Object.entries(x.locals).map(([name, local]) =>
|
31
|
-
unsignedLEB128(local.idx).concat(encodeString(name))
|
32
|
-
)
|
33
|
-
)))
|
34
|
-
);
|
35
|
-
|
36
|
-
return [
|
37
|
-
...encodeSection(0, moduleSection),
|
38
|
-
...encodeSection(1, functionsSection),
|
39
|
-
...encodeSection(2, localsSection),
|
40
|
-
];
|
41
|
-
};
|
42
|
-
|
43
7
|
export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
44
|
-
const types = [], typeCache = {};
|
45
|
-
|
46
|
-
const getType = (params, returns) => {
|
47
|
-
const hash = `${params.join(',')}_${returns.join(',')}`;
|
48
|
-
if (Prefs.optLog) log('assemble', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
|
49
|
-
if (typeCache[hash] !== undefined) return typeCache[hash];
|
50
|
-
|
51
|
-
const type = [ FuncType, ...encodeVector(params), ...encodeVector(returns) ];
|
52
|
-
const idx = types.length;
|
53
|
-
|
54
|
-
types.push(type);
|
55
|
-
|
56
|
-
return typeCache[hash] = idx;
|
57
|
-
};
|
58
|
-
|
59
8
|
let t = performance.now();
|
60
9
|
const time = msg => {
|
61
10
|
if (!Prefs.profileAssemble) return;
|
@@ -64,71 +13,189 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
64
13
|
t = performance.now();
|
65
14
|
};
|
66
15
|
|
67
|
-
let importFuncs =
|
16
|
+
let importFuncs = globalThis.importFuncs = [];
|
17
|
+
globalThis.importDelta = 0;
|
68
18
|
if (!Prefs.treeshakeWasmImports || noTreeshake) {
|
69
19
|
importFuncs = Array.from(importedFuncs);
|
70
20
|
} else {
|
71
|
-
let imports = new Map();
|
72
|
-
|
73
21
|
// tree shake imports
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
22
|
+
const remap = new WeakMap();
|
23
|
+
for (let i = 0; i < funcs.length; i++) {
|
24
|
+
const f = funcs[i];
|
25
|
+
if (f.usesImports) for (let j = 0; j < f.wasm.length; j++) {
|
26
|
+
const x = f.wasm[j];
|
27
|
+
if (x[0] === Opcodes.call && x[1] < importedFuncs.length) {
|
28
|
+
const idx = x[1];
|
78
29
|
const func = importedFuncs[idx];
|
79
30
|
|
80
|
-
if (!
|
81
|
-
|
31
|
+
if (!remap.has(func)) {
|
32
|
+
remap.set(func, importFuncs.length);
|
33
|
+
importFuncs.push(func);
|
34
|
+
}
|
35
|
+
x[1] = remap.get(func);
|
82
36
|
}
|
83
37
|
}
|
84
38
|
}
|
85
39
|
|
86
|
-
|
87
|
-
|
40
|
+
globalThis.importDelta = importedFuncs.length - importFuncs.length;
|
41
|
+
}
|
42
|
+
|
43
|
+
if (Prefs.optLog) log('assemble', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
44
|
+
time('import treeshake');
|
45
|
+
|
46
|
+
// todo: this will just break if it is too small
|
47
|
+
let bufferSize = 1024 * 1024; // 1MB
|
48
|
+
let buffer = new Uint8Array(bufferSize);
|
49
|
+
let offset = 0;
|
50
|
+
|
51
|
+
const ensureBufferSize = added => {
|
52
|
+
if (offset + added >= bufferSize - 64) {
|
53
|
+
const newBuffer = new Uint8Array(bufferSize *= 2);
|
54
|
+
newBuffer.set(buffer);
|
55
|
+
buffer = null; // help gc
|
56
|
+
buffer = newBuffer;
|
57
|
+
}
|
58
|
+
};
|
59
|
+
|
60
|
+
const byte = byte => {
|
61
|
+
ensureBufferSize(1);
|
62
|
+
buffer[offset++] = byte;
|
63
|
+
};
|
64
|
+
|
65
|
+
const array = array => {
|
66
|
+
ensureBufferSize(array.length);
|
67
|
+
buffer.set(array, offset);
|
68
|
+
offset += array.length;
|
69
|
+
};
|
70
|
+
|
71
|
+
const unsigned = n => {
|
72
|
+
n |= 0;
|
73
|
+
if (n >= 0 && n <= 127) return byte(n);
|
74
|
+
|
75
|
+
do {
|
76
|
+
let x = n & 0x7f;
|
77
|
+
n >>>= 7;
|
78
|
+
if (n !== 0) {
|
79
|
+
x |= 0x80;
|
80
|
+
}
|
81
|
+
|
82
|
+
byte(x);
|
83
|
+
} while (n !== 0);
|
84
|
+
};
|
85
|
+
|
86
|
+
const signed = n => {
|
87
|
+
n |= 0;
|
88
|
+
if (n >= 0 && n <= 63) return byte(n);
|
89
|
+
|
90
|
+
while (true) {
|
91
|
+
let x = n & 0x7f;
|
92
|
+
n >>= 7;
|
93
|
+
|
94
|
+
if ((n === 0 && (x & 0x40) === 0) || (n === -1 && (x & 0x40) !== 0)) {
|
95
|
+
byte(x);
|
96
|
+
break;
|
97
|
+
} else {
|
98
|
+
x |= 0x80;
|
99
|
+
}
|
100
|
+
|
101
|
+
byte(x);
|
102
|
+
}
|
103
|
+
};
|
104
|
+
|
105
|
+
const ieee754 = n => {
|
106
|
+
ensureBufferSize(8);
|
107
|
+
array(new Uint8Array(new Float64Array([ n ]).buffer));
|
108
|
+
};
|
109
|
+
|
110
|
+
const string = str => {
|
111
|
+
unsigned(str.length);
|
112
|
+
for (let i = 0; i < str.length; i++) {
|
113
|
+
byte(str.charCodeAt(i));
|
114
|
+
}
|
115
|
+
};
|
116
|
+
|
117
|
+
const section = (id, bytes) => {
|
118
|
+
byte(id);
|
119
|
+
unsigned(bytes);
|
120
|
+
};
|
121
|
+
|
122
|
+
const unsignedPost = () => {
|
123
|
+
const o = offset;
|
124
|
+
offset += 5;
|
125
|
+
return n => {
|
126
|
+
const o2 = offset;
|
127
|
+
offset = o;
|
128
|
+
unsigned(n);
|
129
|
+
|
130
|
+
buffer.set(buffer.subarray(o + 5, o2), offset);
|
131
|
+
offset = o2 - (5 - (offset - o));
|
132
|
+
};
|
133
|
+
};
|
134
|
+
|
135
|
+
array(Magic, Magic.length);
|
136
|
+
time('setup');
|
137
|
+
|
138
|
+
const types = [], typeCache = new Map();
|
139
|
+
const getType = (params, returns) => {
|
140
|
+
const hash = `${params.join()}_${returns.join()}`;
|
141
|
+
if (typeCache.has(hash)) return typeCache.get(hash);
|
142
|
+
|
143
|
+
const type = [ FuncType, params.length, ...params, returns.length, ...returns ];
|
144
|
+
const idx = types.length;
|
145
|
+
|
146
|
+
types.push(type);
|
147
|
+
typeCache.set(hash, idx);
|
148
|
+
return idx;
|
149
|
+
};
|
150
|
+
|
151
|
+
// precache all types to be used
|
152
|
+
for (let i = 0; i < funcs.length; i++) {
|
153
|
+
const func = funcs[i];
|
154
|
+
getType(func.params, func.returns);
|
88
155
|
}
|
89
156
|
|
90
|
-
for (
|
91
|
-
|
157
|
+
for (let i = 0; i < importFuncs.length; i++) {
|
158
|
+
const func = importFuncs[i];
|
159
|
+
getType(func.params, func.returns);
|
92
160
|
}
|
93
161
|
|
94
|
-
|
162
|
+
for (let i = 0; i < tags.length; i++) {
|
163
|
+
const tag = tags[i];
|
164
|
+
getType(tag.params, tag.results);
|
165
|
+
}
|
95
166
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
167
|
+
section(Section.type, unsignedLEB128_length(types.length) + types.reduce((acc, x) => acc + x.length, 0));
|
168
|
+
unsigned(types.length);
|
169
|
+
for (let i = 0; i < types.length; i++) {
|
170
|
+
array(types[i]);
|
171
|
+
}
|
172
|
+
time('type section');
|
173
|
+
|
174
|
+
if (importFuncs.length > 0) {
|
175
|
+
section(Section.import, unsignedLEB128_length(importFuncs.length) + importFuncs.length * 5);
|
176
|
+
unsigned(importFuncs.length);
|
177
|
+
for (let i = 0; i < importFuncs.length; i++) {
|
178
|
+
const x = importFuncs[i];
|
179
|
+
byte(0); byte(1);
|
180
|
+
byte(x.import.charCodeAt(0));
|
181
|
+
byte(ExportDesc.func);
|
182
|
+
byte(getType(x.params, x.returns));
|
183
|
+
}
|
184
|
+
}
|
106
185
|
time('import section');
|
107
186
|
|
108
|
-
const
|
109
|
-
Section.func,
|
110
|
-
encodeVector(funcs.map(x => getType(x.params, x.returns))) // type indexes
|
111
|
-
);
|
112
|
-
time('func section');
|
187
|
+
const indirectFuncs = [], exportFuncs = [];
|
113
188
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
Section.element,
|
125
|
-
encodeVector([ [
|
126
|
-
0x00,
|
127
|
-
Opcodes.i32_const, 0, Opcodes.end,
|
128
|
-
...encodeVector(indirectFuncs.map(x => unsignedLEB128(x.asmIndex)))
|
129
|
-
] ])
|
130
|
-
);
|
131
|
-
time('element section');
|
189
|
+
section(Section.func, unsignedLEB128_length(funcs.length) + funcs.length);
|
190
|
+
unsigned(funcs.length);
|
191
|
+
for (let i = 0; i < funcs.length; i++) {
|
192
|
+
const x = funcs[i];
|
193
|
+
byte(getType(x.params, x.returns));
|
194
|
+
|
195
|
+
if (x.indirect) indirectFuncs.push(x);
|
196
|
+
if (x.export) exportFuncs.push(x);
|
197
|
+
}
|
198
|
+
time('func section');
|
132
199
|
|
133
200
|
if (pages.has('func lut')) {
|
134
201
|
if (data.addedFuncArgcLut) {
|
@@ -182,285 +249,276 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
182
249
|
}
|
183
250
|
time('func lut');
|
184
251
|
|
185
|
-
|
186
|
-
|
252
|
+
if (funcs.table) {
|
253
|
+
section(Section.table, unsignedLEB128_length(indirectFuncs.length) + 3);
|
254
|
+
byte(1); // table count
|
255
|
+
byte(Reftype.funcref); byte(0); // table type
|
256
|
+
unsigned(indirectFuncs.length); // table size
|
257
|
+
time('table section');
|
258
|
+
}
|
187
259
|
|
188
|
-
|
260
|
+
if (Prefs.alwaysMemory && pages.size === 0) pages.set('--always-memory', 0);
|
261
|
+
const usesMemory = pages.size > 0;
|
262
|
+
if (usesMemory) {
|
263
|
+
const pageCount = Math.ceil((pages.size * pageSize) / PageSize);
|
264
|
+
section(Section.memory, unsignedLEB128_length(pageCount) + 2);
|
265
|
+
byte(1); // memory count
|
266
|
+
byte(0); // memory type
|
267
|
+
unsigned(pageCount); // memory size
|
268
|
+
time('memory section');
|
269
|
+
}
|
270
|
+
|
271
|
+
const usesTags = tags.length > 0;
|
272
|
+
if (usesTags) {
|
273
|
+
section(Section.tag, unsignedLEB128_length(tags.length) + tags.length * 2);
|
274
|
+
unsigned(tags.length);
|
275
|
+
for (let i = 0; i < tags.length; i++) {
|
276
|
+
const x = tags[i];
|
277
|
+
byte(0); // tag type
|
278
|
+
byte(getType(x.params, x.results)); // tag signature
|
279
|
+
}
|
280
|
+
time('tag section');
|
281
|
+
}
|
282
|
+
|
283
|
+
const globalsValues = Object.values(globals);
|
189
284
|
if (globalsValues.length > 0) {
|
190
|
-
|
285
|
+
section(Section.global, unsignedLEB128_length(globalsValues.length) + globalsValues.length * 4
|
286
|
+
+ globalsValues.reduce((acc, x) => acc + (x.type === Valtype.f64 ? 8 : signedLEB128_length(x.init ?? 0)), 0));
|
287
|
+
unsigned(globalsValues.length);
|
191
288
|
for (let i = 0; i < globalsValues.length; i++) {
|
192
|
-
const
|
193
|
-
|
194
|
-
switch (global.type) {
|
289
|
+
const x = globalsValues[i];
|
290
|
+
switch (x.type) {
|
195
291
|
case Valtype.i32:
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
292
|
+
byte(Valtype.i32);
|
293
|
+
byte(0x01);
|
294
|
+
byte(Opcodes.i32_const);
|
295
|
+
signed(x.init ?? 0);
|
200
296
|
break;
|
201
297
|
|
202
298
|
case Valtype.i64:
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
299
|
+
byte(Valtype.i64);
|
300
|
+
byte(0x01);
|
301
|
+
byte(Opcodes.i64_const);
|
302
|
+
signed(x.init ?? 0);
|
207
303
|
break;
|
208
304
|
|
209
305
|
case Valtype.f64:
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
306
|
+
byte(Valtype.f64);
|
307
|
+
byte(0x01);
|
308
|
+
byte(Opcodes.f64_const);
|
309
|
+
ieee754(x.init ?? 0);
|
214
310
|
break;
|
215
311
|
}
|
312
|
+
|
313
|
+
byte(Opcodes.end);
|
216
314
|
}
|
315
|
+
time('global section');
|
316
|
+
}
|
217
317
|
|
218
|
-
|
318
|
+
if (exportFuncs.length > 0 || usesMemory || usesTags) {
|
319
|
+
byte(Section.export);
|
320
|
+
const sizeOffset = offset, setSize = unsignedPost();
|
219
321
|
|
220
|
-
|
322
|
+
unsigned(exportFuncs.length + usesMemory + usesTags);
|
323
|
+
if (usesMemory) {
|
324
|
+
string('$');
|
325
|
+
byte(ExportDesc.mem); byte(0);
|
326
|
+
}
|
327
|
+
if (usesTags) {
|
328
|
+
string('0');
|
329
|
+
byte(ExportDesc.tag); byte(0);
|
330
|
+
}
|
221
331
|
|
222
|
-
|
223
|
-
|
332
|
+
for (let i = 0; i < exportFuncs.length; i++) {
|
333
|
+
const x = exportFuncs[i];
|
334
|
+
string(x.name === '#main' ? 'm' : x.name);
|
335
|
+
byte(ExportDesc.func);
|
336
|
+
unsigned(x.index - importDelta);
|
337
|
+
}
|
338
|
+
|
339
|
+
setSize(offset - sizeOffset - 5);
|
340
|
+
time('export section');
|
224
341
|
}
|
225
|
-
time('global section');
|
226
342
|
|
227
|
-
if (
|
343
|
+
if (funcs.table) {
|
344
|
+
section(Section.element, unsignedLEB128_length(indirectFuncs.length) + 5 + indirectFuncs.reduce((acc, x) => acc + unsignedLEB128_length(x.index - importDelta), 0));
|
345
|
+
byte(1); // table index
|
346
|
+
byte(0); // element type
|
347
|
+
byte(Opcodes.i32_const); byte(0); byte(Opcodes.end); // offset
|
228
348
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
// export first tag if used
|
248
|
-
if (tags.length !== 0) exports.unshift([ ...encodeString('0'), ExportDesc.tag, 0x00 ]);
|
249
|
-
time('tag section');
|
250
|
-
|
251
|
-
const exportSection = createSection(
|
252
|
-
Section.export,
|
253
|
-
encodeVector(exports)
|
254
|
-
);
|
255
|
-
time('export section');
|
256
|
-
|
257
|
-
let codeSection = [];
|
349
|
+
unsigned(indirectFuncs.length);
|
350
|
+
for (let i = 0; i < indirectFuncs.length; i++) {
|
351
|
+
const x = indirectFuncs[i];
|
352
|
+
unsigned(x.index - importDelta);
|
353
|
+
}
|
354
|
+
time('element section');
|
355
|
+
}
|
356
|
+
|
357
|
+
if (data.length > 0) {
|
358
|
+
section(Section.data_count, unsignedLEB128_length(data.length));
|
359
|
+
unsigned(data.length);
|
360
|
+
time('data count section');
|
361
|
+
}
|
362
|
+
|
363
|
+
byte(Section.code);
|
364
|
+
const codeSectionSizeOffset = offset, setCodeSectionSize = unsignedPost();
|
365
|
+
|
366
|
+
unsigned(funcs.length);
|
258
367
|
for (let i = 0; i < funcs.length; i++) {
|
368
|
+
const funcSizeOffset = offset, setFuncSize = unsignedPost();
|
369
|
+
|
259
370
|
const x = funcs[i];
|
260
371
|
const locals = Object.values(x.locals).sort((a, b) => a.idx - b.idx);
|
261
372
|
|
262
373
|
const paramCount = x.params.length;
|
263
|
-
let
|
374
|
+
let declCount = 0, lastType, typeCount = 0;
|
264
375
|
for (let i = paramCount; i <= locals.length; i++) {
|
265
376
|
const local = locals[i];
|
266
|
-
if (
|
267
|
-
unsignedLEB128_into(typeCount, localDecl);
|
268
|
-
localDecl.push(lastType);
|
269
|
-
typeCount = 0;
|
377
|
+
if (lastType && local?.type !== lastType) {
|
270
378
|
declCount++;
|
271
379
|
}
|
272
380
|
|
273
|
-
typeCount++;
|
274
381
|
lastType = local?.type;
|
275
382
|
}
|
383
|
+
unsigned(declCount);
|
276
384
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
o[1] > 127
|
286
|
-
) {
|
287
|
-
const n = o[1];
|
288
|
-
o = [ o[0] ];
|
289
|
-
unsignedLEB128_into(n, o);
|
290
|
-
}
|
291
|
-
|
292
|
-
// encode f64.const ops as ieee754 from raw number
|
293
|
-
if (o[0] === Opcodes.f64_const) {
|
294
|
-
const n = o[1];
|
295
|
-
o = ieee754_binary64(n);
|
296
|
-
if (o.length === 8) o.unshift(Opcodes.f64_const);
|
297
|
-
}
|
298
|
-
|
299
|
-
// encode call ops as unsigned leb128 from raw number
|
300
|
-
if ((o[0] === Opcodes.call /* || o[0] === Opcodes.return_call */) && o[1] >= importedFuncs.length) {
|
301
|
-
const n = o[1] - importDelta;
|
302
|
-
o = [ Opcodes.call ];
|
303
|
-
unsignedLEB128_into(n, o);
|
304
|
-
}
|
305
|
-
|
306
|
-
// encode call indirect ops as types from info
|
307
|
-
if (o[0] === Opcodes.call_indirect) {
|
308
|
-
o = [...o];
|
309
|
-
const params = [];
|
310
|
-
for (let i = 0; i < o[1]; i++) {
|
311
|
-
params.push(valtypeBinary, Valtype.i32);
|
312
|
-
}
|
313
|
-
|
314
|
-
let returns = [ valtypeBinary, Valtype.i32 ];
|
315
|
-
if (o.at(-1) === 'no_type_return') {
|
316
|
-
o.pop();
|
317
|
-
returns = [ valtypeBinary ];
|
318
|
-
}
|
319
|
-
|
320
|
-
o[1] = getType(params, returns);
|
321
|
-
}
|
385
|
+
lastType = undefined;
|
386
|
+
for (let i = paramCount; i <= locals.length; i++) {
|
387
|
+
const local = locals[i];
|
388
|
+
if (lastType && local?.type !== lastType) {
|
389
|
+
unsigned(typeCount);
|
390
|
+
byte(lastType);
|
391
|
+
typeCount = 0;
|
392
|
+
}
|
322
393
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
wasm.push(x);
|
327
|
-
}
|
394
|
+
typeCount++;
|
395
|
+
lastType = local?.type;
|
396
|
+
}
|
328
397
|
|
329
|
-
|
398
|
+
for (let i = 0; i < x.wasm.length; i++) {
|
399
|
+
let o = x.wasm[i];
|
400
|
+
const op = o[0];
|
401
|
+
|
402
|
+
// encode local/global ops as unsigned leb128 from raw number
|
403
|
+
if (
|
404
|
+
(op >= Opcodes.local_get && op <= Opcodes.global_set) &&
|
405
|
+
o[1] > 127
|
406
|
+
) {
|
407
|
+
byte(op);
|
408
|
+
unsigned(o[1]);
|
409
|
+
continue;
|
330
410
|
}
|
331
411
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
// encode local/global ops as unsigned leb128 from raw number
|
339
|
-
if (
|
340
|
-
(op >= Opcodes.local_get && op <= Opcodes.global_set) &&
|
341
|
-
o[1] > 127
|
342
|
-
) {
|
343
|
-
wasm.push(op);
|
344
|
-
unsignedLEB128_into(o[1], wasm);
|
345
|
-
continue;
|
346
|
-
}
|
412
|
+
// encode f64.const ops as ieee754 from raw number
|
413
|
+
if (op === Opcodes.f64_const) {
|
414
|
+
byte(op);
|
415
|
+
ieee754(o[1]);
|
416
|
+
continue;
|
417
|
+
}
|
347
418
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
419
|
+
// encode call ops as unsigned leb128 from raw number
|
420
|
+
if ((op === Opcodes.call /* || o[0] === Opcodes.return_call */) && o[1] >= importedFuncs.length) {
|
421
|
+
byte(op);
|
422
|
+
unsigned(o[1] - importDelta);
|
423
|
+
continue;
|
424
|
+
}
|
354
425
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
426
|
+
// encode call indirect ops as types from info
|
427
|
+
if (op === Opcodes.call_indirect) {
|
428
|
+
const params = [];
|
429
|
+
for (let i = 0; i < o[1]; i++) {
|
430
|
+
params.push(valtypeBinary, Valtype.i32);
|
360
431
|
}
|
361
432
|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
}
|
368
|
-
|
369
|
-
let returns = [ valtypeBinary, Valtype.i32 ];
|
370
|
-
if (o.at(-1) === 'no_type_return') {
|
371
|
-
returns = [ valtypeBinary ];
|
372
|
-
}
|
373
|
-
|
374
|
-
wasm.push(op, getType(params, returns), o[2]);
|
375
|
-
continue;
|
376
|
-
}
|
433
|
+
byte(op);
|
434
|
+
byte(getType(params, [ valtypeBinary, Valtype.i32 ]));
|
435
|
+
byte(o[2]);
|
436
|
+
continue;
|
437
|
+
}
|
377
438
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
}
|
439
|
+
for (let j = 0; j < o.length; j++) {
|
440
|
+
const x = o[j];
|
441
|
+
if (x == null || !(x <= 0xff)) continue;
|
442
|
+
buffer[offset++] = x;
|
383
443
|
}
|
384
444
|
}
|
385
445
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
446
|
+
byte(Opcodes.end);
|
447
|
+
setFuncSize(offset - funcSizeOffset - 5);
|
448
|
+
}
|
449
|
+
|
450
|
+
setCodeSectionSize(offset - codeSectionSizeOffset - 5);
|
451
|
+
time('code section');
|
452
|
+
|
453
|
+
section(Section.data, unsignedLEB128_length(data.length) + data.reduce((acc, x) =>
|
454
|
+
acc + (x.page != null ? (3 + signedLEB128_length(pages.allocs.get(x.page) ?? (pages.get(x.page) * pageSize))) : 1)
|
455
|
+
+ unsignedLEB128_length(x.bytes.length) + x.bytes.length, 0));
|
456
|
+
|
457
|
+
unsigned(data.length);
|
458
|
+
for (let i = 0; i < data.length; i++) {
|
459
|
+
const x = data[i];
|
460
|
+
if (x.page != null) { // active
|
461
|
+
let offset = pages.allocs.get(x.page) ?? (pages.get(x.page) * pageSize);
|
462
|
+
if (offset === 0) offset = 16;
|
463
|
+
|
464
|
+
byte(0x00);
|
465
|
+
byte(Opcodes.i32_const);
|
466
|
+
signed(offset);
|
467
|
+
byte(Opcodes.end);
|
468
|
+
} else { // passive
|
469
|
+
byte(0x01);
|
399
470
|
}
|
400
471
|
|
401
|
-
|
472
|
+
unsigned(x.bytes.length);
|
473
|
+
array(x.bytes);
|
402
474
|
}
|
475
|
+
time('data section');
|
403
476
|
|
404
|
-
|
405
|
-
|
406
|
-
|
477
|
+
if (Prefs.d) {
|
478
|
+
byte(Section.custom);
|
479
|
+
const totalSizeOffset = offset, setTotalSize = unsignedPost();
|
480
|
+
string('name');
|
407
481
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
482
|
+
const section = (id, cb) => {
|
483
|
+
byte(id);
|
484
|
+
const sizeOffset = offset, setSize = unsignedPost();
|
485
|
+
cb();
|
486
|
+
setSize(offset - sizeOffset - 5);
|
487
|
+
};
|
413
488
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
dataSection.push(0x00, Opcodes.i32_const, ...signedLEB128(offset), Opcodes.end);
|
425
|
-
} else {
|
426
|
-
// type: passive
|
427
|
-
dataSection.push(0x01);
|
489
|
+
section(0, () => { // module
|
490
|
+
string('js'); // todo: filename?
|
491
|
+
});
|
492
|
+
|
493
|
+
section(1, () => { // funcs
|
494
|
+
unsigned(funcs.length);
|
495
|
+
for (let i = 0; i < funcs.length; i++) {
|
496
|
+
const x = funcs[i];
|
497
|
+
unsigned(x.index - importDelta);
|
498
|
+
string(x.name);
|
428
499
|
}
|
500
|
+
});
|
429
501
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
);
|
502
|
+
section(2, () => { // locals
|
503
|
+
unsigned(funcs.length);
|
504
|
+
for (let i = 0; i < funcs.length; i++) {
|
505
|
+
const x = funcs[i];
|
506
|
+
unsigned(x.index - importDelta);
|
507
|
+
|
508
|
+
const locals = Object.keys(x.locals);
|
509
|
+
unsigned(locals.length);
|
510
|
+
for (let j = 0; j < locals.length; j++) {
|
511
|
+
const name = locals[j];
|
512
|
+
unsigned(x.locals[name]);
|
513
|
+
string(name);
|
514
|
+
}
|
437
515
|
}
|
438
|
-
}
|
516
|
+
});
|
439
517
|
|
440
|
-
|
441
|
-
|
518
|
+
setTotalSize(offset - totalSizeOffset - 5);
|
519
|
+
time('name section');
|
442
520
|
}
|
443
521
|
|
444
|
-
|
445
|
-
|
446
|
-
unsignedLEB128(data.length)
|
447
|
-
);
|
448
|
-
time('data section');
|
449
|
-
|
450
|
-
return Uint8Array.from([
|
451
|
-
...Magic,
|
452
|
-
...typeSection,
|
453
|
-
...importSection,
|
454
|
-
...funcSection,
|
455
|
-
...tableSection,
|
456
|
-
...memorySection,
|
457
|
-
...tagSection,
|
458
|
-
...globalSection,
|
459
|
-
...exportSection,
|
460
|
-
...elementSection,
|
461
|
-
...dataCountSection,
|
462
|
-
...codeSection,
|
463
|
-
...dataSection,
|
464
|
-
...nameSection
|
465
|
-
]);
|
522
|
+
buffer = buffer.subarray(0, offset);
|
523
|
+
return buffer;
|
466
524
|
};
|
package/compiler/codegen.js
CHANGED
@@ -2516,6 +2516,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2516
2516
|
const wrapperArgc = Prefs.indirectWrapperArgc ?? 10;
|
2517
2517
|
const underflow = wrapperArgc - args.length;
|
2518
2518
|
for (let i = 0; i < underflow; i++) args.push(DEFAULT_VALUE());
|
2519
|
+
if (args.length > wrapperArgc) args = args.slice(0, wrapperArgc);
|
2519
2520
|
|
2520
2521
|
for (let i = 0; i < args.length; i++) {
|
2521
2522
|
const arg = args[i];
|
@@ -2715,9 +2716,7 @@ const generateThis = (scope, decl) => {
|
|
2715
2716
|
|
2716
2717
|
if (!scope.constr && !scope.method) {
|
2717
2718
|
// this in a non-constructor context is a reference to globalThis
|
2718
|
-
return
|
2719
|
-
...generate(scope, { type: 'Identifier', name: 'globalThis' })
|
2720
|
-
];
|
2719
|
+
return generate(scope, { type: 'Identifier', name: 'globalThis' });
|
2721
2720
|
}
|
2722
2721
|
|
2723
2722
|
// opt: do not check for pure constructors or strict mode
|
package/compiler/encoding.js
CHANGED
@@ -84,6 +84,28 @@ export const unsignedLEB128_length = n => {
|
|
84
84
|
return length;
|
85
85
|
};
|
86
86
|
|
87
|
+
export const signedLEB128_length = n => {
|
88
|
+
if (n >= -64 && n <= 63) return 1;
|
89
|
+
if (n >= -8192 && n <= 8191) return 2;
|
90
|
+
if (n >= -1048576 && n <= 1048575) return 3;
|
91
|
+
if (n >= -134217728 && n <= 134217727) return 4;
|
92
|
+
|
93
|
+
let length = 0;
|
94
|
+
while (true) {
|
95
|
+
let byte = n & 0x7f;
|
96
|
+
n >>= 7;
|
97
|
+
|
98
|
+
if ((n === 0 && (byte & 0x40) === 0) || (n === -1 && (byte & 0x40) !== 0)) {
|
99
|
+
length++;
|
100
|
+
break;
|
101
|
+
} else {
|
102
|
+
length++;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
return length;
|
107
|
+
};
|
108
|
+
|
87
109
|
export const big_signedLEB128 = n => {
|
88
110
|
// just input for small numbers (for perf as common)
|
89
111
|
if (n >= 0n && n <= 63n) return [ Number(n) ];
|
package/compiler/wrap.js
CHANGED
@@ -401,7 +401,7 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
401
401
|
const surrounding = Prefs.backtraceSurrounding ?? 10;
|
402
402
|
let min = middleIndex - surrounding;
|
403
403
|
let max = middleIndex + surrounding + 1;
|
404
|
-
if (Prefs.backtraceFunc || middleIndex
|
404
|
+
if (Prefs.backtraceFunc || middleIndex === -1) {
|
405
405
|
min = 0;
|
406
406
|
max = func.wasm.length;
|
407
407
|
}
|
@@ -415,7 +415,7 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
415
415
|
longest = Math.max(longest, noAnsi(disasm[j])?.length ?? 0);
|
416
416
|
}
|
417
417
|
|
418
|
-
if (middleIndex
|
418
|
+
if (middleIndex !== -1) {
|
419
419
|
const middle = Math.floor(disasm.length / 2);
|
420
420
|
disasm[middle] = `\x1B[47m\x1B[30m${noAnsi(disasm[middle])}${'\u00a0'.repeat(longest - noAnsi(disasm[middle]).length)}\x1B[0m`;
|
421
421
|
}
|
@@ -429,47 +429,11 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
429
429
|
if (funcInd == null || blobOffset == null ||
|
430
430
|
Number.isNaN(funcInd) || Number.isNaN(blobOffset) || Prefs.backtrace === false) return false;
|
431
431
|
|
432
|
-
|
433
|
-
const func = funcs.find(x => x.asmIndex === funcInd);
|
432
|
+
const func = funcs.find(x => (x.index - importDelta) === funcInd);
|
434
433
|
if (!func) return false;
|
435
434
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
let i = 0;
|
440
|
-
for (; i < wasm.length; i++) {
|
441
|
-
let mismatch = false;
|
442
|
-
for (let j = 0; j < toFind.length; j++) {
|
443
|
-
if (wasm[i + j] !== toFind[j]) {
|
444
|
-
mismatch = true;
|
445
|
-
break;
|
446
|
-
}
|
447
|
-
}
|
448
|
-
|
449
|
-
if (!mismatch) break;
|
450
|
-
}
|
451
|
-
|
452
|
-
if (i === wasm.length) {
|
453
|
-
printBacktrace(-1, func, funcs, globals, exceptions);
|
454
|
-
return false;
|
455
|
-
}
|
456
|
-
|
457
|
-
const offset = (blobOffset - i) - encodeVector(localDecl).length;
|
458
|
-
|
459
|
-
let cumLen = 0;
|
460
|
-
i = 0;
|
461
|
-
for (; i < assembledWasmOps.length; i++) {
|
462
|
-
cumLen += assembledWasmOps[i].filter(x => x != null && x <= 0xff).length;
|
463
|
-
if (cumLen === offset) break;
|
464
|
-
}
|
465
|
-
|
466
|
-
if (cumLen !== offset) {
|
467
|
-
printBacktrace(-1, func, funcs, globals, exceptions);
|
468
|
-
return false;
|
469
|
-
}
|
470
|
-
|
471
|
-
printBacktrace(i + 1, func, funcs, globals, exceptions);
|
472
|
-
return true;
|
435
|
+
printBacktrace(-1, func, funcs, globals, exceptions);
|
436
|
+
return false;
|
473
437
|
};
|
474
438
|
|
475
439
|
const t2 = performance.now();
|
package/foo.js
CHANGED
@@ -1 +1,17 @@
|
|
1
|
-
|
1
|
+
import compile from './compiler/wrap.js';
|
2
|
+
import { Worker, isMainThread } from 'node:worker_threads';
|
3
|
+
|
4
|
+
import { join } from 'node:path';
|
5
|
+
const __dirname = import.meta.dirname;
|
6
|
+
const __filename = join(__dirname, 'foo.js');
|
7
|
+
|
8
|
+
if (isMainThread) {
|
9
|
+
const worker = new Worker(__filename);
|
10
|
+
} else {
|
11
|
+
for (let i = 0; i < 500; i++) {
|
12
|
+
const js = `console.log(globalThis);`;
|
13
|
+
const out = compile(js);
|
14
|
+
out.exports.main();
|
15
|
+
console.log(i);
|
16
|
+
}
|
17
|
+
}
|
package/package.json
CHANGED
package/r.js
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
function isConfigurable(obj, name) {
|
2
|
+
if (Object.hasOwn(obj, name)) return Object.getOwnPropertyDescriptor(obj, name).configurable;
|
3
|
+
return true;
|
4
|
+
}
|
5
|
+
|
6
|
+
function isEnumerable(obj, name) {
|
7
|
+
return Object.hasOwn(obj, name) && Object.getOwnPropertyDescriptor(obj, name).enumerable;
|
8
|
+
}
|
9
|
+
|
10
|
+
function isSameValue(a, b) {
|
11
|
+
if (a === 0 && b === 0) return 1 / a === 1 / b;
|
12
|
+
if (a !== a && b !== b) return true;
|
13
|
+
|
14
|
+
return a === b;
|
15
|
+
}
|
16
|
+
|
17
|
+
function isWritable(obj, name, verifyProp, value) {
|
18
|
+
if (Object.hasOwn(obj, name) && Object.getOwnPropertyDescriptor(obj, name).writable != null) return Object.getOwnPropertyDescriptor(obj, name).writable;
|
19
|
+
if (!Object.hasOwn(obj, name) && Object.isExtensible(obj)) return true;
|
20
|
+
|
21
|
+
var unlikelyValue = Array.isArray(obj) && name === "length" ?
|
22
|
+
Math.pow(2, 32) - 1 :
|
23
|
+
"unlikelyValue";
|
24
|
+
var newValue = value || unlikelyValue;
|
25
|
+
var hadValue = Object.hasOwn(obj, name);
|
26
|
+
var oldValue = obj[name];
|
27
|
+
var writeSucceeded;
|
28
|
+
|
29
|
+
try {
|
30
|
+
obj[name] = newValue;
|
31
|
+
} catch {}
|
32
|
+
|
33
|
+
writeSucceeded = isSameValue(obj[verifyProp || name], newValue);
|
34
|
+
|
35
|
+
if (writeSucceeded) {
|
36
|
+
if (hadValue) {
|
37
|
+
obj[name] = oldValue;
|
38
|
+
} else {
|
39
|
+
delete obj[name];
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
return writeSucceeded;
|
44
|
+
}
|
45
|
+
|
46
|
+
function verifyProperty(obj, name, desc, options) {
|
47
|
+
var originalDesc = Object.getOwnPropertyDescriptor(obj, name);
|
48
|
+
|
49
|
+
if (desc === undefined) {
|
50
|
+
if (originalDesc !== undefined) {
|
51
|
+
throw new Test262Error('verifyProperty: expected undefined descriptor');
|
52
|
+
}
|
53
|
+
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
|
57
|
+
if (!Object.hasOwn(obj, name)) throw new Test262Error('verifyProperty: obj should have own property');
|
58
|
+
|
59
|
+
if (Object.hasOwn(desc, 'value')) {
|
60
|
+
const v = desc.value;
|
61
|
+
if (!isSameValue(originalDesc.value, v)) throw new Test262Error('verifyProperty: descriptor value mismatch');
|
62
|
+
// if (!isSameValue(obj[name], v)) throw new Test262Error('verifyProperty: object value mismatch');
|
63
|
+
}
|
64
|
+
|
65
|
+
if (Object.hasOwn(desc, 'enumerable')) {
|
66
|
+
if (desc.enumerable !== originalDesc.enumerable ||
|
67
|
+
desc.enumerable !== isEnumerable(obj, name)) {
|
68
|
+
throw new Test262Error('enumerable fail');
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
if (Object.hasOwn(desc, 'writable')) {
|
73
|
+
if (desc.writable !== originalDesc.writable ||
|
74
|
+
desc.writable !== isWritable(obj, name)) {
|
75
|
+
throw new Test262Error('writable fail');
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
if (Object.hasOwn(desc, 'configurable')) {
|
80
|
+
if (desc.configurable !== originalDesc.configurable ||
|
81
|
+
desc.configurable !== isConfigurable(obj, name)) {
|
82
|
+
throw new Test262Error('configurable fail');
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
if (options && options.restore) {
|
87
|
+
Object.defineProperty(obj, name, originalDesc);
|
88
|
+
}
|
89
|
+
|
90
|
+
return true;
|
91
|
+
}
|
92
|
+
|
93
|
+
function verifyEqualTo(obj, name, value) {
|
94
|
+
if (!isSameValue(obj[name], value)) {
|
95
|
+
throw new Test262Error('propertyHelper verifyEqualTo failed');
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
function verifyWritable(obj, name, verifyProp, value) {
|
100
|
+
if (!verifyProp) {
|
101
|
+
if (!Object.getOwnPropertyDescriptor(obj, name).writable)
|
102
|
+
throw new Test262Error('propertyHelper verifyWritable failed');
|
103
|
+
}
|
104
|
+
|
105
|
+
if (!isWritable(obj, name, verifyProp, value)) {
|
106
|
+
throw new Test262Error('propertyHelper verifyWritable failed');
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
function verifyNotWritable(obj, name, verifyProp, value) {
|
111
|
+
if (!verifyProp) {
|
112
|
+
if (Object.getOwnPropertyDescriptor(obj, name).writable)
|
113
|
+
throw new Test262Error('propertyHelper verifyNotWritable failed');
|
114
|
+
}
|
115
|
+
|
116
|
+
if (isWritable(obj, name, verifyProp)) {
|
117
|
+
throw new Test262Error('propertyHelper verifyNotWritable failed');
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
function verifyEnumerable(obj, name) {
|
122
|
+
if (!isEnumerable(obj, name)) {
|
123
|
+
throw new Test262Error('propertyHelper verifyEnumerable failed');
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
function verifyNotEnumerable(obj, name) {
|
128
|
+
if (isEnumerable(obj, name)) {
|
129
|
+
throw new Test262Error('propertyHelper verifyNotEnumerable failed');
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
function verifyConfigurable(obj, name) {
|
134
|
+
if (!isConfigurable(obj, name)) {
|
135
|
+
throw new Test262Error('propertyHelper verifyConfigurable failed');
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
function verifyNotConfigurable(obj, name) {
|
140
|
+
if (isConfigurable(obj, name)) {
|
141
|
+
throw new Test262Error('propertyHelper verifyNotConfigurable failed');
|
142
|
+
}
|
143
|
+
}
|
144
|
+
var assert = mustBeTrue => {
|
145
|
+
if (mustBeTrue === true) {
|
146
|
+
return;
|
147
|
+
}
|
148
|
+
|
149
|
+
throw new Test262Error('assert failed');
|
150
|
+
};
|
151
|
+
assert; // idk why exactly but this fixes many tests by forcing indirect ref
|
152
|
+
|
153
|
+
var __assert_throws = (expectedErrorConstructor, func) => {
|
154
|
+
if (typeof func !== 'function') {
|
155
|
+
throw new Test262Error('assert.throws invoked with a non-function value');
|
156
|
+
}
|
157
|
+
|
158
|
+
try {
|
159
|
+
func();
|
160
|
+
} catch {
|
161
|
+
return;
|
162
|
+
}
|
163
|
+
|
164
|
+
throw new Test262Error('assert.throws failed');
|
165
|
+
};
|
166
|
+
|
167
|
+
var __assert__isSameValue = (a, b) => {
|
168
|
+
if (a === b) {
|
169
|
+
// Handle +/-0 vs. -/+0
|
170
|
+
return a !== 0 || 1 / a === 1 / b;
|
171
|
+
}
|
172
|
+
|
173
|
+
// Handle NaN vs. NaN
|
174
|
+
return a !== a && b !== b;
|
175
|
+
};
|
176
|
+
|
177
|
+
var __assert_sameValue = (actual, expected) => {
|
178
|
+
if (assert._isSameValue(actual, expected)) {
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
|
182
|
+
throw new Test262Error('assert.sameValue failed');
|
183
|
+
};
|
184
|
+
|
185
|
+
var __assert_notSameValue = (actual, unexpected) => {
|
186
|
+
if (!assert._isSameValue(actual, unexpected)) {
|
187
|
+
return;
|
188
|
+
}
|
189
|
+
|
190
|
+
throw new Test262Error('assert.notSameValue failed');
|
191
|
+
};
|
192
|
+
// define our $262 here too
|
193
|
+
// var $262 = {
|
194
|
+
// global: globalThis,
|
195
|
+
// gc() { /* noop */ },
|
196
|
+
// detachArrayBuffer(buffer) {
|
197
|
+
// return Porffor.arraybuffer.detach(buffer);
|
198
|
+
// },
|
199
|
+
// getGlobal(name) {
|
200
|
+
// return globalThis[name];
|
201
|
+
// },
|
202
|
+
// // todo: setGlobal
|
203
|
+
// destroy() { /* noop */ },
|
204
|
+
// agent: {}
|
205
|
+
// };
|
206
|
+
|
207
|
+
// function Test262Error(message) {
|
208
|
+
// this.message = message;
|
209
|
+
// this.name = 'Test262Error';
|
210
|
+
// }
|
211
|
+
|
212
|
+
// var __Test262Error_thrower = message => {
|
213
|
+
// throw new Test262Error(message);
|
214
|
+
// };
|
215
|
+
|
216
|
+
var $DONOTEVALUATE = () => {
|
217
|
+
throw 'Test262: This statement should not be evaluated.';
|
218
|
+
};
|
219
|
+
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
|
220
|
+
// This code is governed by the BSD license found in the LICENSE file.
|
221
|
+
/*---
|
222
|
+
esid: sec-array-constructor
|
223
|
+
description: >
|
224
|
+
Property descriptor of Array
|
225
|
+
info: |
|
226
|
+
22.1.1 The Array Constructor
|
227
|
+
|
228
|
+
* is the initial value of the Array property of the global object.
|
229
|
+
|
230
|
+
17 ECMAScript Standard Built-in Objects
|
231
|
+
|
232
|
+
Every other data property described in clauses 18 through 26 and in Annex B.2
|
233
|
+
has the attributes { [[Writable]]: true, [[Enumerable]]: false,
|
234
|
+
[[Configurable]]: true } unless otherwise specified.
|
235
|
+
includes: [propertyHelper.js]
|
236
|
+
---*/
|
237
|
+
|
238
|
+
verifyProperty(this, 'Array', {
|
239
|
+
value: Array,
|
240
|
+
writable: true,
|
241
|
+
enumerable: false,
|
242
|
+
configurable: true,
|
243
|
+
});
|