lexer-external.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. "use strict";
  2. exports.init = init;
  3. exports.parse = parse;
  4. let wasm;
  5. const isLE = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;
  6. function parse(source, name = '@') {
  7. if (!wasm) throw new Error('Not initialized');
  8. const len = source.length + 1;
  9. // need 2 bytes per code point plus analysis space so we double again
  10. const extraMem = (wasm.__heap_base.value || wasm.__heap_base) + len * 4 - wasm.memory.buffer.byteLength;
  11. if (extraMem > 0) wasm.memory.grow(Math.ceil(extraMem / 65536));
  12. const addr = wasm.sa(len);
  13. (isLE ? copyLE : copyBE)(source, new Uint16Array(wasm.memory.buffer, addr, len));
  14. const err_code = wasm.parseCJS(addr, source.length, 0, 0, 0);
  15. if (err_code) {
  16. const err = new Error(`Parse error ${name}${wasm.e()}:${source.slice(0, wasm.e()).split('\n').length}:${wasm.e() - source.lastIndexOf('\n', wasm.e() - 1)}`);
  17. Object.assign(err, {
  18. idx: wasm.e()
  19. });
  20. if (err_code === 5 || err_code === 6 || err_code === 7) Object.assign(err, {
  21. code: 'ERR_LEXER_ESM_SYNTAX'
  22. });
  23. throw err;
  24. }
  25. let exports = new Set(),
  26. reexports = new Set(),
  27. unsafeGetters = new Set();
  28. while (wasm.rre()) {
  29. const reexptStr = decode(source.slice(wasm.res(), wasm.ree()));
  30. if (reexptStr) reexports.add(reexptStr);
  31. }
  32. while (wasm.ru()) unsafeGetters.add(decode(source.slice(wasm.us(), wasm.ue())));
  33. while (wasm.re()) {
  34. let exptStr = decode(source.slice(wasm.es(), wasm.ee()));
  35. if (exptStr !== undefined && !unsafeGetters.has(exptStr)) exports.add(exptStr);
  36. }
  37. return {
  38. exports: [...exports],
  39. reexports: [...reexports]
  40. };
  41. }
  42. function decode(str) {
  43. if (str[0] === '"' || str[0] === '\'') {
  44. try {
  45. const decoded = (0, eval)(str);
  46. // Filter to exclude non-matching UTF-16 surrogate strings
  47. for (let i = 0; i < decoded.length; i++) {
  48. const surrogatePrefix = decoded.charCodeAt(i) & 0xFC00;
  49. if (surrogatePrefix < 0xD800) {
  50. // Not a surrogate
  51. continue;
  52. } else if (surrogatePrefix === 0xD800) {
  53. // Validate surrogate pair
  54. if ((decoded.charCodeAt(++i) & 0xFC00) !== 0xDC00) return;
  55. } else {
  56. // Out-of-range surrogate code (above 0xD800)
  57. return;
  58. }
  59. }
  60. return decoded;
  61. } catch {}
  62. } else {
  63. return str;
  64. }
  65. }
  66. function copyBE(src, outBuf16) {
  67. const len = src.length;
  68. let i = 0;
  69. while (i < len) {
  70. const ch = src.charCodeAt(i);
  71. outBuf16[i++] = (ch & 0xff) << 8 | ch >>> 8;
  72. }
  73. }
  74. function copyLE(src, outBuf16) {
  75. const len = src.length;
  76. let i = 0;
  77. while (i < len) outBuf16[i] = src.charCodeAt(i++);
  78. }
  79. let initPromise;
  80. function init() {
  81. if (initPromise) return initPromise;
  82. return initPromise = (async () => {
  83. const compiled = await WebAssembly.compile((await import('node:fs')).readFileSync(new URL(import.meta.resolve('../lib/lexer.wasm'))));
  84. const {
  85. exports
  86. } = await WebAssembly.instantiate(compiled);
  87. wasm = exports;
  88. })();
  89. }