From c989857aa5ec4713ff6bde4706105dc2cd2b2f40 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 11 Dec 2014 14:48:03 +0100 Subject: [PATCH] Add allowImportExportEverywhere option Closes #174 --- README.md | 4 ++++ acorn.js | 14 ++++++++++---- test/tests-harmony.js | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 44d75747ea..58627b0275 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,10 @@ object referring to that same position. the top level raises an error. Set this to `true` to accept such code. +- **allowImportExportEverywhere**: By default, `import` and `export` + declarations can only appear at a program's top level. Setting this + option to `true` allows them anywhere where a statement is allowed. + - **locations**: When `true`, each node has a `loc` object attached with `start` and `end` subobjects, each of which contains the one-based line and zero-based column numbers in `{line, column}` diff --git a/acorn.js b/acorn.js index d32eaf2bac..22b32f1577 100644 --- a/acorn.js +++ b/acorn.js @@ -71,6 +71,9 @@ // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the @@ -1503,7 +1506,7 @@ var first = true; if (!node.body) node.body = []; while (tokType !== _eof) { - var stmt = parseStatement(); + var stmt = parseStatement(true); node.body.push(stmt); if (first && isUseStrict(stmt)) setStrict(true); first = false; @@ -1524,7 +1527,7 @@ // `if (foo) /blah/.exec(foo);`, where looking at the previous token // does not help. - function parseStatement() { + function parseStatement(topLevel) { if (tokType === _slash || tokType === _assign && tokVal == "/=") readToken(true); @@ -1551,8 +1554,11 @@ case _with: return parseWithStatement(node); case _braceL: return parseBlock(); // no point creating a function for this case _semi: return parseEmptyStatement(node); - case _export: return parseExport(node); - case _import: return parseImport(node); + case _export: + case _import: + if (!topLevel && !options.allowImportExportEverywhere) + raise(tokStart, "'import' and 'export' may only appear at the top level"); + return starttype === _import ? parseImport(node) : parseExport(node); // If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 834979bcff..9723073690 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14138,6 +14138,8 @@ testFail("({ t(eval) { \"use strict\"; } });", "Defining 'eval' in strict mode ( testFail("\"use strict\"; `${test}\\02`;", "Octal literal in strict mode (1:22)", {ecmaVersion: 6}); +testFail("if (1) import \"acorn\";", "'import' and 'export' may only appear at the top level (1:7)", {ecmaVersion: 6}); + test("[...a, ] = b", { type: "Program", loc: {