diff --git a/lexer.js b/lexer.js index 286a170..abfcc5f 100755 --- a/lexer.js +++ b/lexer.js @@ -47,13 +47,21 @@ function parseCJS (source, name = '@') { e.loc = pos; throw e; } - const result = { exports: [..._exports].filter(expt => !unsafeGetters.has(expt)), reexports: [...reexports] }; + const result = { exports: [..._exports].filter(expt => expt !== undefined && !unsafeGetters.has(expt)), reexports: [...reexports].filter(reexpt => reexpt !== undefined) }; resetState(); return result; } -function addExport (name) { - _exports.add(name); +function decode (name) { + if (name[0] === '"' || name[0] === "'") { + try { + return (0, eval)(name); + } + catch {} + } + else { + return name; + } } function parseSource (cjsSource) { @@ -324,10 +332,9 @@ function tryParseObjectDefineOrKeys (keys) { pos++; ch = commentWhitespace(); if (ch !== 39/*'*/ && ch !== 34/*"*/) break; - const exportPos = ++pos; + const exportPos = pos; stringLiteral(ch); - expt = source.slice(exportPos, pos); - pos++; + expt = source.slice(exportPos, ++pos); ch = commentWhitespace(); if (ch !== 44/*,*/) break; pos++; @@ -354,7 +361,7 @@ function tryParseObjectDefineOrKeys (keys) { pos += 5; ch = commentWhitespace(); if (ch !== 58/*:*/) break; - addExport(expt); + _exports.add(decode(expt)); pos = revertPos; return; } @@ -420,13 +427,13 @@ function tryParseObjectDefineOrKeys (keys) { pos++; ch = commentWhitespace(); if (ch !== 41/*)*/) break; - addExport(expt); + _exports.add(decode(expt)); return; } break; } if (expt) { - unsafeGetters.add(expt); + unsafeGetters.add(decode(expt)); } } else if (keys && ch === 107/*k*/ && source.startsWith('eys', pos + 1)) { @@ -794,7 +801,7 @@ function tryParseObjectDefineOrKeys (keys) { const starExportSpecifier = starExportMap[id]; if (starExportSpecifier) { - reexports.add(starExportSpecifier); + reexports.add(decode(starExportSpecifier)); pos = revertPos; return; } @@ -856,7 +863,7 @@ function tryParseExportsDotAssign (assign) { const endPos = pos; ch = commentWhitespace(); if (ch === 61/*=*/) { - addExport(source.slice(startPos, endPos)); + _exports.add(decode(source.slice(startPos, endPos))); return; } } @@ -867,16 +874,15 @@ function tryParseExportsDotAssign (assign) { pos++; ch = commentWhitespace(); if (ch === 39/*'*/ || ch === 34/*"*/) { - pos++; const startPos = pos; stringLiteral(ch); - const endPos = pos++; + const endPos = ++pos; ch = commentWhitespace(); if (ch !== 93/*]*/) break; pos++; ch = commentWhitespace(); if (ch !== 61/*=*/) break; - addExport(source.slice(startPos, endPos)); + _exports.add(decode(source.slice(startPos, endPos))); } break; } @@ -911,21 +917,21 @@ function tryParseRequire (requireType) { if (ch === 40/*(*/) { pos++; ch = commentWhitespace(); - const reexportStart = pos + 1; + const reexportStart = pos; if (ch === 39/*'*/ || ch === 34/*"*/) { stringLiteral(ch); - const reexportEnd = pos++; + const reexportEnd = ++pos; ch = commentWhitespace(); if (ch === 41/*)*/) { switch (requireType) { case ExportAssign: - reexports.add(source.slice(reexportStart, reexportEnd)); + reexports.add(decode(source.slice(reexportStart, reexportEnd))); return true; case ExportStar: - reexports.add(source.slice(reexportStart, reexportEnd)); + reexports.add(decode(source.slice(reexportStart, reexportEnd))); return true; default: - lastStarExportSpecifier = source.slice(reexportStart, reexportEnd); + lastStarExportSpecifier = decode(source.slice(reexportStart, reexportEnd)); return true; } } @@ -954,7 +960,7 @@ function tryParseLiteralExports () { } ch = source.charCodeAt(pos); } - addExport(source.slice(startPos, endPos)); + _exports.add(decode(source.slice(startPos, endPos))); } else if (ch === 46/*.*/ && source.startsWith('..', pos + 1)) { pos += 3; @@ -968,9 +974,9 @@ function tryParseLiteralExports () { ch = commentWhitespace(); } else if (ch === 39/*'*/ || ch === 34/*"*/) { - const startPos = ++pos; + const startPos = pos; stringLiteral(ch); - const endPos = pos++; + const endPos = ++pos; ch = commentWhitespace(); if (ch === 58/*:*/) { pos++; @@ -981,7 +987,7 @@ function tryParseLiteralExports () { return; } ch = source.charCodeAt(pos); - addExport(source.slice(startPos, endPos)); + _exports.add(decode(source.slice(startPos, endPos))); } } else { diff --git a/lib/lexer.wasm b/lib/lexer.wasm index 83e000d..4244f7e 100755 Binary files a/lib/lexer.wasm and b/lib/lexer.wasm differ diff --git a/lib/lexer.wat b/lib/lexer.wat index 9988dc9..666c857 100644 --- a/lib/lexer.wat +++ b/lib/lexer.wat @@ -1222,32 +1222,28 @@ i32.const 0 i32.const 0 i32.load offset=20540 - local.tee 3 i32.const 2 i32.add + local.tee 3 i32.store offset=20540 call 39 i32.const 41 i32.ne br_if 0 (;@2;) - local.get 4 - i32.const 2 - i32.add - local.set 1 block ;; label = @3 local.get 0 i32.const -1 i32.add - local.tee 2 + local.tee 1 i32.const 1 i32.gt_u br_if 0 (;@3;) block ;; label = @4 block ;; label = @5 - local.get 2 + local.get 1 br_table 1 (;@4;) 0 (;@5;) 1 (;@4;) end - local.get 1 + local.get 4 local.get 3 i32.const 0 i32.load offset=4000 @@ -1255,7 +1251,7 @@ i32.const 1 return end - local.get 1 + local.get 4 local.get 3 i32.const 0 i32.load offset=4000 @@ -1265,7 +1261,7 @@ end i32.const 0 i32.load offset=20532 - local.get 1 + local.get 4 i32.store i32.const 0 i32.load offset=20532 @@ -1618,20 +1614,16 @@ br_if 3 (;@1;) end i32.const 0 - i32.const 0 i32.load offset=20540 - i32.const 2 - i32.add - local.tee 2 - i32.store offset=20540 + local.set 2 local.get 0 call 28 i32.const 0 i32.const 0 i32.load offset=20540 - local.tee 0 i32.const 2 i32.add + local.tee 0 i32.store offset=20540 call 39 i32.const 44 @@ -3647,9 +3639,6 @@ br 0 (;@3;) end end - local.get 0 - i32.eqz - br_if 0 (;@1;) local.get 2 local.get 0 i32.const 0 @@ -4488,20 +4477,16 @@ br_if 2 (;@1;) end i32.const 0 - i32.const 0 i32.load offset=20540 - i32.const 2 - i32.add - local.tee 0 - i32.store offset=20540 + local.set 0 local.get 2 call 28 i32.const 0 i32.const 0 i32.load offset=20540 - local.tee 2 i32.const 2 i32.add + local.tee 2 i32.store offset=20540 call 39 i32.const 93 @@ -5384,20 +5369,16 @@ br_if 4 (;@3;) end i32.const 0 - i32.const 0 i32.load offset=20540 - i32.const 2 - i32.add - local.tee 2 - i32.store offset=20540 + local.set 2 local.get 0 call 28 i32.const 0 i32.const 0 i32.load offset=20540 - local.tee 3 i32.const 2 i32.add + local.tee 3 i32.store offset=20540 call 39 local.tee 0 diff --git a/src/lexer.c b/src/lexer.c index d7a84d8..e86f4b5 100755 --- a/src/lexer.c +++ b/src/lexer.c @@ -339,10 +339,9 @@ void tryParseObjectDefineOrKeys (bool keys) { pos++; ch = commentWhitespace(); if (ch != '\'' && ch != '"') break; - exportStart = ++pos; + exportStart = pos; stringLiteral(ch); - exportEnd = pos; - pos++; + exportEnd = ++pos; ch = commentWhitespace(); if (ch != ',') break; pos++; @@ -891,10 +890,9 @@ void tryParseExportsDotAssign (bool assign) { pos++; ch = commentWhitespace(); if (ch == '\'' || ch == '"') { - pos++; uint16_t* startPos = pos; stringLiteral(ch); - uint16_t* endPos = pos++; + uint16_t* endPos = ++pos; ch = commentWhitespace(); if (ch != ']') break; pos++; @@ -934,10 +932,10 @@ bool tryParseRequire (enum RequireType requireType) { if (ch == '(') { pos++; ch = commentWhitespace(); - uint16_t* reexportStart = pos + 1; + uint16_t* reexportStart = pos; if (ch == '\'' || ch == '"') { stringLiteral(ch); - uint16_t* reexportEnd = pos++; + uint16_t* reexportEnd = ++pos; ch = commentWhitespace(); if (ch == ')') { switch (requireType) { @@ -981,9 +979,9 @@ void tryParseLiteralExports () { addExport(startPos, endPos); } else if (ch == '\'' || ch == '"') { - uint16_t* startPos = ++pos; + uint16_t* startPos = pos; stringLiteral(ch); - uint16_t* endPos = pos++; + uint16_t* endPos = ++pos; ch = commentWhitespace(); if (ch == ':') { pos++; diff --git a/src/lexer.js b/src/lexer.js index 0a47e50..2e8fe85 100755 --- a/src/lexer.js +++ b/src/lexer.js @@ -21,19 +21,34 @@ export function parse (source, name = '@') { let exports = new Set(), reexports = new Set(), unsafeGetters = new Set(); - while (wasm.rre()) - reexports.add(source.slice(wasm.res(), wasm.ree())); + while (wasm.rre()) { + const reexptStr = decode(source.slice(wasm.res(), wasm.ree())); + if (reexptStr) + reexports.add(reexptStr); + } while (wasm.ru()) - unsafeGetters.add(source.slice(wasm.us(), wasm.ue())); + unsafeGetters.add(decode(source.slice(wasm.us(), wasm.ue()))); while (wasm.re()) { - let exptStr = source.slice(wasm.es(), wasm.ee()); - if (!unsafeGetters.has(exptStr)) + let exptStr = decode(source.slice(wasm.es(), wasm.ee())); + if (exptStr !== undefined && !unsafeGetters.has(exptStr)) exports.add(exptStr); } return { exports: [...exports], reexports: [...reexports] }; } +function decode (str) { + if (str[0] === '"' || str[0] === '\'') { + try { + return (0, eval)(str); + } + catch {} + } + else { + return str; + } +} + function copyBE (src, outBuf16) { const len = src.length; let i = 0; diff --git a/test/_unit.js b/test/_unit.js index 50a9678..238df40 100755 --- a/test/_unit.js +++ b/test/_unit.js @@ -479,6 +479,9 @@ suite('Lexer', () => { const { exports } = parse(` module.exports = { 'ab cd': foo }; exports['not identifier'] = 'asdf'; + exports['\\u{D83C}\\u{DF10}'] = 1; + exports['\\u{D83C}'] = 1; + exports['\\''] = 1; exports['@notidentifier'] = 'asdf'; Object.defineProperty(exports, "%notidentifier", { value: x }); Object.defineProperty(exports, 'hm🤔', { value: x }); @@ -490,6 +493,9 @@ suite('Lexer', () => { assert.deepStrictEqual(exports, [ 'ab cd', 'not identifier', + '\u{D83C}\u{DF10}', + '\u{D83C}', + '\'', '@notidentifier', '%notidentifier', 'hm🤔',