Skip to content

Commit

Permalink
feat: Add sourceType:commonjs support (#520)
Browse files Browse the repository at this point in the history
* feat: Add sourceType:commonjs support (fixes #519)

* Move originalSourceType into Espree state
  • Loading branch information
nzakas committed Nov 21, 2021
1 parent 6839389 commit 27713ac
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 13 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -145,7 +145,7 @@ const options = {
// You can also set "latest" to use the most recently supported version.
ecmaVersion: 5,

// specify which type of script you're parsing ("script" or "module")
// specify which type of script you're parsing ("script", "module", or "commonjs")
sourceType: "script",

// specify additional language features
Expand All @@ -154,7 +154,7 @@ const options = {
// enable JSX parsing
jsx: false,

// enable return in global scope
// enable return in global scope (set to true automatically when sourceType is "commonjs")
globalReturn: false,

// enable implied strict mode (if ecmaVersion >= 5)
Expand Down
13 changes: 10 additions & 3 deletions lib/espree.js
Expand Up @@ -56,6 +56,8 @@ export default () => Parser => {
code = String(code);
}

// save original source type in case of commonjs
const originalSourceType = opts.sourceType;
const options = normalizeOptions(opts);
const ecmaFeatures = options.ecmaFeatures || {};
const tokenTranslator =
Expand All @@ -74,7 +76,7 @@ export default () => Parser => {
allowReserved: options.allowReserved,

// Truthy value is true for backward compatibility.
allowReturnOutsideFunction: Boolean(ecmaFeatures.globalReturn),
allowReturnOutsideFunction: options.allowReturnOutsideFunction,

// Collect tokens
onToken: token => {
Expand All @@ -98,8 +100,13 @@ export default () => Parser => {
}
}, code);

// Initialize internal state.
/*
* Data that is unique to Espree and is not represented internally in
* Acorn. We put all of this data into a symbol property as a way to
* avoid potential naming conflicts with future versions of Acorn.
*/
this[STATE] = {
originalSourceType: originalSourceType || options.sourceType,
tokens: tokenTranslator ? [] : null,
comments: options.comment === true ? [] : null,
impliedStrict: ecmaFeatures.impliedStrict === true && this.options.ecmaVersion >= 5,
Expand Down Expand Up @@ -144,7 +151,7 @@ export default () => Parser => {
const extra = this[STATE];
const program = super.parse();

program.sourceType = this.options.sourceType;
program.sourceType = extra.originalSourceType;

if (extra.comments) {
program.comments = extra.comments;
Expand Down
12 changes: 11 additions & 1 deletion lib/options.js
Expand Up @@ -73,6 +73,11 @@ function normalizeSourceType(sourceType = "script") {
if (sourceType === "script" || sourceType === "module") {
return sourceType;
}

if (sourceType === "commonjs") {
return "script";
}

throw new Error("Invalid sourceType.");
}

Expand All @@ -88,15 +93,20 @@ export function normalizeOptions(options) {
const ranges = options.range === true;
const locations = options.loc === true;
const allowReserved = ecmaVersion === 3 ? "never" : false;
const ecmaFeatures = options.ecmaFeatures || {};
const allowReturnOutsideFunction = options.sourceType === "commonjs" ||
Boolean(ecmaFeatures.globalReturn);

if (sourceType === "module" && ecmaVersion < 6) {
throw new Error("sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options.");
}

return Object.assign({}, options, {
ecmaVersion,
sourceType,
ranges,
locations,
allowReserved
allowReserved,
allowReturnOutsideFunction
});
}
31 changes: 24 additions & 7 deletions tests/lib/parse.js
Expand Up @@ -41,15 +41,32 @@ describe("parse()", () => {

});

describe("modules", () => {
describe("sourceType", () => {

it("should have correct column number when strict mode error occurs", () => {
describe("module", () => {

try {
espree.parse("function fn(a, a) {\n}", { ecmaVersion: 6, sourceType: "module" });
} catch (err) {
assert.strictEqual(err.column, 16);
}
it("should have correct column number when strict mode error occurs", () => {

try {
espree.parse("function fn(a, a) {\n}", { ecmaVersion: 6, sourceType: "module" });
} catch (err) {
assert.strictEqual(err.column, 16);
}
});

});

describe("commonjs", () => {

it("should parse top-level return", () => {
espree.parse("return;", { sourceType: "commonjs" });
});

it("should have sourceType:commonjs on Program node", () => {
const result = espree.parse("return;", { sourceType: "commonjs" });

assert.strictEqual(result.sourceType, "commonjs");
});
});

});
Expand Down

0 comments on commit 27713ac

Please sign in to comment.