MES手机端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

105 line
2.9 KiB

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