From 588bef99394a3c1e51dee2277888bb1f7979fbab Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 20 Jun 2019 13:17:20 -0400 Subject: [PATCH] Tolerate undeclared exports until @babel/parser@7.5.0 is released. (#230) https://github.com/babel/babel/pull/9864 This hack narrowly targets @babel/parser@7.4.x by tricking Array.from(this.scope.undefinedExports) into returning an empty array, thereby simulating the effect of enabling the allowUndeclaredExports option (which will become available in @babel/parser@7.5.0). --- lib/parsers/babel.js | 35 +++++++++++++++++++++++++---------- test/export-tests.js | 5 +++++ test/undeclared-export.js | 1 + 3 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 test/undeclared-export.js diff --git a/lib/parsers/babel.js b/lib/parsers/babel.js index 843d0779..ed559771 100644 --- a/lib/parsers/babel.js +++ b/lib/parsers/babel.js @@ -1,18 +1,13 @@ "use strict"; -// Prefer the new @babel/parser package, but fall back to babylon if -// that's what's available. -const babelParser = function () { - try { - return require("@babel/parser"); - } catch (e) { - return require("babylon"); - } -}(); +const babelParser = require("@babel/parser"); +const babelParserVersion = require("@babel/parser/package.json").version; exports.options = { allowImportExportEverywhere: true, allowReturnOutsideFunction: true, + // This won't work until @babel/parser@7.5.0 is released. + allowUndeclaredExports: true, plugins: [ "*", "flow", "jsx", // The "*" glob no longer seems to include the following plugins: @@ -55,4 +50,24 @@ function parse(code) { return babelParser.parse(code, exports.options); } -exports.parse = parse; +function tolerantParse(code) { + const arrayFrom = Array.from; + // There is only one use of Array.from in the @babel/parser@7.4.x code, + // Array.from(this.scope.undefinedExports), which determines whether the + // parser complains prematurely about exporting identifiers that were + // not declared in the current module scope. By returning an empty array + // when the source argument is a Map, we can effectively disable that + // error behavior, until https://github.com/babel/babel/pull/9864 is + // released in @babel/parser@7.5.0. + Array.from = function (source) { + return source instanceof Map ? [] : + arrayFrom.apply(this, arguments); + }; + try { + return parse(code); + } finally { + Array.from = arrayFrom; + } +} + +exports.parse = babelParserVersion.startsWith("7.4.") ? tolerantParse : parse; diff --git a/test/export-tests.js b/test/export-tests.js index 3f724862..ee553645 100644 --- a/test/export-tests.js +++ b/test/export-tests.js @@ -317,4 +317,9 @@ describe("export declarations", () => { "from-ordering-c.js", ]); }); + + it("should be tolerant of exporting undeclared identifiers", () => { + import { GlobalArray } from "./undeclared-export.js"; + assert.strictEqual(GlobalArray, Array); + }); }); diff --git a/test/undeclared-export.js b/test/undeclared-export.js new file mode 100644 index 00000000..bc1ca548 --- /dev/null +++ b/test/undeclared-export.js @@ -0,0 +1 @@ +export { Array as GlobalArray }