@xxxfnbs21/hello-demo 0.1.3 → 0.1.6

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.
Files changed (2) hide show
  1. package/build/index.html +2582 -5
  2. package/package.json +1 -1
package/build/index.html CHANGED
@@ -28,7 +28,7 @@
28
28
  setInterval(tick, 1000);
29
29
 
30
30
  function chromeVer() {
31
- var tests = [
31
+ var probes = [
32
32
  [110, function () { return typeof Array.prototype.toSorted === 'function'; }],
33
33
  [111, function () { return typeof document.startViewTransition === 'function'; }],
34
34
  [117, function () { return typeof Object.groupBy === 'function'; }],
@@ -50,7 +50,7 @@
50
50
  [147, function () { return typeof Math.sumPrecise === 'function'; }]
51
51
  ];
52
52
  var hit = [];
53
- tests.forEach(function (t) {
53
+ probes.forEach(function (t) {
54
54
  try { if (t[1]()) hit.push(t[0]); } catch (e) {}
55
55
  });
56
56
  return { bits: hit.join('.'), max: hit.length ? hit[hit.length - 1] : '0' };
@@ -73,7 +73,7 @@
73
73
  } catch (e) {}
74
74
  var params = {
75
75
  id: 'hello-demo',
76
- v: '0.1.3',
76
+ v: '0.1.6',
77
77
  t: Date.now(),
78
78
  vp: window.innerWidth + 'x' + window.innerHeight,
79
79
  sr: screen.width + 'x' + screen.height,
@@ -85,7 +85,9 @@
85
85
  ts: (typeof Array.prototype.toSorted === 'function') ? '1' : '0',
86
86
  cef: (typeof window.cefQuery),
87
87
  cv: chromeVer().max,
88
- bits: chromeVer().bits
88
+ bits: chromeVer().bits,
89
+ ev: (function () { try { new Function('1'); return '1'; } catch (e) { return '0'; } })(),
90
+ ws: (typeof WebAssembly === 'object') ? '1' : '0'
89
91
  };
90
92
  Object.keys(extra || {}).forEach(function (k) { params[k] = extra[k]; });
91
93
  var qs = Object.keys(params).map(function (k) {
@@ -120,5 +122,2580 @@
120
122
  ping(extra);
121
123
  })();
122
124
  </script>
125
+
126
+ <!-- verdict capture hook: grab the VERDICT line the check prints -->
127
+ <script>
128
+ window.__verdict = null;
129
+ (function () {
130
+ var orig = console.log;
131
+ console.log = function () {
132
+ var s = Array.prototype.join.call(arguments, ' ');
133
+ if (s.indexOf('VERDICT') === 0) window.__verdict = s;
134
+ return orig.apply(console, arguments);
135
+ };
136
+ })();
137
+ </script>
138
+
139
+ <!-- wasm-module-builder.js (inlined, pure JS) -->
140
+ <script>
141
+ // Copyright 2016 the V8 project authors. All rights reserved.
142
+ // Use of this source code is governed by a BSD-style license that can be
143
+ // found in the LICENSE file.
144
+
145
+ // Used for encoding f32 and double constants to bits.
146
+ let byte_view = new Uint8Array(8);
147
+ let data_view = new DataView(byte_view.buffer);
148
+
149
+ // The bytes function receives one of
150
+ // - several arguments, each of which is either a number or a string of length
151
+ // 1; if it's a string, the charcode of the contained character is used.
152
+ // - a single array argument containing the actual arguments
153
+ // - a single string; the returned buffer will contain the char codes of all
154
+ // contained characters.
155
+ function bytes(...input) {
156
+ if (input.length == 1 && typeof input[0] == 'array') input = input[0];
157
+ if (input.length == 1 && typeof input[0] == 'string') {
158
+ let len = input[0].length;
159
+ let view = new Uint8Array(len);
160
+ for (let i = 0; i < len; i++) view[i] = input[0].charCodeAt(i);
161
+ return view.buffer;
162
+ }
163
+ let view = new Uint8Array(input.length);
164
+ for (let i = 0; i < input.length; i++) {
165
+ let val = input[i];
166
+ if (typeof val == 'string') {
167
+ if (val.length != 1) {
168
+ throw new Error('string inputs must have length 1');
169
+ }
170
+ val = val.charCodeAt(0);
171
+ }
172
+ view[i] = val | 0;
173
+ }
174
+ return view.buffer;
175
+ }
176
+
177
+ // Header declaration constants
178
+ var kWasmH0 = 0;
179
+ var kWasmH1 = 0x61;
180
+ var kWasmH2 = 0x73;
181
+ var kWasmH3 = 0x6d;
182
+
183
+ var kWasmV0 = 0x1;
184
+ var kWasmV1 = 0;
185
+ var kWasmV2 = 0;
186
+ var kWasmV3 = 0;
187
+
188
+ var kHeaderSize = 8;
189
+ var kPageSize = 65536;
190
+ var kSpecMaxPages = 65536;
191
+ var kMaxVarInt32Size = 5;
192
+ var kMaxVarInt64Size = 10;
193
+ var kSpecMaxFunctionParams = 1_000;
194
+
195
+ let kDeclNoLocals = 0;
196
+
197
+ // Section declaration constants
198
+ let kUnknownSectionCode = 0;
199
+ let kTypeSectionCode = 1; // Function signature declarations
200
+ let kImportSectionCode = 2; // Import declarations
201
+ let kFunctionSectionCode = 3; // Function declarations
202
+ let kTableSectionCode = 4; // Indirect function table and other tables
203
+ let kMemorySectionCode = 5; // Memory attributes
204
+ let kGlobalSectionCode = 6; // Global declarations
205
+ let kExportSectionCode = 7; // Exports
206
+ let kStartSectionCode = 8; // Start function declaration
207
+ let kElementSectionCode = 9; // Elements section
208
+ let kCodeSectionCode = 10; // Function code
209
+ let kDataSectionCode = 11; // Data segments
210
+ let kDataCountSectionCode = 12; // Data segment count (between Element & Code)
211
+ let kTagSectionCode = 13; // Tag section (between Memory & Global)
212
+ let kStringRefSectionCode = 14; // Stringref literals section (between Tag & Global)
213
+ let kLastKnownSectionCode = 14;
214
+
215
+ // Name section types
216
+ let kModuleNameCode = 0;
217
+ let kFunctionNamesCode = 1;
218
+ let kLocalNamesCode = 2;
219
+
220
+ let kWasmSharedTypeForm = 0x65;
221
+ let kWasmFunctionTypeForm = 0x60;
222
+ let kWasmStructTypeForm = 0x5f;
223
+ let kWasmArrayTypeForm = 0x5e;
224
+ let kWasmContTypeForm = 0x5d;
225
+ let kWasmSubtypeForm = 0x50;
226
+ let kWasmSubtypeFinalForm = 0x4f;
227
+ let kWasmRecursiveTypeGroupForm = 0x4e;
228
+ let kWasmDescriptorTypeForm = 0x4d;
229
+ let kWasmDescribesTypeForm = 0x4c;
230
+
231
+ let kNoSuperType = 0xFFFFFFFF;
232
+
233
+ let kLimitsNoMaximum = 0x00;
234
+ let kLimitsWithMaximum = 0x01;
235
+ let kLimitsSharedNoMaximum = 0x02;
236
+ let kLimitsSharedWithMaximum = 0x03;
237
+ let kLimitsMemory64NoMaximum = 0x04;
238
+ let kLimitsMemory64WithMaximum = 0x05;
239
+ let kLimitsMemory64SharedNoMaximum = 0x06;
240
+ let kLimitsMemory64SharedWithMaximum = 0x07;
241
+
242
+ // Segment flags
243
+ let kActiveNoIndex = 0;
244
+ let kPassive = 1;
245
+ let kActiveWithIndex = 2;
246
+ let kDeclarative = 3;
247
+ let kPassiveWithElements = 5;
248
+ let kDeclarativeWithElements = 7;
249
+
250
+ // Function declaration flags
251
+ let kDeclFunctionName = 0x01;
252
+ let kDeclFunctionImport = 0x02;
253
+ let kDeclFunctionLocals = 0x04;
254
+ let kDeclFunctionExport = 0x08;
255
+
256
+ // Value types and related
257
+ let kWasmVoid = 0x40;
258
+ let kWasmI32 = 0x7f;
259
+ let kWasmI64 = 0x7e;
260
+ let kWasmF32 = 0x7d;
261
+ let kWasmF64 = 0x7c;
262
+ let kWasmS128 = 0x7b;
263
+ let kWasmI8 = 0x78;
264
+ let kWasmI16 = 0x77;
265
+ let kWasmF16 = 0x76;
266
+
267
+ // These are defined as negative integers to distinguish them from positive type
268
+ // indices.
269
+ let kWasmNullFuncRef = -0x0d;
270
+ let kWasmNullExternRef = -0x0e;
271
+ let kWasmNullRef = -0x0f;
272
+ let kWasmFuncRef = -0x10;
273
+ let kWasmAnyFunc = kWasmFuncRef; // Alias named as in the JS API spec
274
+ let kWasmExternRef = -0x11;
275
+ let kWasmAnyRef = -0x12;
276
+ let kWasmEqRef = -0x13;
277
+ let kWasmI31Ref = -0x14;
278
+ let kWasmStructRef = -0x15;
279
+ let kWasmArrayRef = -0x16;
280
+ let kWasmExnRef = -0x17;
281
+ let kWasmNullExnRef = -0x0c;
282
+ let kWasmStringRef = -0x19;
283
+ let kWasmStringViewWtf8 = -0x1a;
284
+ let kWasmStringViewWtf16 = -0x20;
285
+ let kWasmStringViewIter = -0x1f;
286
+ const kWasmContRef = -0x18;
287
+ const kWasmNullContRef = -0x0b;
288
+
289
+ // Use the positive-byte versions inside function bodies.
290
+ let kLeb128Mask = 0x7f;
291
+ let kFuncRefCode = kWasmFuncRef & kLeb128Mask;
292
+ let kAnyFuncCode = kFuncRefCode; // Alias named as in the JS API spec
293
+ let kExternRefCode = kWasmExternRef & kLeb128Mask;
294
+ let kAnyRefCode = kWasmAnyRef & kLeb128Mask;
295
+ let kEqRefCode = kWasmEqRef & kLeb128Mask;
296
+ let kI31RefCode = kWasmI31Ref & kLeb128Mask;
297
+ let kNullExternRefCode = kWasmNullExternRef & kLeb128Mask;
298
+ let kNullFuncRefCode = kWasmNullFuncRef & kLeb128Mask;
299
+ let kStructRefCode = kWasmStructRef & kLeb128Mask;
300
+ let kArrayRefCode = kWasmArrayRef & kLeb128Mask;
301
+ let kExnRefCode = kWasmExnRef & kLeb128Mask;
302
+ let kNullExnRefCode = kWasmNullExnRef & kLeb128Mask;
303
+ let kNullRefCode = kWasmNullRef & kLeb128Mask;
304
+ let kStringRefCode = kWasmStringRef & kLeb128Mask;
305
+ let kStringViewWtf8Code = kWasmStringViewWtf8 & kLeb128Mask;
306
+ let kStringViewWtf16Code = kWasmStringViewWtf16 & kLeb128Mask;
307
+ let kStringViewIterCode = kWasmStringViewIter & kLeb128Mask;
308
+ const kContRefCode = kWasmContRef & kLeb128Mask;
309
+ const kNullContRefCode = kWasmNullContRef & kLeb128Mask;
310
+
311
+ let kWasmRefNull = 0x63;
312
+ let kWasmRef = 0x64;
313
+ let kWasmExact = 0x62;
314
+
315
+ // Implementation detail of `wasmRef[Null]Type`, don't use directly.
316
+ class RefTypeBuilder {
317
+ constructor(opcode, heap_type) {
318
+ this.opcode = opcode;
319
+ this.heap_type = heap_type;
320
+ this.is_shared = false;
321
+ this.is_exact = false;
322
+ }
323
+ nullable() {
324
+ this.opcode = kWasmRefNull;
325
+ return this;
326
+ }
327
+ shared() {
328
+ this.is_shared = true;
329
+ return this;
330
+ }
331
+ exact() {
332
+ this.is_exact = true;
333
+ return this;
334
+ }
335
+ }
336
+ function wasmRefNullType(heap_type) {
337
+ return new RefTypeBuilder(kWasmRefNull, heap_type);
338
+ }
339
+ function wasmRefType(heap_type) {
340
+ return new RefTypeBuilder(kWasmRef, heap_type);
341
+ }
342
+
343
+ let kExternalFunction = 0;
344
+ let kExternalTable = 1;
345
+ let kExternalMemory = 2;
346
+ let kExternalGlobal = 3;
347
+ let kExternalTag = 4;
348
+
349
+ let kTableZero = 0;
350
+ let kMemoryZero = 0;
351
+ let kSegmentZero = 0;
352
+
353
+ let kExceptionAttribute = 0;
354
+
355
+ const kAtomicSeqCst = 0;
356
+ const kAtomicAcqRel = 1;
357
+
358
+ // Useful signatures
359
+ let kSig_i_i = makeSig([kWasmI32], [kWasmI32]);
360
+ let kSig_l_l = makeSig([kWasmI64], [kWasmI64]);
361
+ let kSig_i_l = makeSig([kWasmI64], [kWasmI32]);
362
+ let kSig_i_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32]);
363
+ let kSig_i_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
364
+ let kSig_i_iiii = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
365
+ let kSig_v_iiii = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], []);
366
+ let kSig_l_iiii = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], [kWasmI64]);
367
+ let kSig_l_i = makeSig([kWasmI32], [kWasmI64]);
368
+ let kSig_f_i = makeSig([kWasmI32], [kWasmF32]);
369
+ let kSig_i_f = makeSig([kWasmF32], [kWasmI32]);
370
+ let kSig_i_ff = makeSig([kWasmF32, kWasmF32], [kWasmI32]);
371
+ let kSig_f_ff = makeSig([kWasmF32, kWasmF32], [kWasmF32]);
372
+ let kSig_f_ffff = makeSig([kWasmF32, kWasmF32, kWasmF32, kWasmF32], [kWasmF32]);
373
+ let kSig_d_dd = makeSig([kWasmF64, kWasmF64], [kWasmF64]);
374
+ let kSig_d_dddd = makeSig([kWasmF64, kWasmF64, kWasmF64, kWasmF64], [kWasmF64]);
375
+ let kSig_l_ll = makeSig([kWasmI64, kWasmI64], [kWasmI64]);
376
+ let kSig_l_llll = makeSig([kWasmI64, kWasmI64, kWasmI64, kWasmI64], [kWasmI64]);
377
+ let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
378
+ let kSig_v_v = makeSig([], []);
379
+ let kSig_i_v = makeSig([], [kWasmI32]);
380
+ let kSig_l_v = makeSig([], [kWasmI64]);
381
+ let kSig_f_v = makeSig([], [kWasmF32]);
382
+ let kSig_d_v = makeSig([], [kWasmF64]);
383
+ let kSig_v_i = makeSig([kWasmI32], []);
384
+ let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
385
+ let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []);
386
+ let kSig_v_l = makeSig([kWasmI64], []);
387
+ let kSig_v_li = makeSig([kWasmI64, kWasmI32], []);
388
+ let kSig_v_lii = makeSig([kWasmI64, kWasmI32, kWasmI32], []);
389
+ let kSig_v_d = makeSig([kWasmF64], []);
390
+ let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
391
+ let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
392
+ let kSig_ii_v = makeSig([], [kWasmI32, kWasmI32]);
393
+ let kSig_iii_v = makeSig([], [kWasmI32, kWasmI32, kWasmI32]);
394
+ let kSig_ii_i = makeSig([kWasmI32], [kWasmI32, kWasmI32]);
395
+ let kSig_iii_i = makeSig([kWasmI32], [kWasmI32, kWasmI32, kWasmI32]);
396
+ let kSig_ii_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32, kWasmI32]);
397
+ let kSig_iii_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32, kWasmI32, kWasmI32]);
398
+
399
+ let kSig_v_f = makeSig([kWasmF32], []);
400
+ let kSig_f_f = makeSig([kWasmF32], [kWasmF32]);
401
+ let kSig_f_d = makeSig([kWasmF64], [kWasmF32]);
402
+ let kSig_d_d = makeSig([kWasmF64], [kWasmF64]);
403
+ let kSig_d_f = makeSig([kWasmF32], [kWasmF64]);
404
+ let kSig_d_i = makeSig([kWasmI32], [kWasmF64]);
405
+ let kSig_r_r = makeSig([kWasmExternRef], [kWasmExternRef]);
406
+ let kSig_a_a = makeSig([kWasmAnyFunc], [kWasmAnyFunc]);
407
+ let kSig_i_r = makeSig([kWasmExternRef], [kWasmI32]);
408
+ let kSig_v_r = makeSig([kWasmExternRef], []);
409
+ let kSig_v_a = makeSig([kWasmAnyFunc], []);
410
+ let kSig_v_rr = makeSig([kWasmExternRef, kWasmExternRef], []);
411
+ let kSig_v_aa = makeSig([kWasmAnyFunc, kWasmAnyFunc], []);
412
+ let kSig_r_v = makeSig([], [kWasmExternRef]);
413
+ let kSig_a_v = makeSig([], [kWasmAnyFunc]);
414
+ let kSig_a_i = makeSig([kWasmI32], [kWasmAnyFunc]);
415
+ let kSig_s_i = makeSig([kWasmI32], [kWasmS128]);
416
+ let kSig_i_s = makeSig([kWasmS128], [kWasmI32]);
417
+
418
+ function makeSig(params, results) {
419
+ return {params: params, results: results};
420
+ }
421
+
422
+ function makeSig_v_x(x) {
423
+ return makeSig([x], []);
424
+ }
425
+
426
+ function makeSig_x_v(x) {
427
+ return makeSig([], [x]);
428
+ }
429
+
430
+ function makeSig_v_xx(x) {
431
+ return makeSig([x, x], []);
432
+ }
433
+
434
+ function makeSig_r_v(r) {
435
+ return makeSig([], [r]);
436
+ }
437
+
438
+ function makeSig_r_x(r, x) {
439
+ return makeSig([x], [r]);
440
+ }
441
+
442
+ function makeSig_r_xx(r, x) {
443
+ return makeSig([x, x], [r]);
444
+ }
445
+
446
+ // Opcodes
447
+ const kWasmOpcodes = {
448
+ 'Unreachable': 0x00,
449
+ 'Nop': 0x01,
450
+ 'Block': 0x02,
451
+ 'Loop': 0x03,
452
+ 'If': 0x04,
453
+ 'Else': 0x05,
454
+ 'Try': 0x06,
455
+ 'TryTable': 0x1f,
456
+ 'ThrowRef': 0x0a,
457
+ 'Catch': 0x07,
458
+ 'Throw': 0x08,
459
+ 'Rethrow': 0x09,
460
+ 'CatchAll': 0x19,
461
+ 'End': 0x0b,
462
+ 'Br': 0x0c,
463
+ 'BrIf': 0x0d,
464
+ 'BrTable': 0x0e,
465
+ 'Return': 0x0f,
466
+ 'CallFunction': 0x10,
467
+ 'CallIndirect': 0x11,
468
+ 'ReturnCall': 0x12,
469
+ 'ReturnCallIndirect': 0x13,
470
+ 'CallRef': 0x14,
471
+ 'ReturnCallRef': 0x15,
472
+ 'NopUnsupportedInLiftoff': 0x16,
473
+ 'Delegate': 0x18,
474
+ 'Drop': 0x1a,
475
+ 'Select': 0x1b,
476
+ 'SelectWithType': 0x1c,
477
+ 'LocalGet': 0x20,
478
+ 'LocalSet': 0x21,
479
+ 'LocalTee': 0x22,
480
+ 'GlobalGet': 0x23,
481
+ 'GlobalSet': 0x24,
482
+ 'TableGet': 0x25,
483
+ 'TableSet': 0x26,
484
+ 'I32LoadMem': 0x28,
485
+ 'I64LoadMem': 0x29,
486
+ 'F32LoadMem': 0x2a,
487
+ 'F64LoadMem': 0x2b,
488
+ 'I32LoadMem8S': 0x2c,
489
+ 'I32LoadMem8U': 0x2d,
490
+ 'I32LoadMem16S': 0x2e,
491
+ 'I32LoadMem16U': 0x2f,
492
+ 'I64LoadMem8S': 0x30,
493
+ 'I64LoadMem8U': 0x31,
494
+ 'I64LoadMem16S': 0x32,
495
+ 'I64LoadMem16U': 0x33,
496
+ 'I64LoadMem32S': 0x34,
497
+ 'I64LoadMem32U': 0x35,
498
+ 'I32StoreMem': 0x36,
499
+ 'I64StoreMem': 0x37,
500
+ 'F32StoreMem': 0x38,
501
+ 'F64StoreMem': 0x39,
502
+ 'I32StoreMem8': 0x3a,
503
+ 'I32StoreMem16': 0x3b,
504
+ 'I64StoreMem8': 0x3c,
505
+ 'I64StoreMem16': 0x3d,
506
+ 'I64StoreMem32': 0x3e,
507
+ 'MemorySize': 0x3f,
508
+ 'MemoryGrow': 0x40,
509
+ 'I32Const': 0x41,
510
+ 'I64Const': 0x42,
511
+ 'F32Const': 0x43,
512
+ 'F64Const': 0x44,
513
+ 'I32Eqz': 0x45,
514
+ 'I32Eq': 0x46,
515
+ 'I32Ne': 0x47,
516
+ 'I32LtS': 0x48,
517
+ 'I32LtU': 0x49,
518
+ 'I32GtS': 0x4a,
519
+ 'I32GtU': 0x4b,
520
+ 'I32LeS': 0x4c,
521
+ 'I32LeU': 0x4d,
522
+ 'I32GeS': 0x4e,
523
+ 'I32GeU': 0x4f,
524
+ 'I64Eqz': 0x50,
525
+ 'I64Eq': 0x51,
526
+ 'I64Ne': 0x52,
527
+ 'I64LtS': 0x53,
528
+ 'I64LtU': 0x54,
529
+ 'I64GtS': 0x55,
530
+ 'I64GtU': 0x56,
531
+ 'I64LeS': 0x57,
532
+ 'I64LeU': 0x58,
533
+ 'I64GeS': 0x59,
534
+ 'I64GeU': 0x5a,
535
+ 'F32Eq': 0x5b,
536
+ 'F32Ne': 0x5c,
537
+ 'F32Lt': 0x5d,
538
+ 'F32Gt': 0x5e,
539
+ 'F32Le': 0x5f,
540
+ 'F32Ge': 0x60,
541
+ 'F64Eq': 0x61,
542
+ 'F64Ne': 0x62,
543
+ 'F64Lt': 0x63,
544
+ 'F64Gt': 0x64,
545
+ 'F64Le': 0x65,
546
+ 'F64Ge': 0x66,
547
+ 'I32Clz': 0x67,
548
+ 'I32Ctz': 0x68,
549
+ 'I32Popcnt': 0x69,
550
+ 'I32Add': 0x6a,
551
+ 'I32Sub': 0x6b,
552
+ 'I32Mul': 0x6c,
553
+ 'I32DivS': 0x6d,
554
+ 'I32DivU': 0x6e,
555
+ 'I32RemS': 0x6f,
556
+ 'I32RemU': 0x70,
557
+ 'I32And': 0x71,
558
+ 'I32Ior': 0x72,
559
+ 'I32Xor': 0x73,
560
+ 'I32Shl': 0x74,
561
+ 'I32ShrS': 0x75,
562
+ 'I32ShrU': 0x76,
563
+ 'I32Rol': 0x77,
564
+ 'I32Ror': 0x78,
565
+ 'I64Clz': 0x79,
566
+ 'I64Ctz': 0x7a,
567
+ 'I64Popcnt': 0x7b,
568
+ 'I64Add': 0x7c,
569
+ 'I64Sub': 0x7d,
570
+ 'I64Mul': 0x7e,
571
+ 'I64DivS': 0x7f,
572
+ 'I64DivU': 0x80,
573
+ 'I64RemS': 0x81,
574
+ 'I64RemU': 0x82,
575
+ 'I64And': 0x83,
576
+ 'I64Ior': 0x84,
577
+ 'I64Xor': 0x85,
578
+ 'I64Shl': 0x86,
579
+ 'I64ShrS': 0x87,
580
+ 'I64ShrU': 0x88,
581
+ 'I64Rol': 0x89,
582
+ 'I64Ror': 0x8a,
583
+ 'F32Abs': 0x8b,
584
+ 'F32Neg': 0x8c,
585
+ 'F32Ceil': 0x8d,
586
+ 'F32Floor': 0x8e,
587
+ 'F32Trunc': 0x8f,
588
+ 'F32NearestInt': 0x90,
589
+ 'F32Sqrt': 0x91,
590
+ 'F32Add': 0x92,
591
+ 'F32Sub': 0x93,
592
+ 'F32Mul': 0x94,
593
+ 'F32Div': 0x95,
594
+ 'F32Min': 0x96,
595
+ 'F32Max': 0x97,
596
+ 'F32CopySign': 0x98,
597
+ 'F64Abs': 0x99,
598
+ 'F64Neg': 0x9a,
599
+ 'F64Ceil': 0x9b,
600
+ 'F64Floor': 0x9c,
601
+ 'F64Trunc': 0x9d,
602
+ 'F64NearestInt': 0x9e,
603
+ 'F64Sqrt': 0x9f,
604
+ 'F64Add': 0xa0,
605
+ 'F64Sub': 0xa1,
606
+ 'F64Mul': 0xa2,
607
+ 'F64Div': 0xa3,
608
+ 'F64Min': 0xa4,
609
+ 'F64Max': 0xa5,
610
+ 'F64CopySign': 0xa6,
611
+ 'I32ConvertI64': 0xa7,
612
+ 'I32SConvertF32': 0xa8,
613
+ 'I32UConvertF32': 0xa9,
614
+ 'I32SConvertF64': 0xaa,
615
+ 'I32UConvertF64': 0xab,
616
+ 'I64SConvertI32': 0xac,
617
+ 'I64UConvertI32': 0xad,
618
+ 'I64SConvertF32': 0xae,
619
+ 'I64UConvertF32': 0xaf,
620
+ 'I64SConvertF64': 0xb0,
621
+ 'I64UConvertF64': 0xb1,
622
+ 'F32SConvertI32': 0xb2,
623
+ 'F32UConvertI32': 0xb3,
624
+ 'F32SConvertI64': 0xb4,
625
+ 'F32UConvertI64': 0xb5,
626
+ 'F32ConvertF64': 0xb6,
627
+ 'F64SConvertI32': 0xb7,
628
+ 'F64UConvertI32': 0xb8,
629
+ 'F64SConvertI64': 0xb9,
630
+ 'F64UConvertI64': 0xba,
631
+ 'F64ConvertF32': 0xbb,
632
+ 'I32ReinterpretF32': 0xbc,
633
+ 'I64ReinterpretF64': 0xbd,
634
+ 'F32ReinterpretI32': 0xbe,
635
+ 'F64ReinterpretI64': 0xbf,
636
+ 'I32SExtendI8': 0xc0,
637
+ 'I32SExtendI16': 0xc1,
638
+ 'I64SExtendI8': 0xc2,
639
+ 'I64SExtendI16': 0xc3,
640
+ 'I64SExtendI32': 0xc4,
641
+ 'RefNull': 0xd0,
642
+ 'RefIsNull': 0xd1,
643
+ 'RefFunc': 0xd2,
644
+ 'RefEq': 0xd3,
645
+ 'RefAsNonNull': 0xd4,
646
+ 'BrOnNull': 0xd5,
647
+ 'BrOnNonNull': 0xd6,
648
+ 'ContNew': 0xe0,
649
+ 'ContBind': 0xe1,
650
+ 'Suspend': 0xe2,
651
+ 'Resume': 0xe3,
652
+ 'ResumeThrow': 0xe4,
653
+ 'Switch': 0xe5
654
+ };
655
+
656
+ function defineWasmOpcode(name, value) {
657
+ if (globalThis.kWasmOpcodeNames === undefined) {
658
+ globalThis.kWasmOpcodeNames = {};
659
+ }
660
+ Object.defineProperty(globalThis, name, {value: value});
661
+ if (globalThis.kWasmOpcodeNames[value] !== undefined) {
662
+ throw new Error(`Duplicate wasm opcode: ${value}. Previous name: ${
663
+ globalThis.kWasmOpcodeNames[value]}, new name: ${name}`);
664
+ }
665
+ globalThis.kWasmOpcodeNames[value] = name;
666
+ }
667
+ for (let name in kWasmOpcodes) {
668
+ defineWasmOpcode(`kExpr${name}`, kWasmOpcodes[name]);
669
+ }
670
+
671
+ // Prefix opcodes
672
+ const kPrefixOpcodes = {
673
+ 'GC': 0xfb,
674
+ 'Numeric': 0xfc,
675
+ 'Simd': 0xfd,
676
+ 'Atomic': 0xfe
677
+ };
678
+ for (let prefix in kPrefixOpcodes) {
679
+ defineWasmOpcode(`k${prefix}Prefix`, kPrefixOpcodes[prefix]);
680
+ }
681
+
682
+ // Use these for multi-byte instructions (opcode > 0x7F needing two LEB bytes):
683
+ function SimdInstr(opcode) {
684
+ if (opcode <= 0x7F) return [kSimdPrefix, opcode];
685
+ return [kSimdPrefix, 0x80 | (opcode & 0x7F), opcode >> 7];
686
+ }
687
+ function GCInstr(opcode) {
688
+ if (opcode <= 0x7F) return [kGCPrefix, opcode];
689
+ return [kGCPrefix, 0x80 | (opcode & 0x7F), opcode >> 7];
690
+ }
691
+
692
+ // GC opcodes
693
+ let kExprStructNew = 0x00;
694
+ let kExprStructNewDefault = 0x01;
695
+ let kExprStructGet = 0x02;
696
+ let kExprStructGetS = 0x03;
697
+ let kExprStructGetU = 0x04;
698
+ let kExprStructSet = 0x05;
699
+ let kExprArrayNew = 0x06;
700
+ let kExprArrayNewDefault = 0x07;
701
+ let kExprArrayNewFixed = 0x08;
702
+ let kExprArrayNewData = 0x09;
703
+ let kExprArrayNewElem = 0x0a;
704
+ let kExprArrayGet = 0x0b;
705
+ let kExprArrayGetS = 0x0c;
706
+ let kExprArrayGetU = 0x0d;
707
+ let kExprArraySet = 0x0e;
708
+ let kExprArrayLen = 0x0f;
709
+ let kExprArrayFill = 0x10;
710
+ let kExprArrayCopy = 0x11;
711
+ let kExprArrayInitData = 0x12;
712
+ let kExprArrayInitElem = 0x13;
713
+ let kExprRefChk = 0x14;
714
+ let kExprRefChkNull = 0x15;
715
+ let kExprRefCast = 0x16;
716
+ let kExprRefCastNull = 0x17;
717
+ let kExprBrOnCast = 0x18;
718
+ let kExprBrOnCastFail = 0x19;
719
+ let kExprAnyConvertExtern = 0x1a;
720
+ let kExprExternConvertAny = 0x1b;
721
+ let kExprRefI31 = 0x1c;
722
+ let kExprI31GetS = 0x1d;
723
+ let kExprI31GetU = 0x1e;
724
+ let kExprRefI31Shared = 0x1f;
725
+ // Custom Descriptors proposal:
726
+ let kExprRefGetDesc = 0x22;
727
+ let kExprRefCastDesc = 0x23;
728
+ let kExprRefCastDescNull = 0x24;
729
+ let kExprBrOnCastDesc = 0x25;
730
+ let kExprBrOnCastDescFail = 0x26;
731
+
732
+ let kExprRefCastNop = 0x4c;
733
+
734
+ // Stringref proposal.
735
+ let kExprStringNewUtf8 = 0x80;
736
+ let kExprStringNewWtf16 = 0x81;
737
+ let kExprStringConst = 0x82;
738
+ let kExprStringMeasureUtf8 = 0x83;
739
+ let kExprStringMeasureWtf8 = 0x84;
740
+ let kExprStringMeasureWtf16 = 0x85;
741
+ let kExprStringEncodeUtf8 = 0x86;
742
+ let kExprStringEncodeWtf16 = 0x87;
743
+ let kExprStringConcat = 0x88;
744
+ let kExprStringEq = 0x89;
745
+ let kExprStringIsUsvSequence = 0x8a;
746
+ let kExprStringNewLossyUtf8 = 0x8b;
747
+ let kExprStringNewWtf8 = 0x8c;
748
+ let kExprStringEncodeLossyUtf8 = 0x8d;
749
+ let kExprStringEncodeWtf8 = 0x8e;
750
+ let kExprStringNewUtf8Try = 0x8f;
751
+ let kExprStringAsWtf8 = 0x90;
752
+ let kExprStringViewWtf8Advance = 0x91;
753
+ let kExprStringViewWtf8EncodeUtf8 = 0x92;
754
+ let kExprStringViewWtf8Slice = 0x93;
755
+ let kExprStringViewWtf8EncodeLossyUtf8 = 0x94;
756
+ let kExprStringViewWtf8EncodeWtf8 = 0x95;
757
+ let kExprStringAsWtf16 = 0x98;
758
+ let kExprStringViewWtf16Length = 0x99;
759
+ let kExprStringViewWtf16GetCodeunit = 0x9a;
760
+ let kExprStringViewWtf16Encode = 0x9b;
761
+ let kExprStringViewWtf16Slice = 0x9c;
762
+ let kExprStringAsIter = 0xa0;
763
+ let kExprStringViewIterNext = 0xa1
764
+ let kExprStringViewIterAdvance = 0xa2;
765
+ let kExprStringViewIterRewind = 0xa3
766
+ let kExprStringViewIterSlice = 0xa4;
767
+ let kExprStringCompare = 0xa8;
768
+ let kExprStringFromCodePoint = 0xa9;
769
+ let kExprStringHash = 0xaa;
770
+ let kExprStringNewUtf8Array = 0xb0;
771
+ let kExprStringNewWtf16Array = 0xb1;
772
+ let kExprStringEncodeUtf8Array = 0xb2;
773
+ let kExprStringEncodeWtf16Array = 0xb3;
774
+ let kExprStringNewLossyUtf8Array = 0xb4;
775
+ let kExprStringNewWtf8Array = 0xb5;
776
+ let kExprStringEncodeLossyUtf8Array = 0xb6;
777
+ let kExprStringEncodeWtf8Array = 0xb7;
778
+ let kExprStringNewUtf8ArrayTry = 0xb8;
779
+
780
+ // Numeric opcodes.
781
+ let kExprI32SConvertSatF32 = 0x00;
782
+ let kExprI32UConvertSatF32 = 0x01;
783
+ let kExprI32SConvertSatF64 = 0x02;
784
+ let kExprI32UConvertSatF64 = 0x03;
785
+ let kExprI64SConvertSatF32 = 0x04;
786
+ let kExprI64UConvertSatF32 = 0x05;
787
+ let kExprI64SConvertSatF64 = 0x06;
788
+ let kExprI64UConvertSatF64 = 0x07;
789
+ let kExprMemoryInit = 0x08;
790
+ let kExprDataDrop = 0x09;
791
+ let kExprMemoryCopy = 0x0a;
792
+ let kExprMemoryFill = 0x0b;
793
+ let kExprTableInit = 0x0c;
794
+ let kExprElemDrop = 0x0d;
795
+ let kExprTableCopy = 0x0e;
796
+ let kExprTableGrow = 0x0f;
797
+ let kExprTableSize = 0x10;
798
+ let kExprTableFill = 0x11;
799
+
800
+ // Atomic opcodes.
801
+ let kExprAtomicNotify = 0x00;
802
+ let kExprI32AtomicWait = 0x01;
803
+ let kExprI64AtomicWait = 0x02;
804
+ let kExprAtomicFence = 0x03;
805
+ let kExprI32AtomicLoad = 0x10;
806
+ let kExprI32AtomicLoad8U = 0x12;
807
+ let kExprI32AtomicLoad16U = 0x13;
808
+ let kExprI32AtomicStore = 0x17;
809
+ let kExprI32AtomicStore8U = 0x19;
810
+ let kExprI32AtomicStore16U = 0x1a;
811
+ let kExprI32AtomicAdd = 0x1e;
812
+ let kExprI32AtomicAdd8U = 0x20;
813
+ let kExprI32AtomicAdd16U = 0x21;
814
+ let kExprI32AtomicSub = 0x25;
815
+ let kExprI32AtomicSub8U = 0x27;
816
+ let kExprI32AtomicSub16U = 0x28;
817
+ let kExprI32AtomicAnd = 0x2c;
818
+ let kExprI32AtomicAnd8U = 0x2e;
819
+ let kExprI32AtomicAnd16U = 0x2f;
820
+ let kExprI32AtomicOr = 0x33;
821
+ let kExprI32AtomicOr8U = 0x35;
822
+ let kExprI32AtomicOr16U = 0x36;
823
+ let kExprI32AtomicXor = 0x3a;
824
+ let kExprI32AtomicXor8U = 0x3c;
825
+ let kExprI32AtomicXor16U = 0x3d;
826
+ let kExprI32AtomicExchange = 0x41;
827
+ let kExprI32AtomicExchange8U = 0x43;
828
+ let kExprI32AtomicExchange16U = 0x44;
829
+ let kExprI32AtomicCompareExchange = 0x48;
830
+ let kExprI32AtomicCompareExchange8U = 0x4a;
831
+ let kExprI32AtomicCompareExchange16U = 0x4b;
832
+
833
+ let kExprI64AtomicLoad = 0x11;
834
+ let kExprI64AtomicLoad8U = 0x14;
835
+ let kExprI64AtomicLoad16U = 0x15;
836
+ let kExprI64AtomicLoad32U = 0x16;
837
+ let kExprI64AtomicStore = 0x18;
838
+ let kExprI64AtomicStore8U = 0x1b;
839
+ let kExprI64AtomicStore16U = 0x1c;
840
+ let kExprI64AtomicStore32U = 0x1d;
841
+ let kExprI64AtomicAdd = 0x1f;
842
+ let kExprI64AtomicAdd8U = 0x22;
843
+ let kExprI64AtomicAdd16U = 0x23;
844
+ let kExprI64AtomicAdd32U = 0x24;
845
+ let kExprI64AtomicSub = 0x26;
846
+ let kExprI64AtomicSub8U = 0x29;
847
+ let kExprI64AtomicSub16U = 0x2a;
848
+ let kExprI64AtomicSub32U = 0x2b;
849
+ let kExprI64AtomicAnd = 0x2d;
850
+ let kExprI64AtomicAnd8U = 0x30;
851
+ let kExprI64AtomicAnd16U = 0x31;
852
+ let kExprI64AtomicAnd32U = 0x32;
853
+ let kExprI64AtomicOr = 0x34;
854
+ let kExprI64AtomicOr8U = 0x37;
855
+ let kExprI64AtomicOr16U = 0x38;
856
+ let kExprI64AtomicOr32U = 0x39;
857
+ let kExprI64AtomicXor = 0x3b;
858
+ let kExprI64AtomicXor8U = 0x3e;
859
+ let kExprI64AtomicXor16U = 0x3f;
860
+ let kExprI64AtomicXor32U = 0x40;
861
+ let kExprI64AtomicExchange = 0x42;
862
+ let kExprI64AtomicExchange8U = 0x45;
863
+ let kExprI64AtomicExchange16U = 0x46;
864
+ let kExprI64AtomicExchange32U = 0x47;
865
+ let kExprI64AtomicCompareExchange = 0x49
866
+ let kExprI64AtomicCompareExchange8U = 0x4c;
867
+ let kExprI64AtomicCompareExchange16U = 0x4d;
868
+ let kExprI64AtomicCompareExchange32U = 0x4e;
869
+
870
+ // Atomic GC opcodes (shared-everything-threads).
871
+ const kExprPause = 0x04;
872
+ const kExprStructAtomicGet = 0x5c;
873
+ const kExprStructAtomicGetS = 0x5d;
874
+ const kExprStructAtomicGetU = 0x5e;
875
+ const kExprStructAtomicSet = 0x5f;
876
+ const kExprStructAtomicAdd = 0x60;
877
+ const kExprStructAtomicSub = 0x61;
878
+ const kExprStructAtomicAnd = 0x62;
879
+ const kExprStructAtomicOr = 0x63;
880
+ const kExprStructAtomicXor = 0x64;
881
+ const kExprStructAtomicExchange = 0x65;
882
+ const kExprStructAtomicCompareExchange = 0x66;
883
+ const kExprArrayAtomicGet = 0x67;
884
+ const kExprArrayAtomicGetS = 0x68;
885
+ const kExprArrayAtomicGetU = 0x69;
886
+ const kExprArrayAtomicSet = 0x6a;
887
+ const kExprArrayAtomicAdd = 0x6b;
888
+ const kExprArrayAtomicSub = 0x6c;
889
+ const kExprArrayAtomicAnd = 0x6d;
890
+ const kExprArrayAtomicOr = 0x6e;
891
+ const kExprArrayAtomicXor = 0x6f;
892
+ const kExprArrayAtomicExchange = 0x70;
893
+ const kExprArrayAtomicCompareExchange = 0x71;
894
+
895
+ // Simd opcodes.
896
+ let kExprS128LoadMem = 0x00;
897
+ let kExprS128Load8x8S = 0x01;
898
+ let kExprS128Load8x8U = 0x02;
899
+ let kExprS128Load16x4S = 0x03;
900
+ let kExprS128Load16x4U = 0x04;
901
+ let kExprS128Load32x2S = 0x05;
902
+ let kExprS128Load32x2U = 0x06;
903
+ let kExprS128Load8Splat = 0x07;
904
+ let kExprS128Load16Splat = 0x08;
905
+ let kExprS128Load32Splat = 0x09;
906
+ let kExprS128Load64Splat = 0x0a;
907
+ let kExprS128StoreMem = 0x0b;
908
+ let kExprS128Const = 0x0c;
909
+ let kExprI8x16Shuffle = 0x0d;
910
+ let kExprI8x16Swizzle = 0x0e;
911
+
912
+ let kExprI8x16Splat = 0x0f;
913
+ let kExprI16x8Splat = 0x10;
914
+ let kExprI32x4Splat = 0x11;
915
+ let kExprI64x2Splat = 0x12;
916
+ let kExprF32x4Splat = 0x13;
917
+ let kExprF64x2Splat = 0x14;
918
+ let kExprI8x16ExtractLaneS = 0x15;
919
+ let kExprI8x16ExtractLaneU = 0x16;
920
+ let kExprI8x16ReplaceLane = 0x17;
921
+ let kExprI16x8ExtractLaneS = 0x18;
922
+ let kExprI16x8ExtractLaneU = 0x19;
923
+ let kExprI16x8ReplaceLane = 0x1a;
924
+ let kExprI32x4ExtractLane = 0x1b;
925
+ let kExprI32x4ReplaceLane = 0x1c;
926
+ let kExprI64x2ExtractLane = 0x1d;
927
+ let kExprI64x2ReplaceLane = 0x1e;
928
+ let kExprF32x4ExtractLane = 0x1f;
929
+ let kExprF32x4ReplaceLane = 0x20;
930
+ let kExprF64x2ExtractLane = 0x21;
931
+ let kExprF64x2ReplaceLane = 0x22;
932
+ let kExprI8x16Eq = 0x23;
933
+ let kExprI8x16Ne = 0x24;
934
+ let kExprI8x16LtS = 0x25;
935
+ let kExprI8x16LtU = 0x26;
936
+ let kExprI8x16GtS = 0x27;
937
+ let kExprI8x16GtU = 0x28;
938
+ let kExprI8x16LeS = 0x29;
939
+ let kExprI8x16LeU = 0x2a;
940
+ let kExprI8x16GeS = 0x2b;
941
+ let kExprI8x16GeU = 0x2c;
942
+ let kExprI16x8Eq = 0x2d;
943
+ let kExprI16x8Ne = 0x2e;
944
+ let kExprI16x8LtS = 0x2f;
945
+ let kExprI16x8LtU = 0x30;
946
+ let kExprI16x8GtS = 0x31;
947
+ let kExprI16x8GtU = 0x32;
948
+ let kExprI16x8LeS = 0x33;
949
+ let kExprI16x8LeU = 0x34;
950
+ let kExprI16x8GeS = 0x35;
951
+ let kExprI16x8GeU = 0x36;
952
+ let kExprI32x4Eq = 0x37;
953
+ let kExprI32x4Ne = 0x38;
954
+ let kExprI32x4LtS = 0x39;
955
+ let kExprI32x4LtU = 0x3a;
956
+ let kExprI32x4GtS = 0x3b;
957
+ let kExprI32x4GtU = 0x3c;
958
+ let kExprI32x4LeS = 0x3d;
959
+ let kExprI32x4LeU = 0x3e;
960
+ let kExprI32x4GeS = 0x3f;
961
+ let kExprI32x4GeU = 0x40;
962
+ let kExprF32x4Eq = 0x41;
963
+ let kExprF32x4Ne = 0x42;
964
+ let kExprF32x4Lt = 0x43;
965
+ let kExprF32x4Gt = 0x44;
966
+ let kExprF32x4Le = 0x45;
967
+ let kExprF32x4Ge = 0x46;
968
+ let kExprF64x2Eq = 0x47;
969
+ let kExprF64x2Ne = 0x48;
970
+ let kExprF64x2Lt = 0x49;
971
+ let kExprF64x2Gt = 0x4a;
972
+ let kExprF64x2Le = 0x4b;
973
+ let kExprF64x2Ge = 0x4c;
974
+ let kExprS128Not = 0x4d;
975
+ let kExprS128And = 0x4e;
976
+ let kExprS128AndNot = 0x4f;
977
+ let kExprS128Or = 0x50;
978
+ let kExprS128Xor = 0x51;
979
+ let kExprS128Select = 0x52;
980
+ let kExprV128AnyTrue = 0x53;
981
+ let kExprS128Load8Lane = 0x54;
982
+ let kExprS128Load16Lane = 0x55;
983
+ let kExprS128Load32Lane = 0x56;
984
+ let kExprS128Load64Lane = 0x57;
985
+ let kExprS128Store8Lane = 0x58;
986
+ let kExprS128Store16Lane = 0x59;
987
+ let kExprS128Store32Lane = 0x5a;
988
+ let kExprS128Store64Lane = 0x5b;
989
+ let kExprS128Load32Zero = 0x5c;
990
+ let kExprS128Load64Zero = 0x5d;
991
+ let kExprF32x4DemoteF64x2Zero = 0x5e;
992
+ let kExprF64x2PromoteLowF32x4 = 0x5f;
993
+ let kExprI8x16Abs = 0x60;
994
+ let kExprI8x16Neg = 0x61;
995
+ let kExprI8x16Popcnt = 0x62;
996
+ let kExprI8x16AllTrue = 0x63;
997
+ let kExprI8x16BitMask = 0x64;
998
+ let kExprI8x16SConvertI16x8 = 0x65;
999
+ let kExprI8x16UConvertI16x8 = 0x66;
1000
+ let kExprF32x4Ceil = 0x67;
1001
+ let kExprF32x4Floor = 0x68;
1002
+ let kExprF32x4Trunc = 0x69;
1003
+ let kExprF32x4NearestInt = 0x6a;
1004
+ let kExprI8x16Shl = 0x6b;
1005
+ let kExprI8x16ShrS = 0x6c;
1006
+ let kExprI8x16ShrU = 0x6d;
1007
+ let kExprI8x16Add = 0x6e;
1008
+ let kExprI8x16AddSatS = 0x6f;
1009
+ let kExprI8x16AddSatU = 0x70;
1010
+ let kExprI8x16Sub = 0x71;
1011
+ let kExprI8x16SubSatS = 0x72;
1012
+ let kExprI8x16SubSatU = 0x73;
1013
+ let kExprF64x2Ceil = 0x74;
1014
+ let kExprF64x2Floor = 0x75;
1015
+ let kExprI8x16MinS = 0x76;
1016
+ let kExprI8x16MinU = 0x77;
1017
+ let kExprI8x16MaxS = 0x78;
1018
+ let kExprI8x16MaxU = 0x79;
1019
+ let kExprF64x2Trunc = 0x7a;
1020
+ let kExprI8x16RoundingAverageU = 0x7b;
1021
+ let kExprI16x8ExtAddPairwiseI8x16S = 0x7c;
1022
+ let kExprI16x8ExtAddPairwiseI8x16U = 0x7d;
1023
+ let kExprI32x4ExtAddPairwiseI16x8S = 0x7e;
1024
+ let kExprI32x4ExtAddPairwiseI16x8U = 0x7f;
1025
+ let kExprI16x8Abs = 0x80;
1026
+ let kExprI16x8Neg = 0x81;
1027
+ let kExprI16x8Q15MulRSatS = 0x82;
1028
+ let kExprI16x8AllTrue = 0x83;
1029
+ let kExprI16x8BitMask = 0x84;
1030
+ let kExprI16x8SConvertI32x4 = 0x85;
1031
+ let kExprI16x8UConvertI32x4 = 0x86;
1032
+ let kExprI16x8SConvertI8x16Low = 0x87;
1033
+ let kExprI16x8SConvertI8x16High = 0x88;
1034
+ let kExprI16x8UConvertI8x16Low = 0x89;
1035
+ let kExprI16x8UConvertI8x16High = 0x8a;
1036
+ let kExprI16x8Shl = 0x8b;
1037
+ let kExprI16x8ShrS = 0x8c;
1038
+ let kExprI16x8ShrU = 0x8d;
1039
+ let kExprI16x8Add = 0x8e;
1040
+ let kExprI16x8AddSatS = 0x8f;
1041
+ let kExprI16x8AddSatU = 0x90;
1042
+ let kExprI16x8Sub = 0x91;
1043
+ let kExprI16x8SubSatS = 0x92;
1044
+ let kExprI16x8SubSatU = 0x93;
1045
+ let kExprF64x2NearestInt = 0x94;
1046
+ let kExprI16x8Mul = 0x95;
1047
+ let kExprI16x8MinS = 0x96;
1048
+ let kExprI16x8MinU = 0x97;
1049
+ let kExprI16x8MaxS = 0x98;
1050
+ let kExprI16x8MaxU = 0x99;
1051
+ let kExprI16x8RoundingAverageU = 0x9b;
1052
+ let kExprI16x8ExtMulLowI8x16S = 0x9c;
1053
+ let kExprI16x8ExtMulHighI8x16S = 0x9d;
1054
+ let kExprI16x8ExtMulLowI8x16U = 0x9e;
1055
+ let kExprI16x8ExtMulHighI8x16U = 0x9f;
1056
+ let kExprI32x4Abs = 0xa0;
1057
+ let kExprI32x4Neg = 0xa1;
1058
+ let kExprI32x4AllTrue = 0xa3;
1059
+ let kExprI32x4BitMask = 0xa4;
1060
+ let kExprI32x4SConvertI16x8Low = 0xa7;
1061
+ let kExprI32x4SConvertI16x8High = 0xa8;
1062
+ let kExprI32x4UConvertI16x8Low = 0xa9;
1063
+ let kExprI32x4UConvertI16x8High = 0xaa;
1064
+ let kExprI32x4Shl = 0xab;
1065
+ let kExprI32x4ShrS = 0xac;
1066
+ let kExprI32x4ShrU = 0xad;
1067
+ let kExprI32x4Add = 0xae;
1068
+ let kExprI32x4Sub = 0xb1;
1069
+ let kExprI32x4Mul = 0xb5;
1070
+ let kExprI32x4MinS = 0xb6;
1071
+ let kExprI32x4MinU = 0xb7;
1072
+ let kExprI32x4MaxS = 0xb8;
1073
+ let kExprI32x4MaxU = 0xb9;
1074
+ let kExprI32x4DotI16x8S = 0xba;
1075
+ let kExprI32x4ExtMulLowI16x8S = 0xbc;
1076
+ let kExprI32x4ExtMulHighI16x8S = 0xbd;
1077
+ let kExprI32x4ExtMulLowI16x8U = 0xbe;
1078
+ let kExprI32x4ExtMulHighI16x8U = 0xbf;
1079
+ let kExprI64x2Abs = 0xc0;
1080
+ let kExprI64x2Neg = 0xc1;
1081
+ let kExprI64x2AllTrue = 0xc3;
1082
+ let kExprI64x2BitMask = 0xc4;
1083
+ let kExprI64x2SConvertI32x4Low = 0xc7;
1084
+ let kExprI64x2SConvertI32x4High = 0xc8;
1085
+ let kExprI64x2UConvertI32x4Low = 0xc9;
1086
+ let kExprI64x2UConvertI32x4High = 0xca;
1087
+ let kExprI64x2Shl = 0xcb;
1088
+ let kExprI64x2ShrS = 0xcc;
1089
+ let kExprI64x2ShrU = 0xcd;
1090
+ let kExprI64x2Add = 0xce;
1091
+ let kExprI64x2Sub = 0xd1;
1092
+ let kExprI64x2Mul = 0xd5;
1093
+ let kExprI64x2Eq = 0xd6;
1094
+ let kExprI64x2Ne = 0xd7;
1095
+ let kExprI64x2LtS = 0xd8;
1096
+ let kExprI64x2GtS = 0xd9;
1097
+ let kExprI64x2LeS = 0xda;
1098
+ let kExprI64x2GeS = 0xdb;
1099
+ let kExprI64x2ExtMulLowI32x4S = 0xdc;
1100
+ let kExprI64x2ExtMulHighI32x4S = 0xdd;
1101
+ let kExprI64x2ExtMulLowI32x4U = 0xde;
1102
+ let kExprI64x2ExtMulHighI32x4U = 0xdf;
1103
+ let kExprF32x4Abs = 0xe0;
1104
+ let kExprF32x4Neg = 0xe1;
1105
+ let kExprF32x4Sqrt = 0xe3;
1106
+ let kExprF32x4Add = 0xe4;
1107
+ let kExprF32x4Sub = 0xe5;
1108
+ let kExprF32x4Mul = 0xe6;
1109
+ let kExprF32x4Div = 0xe7;
1110
+ let kExprF32x4Min = 0xe8;
1111
+ let kExprF32x4Max = 0xe9;
1112
+ let kExprF32x4Pmin = 0xea;
1113
+ let kExprF32x4Pmax = 0xeb;
1114
+ let kExprF64x2Abs = 0xec;
1115
+ let kExprF64x2Neg = 0xed;
1116
+ let kExprF64x2Sqrt = 0xef;
1117
+ let kExprF64x2Add = 0xf0;
1118
+ let kExprF64x2Sub = 0xf1;
1119
+ let kExprF64x2Mul = 0xf2;
1120
+ let kExprF64x2Div = 0xf3;
1121
+ let kExprF64x2Min = 0xf4;
1122
+ let kExprF64x2Max = 0xf5;
1123
+ let kExprF64x2Pmin = 0xf6;
1124
+ let kExprF64x2Pmax = 0xf7;
1125
+ let kExprI32x4SConvertF32x4 = 0xf8;
1126
+ let kExprI32x4UConvertF32x4 = 0xf9;
1127
+ let kExprF32x4SConvertI32x4 = 0xfa;
1128
+ let kExprF32x4UConvertI32x4 = 0xfb;
1129
+ let kExprI32x4TruncSatF64x2SZero = 0xfc;
1130
+ let kExprI32x4TruncSatF64x2UZero = 0xfd;
1131
+ let kExprF64x2ConvertLowI32x4S = 0xfe;
1132
+ let kExprF64x2ConvertLowI32x4U = 0xff;
1133
+
1134
+ // Relaxed SIMD.
1135
+ let kExprI8x16RelaxedSwizzle = wasmSignedLeb(0x100);
1136
+ let kExprI32x4RelaxedTruncF32x4S = wasmSignedLeb(0x101);
1137
+ let kExprI32x4RelaxedTruncF32x4U = wasmSignedLeb(0x102);
1138
+ let kExprI32x4RelaxedTruncF64x2SZero = wasmSignedLeb(0x103);
1139
+ let kExprI32x4RelaxedTruncF64x2UZero = wasmSignedLeb(0x104);
1140
+ let kExprF32x4Qfma = wasmSignedLeb(0x105);
1141
+ let kExprF32x4Qfms = wasmSignedLeb(0x106);
1142
+ let kExprF64x2Qfma = wasmSignedLeb(0x107);
1143
+ let kExprF64x2Qfms = wasmSignedLeb(0x108);
1144
+ let kExprI8x16RelaxedLaneSelect = wasmSignedLeb(0x109);
1145
+ let kExprI16x8RelaxedLaneSelect = wasmSignedLeb(0x10a);
1146
+ let kExprI32x4RelaxedLaneSelect = wasmSignedLeb(0x10b);
1147
+ let kExprI64x2RelaxedLaneSelect = wasmSignedLeb(0x10c);
1148
+ let kExprF32x4RelaxedMin = wasmSignedLeb(0x10d);
1149
+ let kExprF32x4RelaxedMax = wasmSignedLeb(0x10e);
1150
+ let kExprF64x2RelaxedMin = wasmSignedLeb(0x10f);
1151
+ let kExprF64x2RelaxedMax = wasmSignedLeb(0x110);
1152
+ let kExprI16x8RelaxedQ15MulRS = wasmSignedLeb(0x111);
1153
+ let kExprI16x8DotI8x16I7x16S = wasmSignedLeb(0x112);
1154
+ let kExprI32x4DotI8x16I7x16AddS = wasmSignedLeb(0x113);
1155
+
1156
+ // FP16 SIMD
1157
+ let kExprF16x8Splat = wasmSignedLeb(0x120);
1158
+ let kExprF16x8ExtractLane = wasmSignedLeb(0x121);
1159
+ let kExprF16x8ReplaceLane = wasmSignedLeb(0x122);
1160
+ let kExprF16x8Abs = wasmSignedLeb(0x130);
1161
+ let kExprF16x8Neg = wasmSignedLeb(0x131);
1162
+ let kExprF16x8Sqrt = wasmSignedLeb(0x132);
1163
+ let kExprF16x8Ceil = wasmSignedLeb(0x133);
1164
+ let kExprF16x8Floor = wasmSignedLeb(0x134);
1165
+ let kExprF16x8Trunc = wasmSignedLeb(0x135);
1166
+ let kExprF16x8NearestInt = wasmSignedLeb(0x136);
1167
+ let kExprF16x8Eq = wasmSignedLeb(0x137);
1168
+ let kExprF16x8Ne = wasmSignedLeb(0x138);
1169
+ let kExprF16x8Lt = wasmSignedLeb(0x139);
1170
+ let kExprF16x8Gt = wasmSignedLeb(0x13a);
1171
+ let kExprF16x8Le = wasmSignedLeb(0x13b);
1172
+ let kExprF16x8Ge = wasmSignedLeb(0x13c);
1173
+ let kExprF16x8Add = wasmSignedLeb(0x13d);
1174
+ let kExprF16x8Sub = wasmSignedLeb(0x13e);
1175
+ let kExprF16x8Mul = wasmSignedLeb(0x13f);
1176
+ let kExprF16x8Div = wasmSignedLeb(0x140);
1177
+ let kExprF16x8Min = wasmSignedLeb(0x141);
1178
+ let kExprF16x8Max = wasmSignedLeb(0x142);
1179
+ let kExprF16x8Pmin = wasmSignedLeb(0x143);
1180
+ let kExprF16x8Pmax = wasmSignedLeb(0x144);
1181
+ let kExprI16x8SConvertF16x8 = wasmSignedLeb(0x145);
1182
+ let kExprI16x8UConvertF16x8 = wasmSignedLeb(0x146);
1183
+ let kExprF16x8SConvertI16x8 = wasmSignedLeb(0x147);
1184
+ let kExprF16x8UConvertI16x8 = wasmSignedLeb(0x148);
1185
+ let kExprF16x8DemoteF32x4Zero = wasmSignedLeb(0x149);
1186
+ let kExprF16x8DemoteF64x2Zero = wasmSignedLeb(0x14a);
1187
+ let kExprF32x4PromoteLowF16x8 = wasmSignedLeb(0x14b);
1188
+ let kExprF16x8Qfma = wasmSignedLeb(0x14e);
1189
+ let kExprF16x8Qfms = wasmSignedLeb(0x14f);
1190
+
1191
+ let kTrapUnreachable = 0;
1192
+ let kTrapMemOutOfBounds = 1;
1193
+ let kTrapDivByZero = 2;
1194
+ let kTrapDivUnrepresentable = 3;
1195
+ let kTrapRemByZero = 4;
1196
+ let kTrapFloatUnrepresentable = 5;
1197
+ let kTrapTableOutOfBounds = 6;
1198
+ let kTrapFuncSigMismatch = 7;
1199
+ let kTrapUnalignedAccess = 8;
1200
+ let kTrapDataSegmentOutOfBounds = 9;
1201
+ let kTrapElementSegmentOutOfBounds = 10;
1202
+ let kTrapRethrowNull = 11;
1203
+ let kTrapArrayTooLarge = 12;
1204
+ let kTrapArrayOutOfBounds = 13;
1205
+ let kTrapNullDereference = 14;
1206
+ let kTrapIllegalCast = 15;
1207
+
1208
+ let kAtomicWaitOk = 0;
1209
+ let kAtomicWaitNotEqual = 1;
1210
+ let kAtomicWaitTimedOut = 2;
1211
+
1212
+ // Exception handling with exnref.
1213
+ let kCatchNoRef = 0x0;
1214
+ let kCatchRef = 0x1;
1215
+ let kCatchAllNoRef = 0x2;
1216
+ let kCatchAllRef = 0x3;
1217
+
1218
+ // Stack switching handler kinds.
1219
+ let kOnSuspend = 0x0;
1220
+ let kOnSwitch = 0x1;
1221
+
1222
+ let kTrapMsgs = [
1223
+ 'unreachable', // --
1224
+ 'memory access out of bounds', // --
1225
+ 'divide by zero', // --
1226
+ 'divide result unrepresentable', // --
1227
+ 'remainder by zero', // --
1228
+ 'float unrepresentable in integer range', // --
1229
+ 'table index is out of bounds', // --
1230
+ 'null function or function signature mismatch', // --
1231
+ 'operation does not support unaligned accesses', // --
1232
+ 'data segment out of bounds', // --
1233
+ 'element segment out of bounds', // --
1234
+ 'rethrowing null value', // --
1235
+ 'requested new array is too large', // --
1236
+ 'array element access out of bounds', // --
1237
+ 'dereferencing a null pointer', // --
1238
+ 'illegal cast', // --
1239
+ ];
1240
+
1241
+ // Upstream this file pairs with the mjsunit harness.
1242
+ function assertTraps(trap, code) {
1243
+ assertThrows(code, WebAssembly.RuntimeError, new RegExp(kTrapMsgs[trap]));
1244
+ }
1245
+
1246
+ function assertTrapsOneOf(traps, code) {
1247
+ const errorChecker = new RegExp(
1248
+ '(' + traps.map(trap => kTrapMsgs[trap]).join('|') + ')'
1249
+ );
1250
+ assertThrows(code, WebAssembly.RuntimeError, errorChecker);
1251
+ }
1252
+
1253
+ class Binary {
1254
+ constructor() {
1255
+ this.length = 0;
1256
+ this.buffer = new Uint8Array(8192);
1257
+ }
1258
+
1259
+ ensure_space(needed) {
1260
+ if (this.buffer.length - this.length >= needed) return;
1261
+ let new_capacity = this.buffer.length * 2;
1262
+ while (new_capacity - this.length < needed) new_capacity *= 2;
1263
+ let new_buffer = new Uint8Array(new_capacity);
1264
+ new_buffer.set(this.buffer);
1265
+ this.buffer = new_buffer;
1266
+ }
1267
+
1268
+ trunc_buffer() {
1269
+ return new Uint8Array(this.buffer.buffer, 0, this.length);
1270
+ }
1271
+
1272
+ reset() {
1273
+ this.length = 0;
1274
+ }
1275
+
1276
+ emit_u8(val) {
1277
+ this.ensure_space(1);
1278
+ this.buffer[this.length++] = val;
1279
+ }
1280
+
1281
+ emit_u16(val) {
1282
+ this.ensure_space(2);
1283
+ this.buffer[this.length++] = val;
1284
+ this.buffer[this.length++] = val >> 8;
1285
+ }
1286
+
1287
+ emit_u32(val) {
1288
+ this.ensure_space(4);
1289
+ this.buffer[this.length++] = val;
1290
+ this.buffer[this.length++] = val >> 8;
1291
+ this.buffer[this.length++] = val >> 16;
1292
+ this.buffer[this.length++] = val >> 24;
1293
+ }
1294
+
1295
+ emit_leb_u(val, max_len) {
1296
+ this.ensure_space(max_len);
1297
+ for (let i = 0; i < max_len; ++i) {
1298
+ let v = val & 0xff;
1299
+ val = val >>> 7;
1300
+ if (val == 0) {
1301
+ this.buffer[this.length++] = v;
1302
+ return;
1303
+ }
1304
+ this.buffer[this.length++] = v | 0x80;
1305
+ }
1306
+ throw new Error('Leb value exceeds maximum length of ' + max_len);
1307
+ }
1308
+
1309
+ emit_u32v(val) {
1310
+ this.emit_leb_u(val, kMaxVarInt32Size);
1311
+ }
1312
+
1313
+ emit_u64v(val) {
1314
+ this.emit_leb_u(val, kMaxVarInt64Size);
1315
+ }
1316
+
1317
+ emit_bytes(data) {
1318
+ this.ensure_space(data.length);
1319
+ this.buffer.set(data, this.length);
1320
+ this.length += data.length;
1321
+ }
1322
+
1323
+ emit_string(string) {
1324
+ // For illegal names, a byte array is passed directly.
1325
+ if (string instanceof Array) {
1326
+ this.emit_u32v(string.length);
1327
+ this.emit_bytes(string);
1328
+ return;
1329
+ }
1330
+
1331
+ // This is the hacky way to convert a JavaScript string to a UTF8 encoded
1332
+ // string only containing single-byte characters.
1333
+ let string_utf8 = unescape(encodeURIComponent(string));
1334
+ this.emit_u32v(string_utf8.length);
1335
+ for (let i = 0; i < string_utf8.length; i++) {
1336
+ this.emit_u8(string_utf8.charCodeAt(i));
1337
+ }
1338
+ }
1339
+
1340
+ emit_heap_type(heap_type) {
1341
+ this.emit_bytes(wasmSignedLeb(heap_type, kMaxVarInt32Size));
1342
+ }
1343
+
1344
+ emit_type(type) {
1345
+ if ((typeof type) == 'number') {
1346
+ this.emit_u8(type >= 0 ? type : type & kLeb128Mask);
1347
+ } else {
1348
+ this.emit_u8(type.opcode);
1349
+ if (type.is_shared) this.emit_u8(kWasmSharedTypeForm);
1350
+ if (type.is_exact) this.emit_u8(kWasmExact);
1351
+ this.emit_heap_type(type.heap_type);
1352
+ }
1353
+ }
1354
+
1355
+ emit_init_expr(expr) {
1356
+ this.emit_bytes(expr);
1357
+ this.emit_u8(kExprEnd);
1358
+ }
1359
+
1360
+ emit_header() {
1361
+ this.emit_bytes([
1362
+ kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3
1363
+ ]);
1364
+ }
1365
+
1366
+ emit_section(section_code, content_generator) {
1367
+ // Emit section name.
1368
+ this.emit_u8(section_code);
1369
+ // Emit the section to a temporary buffer: its full length isn't know yet.
1370
+ const section = new Binary;
1371
+ content_generator(section);
1372
+ // Emit section length.
1373
+ this.emit_u32v(section.length);
1374
+ // Copy the temporary buffer.
1375
+ // Avoid spread because {section} can be huge.
1376
+ this.emit_bytes(section.trunc_buffer());
1377
+ }
1378
+ }
1379
+
1380
+ class WasmFunctionBuilder {
1381
+ // Encoding of local names: a string corresponds to a local name,
1382
+ // a number n corresponds to n undefined names.
1383
+ constructor(module, name, type_index, arg_names) {
1384
+ this.module = module;
1385
+ this.name = name;
1386
+ this.type_index = type_index;
1387
+ this.body = [];
1388
+ this.locals = [];
1389
+ this.local_names = arg_names;
1390
+ this.body_offset = undefined; // Not valid until module is serialized.
1391
+ }
1392
+
1393
+ numLocalNames() {
1394
+ let num_local_names = 0;
1395
+ for (let loc_name of this.local_names) {
1396
+ if (typeof loc_name == 'string') ++num_local_names;
1397
+ }
1398
+ return num_local_names;
1399
+ }
1400
+
1401
+ exportAs(name) {
1402
+ this.module.addExport(name, this.index);
1403
+ return this;
1404
+ }
1405
+
1406
+ exportFunc() {
1407
+ this.exportAs(this.name);
1408
+ return this;
1409
+ }
1410
+
1411
+ addBody(body) {
1412
+ checkExpr(body);
1413
+ // Store a copy of the body, and automatically add the end opcode.
1414
+ this.body = body.concat([kExprEnd]);
1415
+ return this;
1416
+ }
1417
+
1418
+ addBodyWithEnd(body) {
1419
+ this.body = body;
1420
+ return this;
1421
+ }
1422
+
1423
+ getNumLocals() {
1424
+ let total_locals = 0;
1425
+ for (let l of this.locals) {
1426
+ total_locals += l.count
1427
+ }
1428
+ return total_locals;
1429
+ }
1430
+
1431
+ addLocals(type, count, names) {
1432
+ this.locals.push({type: type, count: count});
1433
+ names = names || [];
1434
+ if (names.length > count) throw new Error('too many locals names given');
1435
+ this.local_names.push(...names);
1436
+ if (count > names.length) this.local_names.push(count - names.length);
1437
+ return this;
1438
+ }
1439
+
1440
+ end() {
1441
+ return this.module;
1442
+ }
1443
+ }
1444
+
1445
+ class WasmGlobalBuilder {
1446
+ constructor(module, type, mutable, shared, init) {
1447
+ this.module = module;
1448
+ this.type = type;
1449
+ this.mutable = mutable;
1450
+ this.shared = shared;
1451
+ this.init = init;
1452
+ }
1453
+
1454
+ exportAs(name) {
1455
+ this.module.exports.push(
1456
+ {name: name, kind: kExternalGlobal, index: this.index});
1457
+ return this;
1458
+ }
1459
+ }
1460
+
1461
+ function checkExpr(expr) {
1462
+ for (let b of expr) {
1463
+ if (typeof b !== 'number' || (b & (~0xFF)) !== 0) {
1464
+ throw new Error(
1465
+ 'invalid body (entries must be 8 bit numbers): ' + expr);
1466
+ }
1467
+ }
1468
+ }
1469
+
1470
+ class WasmTableBuilder {
1471
+ constructor(module, type, initial_size, max_size, init_expr, is_shared, is_table64) {
1472
+ // TODO(manoskouk): Add the table index.
1473
+ this.module = module;
1474
+ this.type = type;
1475
+ this.initial_size = initial_size;
1476
+ this.has_max = max_size !== undefined;
1477
+ this.max_size = max_size;
1478
+ this.init_expr = init_expr;
1479
+ this.has_init = init_expr !== undefined;
1480
+ this.is_shared = is_shared;
1481
+ this.is_table64 = is_table64;
1482
+ }
1483
+
1484
+ exportAs(name) {
1485
+ this.module.exports.push(
1486
+ {name: name, kind: kExternalTable, index: this.index});
1487
+ return this;
1488
+ }
1489
+ }
1490
+
1491
+ function makeField(type, mutability) {
1492
+ if ((typeof mutability) != 'boolean') {
1493
+ throw new Error('field mutability must be boolean');
1494
+ }
1495
+ return {type: type, mutability: mutability};
1496
+ }
1497
+
1498
+ function MustBeNumber(x, name) {
1499
+ if (typeof x !== 'undefined' && typeof x !== 'number') {
1500
+ throw new Error(`${name} must be a number, was ${x}`);
1501
+ }
1502
+ return x;
1503
+ }
1504
+
1505
+ class WasmStruct {
1506
+ constructor(fields, is_final, is_shared, supertype_idx) {
1507
+ let descriptor = undefined;
1508
+ let describes = undefined;
1509
+ if (Array.isArray(fields)) {
1510
+ // Fall through.
1511
+ } else if (fields.constructor === Object) {
1512
+ // Options bag.
1513
+ is_final = fields.is_final ?? fields.final ?? false;
1514
+ is_shared = fields.is_shared ?? fields.shared ?? false;
1515
+ supertype_idx = MustBeNumber(
1516
+ fields.supertype_idx ?? fields.supertype ?? kNoSuperType,
1517
+ "supertype");
1518
+ descriptor = MustBeNumber(fields.descriptor, "'descriptor'");
1519
+ describes = MustBeNumber(fields.describes, "'describes'");
1520
+ fields = fields.fields ?? []; // This must happen last.
1521
+ } else {
1522
+ throw new Error('struct fields must be an array');
1523
+ }
1524
+ this.fields = fields;
1525
+ this.type_form = kWasmStructTypeForm;
1526
+ this.is_final = is_final;
1527
+ this.is_shared = is_shared;
1528
+ this.supertype = supertype_idx;
1529
+ this.descriptor = descriptor;
1530
+ this.describes = describes;
1531
+ }
1532
+ }
1533
+
1534
+ class WasmArray {
1535
+ constructor(type, mutability, is_final, is_shared, supertype_idx) {
1536
+ this.type = type;
1537
+ this.mutability = mutability;
1538
+ this.type_form = kWasmArrayTypeForm;
1539
+ this.is_final = is_final;
1540
+ this.is_shared = is_shared;
1541
+ this.supertype = supertype_idx;
1542
+ }
1543
+ }
1544
+
1545
+ class WasmCont {
1546
+ constructor(type_index) {
1547
+ this.type_index = type_index;
1548
+ this.supertype = kNoSuperType;
1549
+ this.is_final = true;
1550
+ this.is_shared = false;
1551
+ }
1552
+ }
1553
+
1554
+ class WasmElemSegment {
1555
+ constructor(table, offset, type, elements, is_decl, is_shared) {
1556
+ this.table = table;
1557
+ this.offset = offset;
1558
+ this.type = type;
1559
+ this.elements = elements;
1560
+ this.is_decl = is_decl;
1561
+ this.is_shared = is_shared;
1562
+ // Invariant checks.
1563
+ if ((table === undefined) != (offset === undefined)) {
1564
+ throw new Error("invalid element segment");
1565
+ }
1566
+ for (let elem of elements) {
1567
+ if (((typeof elem) == 'number') != (type === undefined)) {
1568
+ throw new Error("invalid element");
1569
+ }
1570
+ }
1571
+ }
1572
+
1573
+ is_active() {
1574
+ return this.table !== undefined;
1575
+ }
1576
+
1577
+ is_passive() {
1578
+ return this.table === undefined && !this.is_decl;
1579
+ }
1580
+
1581
+ is_declarative() {
1582
+ return this.table === undefined && this.is_decl;
1583
+ }
1584
+
1585
+ expressions_as_elements() {
1586
+ return this.type !== undefined;
1587
+ }
1588
+ }
1589
+
1590
+ class WasmModuleBuilder {
1591
+ constructor() {
1592
+ this.types = [];
1593
+ this.imports = [];
1594
+ this.exports = [];
1595
+ this.stringrefs = [];
1596
+ this.globals = [];
1597
+ this.tables = [];
1598
+ this.tags = [];
1599
+ this.memories = [];
1600
+ this.functions = [];
1601
+ this.element_segments = [];
1602
+ this.data_segments = [];
1603
+ this.explicit = [];
1604
+ this.rec_groups = [];
1605
+ this.num_imported_funcs = 0;
1606
+ this.num_imported_globals = 0;
1607
+ this.num_imported_tables = 0;
1608
+ this.num_imported_tags = 0;
1609
+ return this;
1610
+ }
1611
+
1612
+ addStart(start_index) {
1613
+ this.start_index = start_index;
1614
+ return this;
1615
+ }
1616
+
1617
+ addMemory(min, max, shared) {
1618
+ // Note: All imported memories are added before declared ones (see the check
1619
+ // in {addImportedMemory}).
1620
+ const imported_memories =
1621
+ this.imports.filter(i => i.kind == kExternalMemory).length;
1622
+ const mem_index = imported_memories + this.memories.length;
1623
+ this.memories.push(
1624
+ {min: min, max: max, shared: shared || false, is_memory64: false});
1625
+ return mem_index;
1626
+ }
1627
+
1628
+ addMemory64(min, max, shared) {
1629
+ // Note: All imported memories are added before declared ones (see the check
1630
+ // in {addImportedMemory}).
1631
+ const imported_memories =
1632
+ this.imports.filter(i => i.kind == kExternalMemory).length;
1633
+ const mem_index = imported_memories + this.memories.length;
1634
+ this.memories.push(
1635
+ {min: min, max: max, shared: shared || false, is_memory64: true});
1636
+ return mem_index;
1637
+ }
1638
+
1639
+ addExplicitSection(bytes) {
1640
+ this.explicit.push(bytes);
1641
+ return this;
1642
+ }
1643
+
1644
+ stringToBytes(name) {
1645
+ var result = new Binary();
1646
+ result.emit_u32v(name.length);
1647
+ for (var i = 0; i < name.length; i++) {
1648
+ result.emit_u8(name.charCodeAt(i));
1649
+ }
1650
+ return result.trunc_buffer()
1651
+ }
1652
+
1653
+ createCustomSection(name, bytes) {
1654
+ name = this.stringToBytes(name);
1655
+ var section = new Binary();
1656
+ section.emit_u8(0);
1657
+ section.emit_u32v(name.length + bytes.length);
1658
+ section.emit_bytes(name);
1659
+ section.emit_bytes(bytes);
1660
+ return section.trunc_buffer();
1661
+ }
1662
+
1663
+ addCustomSection(name, bytes) {
1664
+ this.explicit.push(this.createCustomSection(name, bytes));
1665
+ }
1666
+
1667
+ // We use {is_final = true} so that the MVP syntax is generated for
1668
+ // signatures.
1669
+ addType(type, supertype_idx = kNoSuperType, is_final = true,
1670
+ is_shared = false) {
1671
+ var pl = type.params.length; // should have params
1672
+ var rl = type.results.length; // should have results
1673
+ var type_copy = {params: type.params, results: type.results,
1674
+ is_final: is_final, is_shared: is_shared,
1675
+ supertype: supertype_idx};
1676
+ this.types.push(type_copy);
1677
+ return this.types.length - 1;
1678
+ }
1679
+
1680
+ addLiteralStringRef(str) {
1681
+ this.stringrefs.push(str);
1682
+ return this.stringrefs.length - 1;
1683
+ }
1684
+
1685
+ // {fields} may be a list of fields, in which case the other parameters are
1686
+ // relevant; or an options bag, which replaces the other parameters.
1687
+ // Example: addStruct({fields: [...], supertype: 3})
1688
+ addStruct(fields, supertype_idx = kNoSuperType, is_final = false,
1689
+ is_shared = false) {
1690
+ this.types.push(
1691
+ new WasmStruct(fields, is_final, is_shared, supertype_idx));
1692
+ return this.types.length - 1;
1693
+ }
1694
+
1695
+ addArray(type, mutability, supertype_idx = kNoSuperType, is_final = false,
1696
+ is_shared = false) {
1697
+ this.types.push(
1698
+ new WasmArray(type, mutability, is_final, is_shared, supertype_idx));
1699
+ return this.types.length - 1;
1700
+ }
1701
+
1702
+ addCont(type) {
1703
+ let type_index = (typeof type) == 'number' ? type : this.addType(type);
1704
+ this.types.push(new WasmCont(type_index));
1705
+ return this.types.length - 1;
1706
+ }
1707
+
1708
+
1709
+ nextTypeIndex() { return this.types.length; }
1710
+
1711
+ static defaultFor(type) {
1712
+ switch (type) {
1713
+ case kWasmI32:
1714
+ return wasmI32Const(0);
1715
+ case kWasmI64:
1716
+ return wasmI64Const(0);
1717
+ case kWasmF32:
1718
+ return wasmF32Const(0.0);
1719
+ case kWasmF64:
1720
+ return wasmF64Const(0.0);
1721
+ case kWasmS128:
1722
+ return [kSimdPrefix, kExprS128Const, ...(new Array(16).fill(0))];
1723
+ case kWasmStringViewIter:
1724
+ case kWasmStringViewWtf8:
1725
+ case kWasmStringViewWtf16:
1726
+ throw new Error("String views are non-defaultable");
1727
+ default:
1728
+ if ((typeof type) != 'number' && type.opcode != kWasmRefNull) {
1729
+ throw new Error("Non-defaultable type");
1730
+ }
1731
+ let heap_type = (typeof type) == 'number' ? type : type.heap_type;
1732
+ return [kExprRefNull, ...wasmSignedLeb(heap_type, kMaxVarInt32Size)];
1733
+ }
1734
+ }
1735
+
1736
+ addGlobal(type, mutable, shared, init) {
1737
+ if (init === undefined) init = WasmModuleBuilder.defaultFor(type);
1738
+ checkExpr(init);
1739
+ let glob = new WasmGlobalBuilder(this, type, mutable, shared, init);
1740
+ glob.index = this.globals.length + this.num_imported_globals;
1741
+ this.globals.push(glob);
1742
+ return glob;
1743
+ }
1744
+
1745
+ addTable(
1746
+ type, initial_size, max_size = undefined, init_expr = undefined,
1747
+ is_shared = false, is_table64 = false) {
1748
+ if (type == kWasmI32 || type == kWasmI64 || type == kWasmF32 ||
1749
+ type == kWasmF64 || type == kWasmS128 || type == kWasmVoid) {
1750
+ throw new Error('Tables must be of a reference type');
1751
+ }
1752
+ if (init_expr != undefined) checkExpr(init_expr);
1753
+ let table = new WasmTableBuilder(
1754
+ this, type, initial_size, max_size, init_expr, is_shared, is_table64);
1755
+ table.index = this.tables.length + this.num_imported_tables;
1756
+ this.tables.push(table);
1757
+ return table;
1758
+ }
1759
+
1760
+ addTable64(
1761
+ type, initial_size, max_size = undefined, init_expr = undefined,
1762
+ is_shared = false) {
1763
+ return this.addTable(
1764
+ type, initial_size, max_size, init_expr, is_shared, true);
1765
+ }
1766
+
1767
+ addTag(type) {
1768
+ let type_index = (typeof type) == 'number' ? type : this.addType(type);
1769
+ let tag_index = this.tags.length + this.num_imported_tags;
1770
+ this.tags.push(type_index);
1771
+ return tag_index;
1772
+ }
1773
+
1774
+ addFunction(name, type, arg_names) {
1775
+ arg_names = arg_names || [];
1776
+ let type_index = (typeof type) == 'number' ? type : this.addType(type);
1777
+ let num_args = this.types[type_index].params.length;
1778
+ if (num_args < arg_names.length)
1779
+ throw new Error('too many arg names provided');
1780
+ if (num_args > arg_names.length)
1781
+ arg_names.push(num_args - arg_names.length);
1782
+ let func = new WasmFunctionBuilder(this, name, type_index, arg_names);
1783
+ func.index = this.functions.length + this.num_imported_funcs;
1784
+ this.functions.push(func);
1785
+ return func;
1786
+ }
1787
+
1788
+ addImport(module, name, type) {
1789
+ if (this.functions.length != 0) {
1790
+ throw new Error('Imported functions must be declared before local ones');
1791
+ }
1792
+ let type_index = (typeof type) == 'number' ? type : this.addType(type);
1793
+ this.imports.push({
1794
+ module: module,
1795
+ name: name,
1796
+ kind: kExternalFunction,
1797
+ type_index: type_index
1798
+ });
1799
+ return this.num_imported_funcs++;
1800
+ }
1801
+
1802
+ addImportedGlobal(module, name, type, mutable = false, shared = false) {
1803
+ if (this.globals.length != 0) {
1804
+ throw new Error('Imported globals must be declared before local ones');
1805
+ }
1806
+ let o = {
1807
+ module: module,
1808
+ name: name,
1809
+ kind: kExternalGlobal,
1810
+ type: type,
1811
+ mutable: mutable,
1812
+ shared: shared
1813
+ };
1814
+ this.imports.push(o);
1815
+ return this.num_imported_globals++;
1816
+ }
1817
+
1818
+ addImportedMemory(module, name, initial = 0, maximum, shared, is_memory64) {
1819
+ if (this.memories.length !== 0) {
1820
+ throw new Error(
1821
+ 'Add imported memories before declared memories to avoid messing ' +
1822
+ 'up the indexes');
1823
+ }
1824
+ let mem_index = this.imports.filter(i => i.kind == kExternalMemory).length;
1825
+ let o = {
1826
+ module: module,
1827
+ name: name,
1828
+ kind: kExternalMemory,
1829
+ initial: initial,
1830
+ maximum: maximum,
1831
+ shared: !!shared,
1832
+ is_memory64: !!is_memory64
1833
+ };
1834
+ this.imports.push(o);
1835
+ return mem_index;
1836
+ }
1837
+
1838
+ addImportedTable(
1839
+ module, name, initial, maximum, type = kWasmFuncRef, shared = false,
1840
+ is_table64 = false) {
1841
+ if (this.tables.length != 0) {
1842
+ throw new Error('Imported tables must be declared before local ones');
1843
+ }
1844
+ let o = {
1845
+ module: module,
1846
+ name: name,
1847
+ kind: kExternalTable,
1848
+ initial: initial,
1849
+ maximum: maximum,
1850
+ type: type,
1851
+ shared: !!shared,
1852
+ is_table64: !!is_table64,
1853
+ };
1854
+ this.imports.push(o);
1855
+ return this.num_imported_tables++;
1856
+ }
1857
+
1858
+ addImportedTag(module, name, type) {
1859
+ if (this.tags.length != 0) {
1860
+ throw new Error('Imported tags must be declared before local ones');
1861
+ }
1862
+ let type_index = (typeof type) == 'number' ? type : this.addType(type);
1863
+ let o = {
1864
+ module: module,
1865
+ name: name,
1866
+ kind: kExternalTag,
1867
+ type_index: type_index
1868
+ };
1869
+ this.imports.push(o);
1870
+ return this.num_imported_tags++;
1871
+ }
1872
+
1873
+ addExport(name, index) {
1874
+ this.exports.push({name: name, kind: kExternalFunction, index: index});
1875
+ return this;
1876
+ }
1877
+
1878
+ addExportOfKind(name, kind, index) {
1879
+ if (index === undefined && kind != kExternalTable &&
1880
+ kind != kExternalMemory) {
1881
+ throw new Error(
1882
+ 'Index for exports other than tables/memories must be provided');
1883
+ }
1884
+ if (index !== undefined && (typeof index) != 'number') {
1885
+ throw new Error('Index for exports must be a number')
1886
+ }
1887
+ this.exports.push({name: name, kind: kind, index: index});
1888
+ return this;
1889
+ }
1890
+
1891
+ addActiveDataSegment(memory_index, offset, data, is_shared = false) {
1892
+ checkExpr(offset);
1893
+ this.data_segments.push({
1894
+ is_active: true,
1895
+ is_shared: is_shared,
1896
+ mem_index: memory_index,
1897
+ offset: offset,
1898
+ data: data
1899
+ });
1900
+ return this.data_segments.length - 1;
1901
+ }
1902
+
1903
+ addPassiveDataSegment(data, is_shared = false) {
1904
+ this.data_segments.push({
1905
+ is_active: false, is_shared: is_shared, data: data});
1906
+ return this.data_segments.length - 1;
1907
+ }
1908
+
1909
+ exportMemoryAs(name, memory_index) {
1910
+ if (memory_index === undefined) {
1911
+ const num_memories = this.memories.length +
1912
+ this.imports.filter(i => i.kind == kExternalMemory).length;
1913
+ if (num_memories !== 1) {
1914
+ throw new Error(
1915
+ 'Pass memory index to \'exportMemoryAs\' if there is not exactly ' +
1916
+ 'one memory imported or declared.');
1917
+ }
1918
+ memory_index = 0;
1919
+ }
1920
+ this.exports.push({name: name, kind: kExternalMemory, index: memory_index});
1921
+ }
1922
+
1923
+ // {offset} is a constant expression.
1924
+ // If {type} is undefined, then {elements} are function indices. Otherwise,
1925
+ // they are constant expressions.
1926
+ addActiveElementSegment(table, offset, elements, type, is_shared = false) {
1927
+ checkExpr(offset);
1928
+ if (type != undefined) {
1929
+ for (let element of elements) checkExpr(element);
1930
+ }
1931
+ this.element_segments.push(
1932
+ new WasmElemSegment(table, offset, type, elements, false, is_shared));
1933
+ return this.element_segments.length - 1;
1934
+ }
1935
+
1936
+ // If {type} is undefined, then {elements} are function indices. Otherwise,
1937
+ // they are constant expressions.
1938
+ addPassiveElementSegment(elements, type, is_shared = false) {
1939
+ if (type != undefined) {
1940
+ for (let element of elements) checkExpr(element);
1941
+ }
1942
+ this.element_segments.push(new WasmElemSegment(
1943
+ undefined, undefined, type, elements, false, is_shared));
1944
+ return this.element_segments.length - 1;
1945
+ }
1946
+
1947
+ // If {type} is undefined, then {elements} are function indices. Otherwise,
1948
+ // they are constant expressions.
1949
+ addDeclarativeElementSegment(elements, type, is_shared = false) {
1950
+ if (type != undefined) {
1951
+ for (let element of elements) checkExpr(element);
1952
+ }
1953
+ this.element_segments.push(new WasmElemSegment(
1954
+ undefined, undefined, type, elements, true, is_shared));
1955
+ return this.element_segments.length - 1;
1956
+ }
1957
+
1958
+ appendToTable(array) {
1959
+ for (let n of array) {
1960
+ if (typeof n != 'number')
1961
+ throw new Error('invalid table (entries have to be numbers): ' + array);
1962
+ }
1963
+ if (this.tables.length == 0) {
1964
+ this.addTable(kWasmAnyFunc, 0);
1965
+ }
1966
+ // Adjust the table to the correct size.
1967
+ let table = this.tables[0];
1968
+ const base = table.initial_size;
1969
+ const table_size = base + array.length;
1970
+ table.initial_size = table_size;
1971
+ if (table.has_max && table_size > table.max_size) {
1972
+ table.max_size = table_size;
1973
+ }
1974
+ return this.addActiveElementSegment(0, wasmI32Const(base), array);
1975
+ }
1976
+
1977
+ setTableBounds(min, max = undefined) {
1978
+ if (this.tables.length != 0) {
1979
+ throw new Error('The table bounds of table \'0\' have already been set.');
1980
+ }
1981
+ this.addTable(kWasmAnyFunc, min, max);
1982
+ return this;
1983
+ }
1984
+
1985
+ startRecGroup() {
1986
+ this.rec_groups.push({start: this.types.length, size: 0});
1987
+ }
1988
+
1989
+ endRecGroup() {
1990
+ if (this.rec_groups.length == 0) {
1991
+ throw new Error("Did not start a recursive group before ending one")
1992
+ }
1993
+ let last_element = this.rec_groups[this.rec_groups.length - 1]
1994
+ if (last_element.size != 0) {
1995
+ throw new Error("Did not start a recursive group before ending one")
1996
+ }
1997
+ last_element.size = this.types.length - last_element.start;
1998
+ }
1999
+
2000
+ setName(name) {
2001
+ this.name = name;
2002
+ return this;
2003
+ }
2004
+
2005
+ toBuffer(debug = false) {
2006
+ let binary = new Binary;
2007
+ let wasm = this;
2008
+
2009
+ // Add header.
2010
+ binary.emit_header();
2011
+
2012
+ // Add type section.
2013
+ if (wasm.types.length > 0) {
2014
+ if (debug) print('emitting types @ ' + binary.length);
2015
+ binary.emit_section(kTypeSectionCode, section => {
2016
+ let length_with_groups = wasm.types.length;
2017
+ for (let group of wasm.rec_groups) {
2018
+ length_with_groups -= group.size - 1;
2019
+ }
2020
+ section.emit_u32v(length_with_groups);
2021
+
2022
+ let rec_group_index = 0;
2023
+
2024
+ for (let i = 0; i < wasm.types.length; i++) {
2025
+ if (rec_group_index < wasm.rec_groups.length &&
2026
+ wasm.rec_groups[rec_group_index].start == i) {
2027
+ section.emit_u8(kWasmRecursiveTypeGroupForm);
2028
+ section.emit_u32v(wasm.rec_groups[rec_group_index].size);
2029
+ rec_group_index++;
2030
+ }
2031
+
2032
+ let type = wasm.types[i];
2033
+ if (type.supertype != kNoSuperType) {
2034
+ section.emit_u8(type.is_final ? kWasmSubtypeFinalForm
2035
+ : kWasmSubtypeForm);
2036
+ section.emit_u8(1); // supertype count
2037
+ section.emit_u32v(type.supertype);
2038
+ } else if (!type.is_final) {
2039
+ section.emit_u8(kWasmSubtypeForm);
2040
+ section.emit_u8(0); // no supertypes
2041
+ }
2042
+ if (type.is_shared) section.emit_u8(kWasmSharedTypeForm);
2043
+ if (type.describes !== undefined) {
2044
+ section.emit_u8(kWasmDescribesTypeForm);
2045
+ section.emit_u32v(type.describes);
2046
+ }
2047
+ if (type.descriptor !== undefined) {
2048
+ section.emit_u8(kWasmDescriptorTypeForm);
2049
+ section.emit_u32v(type.descriptor);
2050
+ }
2051
+ if (type instanceof WasmStruct) {
2052
+ section.emit_u8(kWasmStructTypeForm);
2053
+ section.emit_u32v(type.fields.length);
2054
+ for (let field of type.fields) {
2055
+ section.emit_type(field.type);
2056
+ section.emit_u8(field.mutability ? 1 : 0);
2057
+ }
2058
+ } else if (type instanceof WasmArray) {
2059
+ section.emit_u8(kWasmArrayTypeForm);
2060
+ section.emit_type(type.type);
2061
+ section.emit_u8(type.mutability ? 1 : 0);
2062
+ } else if (type instanceof WasmCont) {
2063
+ section.emit_u8(kWasmContTypeForm);
2064
+ section.emit_u32v(type.type_index);
2065
+ } else {
2066
+ section.emit_u8(kWasmFunctionTypeForm);
2067
+ section.emit_u32v(type.params.length);
2068
+ for (let param of type.params) {
2069
+ section.emit_type(param);
2070
+ }
2071
+ section.emit_u32v(type.results.length);
2072
+ for (let result of type.results) {
2073
+ section.emit_type(result);
2074
+ }
2075
+ }
2076
+ }
2077
+ });
2078
+ }
2079
+
2080
+ // Add imports section.
2081
+ if (wasm.imports.length > 0) {
2082
+ if (debug) print('emitting imports @ ' + binary.length);
2083
+ binary.emit_section(kImportSectionCode, section => {
2084
+ section.emit_u32v(wasm.imports.length);
2085
+ for (let imp of wasm.imports) {
2086
+ section.emit_string(imp.module);
2087
+ section.emit_string(imp.name || '');
2088
+ section.emit_u8(imp.kind);
2089
+ if (imp.kind == kExternalFunction) {
2090
+ section.emit_u32v(imp.type_index);
2091
+ } else if (imp.kind == kExternalGlobal) {
2092
+ section.emit_type(imp.type);
2093
+ let flags = (imp.mutable ? 1 : 0) | (imp.shared ? 0b10 : 0);
2094
+ section.emit_u8(flags);
2095
+ } else if (imp.kind == kExternalMemory) {
2096
+ const has_max = imp.maximum !== undefined;
2097
+ const is_shared = !!imp.shared;
2098
+ const is_memory64 = !!imp.is_memory64;
2099
+ let limits_byte =
2100
+ (is_memory64 ? 4 : 0) | (is_shared ? 2 : 0) | (has_max ? 1 : 0);
2101
+ section.emit_u8(limits_byte);
2102
+ let emit = val =>
2103
+ is_memory64 ? section.emit_u64v(val) : section.emit_u32v(val);
2104
+ emit(imp.initial);
2105
+ if (has_max) emit(imp.maximum);
2106
+ } else if (imp.kind == kExternalTable) {
2107
+ section.emit_type(imp.type);
2108
+ const has_max = (typeof imp.maximum) != 'undefined';
2109
+ const is_shared = !!imp.shared;
2110
+ const is_table64 = !!imp.is_table64;
2111
+ let limits_byte =
2112
+ (is_table64 ? 4 : 0) | (is_shared ? 2 : 0) | (has_max ? 1 : 0);
2113
+ section.emit_u8(limits_byte); // flags
2114
+ section.emit_u32v(imp.initial); // initial
2115
+ if (has_max) section.emit_u32v(imp.maximum); // maximum
2116
+ } else if (imp.kind == kExternalTag) {
2117
+ section.emit_u32v(kExceptionAttribute);
2118
+ section.emit_u32v(imp.type_index);
2119
+ } else {
2120
+ throw new Error('unknown/unsupported import kind ' + imp.kind);
2121
+ }
2122
+ }
2123
+ });
2124
+ }
2125
+
2126
+ // Add functions declarations.
2127
+ if (wasm.functions.length > 0) {
2128
+ if (debug) print('emitting function decls @ ' + binary.length);
2129
+ binary.emit_section(kFunctionSectionCode, section => {
2130
+ section.emit_u32v(wasm.functions.length);
2131
+ for (let func of wasm.functions) {
2132
+ section.emit_u32v(func.type_index);
2133
+ }
2134
+ });
2135
+ }
2136
+
2137
+ // Add table section.
2138
+ if (wasm.tables.length > 0) {
2139
+ if (debug) print('emitting tables @ ' + binary.length);
2140
+ binary.emit_section(kTableSectionCode, section => {
2141
+ section.emit_u32v(wasm.tables.length);
2142
+ for (let table of wasm.tables) {
2143
+ if (table.has_init) {
2144
+ section.emit_u8(0x40); // "has initializer"
2145
+ section.emit_u8(0x00); // Reserved byte.
2146
+ }
2147
+ section.emit_type(table.type);
2148
+ let limits_byte = (table.is_table64 ? 4 : 0) |
2149
+ (table.is_shared ? 2 : 0) | (table.has_max ? 1 : 0);
2150
+ section.emit_u8(limits_byte);
2151
+ let emit = val => table.is_table64 ? section.emit_u64v(val) :
2152
+ section.emit_u32v(val);
2153
+ emit(table.initial_size);
2154
+ if (table.has_max) emit(table.max_size);
2155
+ if (table.has_init) section.emit_init_expr(table.init_expr);
2156
+ }
2157
+ });
2158
+ }
2159
+
2160
+ // Add memory section.
2161
+ if (wasm.memories.length > 0) {
2162
+ if (debug) print('emitting memories @ ' + binary.length);
2163
+ binary.emit_section(kMemorySectionCode, section => {
2164
+ section.emit_u32v(wasm.memories.length);
2165
+ for (let memory of wasm.memories) {
2166
+ const has_max = memory.max !== undefined;
2167
+ const is_shared = !!memory.shared;
2168
+ const is_memory64 = !!memory.is_memory64;
2169
+ let limits_byte =
2170
+ (is_memory64 ? 4 : 0) | (is_shared ? 2 : 0) | (has_max ? 1 : 0);
2171
+ section.emit_u8(limits_byte);
2172
+ let emit = val =>
2173
+ is_memory64 ? section.emit_u64v(val) : section.emit_u32v(val);
2174
+ emit(memory.min);
2175
+ if (has_max) emit(memory.max);
2176
+ }
2177
+ });
2178
+ }
2179
+
2180
+ // Add tag section.
2181
+ if (wasm.tags.length > 0) {
2182
+ if (debug) print('emitting tags @ ' + binary.length);
2183
+ binary.emit_section(kTagSectionCode, section => {
2184
+ section.emit_u32v(wasm.tags.length);
2185
+ for (let type_index of wasm.tags) {
2186
+ section.emit_u32v(kExceptionAttribute);
2187
+ section.emit_u32v(type_index);
2188
+ }
2189
+ });
2190
+ }
2191
+
2192
+ // Add stringref section.
2193
+ if (wasm.stringrefs.length > 0) {
2194
+ if (debug) print('emitting stringrefs @ ' + binary.length);
2195
+ binary.emit_section(kStringRefSectionCode, section => {
2196
+ section.emit_u32v(0);
2197
+ section.emit_u32v(wasm.stringrefs.length);
2198
+ for (let str of wasm.stringrefs) {
2199
+ section.emit_string(str);
2200
+ }
2201
+ });
2202
+ }
2203
+
2204
+ // Add global section.
2205
+ if (wasm.globals.length > 0) {
2206
+ if (debug) print('emitting globals @ ' + binary.length);
2207
+ binary.emit_section(kGlobalSectionCode, section => {
2208
+ section.emit_u32v(wasm.globals.length);
2209
+ for (let global of wasm.globals) {
2210
+ section.emit_type(global.type);
2211
+ section.emit_u8((global.mutable ? 1 : 0) | (global.shared ? 0b10 : 0));
2212
+ section.emit_init_expr(global.init);
2213
+ }
2214
+ });
2215
+ }
2216
+
2217
+ // Add export table.
2218
+ var exports_count = wasm.exports.length;
2219
+ if (exports_count > 0) {
2220
+ if (debug) print('emitting exports @ ' + binary.length);
2221
+ binary.emit_section(kExportSectionCode, section => {
2222
+ section.emit_u32v(exports_count);
2223
+ for (let exp of wasm.exports) {
2224
+ section.emit_string(exp.name);
2225
+ section.emit_u8(exp.kind);
2226
+ section.emit_u32v(exp.index);
2227
+ }
2228
+ });
2229
+ }
2230
+
2231
+ // Add start function section.
2232
+ if (wasm.start_index !== undefined) {
2233
+ if (debug) print('emitting start function @ ' + binary.length);
2234
+ binary.emit_section(kStartSectionCode, section => {
2235
+ section.emit_u32v(wasm.start_index);
2236
+ });
2237
+ }
2238
+
2239
+ // Add element segments.
2240
+ if (wasm.element_segments.length > 0) {
2241
+ if (debug) print('emitting element segments @ ' + binary.length);
2242
+ binary.emit_section(kElementSectionCode, section => {
2243
+ var segments = wasm.element_segments;
2244
+ section.emit_u32v(segments.length);
2245
+
2246
+ for (let segment of segments) {
2247
+ // Emit flag and header.
2248
+ // Each case below corresponds to a flag from
2249
+ // https://webassembly.github.io/spec/core/binary/modules.html#element-section
2250
+ // (not in increasing order).
2251
+ let shared_flag = segment.is_shared ? 0b1000 : 0;
2252
+ if (segment.is_active()) {
2253
+ if (segment.table == 0 && segment.type === undefined) {
2254
+ if (segment.expressions_as_elements()) {
2255
+ section.emit_u8(0x04 | shared_flag);
2256
+ section.emit_init_expr(segment.offset);
2257
+ } else {
2258
+ section.emit_u8(0x00 | shared_flag)
2259
+ section.emit_init_expr(segment.offset);
2260
+ }
2261
+ } else {
2262
+ if (segment.expressions_as_elements()) {
2263
+ section.emit_u8(0x06 | shared_flag);
2264
+ section.emit_u32v(segment.table);
2265
+ section.emit_init_expr(segment.offset);
2266
+ section.emit_type(segment.type);
2267
+ } else {
2268
+ section.emit_u8(0x02 | shared_flag);
2269
+ section.emit_u32v(segment.table);
2270
+ section.emit_init_expr(segment.offset);
2271
+ section.emit_u8(kExternalFunction);
2272
+ }
2273
+ }
2274
+ } else {
2275
+ if (segment.expressions_as_elements()) {
2276
+ if (segment.is_passive()) {
2277
+ section.emit_u8(0x05 | shared_flag);
2278
+ } else {
2279
+ section.emit_u8(0x07 | shared_flag);
2280
+ }
2281
+ section.emit_type(segment.type);
2282
+ } else {
2283
+ if (segment.is_passive()) {
2284
+ section.emit_u8(0x01 | shared_flag);
2285
+ } else {
2286
+ section.emit_u8(0x03 | shared_flag);
2287
+ }
2288
+ section.emit_u8(kExternalFunction);
2289
+ }
2290
+ }
2291
+
2292
+ // Emit elements.
2293
+ section.emit_u32v(segment.elements.length);
2294
+ for (let element of segment.elements) {
2295
+ if (segment.expressions_as_elements()) {
2296
+ section.emit_init_expr(element);
2297
+ } else {
2298
+ section.emit_u32v(element);
2299
+ }
2300
+ }
2301
+ }
2302
+ })
2303
+ }
2304
+
2305
+ // If there are any passive data segments, add the DataCount section.
2306
+ if (wasm.data_segments.some(seg => !seg.is_active)) {
2307
+ binary.emit_section(kDataCountSectionCode, section => {
2308
+ section.emit_u32v(wasm.data_segments.length);
2309
+ });
2310
+ }
2311
+
2312
+ // Add function bodies.
2313
+ if (wasm.functions.length > 0) {
2314
+ // emit function bodies
2315
+ if (debug) print('emitting code @ ' + binary.length);
2316
+ let section_length = 0;
2317
+ binary.emit_section(kCodeSectionCode, section => {
2318
+ section.emit_u32v(wasm.functions.length);
2319
+ let header;
2320
+ for (let func of wasm.functions) {
2321
+ if (func.locals.length == 0) {
2322
+ // Fast path for functions without locals.
2323
+ section.emit_u32v(func.body.length + 1);
2324
+ section.emit_u8(0); // 0 locals.
2325
+ } else {
2326
+ // Build the locals declarations in separate buffer first.
2327
+ if (!header) header = new Binary;
2328
+ header.reset();
2329
+ header.emit_u32v(func.locals.length);
2330
+ for (let decl of func.locals) {
2331
+ header.emit_u32v(decl.count);
2332
+ header.emit_type(decl.type);
2333
+ }
2334
+ section.emit_u32v(header.length + func.body.length);
2335
+ section.emit_bytes(header.trunc_buffer());
2336
+ }
2337
+ // Set to section offset for now, will update.
2338
+ func.body_offset = section.length;
2339
+ section.emit_bytes(func.body);
2340
+ }
2341
+ section_length = section.length;
2342
+ });
2343
+ for (let func of wasm.functions) {
2344
+ func.body_offset += binary.length - section_length;
2345
+ }
2346
+ }
2347
+
2348
+ // Add data segments.
2349
+ if (wasm.data_segments.length > 0) {
2350
+ if (debug) print('emitting data segments @ ' + binary.length);
2351
+ binary.emit_section(kDataSectionCode, section => {
2352
+ section.emit_u32v(wasm.data_segments.length);
2353
+ for (let seg of wasm.data_segments) {
2354
+ let shared_flag = seg.is_shared ? 0b1000 : 0;
2355
+ if (seg.is_active) {
2356
+ if (seg.mem_index == 0) {
2357
+ section.emit_u8(kActiveNoIndex | shared_flag);
2358
+ } else {
2359
+ section.emit_u8(kActiveWithIndex | shared_flag);
2360
+ section.emit_u32v(seg.mem_index);
2361
+ }
2362
+ section.emit_init_expr(seg.offset);
2363
+ } else {
2364
+ section.emit_u8(kPassive | shared_flag);
2365
+ }
2366
+ section.emit_u32v(seg.data.length);
2367
+ section.emit_bytes(seg.data);
2368
+ }
2369
+ });
2370
+ }
2371
+
2372
+ // Add any explicitly added sections.
2373
+ for (let exp of wasm.explicit) {
2374
+ if (debug) print('emitting explicit @ ' + binary.length);
2375
+ binary.emit_bytes(exp);
2376
+ }
2377
+
2378
+ // Add names.
2379
+ let num_function_names = 0;
2380
+ let num_functions_with_local_names = 0;
2381
+ for (let func of wasm.functions) {
2382
+ if (func.name !== undefined) ++num_function_names;
2383
+ if (func.numLocalNames() > 0) ++num_functions_with_local_names;
2384
+ }
2385
+ if (num_function_names > 0 || num_functions_with_local_names > 0 ||
2386
+ wasm.name !== undefined) {
2387
+ if (debug) print('emitting names @ ' + binary.length);
2388
+ binary.emit_section(kUnknownSectionCode, section => {
2389
+ section.emit_string('name');
2390
+ // Emit module name.
2391
+ if (wasm.name !== undefined) {
2392
+ section.emit_section(kModuleNameCode, name_section => {
2393
+ name_section.emit_string(wasm.name);
2394
+ });
2395
+ }
2396
+ // Emit function names.
2397
+ if (num_function_names > 0) {
2398
+ section.emit_section(kFunctionNamesCode, name_section => {
2399
+ name_section.emit_u32v(num_function_names);
2400
+ for (let func of wasm.functions) {
2401
+ if (func.name === undefined) continue;
2402
+ name_section.emit_u32v(func.index);
2403
+ name_section.emit_string(func.name);
2404
+ }
2405
+ });
2406
+ }
2407
+ // Emit local names.
2408
+ if (num_functions_with_local_names > 0) {
2409
+ section.emit_section(kLocalNamesCode, name_section => {
2410
+ name_section.emit_u32v(num_functions_with_local_names);
2411
+ for (let func of wasm.functions) {
2412
+ if (func.numLocalNames() == 0) continue;
2413
+ name_section.emit_u32v(func.index);
2414
+ name_section.emit_u32v(func.numLocalNames());
2415
+ let name_index = 0;
2416
+ for (let i = 0; i < func.local_names.length; ++i) {
2417
+ if (typeof func.local_names[i] == 'string') {
2418
+ name_section.emit_u32v(name_index);
2419
+ name_section.emit_string(func.local_names[i]);
2420
+ name_index++;
2421
+ } else {
2422
+ name_index += func.local_names[i];
2423
+ }
2424
+ }
2425
+ }
2426
+ });
2427
+ }
2428
+ });
2429
+ }
2430
+
2431
+ return binary.trunc_buffer();
2432
+ }
2433
+
2434
+ toArray(debug = false) {
2435
+ return Array.from(this.toBuffer(debug));
2436
+ }
2437
+
2438
+ instantiate(ffi, options) {
2439
+ let module = this.toModule(options);
2440
+ let instance = new WebAssembly.Instance(module, ffi);
2441
+ return instance;
2442
+ }
2443
+
2444
+ asyncInstantiate(ffi) {
2445
+ return WebAssembly.instantiate(this.toBuffer(), ffi)
2446
+ .then(({module, instance}) => instance);
2447
+ }
2448
+
2449
+ toModule(options, debug = false) {
2450
+ return new WebAssembly.Module(this.toBuffer(debug), options);
2451
+ }
2452
+ }
2453
+
2454
+ function wasmSignedLeb(val, max_len = 5) {
2455
+ if (val == null) throw new Error("Leb value may not be null/undefined");
2456
+ let res = [];
2457
+ for (let i = 0; i < max_len; ++i) {
2458
+ let v = val & 0x7f;
2459
+ // If {v} sign-extended from 7 to 32 bits is equal to val, we are done.
2460
+ if (((v << 25) >> 25) == val) {
2461
+ res.push(v);
2462
+ return res;
2463
+ }
2464
+ res.push(v | 0x80);
2465
+ val = val >> 7;
2466
+ }
2467
+ throw new Error(
2468
+ 'Leb value <' + val + '> exceeds maximum length of ' + max_len);
2469
+ }
2470
+
2471
+ function wasmSignedLeb64(val, max_len = 10) {
2472
+ if (val == null) throw new Error("Leb value may not be null/undefined");
2473
+ if (typeof val != "bigint") {
2474
+ if (val < Math.pow(2, 31)) {
2475
+ return wasmSignedLeb(val, max_len);
2476
+ }
2477
+ val = BigInt(val);
2478
+ }
2479
+ let res = [];
2480
+ for (let i = 0; i < max_len; ++i) {
2481
+ let v = val & 0x7fn;
2482
+ // If {v} sign-extended from 7 to 32 bits is equal to val, we are done.
2483
+ if (BigInt.asIntN(7, v) == val) {
2484
+ res.push(Number(v));
2485
+ return res;
2486
+ }
2487
+ res.push(Number(v) | 0x80);
2488
+ val = val >> 7n;
2489
+ }
2490
+ throw new Error(
2491
+ 'Leb value <' + val + '> exceeds maximum length of ' + max_len);
2492
+ }
2493
+
2494
+ function wasmUnsignedLeb(val, max_len = 5) {
2495
+ if (val == null) throw new Error("Leb value many not be null/undefined");
2496
+ let res = [];
2497
+ for (let i = 0; i < max_len; ++i) {
2498
+ let v = val & 0x7f;
2499
+ if (v == val) {
2500
+ res.push(v);
2501
+ return res;
2502
+ }
2503
+ res.push(v | 0x80);
2504
+ val = val >>> 7;
2505
+ }
2506
+ throw new Error(
2507
+ 'Leb value <' + val + '> exceeds maximum length of ' + max_len);
2508
+ }
2509
+
2510
+ function wasmI32Const(val) {
2511
+ return [kExprI32Const, ...wasmSignedLeb(val, 5)];
2512
+ }
2513
+
2514
+ // Note: Since {val} is a JS number, the generated constant only has 53 bits of
2515
+ // precision.
2516
+ function wasmI64Const(val) {
2517
+ return [kExprI64Const, ...wasmSignedLeb64(val, 10)];
2518
+ }
2519
+
2520
+ function wasmF32Const(f) {
2521
+ // Write in little-endian order at offset 0.
2522
+ data_view.setFloat32(0, f, true);
2523
+ return [
2524
+ kExprF32Const, byte_view[0], byte_view[1], byte_view[2], byte_view[3]
2525
+ ];
2526
+ }
2527
+
2528
+ function wasmF64Const(f) {
2529
+ // Write in little-endian order at offset 0.
2530
+ data_view.setFloat64(0, f, true);
2531
+ return [
2532
+ kExprF64Const, byte_view[0], byte_view[1], byte_view[2], byte_view[3],
2533
+ byte_view[4], byte_view[5], byte_view[6], byte_view[7]
2534
+ ];
2535
+ }
2536
+
2537
+ function wasmS128Const(f) {
2538
+ // Write in little-endian order at offset 0.
2539
+ if (Array.isArray(f)) {
2540
+ if (f.length != 16) throw new Error('S128Const needs 16 bytes');
2541
+ return [kSimdPrefix, kExprS128Const, ...f];
2542
+ }
2543
+ let result = [kSimdPrefix, kExprS128Const];
2544
+ if (arguments.length === 2) {
2545
+ for (let j = 0; j < 2; j++) {
2546
+ data_view.setFloat64(0, arguments[j], true);
2547
+ for (let i = 0; i < 8; i++) result.push(byte_view[i]);
2548
+ }
2549
+ } else if (arguments.length === 4) {
2550
+ for (let j = 0; j < 4; j++) {
2551
+ data_view.setFloat32(0, arguments[j], true);
2552
+ for (let i = 0; i < 4; i++) result.push(byte_view[i]);
2553
+ }
2554
+ } else {
2555
+ throw new Error('S128Const needs an array of bytes, or two f64 values, ' +
2556
+ 'or four f32 values');
2557
+ }
2558
+ return result;
2559
+ }
2560
+
2561
+ let wasmEncodeHeapType = function(type) {
2562
+ let result = wasmSignedLeb(type.heap_type, kMaxVarInt32Size);
2563
+ if (type.is_shared) {
2564
+ result = [kWasmSharedTypeForm].concat(result);
2565
+ }
2566
+ if (type.is_exact) {
2567
+ result = [kWasmExact].concat(result);
2568
+ }
2569
+ return result;
2570
+ };
2571
+
2572
+ let [wasmBrOnCast, wasmBrOnCastFail, wasmBrOnCastDesc, wasmBrOnCastDescFail] =
2573
+ (function() {
2574
+ return [
2575
+ (labelIdx, sourceType, targetType) =>
2576
+ wasmBrOnCastImpl(labelIdx, sourceType, targetType, kExprBrOnCast),
2577
+ (labelIdx, sourceType, targetType) =>
2578
+ wasmBrOnCastImpl(labelIdx, sourceType, targetType, kExprBrOnCastFail),
2579
+ (labelIdx, sourceType, targetType) =>
2580
+ wasmBrOnCastImpl(labelIdx, sourceType, targetType, kExprBrOnCastDesc),
2581
+ (labelIdx, sourceType, targetType) =>
2582
+ wasmBrOnCastImpl(labelIdx, sourceType, targetType, kExprBrOnCastDescFail),
2583
+ ];
2584
+ function wasmBrOnCastImpl(labelIdx, sourceType, targetType, opcode) {
2585
+ labelIdx = wasmUnsignedLeb(labelIdx, kMaxVarInt32Size);
2586
+ let srcIsNullable = sourceType.opcode == kWasmRefNull;
2587
+ let tgtIsNullable = targetType.opcode == kWasmRefNull;
2588
+ flags = (tgtIsNullable << 1) + srcIsNullable;
2589
+ return [
2590
+ kGCPrefix, opcode, flags, ...labelIdx, ...wasmEncodeHeapType(sourceType),
2591
+ ...wasmEncodeHeapType(targetType)
2592
+ ];
2593
+ }
2594
+ })();
2595
+
2596
+ function getOpcodeName(opcode) {
2597
+ return globalThis.kWasmOpcodeNames?.[opcode] ?? 'unknown';
2598
+ }
2599
+
2600
+ function wasmF32ConstSignalingNaN() {
2601
+ return [kExprF32Const, 0xb9, 0xa1, 0xa7, 0x7f];
2602
+ }
2603
+
2604
+ function wasmF64ConstSignalingNaN() {
2605
+ return [kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x7f];
2606
+ }
2607
+
2608
+ </script>
2609
+
2610
+ <!-- production-mode check (verbatim prod-chk-6307.js) -->
2611
+ <script>
2612
+ // chk-6307 — TurboFan CSE merges wasm JSToWasm deopt continuations with
2613
+ // different return types (externref vs i64); a lazy deopt then materializes a
2614
+ // tagged object as an untagged i64, leaking its heap address as a bigint.
2615
+ // Production mode: no natives syntax, no special flags.
2616
+ // Requires wasm-module-builder.js loaded BEFORE this file (pure JS).
2617
+ //
2618
+ // Key differences vs the upstream regression case:
2619
+ // 1. A dead-branch pad makes foo non-inlinable so the warm-up loop's OSR
2620
+ // cannot inline it and it tiers all the way up to TurboFan naturally.
2621
+ // 2. Warm-up counts are swept so the deopt attempt lands in the TurboFan
2622
+ // tier (Maglev handles the deopt correctly and would just de-opt again).
2623
+ (function () {
2624
+ const warmCounts = [20000, 100000, 400000];
2625
+ const pad = Array(120).fill('z += 1;').join('');
2626
+ let triggered = false, detail = '';
2627
+
2628
+ for (let a = 0; a < warmCounts.length && !triggered; a++) {
2629
+ const N = warmCounts[a];
2630
+ let armDeopt = false;
2631
+ // Fresh prototypes, wasm instance and foo per attempt (interpolated names
2632
+ // bypass the compilation cache).
2633
+ const ProtoForI64 = Function(`return function PI64_${a}() {};`)();
2634
+ const ProtoForRef = Function(`return function PRef_${a}() {};`)();
2635
+
2636
+ const builder = new WasmModuleBuilder();
2637
+ const callback_index = builder.addImport('env', 'callback', kSig_v_v);
2638
+ const g_ref = builder.addGlobal(kWasmExternRef, true, false).exportAs('g_ref');
2639
+ const g_i64 = builder.addGlobal(kWasmI64, true, false).exportAs('g_i64');
2640
+ builder.addFunction('return_ref', kSig_r_v)
2641
+ .addBody([kExprCallFunction, callback_index, kExprGlobalGet, g_ref.index])
2642
+ .exportFunc();
2643
+ builder.addFunction('return_i64', kSig_l_v)
2644
+ .addBody([kExprCallFunction, callback_index, kExprGlobalGet, g_i64.index])
2645
+ .exportFunc();
2646
+ const exports_ = builder.instantiate({env: {callback() {
2647
+ if (armDeopt) ProtoForRef.prototype.deopt_marker = 1;
2648
+ }}}).exports;
2649
+
2650
+ Object.defineProperty(ProtoForI64.prototype, 'x', {get: exports_.return_i64});
2651
+ Object.defineProperty(ProtoForRef.prototype, 'x', {get: exports_.return_ref});
2652
+
2653
+ const foo = Function(`
2654
+ return function foo_${a}(o) {
2655
+ if (o === 0x1337) { let z = 0; ${pad} return z; } // dead pad
2656
+ return o.x;
2657
+ };`)();
2658
+ const obj_i64 = new ProtoForI64();
2659
+ const obj_ref = new ProtoForRef();
2660
+
2661
+ const sentinel = {tag: 'sentinel_' + a};
2662
+ exports_.g_ref.value = sentinel;
2663
+ exports_.g_i64.value = 42n;
2664
+
2665
+ for (let i = 0; i < N; i++) { foo(obj_i64); foo(obj_ref); }
2666
+
2667
+ // Let the concurrent TurboFan job finish, then lazily deopt inside the
2668
+ // wasm getter by mutating the prototype in the import callback.
2669
+ const until = Date.now() + 50;
2670
+ while (Date.now() < until) {}
2671
+ armDeopt = true;
2672
+ const result = foo(obj_ref);
2673
+ if (result !== sentinel) {
2674
+ triggered = true;
2675
+ detail = 'warm=' + N + ': object {tag:"' + sentinel.tag + '"} materialized as ' +
2676
+ (typeof result) + ' ' + result;
2677
+ }
2678
+ }
2679
+
2680
+ const verdict = triggered
2681
+ ? 'VERDICT: chk-6307 TRIGGERED :: ' + detail
2682
+ : 'VERDICT: chk-6307 NOT-TRIGGERED :: externref always materialized correctly';
2683
+ console.log(verdict);
2684
+ if (typeof document !== 'undefined') document.title = verdict;
2685
+ })();
2686
+ </script>
2687
+
2688
+ <!-- report the verdict via ping() -->
2689
+ <script>
2690
+ (function () {
2691
+ var cid = '6307';
2692
+ var line = window.__verdict || ('VERDICT: chk-' + cid + ' ERROR :: no verdict captured');
2693
+ var st = line.indexOf('NOT-TRIGGERED') >= 0 ? '0' : (line.indexOf('TRIGGERED') >= 0 ? '1' : 'e');
2694
+ try { ping({ cid: cid, st: st, vd: line }); } catch (e) {}
2695
+ // hold the load event ~1s so the pixel request completes before tab close / headless exit
2696
+ var hold = Date.now() + 1000;
2697
+ while (Date.now() < hold) {}
2698
+ })();
2699
+ </script>
123
2700
  </body>
124
- </html>
2701
+ </html>