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