11cb0ef41Sopenharmony_ci# CJS Module Lexer 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci[![Build Status][travis-image]][travis-url] 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciA [very fast](#benchmarks) JS CommonJS module syntax lexer used to detect the most likely list of named exports of a CommonJS module. 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciOutputs the list of named exports (`exports.name = ...`) and possible module reexports (`module.exports = require('...')`), including the common transpiler variations of these cases. 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciForked from https://github.com/guybedford/es-module-lexer. 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci_Comprehensively handles the JS language grammar while remaining small and fast. - ~90ms per MB of JS cold and ~15ms per MB of JS warm, [see benchmarks](#benchmarks) for more info._ 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci### Usage 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci``` 161cb0ef41Sopenharmony_cinpm install cjs-module-lexer 171cb0ef41Sopenharmony_ci``` 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciFor use in CommonJS: 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci```js 221cb0ef41Sopenharmony_ciconst { parse } = require('cjs-module-lexer'); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// `init` return a promise for parity with the ESM API, but you do not have to call it 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciconst { exports, reexports } = parse(` 271cb0ef41Sopenharmony_ci // named exports detection 281cb0ef41Sopenharmony_ci module.exports.a = 'a'; 291cb0ef41Sopenharmony_ci (function () { 301cb0ef41Sopenharmony_ci exports.b = 'b'; 311cb0ef41Sopenharmony_ci })(); 321cb0ef41Sopenharmony_ci Object.defineProperty(exports, 'c', { value: 'c' }); 331cb0ef41Sopenharmony_ci /* exports.d = 'not detected'; */ 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci // reexports detection 361cb0ef41Sopenharmony_ci if (maybe) module.exports = require('./dep1.js'); 371cb0ef41Sopenharmony_ci if (another) module.exports = require('./dep2.js'); 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // literal exports assignments 401cb0ef41Sopenharmony_ci module.exports = { a, b: c, d, 'e': f } 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci // __esModule detection 431cb0ef41Sopenharmony_ci Object.defineProperty(module.exports, '__esModule', { value: true }) 441cb0ef41Sopenharmony_ci`); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci// exports === ['a', 'b', 'c', '__esModule'] 471cb0ef41Sopenharmony_ci// reexports === ['./dep1.js', './dep2.js'] 481cb0ef41Sopenharmony_ci``` 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ciWhen using the ESM version, Wasm is supported instead: 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci```js 531cb0ef41Sopenharmony_ciimport { parse, init } from 'cjs-module-lexer'; 541cb0ef41Sopenharmony_ci// init needs to be called and waited upon 551cb0ef41Sopenharmony_ciawait init(); 561cb0ef41Sopenharmony_ciconst { exports, reexports } = parse(source); 571cb0ef41Sopenharmony_ci``` 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciThe Wasm build is around 1.5x faster and without a cold start. 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci### Grammar 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ciCommonJS exports matches are run against the source token stream. 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ciThe token grammar is: 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci``` 681cb0ef41Sopenharmony_ciIDENTIFIER: As defined by ECMA-262, without support for identifier `\` escapes, filtered to remove strict reserved words: 691cb0ef41Sopenharmony_ci "implements", "interface", "let", "package", "private", "protected", "public", "static", "yield", "enum" 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ciSTRING_LITERAL: A `"` or `'` bounded ECMA-262 string literal. 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ciMODULE_EXPORTS: `module` `.` `exports` 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ciEXPORTS_IDENTIFIER: MODULE_EXPORTS_IDENTIFIER | `exports` 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciEXPORTS_DOT_ASSIGN: EXPORTS_IDENTIFIER `.` IDENTIFIER `=` 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ciEXPORTS_LITERAL_COMPUTED_ASSIGN: EXPORTS_IDENTIFIER `[` STRING_LITERAL `]` `=` 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ciEXPORTS_LITERAL_PROP: (IDENTIFIER (`:` IDENTIFIER)?) | (STRING_LITERAL `:` IDENTIFIER) 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ciEXPORTS_SPREAD: `...` (IDENTIFIER | REQUIRE) 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ciEXPORTS_MEMBER: EXPORTS_DOT_ASSIGN | EXPORTS_LITERAL_COMPUTED_ASSIGN 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ciEXPORTS_DEFINE: `Object` `.` `defineProperty `(` EXPORTS_IDENFITIER `,` STRING_LITERAL 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciEXPORTS_DEFINE_VALUE: EXPORTS_DEFINE `, {` 901cb0ef41Sopenharmony_ci (`enumerable: true,`)? 911cb0ef41Sopenharmony_ci ( 921cb0ef41Sopenharmony_ci `value:` | 931cb0ef41Sopenharmony_ci `get` (`: function` IDENTIFIER? )? `() {` return IDENTIFIER (`.` IDENTIFIER | `[` STRING_LITERAL `]`)? `;`? `}` `,`? 941cb0ef41Sopenharmony_ci ) 951cb0ef41Sopenharmony_ci `})` 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ciEXPORTS_LITERAL: MODULE_EXPORTS `=` `{` (EXPORTS_LITERAL_PROP | EXPORTS_SPREAD) `,`)+ `}` 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ciREQUIRE: `require` `(` STRING_LITERAL `)` 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciEXPORTS_ASSIGN: (`var` | `const` | `let`) IDENTIFIER `=` (`_interopRequireWildcard (`)? REQUIRE 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ciMODULE_EXPORTS_ASSIGN: MODULE_EXPORTS `=` REQUIRE 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ciEXPORT_STAR: (`__export` | `__exportStar`) `(` REQUIRE 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ciEXPORT_STAR_LIB: `Object.keys(` IDENTIFIER$1 `).forEach(function (` IDENTIFIER$2 `) {` 1081cb0ef41Sopenharmony_ci ( 1091cb0ef41Sopenharmony_ci ( 1101cb0ef41Sopenharmony_ci `if (` IDENTIFIER$2 `===` ( `'default'` | `"default"` ) `||` IDENTIFIER$2 `===` ( '__esModule' | `"__esModule"` ) `) return` `;`? 1111cb0ef41Sopenharmony_ci ( 1121cb0ef41Sopenharmony_ci (`if (Object` `.prototype`? `.hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)) return` `;`?)? 1131cb0ef41Sopenharmony_ci (`if (` IDENTIFIER$2 `in` EXPORTS_IDENTIFIER `&&` EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] ===` IDENTIFIER$1 `[` IDENTIFIER$2 `]) return` `;`)? 1141cb0ef41Sopenharmony_ci )? 1151cb0ef41Sopenharmony_ci ) | 1161cb0ef41Sopenharmony_ci `if (` IDENTIFIER$2 `!==` ( `'default'` | `"default"` ) (`&& !` (`Object` `.prototype`? `.hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)` | IDENTIFIER `.hasOwnProperty(` IDENTIFIER$2 `)`))? `)` 1171cb0ef41Sopenharmony_ci ) 1181cb0ef41Sopenharmony_ci ( 1191cb0ef41Sopenharmony_ci EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] =` IDENTIFIER$1 `[` IDENTIFIER$2 `]` `;`? | 1201cb0ef41Sopenharmony_ci `Object.defineProperty(` EXPORTS_IDENTIFIER `, ` IDENTIFIER$2 `, { enumerable: true, get` (`: function` IDENTIFIER? )? `() { return ` IDENTIFIER$1 `[` IDENTIFIER$2 `]` `;`? `}` `,`? `})` `;`? 1211cb0ef41Sopenharmony_ci ) 1221cb0ef41Sopenharmony_ci `})` 1231cb0ef41Sopenharmony_ci``` 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ciSpacing between tokens is taken to be any ECMA-262 whitespace, ECMA-262 block comment or ECMA-262 line comment. 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci* The returned export names are taken to be the combination of: 1281cb0ef41Sopenharmony_ci 1. All `IDENTIFIER` and `STRING_LITERAL` slots for `EXPORTS_MEMBER` and `EXPORTS_LITERAL` matches. 1291cb0ef41Sopenharmony_ci 2. The first `STRING_LITERAL` slot for all `EXPORTS_DEFINE_VALUE` matches where that same string is not an `EXPORTS_DEFINE` match that is not also an `EXPORTS_DEFINE_VALUE` match. 1301cb0ef41Sopenharmony_ci* The reexport specifiers are taken to be the combination of: 1311cb0ef41Sopenharmony_ci 1. The `REQUIRE` matches of the last matched of either `MODULE_EXPORTS_ASSIGN` or `EXPORTS_LITERAL`. 1321cb0ef41Sopenharmony_ci 2. All _top-level_ `EXPORT_STAR` `REQUIRE` matches and `EXPORTS_ASSIGN` matches whose `IDENTIFIER` also matches the first `IDENTIFIER` in `EXPORT_STAR_LIB`. 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci### Parsing Examples 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci#### Named Exports Parsing 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ciThe basic matching rules for named exports are `exports.name`, `exports['name']` or `Object.defineProperty(exports, 'name', ...)`. This matching is done without scope analysis and regardless of the expression position: 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci```js 1411cb0ef41Sopenharmony_ci// DETECTS EXPORTS: a, b 1421cb0ef41Sopenharmony_ci(function (exports) { 1431cb0ef41Sopenharmony_ci exports.a = 'a'; 1441cb0ef41Sopenharmony_ci exports['b'] = 'b'; 1451cb0ef41Sopenharmony_ci})(exports); 1461cb0ef41Sopenharmony_ci``` 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ciBecause there is no scope analysis, the above detection may overclassify: 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci```js 1511cb0ef41Sopenharmony_ci// DETECTS EXPORTS: a, b, c 1521cb0ef41Sopenharmony_ci(function (exports, Object) { 1531cb0ef41Sopenharmony_ci exports.a = 'a'; 1541cb0ef41Sopenharmony_ci exports['b'] = 'b'; 1551cb0ef41Sopenharmony_ci if (false) 1561cb0ef41Sopenharmony_ci exports.c = 'c'; 1571cb0ef41Sopenharmony_ci})(NOT_EXPORTS, NOT_OBJECT); 1581cb0ef41Sopenharmony_ci``` 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ciIt will in turn underclassify in cases where the identifiers are renamed: 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci```js 1631cb0ef41Sopenharmony_ci// DETECTS: NO EXPORTS 1641cb0ef41Sopenharmony_ci(function (e) { 1651cb0ef41Sopenharmony_ci e.a = 'a'; 1661cb0ef41Sopenharmony_ci e['b'] = 'b'; 1671cb0ef41Sopenharmony_ci})(exports); 1681cb0ef41Sopenharmony_ci``` 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci#### Getter Exports Parsing 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci`Object.defineProperty` is detected for specifically value and getter forms returning an identifier or member expression: 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci```js 1751cb0ef41Sopenharmony_ci// DETECTS: a, b, c, d, __esModule 1761cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'a', { 1771cb0ef41Sopenharmony_ci enumerable: true, 1781cb0ef41Sopenharmony_ci get: function () { 1791cb0ef41Sopenharmony_ci return q.p; 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci}); 1821cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'b', { 1831cb0ef41Sopenharmony_ci enumerable: true, 1841cb0ef41Sopenharmony_ci get: function () { 1851cb0ef41Sopenharmony_ci return q['p']; 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci}); 1881cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'c', { 1891cb0ef41Sopenharmony_ci enumerable: true, 1901cb0ef41Sopenharmony_ci get () { 1911cb0ef41Sopenharmony_ci return b; 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci}); 1941cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'd', { value: 'd' }); 1951cb0ef41Sopenharmony_ciObject.defineProperty(exports, '__esModule', { value: true }); 1961cb0ef41Sopenharmony_ci``` 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ciValue properties are also detected specifically: 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci```js 2011cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'a', { 2021cb0ef41Sopenharmony_ci value: 'no problem' 2031cb0ef41Sopenharmony_ci}); 2041cb0ef41Sopenharmony_ci``` 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ciTo avoid matching getters that have side effects, any getter for an export name that does not support the forms above will 2071cb0ef41Sopenharmony_ciopt-out of the getter matching: 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci```js 2101cb0ef41Sopenharmony_ci// DETECTS: NO EXPORTS 2111cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'a', { 2121cb0ef41Sopenharmony_ci get () { 2131cb0ef41Sopenharmony_ci return 'nope'; 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci}); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ciif (false) { 2181cb0ef41Sopenharmony_ci Object.defineProperty(module.exports, 'a', { 2191cb0ef41Sopenharmony_ci get () { 2201cb0ef41Sopenharmony_ci return dynamic(); 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci }) 2231cb0ef41Sopenharmony_ci} 2241cb0ef41Sopenharmony_ci``` 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ciAlternative object definition structures or getter function bodies are not detected: 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci```js 2291cb0ef41Sopenharmony_ci// DETECTS: NO EXPORTS 2301cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'a', { 2311cb0ef41Sopenharmony_ci enumerable: false, 2321cb0ef41Sopenharmony_ci get () { 2331cb0ef41Sopenharmony_ci return p; 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci}); 2361cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'b', { 2371cb0ef41Sopenharmony_ci configurable: true, 2381cb0ef41Sopenharmony_ci get () { 2391cb0ef41Sopenharmony_ci return p; 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci}); 2421cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'c', { 2431cb0ef41Sopenharmony_ci get: () => p 2441cb0ef41Sopenharmony_ci}); 2451cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'd', { 2461cb0ef41Sopenharmony_ci enumerable: true, 2471cb0ef41Sopenharmony_ci get: function () { 2481cb0ef41Sopenharmony_ci return dynamic(); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci}); 2511cb0ef41Sopenharmony_ciObject.defineProperty(exports, 'e', { 2521cb0ef41Sopenharmony_ci enumerable: true, 2531cb0ef41Sopenharmony_ci get () { 2541cb0ef41Sopenharmony_ci return 'str'; 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci}); 2571cb0ef41Sopenharmony_ci``` 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci`Object.defineProperties` is also not supported. 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci#### Exports Object Assignment 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ciA best-effort is made to detect `module.exports` object assignments, but because this is not a full parser, arbitrary expressions are not handled in the 2641cb0ef41Sopenharmony_ciobject parsing process. 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ciSimple object definitions are supported: 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci```js 2691cb0ef41Sopenharmony_ci// DETECTS EXPORTS: a, b, c 2701cb0ef41Sopenharmony_cimodule.exports = { 2711cb0ef41Sopenharmony_ci a, 2721cb0ef41Sopenharmony_ci 'b': b, 2731cb0ef41Sopenharmony_ci c: c, 2741cb0ef41Sopenharmony_ci ...d 2751cb0ef41Sopenharmony_ci}; 2761cb0ef41Sopenharmony_ci``` 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ciObject properties that are not identifiers or string expressions will bail out of the object detection, while spreads are ignored: 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci```js 2811cb0ef41Sopenharmony_ci// DETECTS EXPORTS: a, b 2821cb0ef41Sopenharmony_cimodule.exports = { 2831cb0ef41Sopenharmony_ci a, 2841cb0ef41Sopenharmony_ci ...d, 2851cb0ef41Sopenharmony_ci b: require('c'), 2861cb0ef41Sopenharmony_ci c: "not detected since require('c') above bails the object detection" 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci``` 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci`Object.defineProperties` is not currently supported either. 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci#### module.exports reexport assignment 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ciAny `module.exports = require('mod')` assignment is detected as a reexport, but only the last one is returned: 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci```js 2971cb0ef41Sopenharmony_ci// DETECTS REEXPORTS: c 2981cb0ef41Sopenharmony_cimodule.exports = require('a'); 2991cb0ef41Sopenharmony_ci(module => module.exports = require('b'))(NOT_MODULE); 3001cb0ef41Sopenharmony_ciif (false) module.exports = require('c'); 3011cb0ef41Sopenharmony_ci``` 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ciThis is to avoid over-classification in Webpack bundles with externals which include `module.exports = require('external')` in their source for every external dependency. 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ciIn exports object assignment, any spread of `require()` are detected as multiple separate reexports: 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci```js 3081cb0ef41Sopenharmony_ci// DETECTS REEXPORTS: a, b 3091cb0ef41Sopenharmony_cimodule.exports = require('ignored'); 3101cb0ef41Sopenharmony_cimodule.exports = { 3111cb0ef41Sopenharmony_ci ...require('a'), 3121cb0ef41Sopenharmony_ci ...require('b') 3131cb0ef41Sopenharmony_ci}; 3141cb0ef41Sopenharmony_ci``` 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci#### Transpiler Re-exports 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ciFor named exports, transpiler output works well with the rules described above. 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ciBut for star re-exports, special care is taken to support common patterns of transpiler outputs from Babel and TypeScript as well as bundlers like RollupJS. 3211cb0ef41Sopenharmony_ciThese reexport and star reexport patterns are restricted to only be detected at the top-level as provided by the direct output of these tools. 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ciFor example, `export * from 'external'` is output by Babel as: 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci```js 3261cb0ef41Sopenharmony_ci"use strict"; 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ciexports.__esModule = true; 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_civar _external = require("external"); 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ciObject.keys(_external).forEach(function (key) { 3331cb0ef41Sopenharmony_ci if (key === "default" || key === "__esModule") return; 3341cb0ef41Sopenharmony_ci exports[key] = _external[key]; 3351cb0ef41Sopenharmony_ci}); 3361cb0ef41Sopenharmony_ci``` 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ciWhere the `var _external = require("external")` is specifically detected as well as the `Object.keys(_external)` statement, down to the exact 3391cb0ef41Sopenharmony_cifor of that entire expression including minor variations of the output. The `_external` and `key` identifiers are carefully matched in this 3401cb0ef41Sopenharmony_cidetection. 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ciSimilarly for TypeScript, `export * from 'external'` is output as: 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci```js 3451cb0ef41Sopenharmony_ci"use strict"; 3461cb0ef41Sopenharmony_cifunction __export(m) { 3471cb0ef41Sopenharmony_ci for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ciObject.defineProperty(exports, "__esModule", { value: true }); 3501cb0ef41Sopenharmony_ci__export(require("external")); 3511cb0ef41Sopenharmony_ci``` 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ciWhere the `__export(require("external"))` statement is explicitly detected as a reexport, including variations `tslib.__export` and `__exportStar`. 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci### Environment Support 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ciNode.js 10+, and [all browsers with Web Assembly support](https://caniuse.com/#feat=wasm). 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci### JS Grammar Support 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci* Token state parses all line comments, block comments, strings, template strings, blocks, parens and punctuators. 3621cb0ef41Sopenharmony_ci* Division operator / regex token ambiguity is handled via backtracking checks against punctuator prefixes, including closing brace or paren backtracking. 3631cb0ef41Sopenharmony_ci* Always correctly parses valid JS source, but may parse invalid JS source without errors. 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci### Benchmarks 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ciBenchmarks can be run with `npm run bench`. 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ciCurrent results: 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ciJS Build: 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci``` 3741cb0ef41Sopenharmony_ciModule load time 3751cb0ef41Sopenharmony_ci> 4ms 3761cb0ef41Sopenharmony_ciCold Run, All Samples 3771cb0ef41Sopenharmony_citest/samples/*.js (3635 KiB) 3781cb0ef41Sopenharmony_ci> 299ms 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ciWarm Runs (average of 25 runs) 3811cb0ef41Sopenharmony_citest/samples/angular.js (1410 KiB) 3821cb0ef41Sopenharmony_ci> 13.96ms 3831cb0ef41Sopenharmony_citest/samples/angular.min.js (303 KiB) 3841cb0ef41Sopenharmony_ci> 4.72ms 3851cb0ef41Sopenharmony_citest/samples/d3.js (553 KiB) 3861cb0ef41Sopenharmony_ci> 6.76ms 3871cb0ef41Sopenharmony_citest/samples/d3.min.js (250 KiB) 3881cb0ef41Sopenharmony_ci> 4ms 3891cb0ef41Sopenharmony_citest/samples/magic-string.js (34 KiB) 3901cb0ef41Sopenharmony_ci> 0.64ms 3911cb0ef41Sopenharmony_citest/samples/magic-string.min.js (20 KiB) 3921cb0ef41Sopenharmony_ci> 0ms 3931cb0ef41Sopenharmony_citest/samples/rollup.js (698 KiB) 3941cb0ef41Sopenharmony_ci> 8.48ms 3951cb0ef41Sopenharmony_citest/samples/rollup.min.js (367 KiB) 3961cb0ef41Sopenharmony_ci> 5.36ms 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ciWarm Runs, All Samples (average of 25 runs) 3991cb0ef41Sopenharmony_citest/samples/*.js (3635 KiB) 4001cb0ef41Sopenharmony_ci> 40.28ms 4011cb0ef41Sopenharmony_ci``` 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ciWasm Build: 4041cb0ef41Sopenharmony_ci``` 4051cb0ef41Sopenharmony_ciModule load time 4061cb0ef41Sopenharmony_ci> 10ms 4071cb0ef41Sopenharmony_ciCold Run, All Samples 4081cb0ef41Sopenharmony_citest/samples/*.js (3635 KiB) 4091cb0ef41Sopenharmony_ci> 43ms 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ciWarm Runs (average of 25 runs) 4121cb0ef41Sopenharmony_citest/samples/angular.js (1410 KiB) 4131cb0ef41Sopenharmony_ci> 9.32ms 4141cb0ef41Sopenharmony_citest/samples/angular.min.js (303 KiB) 4151cb0ef41Sopenharmony_ci> 3.16ms 4161cb0ef41Sopenharmony_citest/samples/d3.js (553 KiB) 4171cb0ef41Sopenharmony_ci> 5ms 4181cb0ef41Sopenharmony_citest/samples/d3.min.js (250 KiB) 4191cb0ef41Sopenharmony_ci> 2.32ms 4201cb0ef41Sopenharmony_citest/samples/magic-string.js (34 KiB) 4211cb0ef41Sopenharmony_ci> 0.16ms 4221cb0ef41Sopenharmony_citest/samples/magic-string.min.js (20 KiB) 4231cb0ef41Sopenharmony_ci> 0ms 4241cb0ef41Sopenharmony_citest/samples/rollup.js (698 KiB) 4251cb0ef41Sopenharmony_ci> 6.28ms 4261cb0ef41Sopenharmony_citest/samples/rollup.min.js (367 KiB) 4271cb0ef41Sopenharmony_ci> 3.6ms 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ciWarm Runs, All Samples (average of 25 runs) 4301cb0ef41Sopenharmony_citest/samples/*.js (3635 KiB) 4311cb0ef41Sopenharmony_ci> 27.76ms 4321cb0ef41Sopenharmony_ci``` 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci### Wasm Build Steps 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ciTo build download the WASI SDK from https://github.com/WebAssembly/wasi-sdk/releases. 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ciThe Makefile assumes the existence of "wasi-sdk-11.0" and "wabt" (optional) as sibling folders to this project. 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ciThe build through the Makefile is then run via `make lib/lexer.wasm`, which can also be triggered via `npm run build-wasm` to create `dist/lexer.js`. 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ciOn Windows it may be preferable to use the Linux subsystem. 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ciAfter the Web Assembly build, the CJS build can be triggered via `npm run build`. 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ciOptimization passes are run with [Binaryen](https://github.com/WebAssembly/binaryen) prior to publish to reduce the Web Assembly footprint. 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci### License 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ciMIT 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci[travis-url]: https://travis-ci.org/guybedford/es-module-lexer 4531cb0ef41Sopenharmony_ci[travis-image]: https://travis-ci.org/guybedford/es-module-lexer.svg?branch=master 454