@crossbind/core-embind-jsi 2.0.0-beta.60 → 2.0.0-beta.63

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/js/embind.js CHANGED
@@ -323,7 +323,9 @@ if (ENVIRONMENT_IS_SHELL) {
323
323
  }
324
324
 
325
325
  setWindowTitle = (title) => document.title = title;
326
- } else {
326
+ } else if (!ENVIRONMENT_IS_NODE) {
327
+ // Node is not an error: it hosts this runtime inside a Node-API addon, which uses none of the
328
+ // file-loading hooks above.
327
329
  throw new Error('environment detection error');
328
330
  }
329
331
 
@@ -422,205 +424,6 @@ function _free() {
422
424
  // console.warn("free() called but not included in the build - add '_free' to EXPORTED_FUNCTIONS");
423
425
  }
424
426
 
425
- // Memory management
426
-
427
- var HEAP = [],
428
- /** @type {!Int8Array} */
429
- HEAP8 = [],
430
- /** @type {!Uint8Array} */
431
- HEAPU8 = [],
432
- /** @type {!Int16Array} */
433
- HEAP16 = [],
434
- /** @type {!Uint16Array} */
435
- HEAPU16 = [],
436
- /** @type {!Int32Array} */
437
- HEAP32 = [],
438
- /** @type {!Uint32Array} */
439
- HEAPU32 = [],
440
- /** @type {!Float32Array} */
441
- HEAPF32 = [],
442
- /* BigInt64Array type is not correctly defined in closure
443
- /** not-@type {!BigInt64Array} */
444
- HEAP64 = [],
445
- /* BigUInt64Array type is not correctly defined in closure
446
- /** not-t@type {!BigUint64Array} */
447
- HEAPU64 = [],
448
- /** @type {!Float64Array} */
449
- HEAPF64 = [],
450
-
451
- DATA_VIEW = [];
452
-
453
-
454
- var HEAP_OFFSET = [];
455
-
456
- function updateMemoryViews(offset, offset2, offset3, offset4) {
457
- // var b = wasmMemory.buffer;
458
- var b = globalThis.jsiArrayBuffer;
459
- var b2 = globalThis.jsiArrayBuffer2;
460
- var b3 = globalThis.jsiArrayBuffer3;
461
- var b4 = globalThis.jsiArrayBuffer4;
462
-
463
- // console.log('length: ' + b.byteLength + ', offset 1: ' + offset + ', offset 2: ' + offset2 + ', offset 3: ' + offset3 + ', offset 4: ' + offset4);
464
-
465
- HEAP_OFFSET = [offset, offset2, offset3, offset4];
466
-
467
- HEAP8.push(new Int8Array(b));
468
- HEAP8.push(new Int8Array(b2));
469
- HEAP8.push(new Int8Array(b3));
470
- HEAP8.push(new Int8Array(b4));
471
-
472
- HEAPU8.push(new Uint8Array(b));
473
- HEAPU8.push(new Uint8Array(b2));
474
- HEAPU8.push(new Uint8Array(b3));
475
- HEAPU8.push(new Uint8Array(b4));
476
-
477
- DATA_VIEW.push(new DataView(b));
478
- DATA_VIEW.push(new DataView(b2));
479
- DATA_VIEW.push(new DataView(b3));
480
- DATA_VIEW.push(new DataView(b4));
481
- }
482
-
483
- function __crossbind_register_heap_window(offset, arrayBuffer) {
484
- for (let i = 0; i < HEAP_OFFSET.length; i++) {
485
- if (HEAP_OFFSET[i] === offset) return;
486
- }
487
- HEAP_OFFSET.push(offset);
488
- HEAP8.push(new Int8Array(arrayBuffer));
489
- HEAPU8.push(new Uint8Array(arrayBuffer));
490
- DATA_VIEW.push(new DataView(arrayBuffer));
491
- }
492
- globalThis.__crossbind_register_heap_window = __crossbind_register_heap_window;
493
-
494
- const UINT32_MAX_BIGINT = 4294967295n;
495
-
496
- function findHeapIndex(ptr) {
497
- let bestIdx = -1;
498
- let bestDelta = UINT32_MAX_BIGINT;
499
- for (let i = 0; i < HEAP_OFFSET.length; i++) {
500
- const offset = HEAP_OFFSET[i];
501
- if (ptr >= offset) {
502
- const delta = ptr - offset;
503
- if (delta < bestDelta) {
504
- bestDelta = delta;
505
- bestIdx = i;
506
- }
507
- }
508
- }
509
- return bestIdx;
510
- }
511
-
512
- function getHeapIndex(ptr) {
513
- let bestIdx = findHeapIndex(ptr);
514
-
515
- // Self-healing: a pointer can land outside every window (fresh heap regions from
516
- // by-value returns, allocator arenas, ...). Ask native to register a covering
517
- // window and retry once before giving up.
518
- if (bestIdx === -1 && typeof globalThis.__crossbind_ensure_heap_window === 'function') {
519
- globalThis.__crossbind_ensure_heap_window(ptr);
520
- bestIdx = findHeapIndex(ptr);
521
- }
522
-
523
- if (bestIdx === -1) {
524
- throw (`Heap error !!! pointer: ${ptr}, no covering window in: ${HEAP_OFFSET}`);
525
- }
526
-
527
- return bestIdx;
528
- }
529
-
530
- function writeToMemoryUsingShift(pointer, signed, shift, value) {
531
- // console.log(`writeToMemory, pointer: ${pointer}`);
532
- const pi = getHeapIndex(pointer);
533
- const offset = Number(pointer - HEAP_OFFSET[pi]);
534
- const shiftAsInt = Number(shift);
535
- // console.log(`writeToMemory, pi: ${pi}, shift: ${shiftAsInt}, signed: ${signed}, value: ${value}, pointer: ${pointer}`);
536
-
537
- switch (shiftAsInt) {
538
- case 0: result = signed ? DATA_VIEW[pi].setInt8(offset, value, true) : DATA_VIEW[pi].setUint8(offset, value, true);
539
- break;
540
- case 1: result = signed ? DATA_VIEW[pi].setInt16(offset, value, true) : DATA_VIEW[pi].setUint16(offset, value, true);
541
- break;
542
- case 2: result = signed ? DATA_VIEW[pi].setInt32(offset, value, true) : DATA_VIEW[pi].setUint32(offset, value, true);
543
- break;
544
- case 3: result = signed ? DATA_VIEW[pi].setBigInt64(offset, value, true) : DATA_VIEW[pi].setBigUint64(offset, value, true);
545
- break;
546
- default:
547
- throw new TypeError("Unknown heap type");
548
- }
549
- }
550
-
551
- function readFromMemoryUsingShift(pointer, signed, shift, isFloat = false) {
552
- // console.log(`readFromMemory, pointer: ${pointer}`);
553
- const pi = getHeapIndex(pointer);
554
- const offset = Number(pointer - HEAP_OFFSET[pi]);
555
- // console.log(`readFromMemory, pi: ${pi}, shift: ${shift}, signed: ${signed}, pointer: ${pointer}, offset: ${offset}`);
556
- const shiftAsInt = Number(shift);
557
-
558
- let result = null;
559
- if (isFloat) {
560
- switch (shiftAsInt) {
561
- case 2: result = DATA_VIEW[pi].getFloat32(offset, true);
562
- break;
563
- case 3: result = DATA_VIEW[pi].getFloat64(offset, true);
564
- break;
565
- default:
566
- throw new TypeError("Unknown heap type");
567
- }
568
- } else {
569
- switch (shiftAsInt) {
570
- case 0: result = signed ? DATA_VIEW[pi].getInt8(offset, true) : DATA_VIEW[pi].getUint8(offset, true);
571
- break;
572
- case 1: result = signed ? DATA_VIEW[pi].getInt16(offset, true) : DATA_VIEW[pi].getUint16(offset, true);
573
- break;
574
- case 2: result = signed ? DATA_VIEW[pi].getInt32(offset, true) : DATA_VIEW[pi].getUint32(offset, true);
575
- break;
576
- case 3: result = signed ? DATA_VIEW[pi].getBigInt64(offset, true) : DATA_VIEW[pi].getBigUint64(offset, true);
577
- break;
578
- default:
579
- throw new TypeError("Unknown heap type");
580
- }
581
- }
582
-
583
- // console.log(`readFromMemory, result 1: ${result}`);
584
-
585
- return result;
586
- }
587
-
588
- function readFromMemoryUsingBit(pointer, signed, bit) {
589
- let shift = 0;
590
- switch (bit) {
591
- case 8: shift = 0;
592
- break;
593
- case 16: shift = 1;
594
- break;
595
- case 32: shift = 2;
596
- break;
597
- case 64: shift = 3;
598
- break;
599
- default:
600
- throw new TypeError("Unknown bit");
601
- }
602
-
603
- return readFromMemoryUsingShift(pointer, signed, shift);
604
- }
605
-
606
- function readFromMemoryUsingSize(pointer, signed, bit) {
607
- let shift = 0;
608
- switch (bit) {
609
- case 1: shift = 0;
610
- break;
611
- case 2: shift = 1;
612
- break;
613
- case 4: shift = 2;
614
- break;
615
- default:
616
- throw new TypeError("Unknown size");
617
- }
618
-
619
- return readFromMemoryUsingShift(pointer, signed, shift);
620
- }
621
-
622
- globalThis.updateMemoryViews = updateMemoryViews;
623
-
624
427
  assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time')
625
428
 
626
429
  assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined,
@@ -1036,7 +839,6 @@ function createWasm() {
1036
839
  // mode.
1037
840
  // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode.
1038
841
  //assert(wasmMemory.buffer.byteLength === 16777216);
1039
- updateMemoryViews();
1040
842
 
1041
843
  wasmTable = Module['asm']['__indirect_function_table'];
1042
844
  assert(wasmTable, "table not found in wasm exports");
@@ -1365,6 +1167,29 @@ function __embind_register_jsiValue(rawType, name) {
1365
1167
  }
1366
1168
  globalThis.__embind_register_jsiValue = __embind_register_jsiValue;
1367
1169
 
1170
+ // A Rust byte or double slice argument: the view itself reaches the adapter, which reads its
1171
+ // elements in place. Another typed array or a plain array is copied into a new view first, and so is
1172
+ // a view over a SharedArrayBuffer, which another thread could write during the call.
1173
+ function __crossbind_register_typed_arg(rawType, name, isDoubles, isOptional) {
1174
+ const View = isDoubles ? Float64Array : Uint8Array;
1175
+ const isLent = isDoubles
1176
+ ? (value) => value instanceof Float64Array
1177
+ : (value) => value instanceof Uint8Array || value instanceof Uint8ClampedArray || value instanceof Int8Array;
1178
+ const Shared = typeof SharedArrayBuffer === 'undefined' ? null : SharedArrayBuffer;
1179
+ registerType(rawType, {
1180
+ name,
1181
+ 'argPackAdvance': 0n,
1182
+ 'toWireType': function (destructors, value) {
1183
+ if (isOptional && (value === null || value === undefined)) return null;
1184
+ if (isLent(value) && !(Shared && value.buffer instanceof Shared)) return value;
1185
+ if (Array.isArray(value) || (ArrayBuffer.isView(value) && !(value instanceof DataView))) return View.from(value);
1186
+ throwBindingError(`Cannot pass ${embindRepr(value)} as a ${name}`);
1187
+ },
1188
+ destructorFunction: null,
1189
+ });
1190
+ }
1191
+ globalThis.__crossbind_register_typed_arg = __crossbind_register_typed_arg;
1192
+
1368
1193
  function getShiftFromSize(size) {
1369
1194
  switch (size) {
1370
1195
  case 1: return 0;
@@ -1397,10 +1222,6 @@ function __embind_register_bool(rawType, name, size, trueValue, falseValue) {
1397
1222
  return o ? trueValue : falseValue;
1398
1223
  },
1399
1224
  'argPackAdvance': 8n,
1400
- 'readValueFromPointer': function (pointer) {
1401
- // console.log('__embind_register_bool readValueFromPointer', pointer);
1402
- return this['fromWireType'](readFromMemoryUsingSize(pointer, true, size));
1403
- },
1404
1225
  destructorFunction: null, // This type does not need a destructor
1405
1226
  });
1406
1227
  }
@@ -1422,9 +1243,6 @@ function __embind_register_optional(rawOptionalType, rawInnerType) {
1422
1243
  return inner['toWireType'](destructors, o);
1423
1244
  },
1424
1245
  'argPackAdvance': 8n,
1425
- 'readValueFromPointer': function (pointer) {
1426
- throw new Error(`std::optional<${inner.name}> cannot be read from raw memory`);
1427
- },
1428
1246
  destructorFunction: null,
1429
1247
  }];
1430
1248
  });
@@ -1444,31 +1262,6 @@ function embindRepr(v) {
1444
1262
  }
1445
1263
 
1446
1264
 
1447
- function integerReadValueFromPointer(name, shift, signed) {
1448
- // integers are quite common, so generate very specialized functions
1449
- switch (shift) {
1450
- case 0:
1451
- case 0n: return signed ?
1452
- function readS8FromPointer(pointer) { return readFromMemoryUsingShift(pointer, true, 0); } :
1453
- function readU8FromPointer(pointer) { return readFromMemoryUsingShift(pointer, false, 0); };
1454
- case 1:
1455
- case 1n: return signed ?
1456
- function readS16FromPointer(pointer) { return readFromMemoryUsingShift(pointer, true, 1); } :
1457
- function readU16FromPointer(pointer) { return readFromMemoryUsingShift(pointer, false, 1); };
1458
- case 2:
1459
- case 2n: return signed ?
1460
- function readS32FromPointer(pointer) { return readFromMemoryUsingShift(pointer, true, 2); } :
1461
- function readU32FromPointer(pointer) { return readFromMemoryUsingShift(pointer, false, 2); };
1462
- case 3:
1463
- case 3n: return signed ?
1464
- function readS64FromPointer(pointer) { return readFromMemoryUsingShift(pointer, true, 3); } :
1465
- function readU64FromPointer(pointer) { return readFromMemoryUsingShift(pointer, false, 3); };
1466
- default:
1467
- throw new TypeError("Unknown integer type: " + name);
1468
- }
1469
- }
1470
-
1471
-
1472
1265
  function __embind_register_integer(primitiveType, name, size, minRange, maxRange) {
1473
1266
  // console.log('integer', name, primitiveType, size, minRange, maxRange);
1474
1267
  name = readLatin1String(name);
@@ -1488,6 +1281,13 @@ function __embind_register_integer(primitiveType, name, size, minRange, maxRange
1488
1281
  }
1489
1282
 
1490
1283
  var isUnsignedType = (name.includes('unsigned'));
1284
+ // As the wasm glue does (embindArgumentGuards.js): an enum member crosses as its value, and a one-letter string
1285
+ // as its code when the integer is a char.
1286
+ var fromJs = (value) => {
1287
+ if (typeof value == "string" && size == 1 && value.length == 1) return value.charCodeAt(0);
1288
+ if (value !== null && typeof value == "object" && typeof value.value == "number") return value.value;
1289
+ return value;
1290
+ };
1491
1291
  var checkAssertions = (value, toTypeName) => {
1492
1292
  if (typeof value != "number" && typeof value != "boolean" && typeof value != "bigint") {
1493
1293
  throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${toTypeName}`);
@@ -1499,11 +1299,13 @@ function __embind_register_integer(primitiveType, name, size, minRange, maxRange
1499
1299
  var toWireType;
1500
1300
  if (isUnsignedType) {
1501
1301
  toWireType = function (destructors, value) {
1302
+ value = fromJs(value);
1502
1303
  checkAssertions(value, this.name);
1503
1304
  return value >>> 0;
1504
1305
  }
1505
1306
  } else {
1506
1307
  toWireType = function (destructors, value) {
1308
+ value = fromJs(value);
1507
1309
  checkAssertions(value, this.name);
1508
1310
  // The VM will perform JS to Wasm value conversion, according to the spec:
1509
1311
  // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue
@@ -1515,7 +1317,6 @@ function __embind_register_integer(primitiveType, name, size, minRange, maxRange
1515
1317
  'fromWireType': fromWireType,
1516
1318
  'toWireType': toWireType,
1517
1319
  'argPackAdvance': 8n,
1518
- 'readValueFromPointer': integerReadValueFromPointer(name, shift, minRange !== 0),
1519
1320
  destructorFunction: null, // This type does not need a destructor
1520
1321
  });
1521
1322
  }
@@ -1528,8 +1329,6 @@ function __embind_register_bigint(primitiveType, name, size, minRange, maxRange)
1528
1329
  // console.log('bigint', name, primitiveType, size, minRange, maxRange);
1529
1330
  name = readLatin1String(name);
1530
1331
 
1531
- var shift = getShiftFromSize(size);
1532
-
1533
1332
  var isUnsignedType = (name.indexOf('u') != -1);
1534
1333
 
1535
1334
  // maxRange comes through as -1 for uint64_t (see issue 13902). Work around that temporarily
@@ -1558,7 +1357,6 @@ function __embind_register_bigint(primitiveType, name, size, minRange, maxRange)
1558
1357
  return BigInt(value);
1559
1358
  },
1560
1359
  'argPackAdvance': 8n,
1561
- 'readValueFromPointer': integerReadValueFromPointer(name, shift, !isUnsignedType),
1562
1360
  destructorFunction: null, // This type does not need a destructor
1563
1361
  });
1564
1362
  }
@@ -1566,28 +1364,8 @@ function __embind_register_bigint(primitiveType, name, size, minRange, maxRange)
1566
1364
  globalThis.__embind_register_bigint = __embind_register_bigint;
1567
1365
 
1568
1366
 
1569
- function floatReadValueFromPointer(name, shift) {
1570
- switch (shift) {
1571
- case 2:
1572
- case 2n:
1573
- return function (pointer) {
1574
- return readFromMemoryUsingShift(pointer, true, 2, true);
1575
- };
1576
- case 3:
1577
- case 3n:
1578
- return function (pointer) {
1579
- return readFromMemoryUsingShift(pointer, true, 3, true);
1580
- };
1581
- default:
1582
- throw new TypeError("Unknown float type: " + name);
1583
- }
1584
- }
1585
-
1586
-
1587
-
1588
1367
  function __embind_register_float(rawType, name, size) {
1589
1368
  // console.log('float', name, rawType, size);
1590
- var shift = getShiftFromSize(size);
1591
1369
  name = readLatin1String(name);
1592
1370
  registerType(rawType, {
1593
1371
  name: name,
@@ -1603,7 +1381,6 @@ function __embind_register_float(rawType, name, size) {
1603
1381
  return value;
1604
1382
  },
1605
1383
  'argPackAdvance': 8n,
1606
- 'readValueFromPointer': floatReadValueFromPointer(name, shift),
1607
1384
  destructorFunction: null, // This type does not need a destructor
1608
1385
  });
1609
1386
  }
@@ -1611,219 +1388,14 @@ function __embind_register_float(rawType, name, size) {
1611
1388
  globalThis.__embind_register_float = __embind_register_float;
1612
1389
 
1613
1390
 
1614
- function simpleReadValueFromPointer(pointer) {
1615
- /* console.log(
1616
- 'simpleReadValueFromPointer :',
1617
- this.name, JSON.stringify(pointer, null, 2),
1618
- readFromMemoryUsingShift(pointer, true, 2)
1619
- ); */
1620
- return this['fromWireType'](readFromMemoryUsingShift(pointer, true, 2));
1621
- }
1622
-
1623
- function simpleReadValueFromPointer64(pointer) {
1624
- /* console.log(
1625
- 'simpleReadValueFromPointer :',
1626
- this.name, JSON.stringify(pointer, null, 3),
1627
- readFromMemoryUsingShift(pointer, true, 3)
1628
- ); */
1629
- return this['fromWireType'](readFromMemoryUsingShift(pointer, false, 3));
1630
- }
1631
-
1632
-
1633
- function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
1634
- // console.log('stringToUTF8Array');
1635
- assert(typeof str === 'string');
1636
- // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
1637
- // undefined and false each don't write out any bytes.
1638
- if (!(maxBytesToWrite > 0))
1639
- return 0;
1640
-
1641
- var startIdx = outIdx;
1642
- var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
1643
- for (var i = 0; i < str.length; ++i) {
1644
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
1645
- // unit, not a Unicode code point of the character! So decode
1646
- // UTF16->UTF32->UTF8.
1647
- // See http://unicode.org/faq/utf_bom.html#utf16-3
1648
- // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
1649
- // and https://www.ietf.org/rfc/rfc2279.txt
1650
- // and https://tools.ietf.org/html/rfc3629
1651
- var u = str.charCodeAt(i); // possibly a lead surrogate
1652
- if (u >= 0xD800 && u <= 0xDFFF) {
1653
- var u1 = str.charCodeAt(++i);
1654
- u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
1655
- }
1656
- if (u <= 0x7F) {
1657
- if (outIdx >= endIdx) break;
1658
- heap[outIdx++] = u;
1659
- } else if (u <= 0x7FF) {
1660
- if (outIdx + 1 >= endIdx) break;
1661
- heap[outIdx++] = 0xC0 | (u >> 6);
1662
- heap[outIdx++] = 0x80 | (u & 63);
1663
- } else if (u <= 0xFFFF) {
1664
- if (outIdx + 2 >= endIdx) break;
1665
- heap[outIdx++] = 0xE0 | (u >> 12);
1666
- heap[outIdx++] = 0x80 | ((u >> 6) & 63);
1667
- heap[outIdx++] = 0x80 | (u & 63);
1668
- } else {
1669
- if (outIdx + 3 >= endIdx) break;
1670
- if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
1671
- heap[outIdx++] = 0xF0 | (u >> 18);
1672
- heap[outIdx++] = 0x80 | ((u >> 12) & 63);
1673
- heap[outIdx++] = 0x80 | ((u >> 6) & 63);
1674
- heap[outIdx++] = 0x80 | (u & 63);
1675
- }
1676
- }
1677
- // Null-terminate the pointer to the buffer.
1678
- heap[outIdx] = 0;
1679
- return outIdx - startIdx;
1680
- }
1681
- function stringToUTF8(str, outPtr, maxBytesToWrite) {
1682
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
1683
-
1684
- const index = getHeapIndex(outPtr);
1685
- return stringToUTF8Array(str, HEAPU8[index], outPtr - HEAP_OFFSET[index], maxBytesToWrite);
1686
- }
1687
-
1688
- function lengthBytesUTF8(str) {
1689
- var len = 0;
1690
- for (var i = 0; i < str.length; ++i) {
1691
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
1692
- // unit, not a Unicode code point of the character! So decode
1693
- // UTF16->UTF32->UTF8.
1694
- // See http://unicode.org/faq/utf_bom.html#utf16-3
1695
- var c = str.charCodeAt(i); // possibly a lead surrogate
1696
- if (c <= 0x7F) {
1697
- len++;
1698
- } else if (c <= 0x7FF) {
1699
- len += 2;
1700
- } else if (c >= 0xD800 && c <= 0xDFFF) {
1701
- len += 4; ++i;
1702
- } else {
1703
- len += 3;
1704
- }
1705
- }
1706
- return len;
1707
- }
1708
-
1709
- var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
1710
-
1711
- /**
1712
- * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
1713
- * array that contains uint8 values, returns a copy of that string as a
1714
- * Javascript String object.
1715
- * heapOrArray is either a regular array, or a JavaScript typed array view.
1716
- * @param {number} idx
1717
- * @param {number=} maxBytesToRead
1718
- * @return {string}
1719
- */
1720
- function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
1721
- var endIdx = idx + maxBytesToRead;
1722
- var endPtr = idx;
1723
- // TextDecoder needs to know the byte length in advance, it doesn't stop on
1724
- // null terminator by itself. Also, use the length info to avoid running tiny
1725
- // strings through TextDecoder, since .subarray() allocates garbage.
1726
- // (As a tiny code save trick, compare endPtr against endIdx using a negation,
1727
- // so that undefined means Infinity)
1728
- while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
1729
-
1730
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
1731
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
1732
- }
1733
- var str = '';
1734
- // If building with TextDecoder, we have already computed the string length
1735
- // above, so test loop end condition against that
1736
- while (idx < endPtr) {
1737
- // For UTF8 byte structure, see:
1738
- // http://en.wikipedia.org/wiki/UTF-8#Description
1739
- // https://www.ietf.org/rfc/rfc2279.txt
1740
- // https://tools.ietf.org/html/rfc3629
1741
- var u0 = heapOrArray[idx++];
1742
- if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
1743
- var u1 = heapOrArray[idx++] & 63;
1744
- if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
1745
- var u2 = heapOrArray[idx++] & 63;
1746
- if ((u0 & 0xF0) == 0xE0) {
1747
- u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
1748
- } else {
1749
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
1750
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
1751
- }
1752
-
1753
- if (u0 < 0x10000) {
1754
- str += String.fromCharCode(u0);
1755
- } else {
1756
- var ch = u0 - 0x10000;
1757
- str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
1758
- }
1759
- }
1760
- return str;
1761
- }
1762
-
1763
-
1764
- /**
1765
- * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
1766
- * emscripten HEAP, returns a copy of that string as a Javascript String object.
1767
- *
1768
- * @param {number} ptr
1769
- * @param {number=} maxBytesToRead - An optional length that specifies the
1770
- * maximum number of bytes to read. You can omit this parameter to scan the
1771
- * string until the first 0 byte. If maxBytesToRead is passed, and the string
1772
- * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
1773
- * string will cut short at that byte index (i.e. maxBytesToRead will not
1774
- * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
1775
- * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
1776
- * JS JIT optimizations off, so it is worth to consider consistently using one
1777
- * @return {string}
1778
- */
1779
- function UTF8ToString(ptr, maxBytesToRead) {
1780
- assert(typeof ptr === 'bigint' || typeof ptr === 'number');
1781
- const index = getHeapIndex(ptr);
1782
-
1783
- return ptr ? UTF8ArrayToString(HEAPU8[index], ptr - HEAP_OFFSET[index], maxBytesToRead) : '';
1784
- }
1785
1391
  function __embind_register_std_string(rawType, name) {
1786
1392
  name = readLatin1String(name);
1787
- var stdStringIsUTF8
1788
- //process only std::string bindings with UTF8 support, in contrast to e.g. std::basic_string<unsigned char>
1789
- = (name === "std::string");
1790
1393
 
1791
1394
  registerType(rawType, {
1792
1395
  name: name,
1396
+ // The C++ BindingType has already turned the std::string into a JS string (wire.h).
1793
1397
  'fromWireType': function (value) {
1794
- if (typeof value !== 'bigint') {
1795
- return value;
1796
- }
1797
-
1798
- var length = readFromMemoryUsingShift(value, false, 2) //HEAPU32[value >> 2];
1799
- var payload = value + 8n;
1800
- var str;
1801
- if (stdStringIsUTF8) {
1802
- var decodeStartPtr = payload;
1803
- for (var i = 0n; i <= length; ++i) {
1804
- var currentBytePtr = payload + i;
1805
- const heapIndex = getHeapIndex(currentBytePtr);
1806
- if (i == length || HEAPU8[heapIndex][currentBytePtr - HEAP_OFFSET[heapIndex]] == 0) {
1807
- var maxRead = currentBytePtr - decodeStartPtr;
1808
- var stringSegment = UTF8ToString(decodeStartPtr, maxRead);
1809
- if (str === undefined) {
1810
- str = stringSegment
1811
- } else {
1812
- str += String.fromCharCode(0);
1813
- str += stringSegment
1814
- }
1815
- decodeStartPtr = currentBytePtr + 1n
1816
- }
1817
- }
1818
- } else {
1819
- /* var a = new Array(length);
1820
- for (var i = 0; i < length; ++i) {
1821
- a[i] = String.fromCharCode(HEAPU8[payload + i])
1822
- }
1823
- str = a.join("") */
1824
- }
1825
- _free(value);
1826
- return str;
1398
+ return value;
1827
1399
  },
1828
1400
  'toWireType': function (destructors, value, usePointer = false) {
1829
1401
  return value;
@@ -1872,7 +1444,6 @@ function __embind_register_std_string(rawType, name) {
1872
1444
  return base; */
1873
1445
  },
1874
1446
  'argPackAdvance': 8n,
1875
- 'readValueFromPointer': simpleReadValueFromPointer64,
1876
1447
  destructorFunction: function (ptr) { _free(ptr); },
1877
1448
  });
1878
1449
  }
@@ -1880,135 +1451,6 @@ function __embind_register_std_string(rawType, name) {
1880
1451
  globalThis.__embind_register_std_string = __embind_register_std_string;
1881
1452
 
1882
1453
 
1883
- var UTF16Decoder = (function () {
1884
- try {
1885
- return typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined;
1886
- } catch (e) {
1887
- return undefined;
1888
- }
1889
- })();
1890
- function UTF16ToString(ptr, maxBytesToRead) {
1891
- assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!');
1892
- var endPtr = ptr;
1893
- // TextDecoder needs to know the byte length in advance, it doesn't stop on
1894
- // null terminator by itself.
1895
- // Also, use the length info to avoid running tiny strings through
1896
- // TextDecoder, since .subarray() allocates garbage.
1897
- var idx = endPtr >> 1;
1898
- var maxIdx = idx + maxBytesToRead / 2;
1899
- // If maxBytesToRead is not passed explicitly, it will be undefined, and this
1900
- // will always evaluate to true. This saves on code size.
1901
- while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
1902
- endPtr = idx << 1;
1903
-
1904
- if (endPtr - ptr > 32 && UTF16Decoder)
1905
- return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
1906
-
1907
- // Fallback: decode without UTF16Decoder
1908
- var str = '';
1909
-
1910
- // If maxBytesToRead is not passed explicitly, it will be undefined, and the
1911
- // for-loop's condition will always evaluate to true. The loop is then
1912
- // terminated on the first null char.
1913
- for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {
1914
- var codeUnit = HEAP16[(((ptr) + (i * 2)) >> 1)];
1915
- if (codeUnit == 0) break;
1916
- // fromCharCode constructs a character from a UTF-16 code unit, so we can
1917
- // pass the UTF16 string right through.
1918
- str += String.fromCharCode(codeUnit);
1919
- }
1920
-
1921
- return str;
1922
- }
1923
-
1924
- function stringToUTF16(str, outPtr, maxBytesToWrite) {
1925
- assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!');
1926
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
1927
- // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
1928
- if (maxBytesToWrite === undefined) {
1929
- maxBytesToWrite = 0x7FFFFFFF;
1930
- }
1931
- if (maxBytesToWrite < 2) return 0;
1932
- maxBytesToWrite -= 2; // Null terminator.
1933
- var startPtr = outPtr;
1934
- var numCharsToWrite = (maxBytesToWrite < str.length * 2) ? (maxBytesToWrite / 2) : str.length;
1935
- for (var i = 0; i < numCharsToWrite; ++i) {
1936
- // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
1937
- var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
1938
- HEAP16[((outPtr) >> 1)] = codeUnit;
1939
- outPtr += 2;
1940
- }
1941
- // Null-terminate the pointer to the HEAP.
1942
- HEAP16[((outPtr) >> 1)] = 0;
1943
- return outPtr - startPtr;
1944
- }
1945
-
1946
- function lengthBytesUTF16(str) {
1947
- return str.length * 2;
1948
- }
1949
-
1950
- function UTF32ToString(ptr, maxBytesToRead) {
1951
- assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!');
1952
- var i = 0;
1953
-
1954
- var str = '';
1955
- // If maxBytesToRead is not passed explicitly, it will be undefined, and this
1956
- // will always evaluate to true. This saves on code size.
1957
- while (!(i >= maxBytesToRead / 4)) {
1958
- var utf32 = HEAP32[(((ptr) + (i * 4)) >> 2)];
1959
- if (utf32 == 0) break;
1960
- ++i;
1961
- // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
1962
- // See http://unicode.org/faq/utf_bom.html#utf16-3
1963
- if (utf32 >= 0x10000) {
1964
- var ch = utf32 - 0x10000;
1965
- str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
1966
- } else {
1967
- str += String.fromCharCode(utf32);
1968
- }
1969
- }
1970
- return str;
1971
- }
1972
-
1973
- function stringToUTF32(str, outPtr, maxBytesToWrite) {
1974
- assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!');
1975
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
1976
- // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
1977
- if (maxBytesToWrite === undefined) {
1978
- maxBytesToWrite = 0x7FFFFFFF;
1979
- }
1980
- if (maxBytesToWrite < 4) return 0;
1981
- var startPtr = outPtr;
1982
- var endPtr = startPtr + maxBytesToWrite - 4;
1983
- for (var i = 0; i < str.length; ++i) {
1984
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
1985
- // See http://unicode.org/faq/utf_bom.html#utf16-3
1986
- var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
1987
- if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
1988
- var trailSurrogate = str.charCodeAt(++i);
1989
- codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
1990
- }
1991
- HEAP32[((outPtr) >> 2)] = codeUnit;
1992
- outPtr += 4;
1993
- if (outPtr + 4 > endPtr) break;
1994
- }
1995
- // Null-terminate the pointer to the HEAP.
1996
- HEAP32[((outPtr) >> 2)] = 0;
1997
- return outPtr - startPtr;
1998
- }
1999
-
2000
- function lengthBytesUTF32(str) {
2001
- var len = 0;
2002
- for (var i = 0; i < str.length; ++i) {
2003
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
2004
- // See http://unicode.org/faq/utf_bom.html#utf16-3
2005
- var codeUnit = str.charCodeAt(i);
2006
- if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
2007
- len += 4;
2008
- }
2009
-
2010
- return len;
2011
- }
2012
1454
  function __embind_register_std_wstring(rawType, charSize, name) {
2013
1455
  name = readLatin1String(name);
2014
1456
  registerType(rawType, {
@@ -2024,7 +1466,6 @@ function __embind_register_std_wstring(rawType, charSize, name) {
2024
1466
  return value;
2025
1467
  },
2026
1468
  'argPackAdvance': 8n,
2027
- 'readValueFromPointer': simpleReadValueFromPointer,
2028
1469
  destructorFunction: function (ptr) { _free(ptr); },
2029
1470
  });
2030
1471
  }
@@ -2130,7 +1571,6 @@ function __embind_register_emval(rawType, name) {
2130
1571
  return Emval.toHandle(value);
2131
1572
  },
2132
1573
  'argPackAdvance': 8n,
2133
- 'readValueFromPointer': simpleReadValueFromPointer,
2134
1574
  destructorFunction: null, // This type does not need a destructor
2135
1575
 
2136
1576
  // TODO: do we need a deleteObject here? write a test where
@@ -2183,6 +1623,19 @@ function __crossbind_v_to_array(h) {
2183
1623
  }
2184
1624
  globalThis.__crossbind_v_to_array = __crossbind_v_to_array;
2185
1625
 
1626
+ // A handle's own value, so the adapter can copy a typed array straight from its backing store.
1627
+ function __crossbind_v_value(h) {
1628
+ return Emval.toValue(h);
1629
+ }
1630
+ globalThis.__crossbind_v_value = __crossbind_v_value;
1631
+
1632
+ // A typed array's length read here, so no handle is made for the number (web.cpp reads it alike).
1633
+ function __crossbind_v_length(h) {
1634
+ const value = Emval.toValue(h);
1635
+ return value && value.length !== undefined ? value.length : 0;
1636
+ }
1637
+ globalThis.__crossbind_v_length = __crossbind_v_length;
1638
+
2186
1639
  // Any JS value the adapter already built (a typed array, say) gets a handle of its own.
2187
1640
  function __crossbind_v_from_value(v) {
2188
1641
  return Emval.toHandle(v);
@@ -2233,35 +1686,14 @@ function __crossbind_v_call(f, args) {
2233
1686
  globalThis.__crossbind_v_call = __crossbind_v_call;
2234
1687
 
2235
1688
  function __embind_register_memory_view(rawType, dataTypeIndex, name) {
2236
- var typeMapping = [
2237
- Int8Array,
2238
- Uint8Array,
2239
- Int16Array,
2240
- Uint16Array,
2241
- Int32Array,
2242
- Uint32Array,
2243
- Float32Array,
2244
- Float64Array,
2245
- BigInt64Array,
2246
- BigUint64Array,
2247
- ];
2248
-
2249
- var TA = typeMapping[dataTypeIndex];
2250
-
2251
- function decodeMemoryView(handle) {
2252
- handle = handle >>> 2;
2253
- var heap = HEAPU32;
2254
- var size = heap[handle]; // in elements
2255
- var data = heap[handle + 1]; // byte offset into emscripten heap
2256
- return new TA(heap.buffer, data, size);
2257
- }
2258
-
2259
1689
  name = readLatin1String(name);
2260
1690
  registerType(rawType, {
2261
1691
  name: name,
2262
- 'fromWireType': decodeMemoryView,
1692
+ // C++ copies the elements into a typed array of the right kind (wire.h copyToTypedArray).
1693
+ 'fromWireType': function (typedArray) {
1694
+ return typedArray;
1695
+ },
2263
1696
  'argPackAdvance': 8n,
2264
- 'readValueFromPointer': decodeMemoryView,
2265
1697
  }, {
2266
1698
  ignoreDuplicateRegistrations: true,
2267
1699
  });
@@ -2373,8 +1805,21 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
2373
1805
  argsListWired = "thisWired" + (argsListWired.length > 0 ? ", " : "") + argsListWired;
2374
1806
  }
2375
1807
 
2376
- invokerFnBody +=
2377
- (returns || isAsync ? "var rv = " : "") + "invoker(fn" + (argsListWired.length > 0 ? ", " : "") + argsListWired + ");\n";
1808
+ if (cppInvokerFunc.rawFunction) {
1809
+ // Call the host function with a fixed argument list: going through the dyn caller cost a
1810
+ // rest array, a slice and a spread call on every call.
1811
+ // The generated code runs in the global scope, so it reaches the parked error through the object this
1812
+ // module calls globalThis: a Node loader bundle gives each runtime its own.
1813
+ args1.push("raw", "throwParked", "crossbindScope");
1814
+ args2.push(cppInvokerFunc.rawFunction, throwParkedError, globalThis);
1815
+ invokerFnBody +=
1816
+ "crossbindScope.__crossbindParkedError = null;\n" +
1817
+ (returns || isAsync ? "var rv = " : "") + "raw(" + argsListWired + ");\n" +
1818
+ "if (crossbindScope.__crossbindParkedError) throwParked();\n";
1819
+ } else {
1820
+ invokerFnBody +=
1821
+ (returns || isAsync ? "var rv = " : "") + "invoker(fn" + (argsListWired.length > 0 ? ", " : "") + argsListWired + ");\n";
1822
+ }
2378
1823
 
2379
1824
  if (needsDestructorStack) {
2380
1825
  invokerFnBody += "runDestructors(destructors);\n";
@@ -2491,8 +1936,14 @@ globalThis.__crossbind_park_error = function (message, code) {
2491
1936
  globalThis.__crossbindParkedError = error;
2492
1937
  };
2493
1938
 
1939
+ function throwParkedError() {
1940
+ const parked = globalThis.__crossbindParkedError;
1941
+ globalThis.__crossbindParkedError = null;
1942
+ throw parked;
1943
+ }
1944
+
2494
1945
  function getDynCaller(signature, rawFunction, slice) {
2495
- return (...args) => {
1946
+ const caller = (...args) => {
2496
1947
  //console.log('getDynCallerReturn', signature, rawFunction, args.length, ...args);
2497
1948
  if (slice) {
2498
1949
  args = args.slice(1);
@@ -2506,6 +1957,9 @@ function getDynCaller(signature, rawFunction, slice) {
2506
1957
  }
2507
1958
  return result;
2508
1959
  };
1960
+ // craftInvokerFunction calls a sliced function directly, without the fn argument this drops.
1961
+ if (slice) caller.rawFunction = rawFunction;
1962
+ return caller;
2509
1963
  }
2510
1964
 
2511
1965
  function getWasmTableEntry(rawFunction) { return (a, b, c) => { console.log('getWasmTableEntry', rawFunction, a, b, c); }; }
@@ -2692,7 +2146,6 @@ function __embind_finalize_value_array(rawTupleType) {
2692
2146
  return ptr;
2693
2147
  },
2694
2148
  'argPackAdvance': 8n,
2695
- 'readValueFromPointer': simpleReadValueFromPointer,
2696
2149
  destructorFunction: rawDestructor,
2697
2150
  }];
2698
2151
  });
@@ -2810,7 +2263,6 @@ function __embind_finalize_value_object(structType) {
2810
2263
  return ptr;
2811
2264
  },
2812
2265
  'argPackAdvance': 8n,
2813
- 'readValueFromPointer': simpleReadValueFromPointer,
2814
2266
  destructorFunction: rawDestructor,
2815
2267
  }];
2816
2268
  });
@@ -3079,8 +2531,9 @@ function attachFinalizer(handle) {
3079
2531
  // https://github.com/tc39/proposal-weakrefs), then attach finalizers
3080
2532
  // for class handles. We check for the presence of FinalizationRegistry
3081
2533
  // at run-time, not build-time.
2534
+ // A collected handle is released without the warning upstream prints under ASSERTIONS, as a release wasm build
2535
+ // does: JavaScript never has to call .delete() on what crossbind hands it.
3082
2536
  finalizationRegistry = new FinalizationRegistry((info) => {
3083
- console.warn(info.leakWarning.stack.replace(/^Error: /, ''));
3084
2537
  releaseClassHandle(info.$$);
3085
2538
  });
3086
2539
  attachFinalizer = (handle) => {
@@ -3088,20 +2541,7 @@ function attachFinalizer(handle) {
3088
2541
  var hasSmartPtr = !!$$.smartPtr;
3089
2542
  if (hasSmartPtr) {
3090
2543
  // We should not call the destructor on raw pointers in case other code expects the pointee to live
3091
- var info = { $$: $$ };
3092
- // Create a warning as an Error instance in advance so that we can store
3093
- // the current stacktrace and point to it when / if a leak is detected.
3094
- // This is more useful than the empty stacktrace of `FinalizationRegistry`
3095
- // callback.
3096
- var cls = $$.ptrType.registeredClass;
3097
- info.leakWarning = new Error(`Embind found a leaked C++ instance ${cls.name} <${ptrToString($$.ptr)}>.\n` +
3098
- "We'll free it automatically in this case, but this functionality is not reliable across various environments.\n" +
3099
- "Make sure to invoke .delete() manually once you're done with the instance instead.\n" +
3100
- "Originally allocated"); // `.stack` will add "at ..." after this sentence
3101
- if ('captureStackTrace' in Error) {
3102
- Error.captureStackTrace(info.leakWarning, RegisteredPointer_fromWireType);
3103
- }
3104
- finalizationRegistry.register(handle, info, handle);
2544
+ finalizationRegistry.register(handle, { $$: $$ }, handle);
3105
2545
  }
3106
2546
  return handle;
3107
2547
  };
@@ -3375,7 +2815,6 @@ function init_RegisteredPointer() {
3375
2815
  RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee;
3376
2816
  RegisteredPointer.prototype.destructor = RegisteredPointer_destructor;
3377
2817
  RegisteredPointer.prototype['argPackAdvance'] = 8n;
3378
- RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer64;
3379
2818
  RegisteredPointer.prototype['deleteObject'] = RegisteredPointer_deleteObject;
3380
2819
  RegisteredPointer.prototype['fromWireType'] = RegisteredPointer_fromWireType;
3381
2820
  }
@@ -4078,16 +3517,7 @@ globalThis.__embind_register_smart_ptr = __embind_register_smart_ptr;
4078
3517
 
4079
3518
 
4080
3519
 
4081
- function enumReadValueFromPointer(name, shift, signed) {
4082
- //console.log('enumReadValueFromPointer');
4083
- return (pointer) => {
4084
- return this['fromWireType'](readFromMemoryUsingShift(pointer, signed, shift));
4085
- }
4086
- }
4087
-
4088
-
4089
3520
  function __embind_register_enum(rawType, name, size, isSigned) {
4090
- var shift = getShiftFromSize(size);
4091
3521
  name = readLatin1String(name);
4092
3522
 
4093
3523
  function ctor() { }
@@ -4101,11 +3531,13 @@ function __embind_register_enum(rawType, name, size, isSigned) {
4101
3531
  return this.constructor.values[c];
4102
3532
  },
4103
3533
  'toWireType': function (destructors, c) {
4104
- //console.log('__embind_register_enum, toWireType', ctor, c.value);
4105
- return c.value;
3534
+ // A number crosses as it is, as the wasm glue takes it; anything but a member or a number throws instead of
3535
+ // crossing as undefined.
3536
+ if (typeof c == "number") return c;
3537
+ if (c !== null && typeof c == "object" && typeof c.value == "number") return c.value;
3538
+ throw new TypeError(`${this.name} takes a member of the enum or its number, got ${embindRepr(c)}`);
4106
3539
  },
4107
3540
  'argPackAdvance': 8n,
4108
- 'readValueFromPointer': enumReadValueFromPointer(name, shift, isSigned),
4109
3541
  destructorFunction: null,
4110
3542
  });
4111
3543
  exposePublicSymbol(name, ctor);
@@ -4159,11 +3591,15 @@ globalThis.__emval_incref = __emval_incref;
4159
3591
 
4160
3592
 
4161
3593
 
4162
- function __emval_run_destructors(handle) {
4163
- // console.log('__emval_run_destructors');
4164
- var destructors = Emval.toValue(handle);
4165
- runDestructors(destructors);
4166
- __emval_decref(handle);
3594
+ // __emval_as and __emval_call_method queue one list each; C++ runs it once it has read the
3595
+ // converted value (DestructorsRunner in val.h), so nesting unwinds in order. Called from a C++
3596
+ // destructor, so it must not throw.
3597
+ var emval_destructorsStack = [];
3598
+ function __emval_run_destructors() {
3599
+ var destructors = emval_destructorsStack.pop();
3600
+ if (destructors) {
3601
+ runDestructors(destructors);
3602
+ }
4167
3603
  }
4168
3604
  globalThis.__emval_run_destructors = __emval_run_destructors;
4169
3605
 
@@ -4206,86 +3642,28 @@ function __emval_new_cstring(v) {
4206
3642
  globalThis.__emval_new_cstring = __emval_new_cstring;
4207
3643
 
4208
3644
 
3645
+ // C++ decodes both into a JS string before calling (bind.cpp).
4209
3646
  function __emval_new_u8string(v) {
4210
- // console.log('__emval_new_u8string');
4211
- return Emval.toHandle(UTF8ToString(v));
3647
+ return Emval.toHandle(v);
4212
3648
  }
4213
3649
  globalThis.__emval_new_u8string = __emval_new_u8string;
4214
3650
 
4215
3651
  function __emval_new_u16string(v) {
4216
- // console.log('__emval_new_u16string');
4217
- return Emval.toHandle(UTF16ToString(v));
3652
+ return Emval.toHandle(v);
4218
3653
  }
4219
3654
  globalThis.__emval_new_u16string = __emval_new_u16string;
4220
3655
 
4221
3656
  BigInt.prototype.toJSON = function () { return this.toString() }
4222
- function __emval_take_value(type, arg) {
4223
- //console.log('__emval_take_value', JSON.stringify({type, arg}, null, 2));
3657
+ function __emval_take_value(type, value) {
4224
3658
  type = requireRegisteredType(type, '_emval_take_value');
4225
- //console.log('************** 2:', JSON.stringify({type, arg}, null, 2));
4226
- //console.log('************** 2.5:', type['readValueFromPointer']);
4227
- var v = type['readValueFromPointer'](arg);
4228
- //console.log('************** 3:', v);
4229
- const f = Emval.toHandle(v);
4230
- //console.log('************** 4:', f);
4231
- return f;
3659
+ return Emval.toHandle(type['fromWireType'](value));
4232
3660
  }
4233
3661
  globalThis.__emval_take_value = __emval_take_value;
4234
3662
 
4235
3663
 
4236
- function craftEmvalAllocator(argCount) {
4237
- /*This function returns a new function that looks like this:
4238
- function emval_allocator_3(constructor, argTypes, args) {
4239
- var argType0 = requireRegisteredType(HEAP32[(argTypes >> 2)], "parameter 0");
4240
- var arg0 = argType0['readValueFromPointer'](args);
4241
- var argType1 = requireRegisteredType(HEAP32[(argTypes >> 2) + 1], "parameter 1");
4242
- var arg1 = argType1['readValueFromPointer'](args + 8);
4243
- var argType2 = requireRegisteredType(HEAP32[(argTypes >> 2) + 2], "parameter 2");
4244
- var arg2 = argType2['readValueFromPointer'](args + 16);
4245
- var obj = new constructor(arg0, arg1, arg2);
4246
- return Emval.toHandle(obj);
4247
- } */
4248
- var argsList = "";
4249
- for (var i = 0; i < argCount; ++i) {
4250
- argsList += (i !== 0 ? ", " : "") + "arg" + i; // 'arg0, arg1, ..., argn'
4251
- }
4252
-
4253
- var functionBody =
4254
- "return function emval_allocator_" + argCount + "(constructor, argTypes, args) {\n";
4255
-
4256
- for (var i = 0; i < argCount; ++i) {
4257
- functionBody +=
4258
- "var argType" + i + " = requireRegisteredType(argTypes[" + i + "], 'parameter " + i + "');\n" +
4259
- "var arg" + i + " = argType" + i + ".readValueFromPointer(args);\n" +
4260
- "args += argType" + i + "['argPackAdvance'];\n";
4261
- }
4262
- functionBody +=
4263
- "var obj = new constructor(" + argsList + ");\n" +
4264
- "return valueToHandle(obj);\n" +
4265
- "}\n";
4266
-
4267
- /*jshint evil:true*/
4268
- return (new Function("requireRegisteredType", "Module", "valueToHandle", "readFromMemoryUsingShift", functionBody))(
4269
- requireRegisteredType, Module, Emval.toHandle, readFromMemoryUsingShift);
4270
- }
4271
-
4272
- var emval_newers = {};
4273
-
4274
- function __emval_new(handle, argCount, argTypes, args) {
4275
- argCount = Number(argCount);
4276
- //console.log('__emval_new', handle, argCount, argTypes.length, argTypes, args);
4277
- handle = Emval.toValue(handle);
4278
-
4279
- var newer = emval_newers[argCount];
4280
- if (!newer) {
4281
- newer = craftEmvalAllocator(argCount);
4282
- emval_newers[argCount] = newer;
4283
- }
4284
-
4285
- //console.log('__emval_new response2');
4286
- const a = newer(handle, argTypes, args);;
4287
- //console.log('__emval_new response: ', a);
4288
- return a;
3664
+ function __emval_new(handle, argCount, argTypes, ...wires) {
3665
+ var constructor = Emval.toValue(handle);
3666
+ return Emval.toHandle(new constructor(...emval_fromWireTypes(argCount, argTypes, wires)));
4289
3667
  }
4290
3668
  globalThis.__emval_new = __emval_new;
4291
3669
 
@@ -4305,9 +3683,10 @@ const globalIgnoreList = [
4305
3683
  function emval_get_global() {
4306
3684
  if (typeof globalThis == 'object') {
4307
3685
  const global = {};
4308
- Object.keys(globalThis).filter(key => !key.startsWith('_') && !globalIgnoreList.includes(key)).forEach(key => {
4309
- global[key] = globalThis[key];
4310
- });
3686
+ // for...in: a Node loader bundle's globalThis inherits the global's properties.
3687
+ for (const key in globalThis) {
3688
+ if (!key.startsWith('_') && !globalIgnoreList.includes(key)) global[key] = globalThis[key];
3689
+ }
4311
3690
 
4312
3691
  return global;
4313
3692
  }
@@ -4353,18 +3732,12 @@ function __emval_set_property(handle, key, value) {
4353
3732
  globalThis.__emval_set_property = __emval_set_property;
4354
3733
 
4355
3734
 
4356
- function __emval_as(handle, returnType, destructorsRef) {
4357
- //console.log('__emval_as');
3735
+ function __emval_as(handle, returnType) {
4358
3736
  handle = Emval.toValue(handle);
4359
- //console.log('__emval_as 2');
4360
3737
  returnType = requireRegisteredType(returnType, 'emval::as');
4361
- //console.log('__emval_as 3');
4362
3738
  var destructors = [];
4363
- var rd = Emval.toHandle(destructors);
4364
- //console.log('__emval_as 4', Number(rd));
4365
- writeToMemoryUsingShift(destructorsRef, false, 3, rd);
4366
3739
  const output = returnType['toWireType'](destructors, handle);
4367
- //console.log('__emval_as 5', Number(output));
3740
+ emval_destructorsStack.push(destructors);
4368
3741
  return output;
4369
3742
  }
4370
3743
  globalThis.__emval_as = __emval_as;
@@ -4436,21 +3809,14 @@ function emval_lookupTypes(argCount, argTypes) {
4436
3809
  return a;
4437
3810
  }
4438
3811
 
4439
- function __emval_call(handle, argCount, argTypes, argv) {
4440
- //console.log('__emval_call', handle, argCount, argTypes, argv);
3812
+ function emval_fromWireTypes(argCount, argTypes, wires) {
3813
+ var types = emval_lookupTypes(Number(argCount), argTypes);
3814
+ return types.map((type, i) => type['fromWireType'](wires[i]));
3815
+ }
3816
+
3817
+ function __emval_call(handle, argCount, argTypes, ...wires) {
4441
3818
  handle = Emval.toValue(handle);
4442
- var types = emval_lookupTypes(argCount, argTypes);
4443
- //console.log('ooooo', types);
4444
- var args = new Array(argCount);
4445
- for (var i = 0; i < argCount; ++i) {
4446
- var type = types[i];
4447
- args[i] = type['readValueFromPointer'](argv);
4448
- //console.log(args[i]);
4449
- argv += type['argPackAdvance'];
4450
- }
4451
- //console.log('ooooo3');
4452
- var rv = handle.apply(undefined, args);
4453
- //console.log('ooooo2');
3819
+ var rv = handle.apply(undefined, emval_fromWireTypes(argCount, argTypes, wires));
4454
3820
  return Emval.toHandle(rv);
4455
3821
  }
4456
3822
  globalThis.__emval_call = __emval_call;
@@ -4481,19 +3847,19 @@ function __emval_get_method_caller(argCount, argTypes) {
4481
3847
  var args = [retType];
4482
3848
 
4483
3849
  var argsList = ""; // 'arg0, arg1, arg2, ... , argN'
3850
+ var wiresList = ""; // ', wire0, wire1, ... , wireN'
4484
3851
  for (var i = 0; i < argCount - 1; ++i) {
4485
3852
  argsList += (i !== 0 ? ", " : "") + "arg" + i;
3853
+ wiresList += ", wire" + i;
4486
3854
  params.push("argType" + i);
4487
3855
  args.push(types[1 + i]);
4488
3856
  }
4489
3857
  var functionName = makeLegalFunctionName("methodCaller_" + signatureName);
4490
3858
  var functionBody =
4491
- "return function " + functionName + "(handle, name, destructors, args) {\n";
4492
- var offset = 0n;
3859
+ "return function " + functionName + "(handle, name, destructors" + wiresList + ") {\n";
4493
3860
  for (var i = 0; i < argCount - 1; ++i) {
4494
3861
  functionBody +=
4495
- " var arg" + i + " = argType" + i + ".readValueFromPointer(args" + (offset ? ("+" + offset + "n") : "") + ");\n";
4496
- offset += types[i + 1]['argPackAdvance'];
3862
+ " var arg" + i + " = argType" + i + ".fromWireType(wire" + i + ");\n";
4497
3863
  }
4498
3864
  functionBody +=
4499
3865
  " var rv = handle[name](" + argsList + ");\n";
@@ -4517,34 +3883,22 @@ function __emval_get_method_caller(argCount, argTypes) {
4517
3883
  }
4518
3884
  globalThis.__emval_get_method_caller = __emval_get_method_caller;
4519
3885
 
4520
- function emval_allocateDestructors(destructorsRef) {
4521
- //console.log('emval_allocateDestructors');
4522
- var destructors = [];
4523
- writeToMemoryUsingShift(destructorsRef, false, 3, Emval.toHandle(destructors));
4524
- //console.log('emval_allocateDestructors 2');
4525
- return destructors;
4526
- }
4527
-
4528
-
4529
-
4530
- function __emval_call_method(caller, handle, methodName, destructorsRef, args) {
4531
- //console.log('__emval_call_method');
3886
+ function __emval_call_method(caller, handle, methodName, ...wires) {
4532
3887
  caller = emval_methodCallers[caller];
4533
3888
  handle = Emval.toValue(handle);
4534
3889
  methodName = getStringOrSymbol(methodName);
4535
- return caller(handle, methodName, emval_allocateDestructors(destructorsRef), args);
3890
+ var destructors = [];
3891
+ var rv = caller(handle, methodName, destructors, ...wires);
3892
+ emval_destructorsStack.push(destructors);
3893
+ return rv;
4536
3894
  }
4537
3895
  globalThis.__emval_call_method = __emval_call_method;
4538
3896
 
4539
-
4540
-
4541
-
4542
- function __emval_call_void_method(caller, handle, methodName, args) {
4543
- //console.log('__emval_call_void_method');
3897
+ function __emval_call_void_method(caller, handle, methodName, ...wires) {
4544
3898
  caller = emval_methodCallers[caller];
4545
3899
  handle = Emval.toValue(handle);
4546
3900
  methodName = getStringOrSymbol(methodName);
4547
- caller(handle, methodName, null, args);
3901
+ caller(handle, methodName, null, ...wires);
4548
3902
  }
4549
3903
  globalThis.__emval_call_void_method = __emval_call_void_method;
4550
3904