Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion acorn-loose/src/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ lp.parseTopLevel = function() {
while (this.tok.type !== tt.eof) node.body.push(this.parseStatement())
this.toks.adaptDirectivePrologue(node.body)
this.last = this.tok
node.sourceType = this.options.sourceType
node.sourceType = this.options.sourceType === "commonjs" ? "script" : this.options.sourceType
return this.finishNode(node, "Program")
}

Expand Down
4 changes: 2 additions & 2 deletions acorn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ required):
implemented through plugins.

- **sourceType**: Indicate the mode the code should be parsed in. Can be
either `"script"` or `"module"`. This influences global strict mode
either `"script"`, `"module"` or `"commonjs"`. This influences global strict mode
and parsing of `import` and `export` declarations.

**NOTE**: If set to `"module"`, then static `import` / `export` syntax
will be valid, even if `ecmaVersion` is less than 6.
will be valid, even if `ecmaVersion` is less than 6. If set to `"commonjs"`, it is the same as `"script"` except that the top-level scope behaves like a function.

- **onInsertedSemicolon**: If given a callback, that callback will be
called whenever a missing semicolon is inserted by the parser. The
Expand Down
4 changes: 2 additions & 2 deletions acorn/src/acorn.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,10 +614,10 @@ export interface Options {

/**
* `sourceType` indicates the mode the code should be parsed in.
* Can be either `"script"` or `"module"`. This influences global
* Can be either `"script"`, `"module"` or `"commonjs"`. This influences global
* strict mode and parsing of `import` and `export` declarations.
*/
sourceType?: "script" | "module"
sourceType?: "script" | "module" | "commonjs"

/**
* a callback that will be called when a semicolon is automatically inserted.
Expand Down
2 changes: 1 addition & 1 deletion acorn/src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const defaultOptions = {
// for new syntax features.
ecmaVersion: null,
// `sourceType` indicates the mode the code should be parsed in.
// Can be either `"script"` or `"module"`. This influences global
// Can be either `"script"`, `"module"` or `"commonjs"`. This influences global
// strict mode and parsing of `import` and `export` declarations.
sourceType: "script",
// `onInsertedSemicolon` can be a callback that will be called when
Expand Down
6 changes: 5 additions & 1 deletion acorn/src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ export class Parser {

// Scope tracking for duplicate variable names (see scope.js)
this.scopeStack = []
this.enterScope(SCOPE_TOP)
this.enterScope(
this.options.sourceType === "commonjs"
? SCOPE_FUNCTION // In commonjs, the top-level scope behaves like a function scope
: SCOPE_TOP
)

// For RegExp validation
this.regexpState = null
Expand Down
2 changes: 1 addition & 1 deletion acorn/src/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pp.parseTopLevel = function(node) {
this.raiseRecoverable(this.undefinedExports[name].start, `Export '${name}' is not defined`)
this.adaptDirectivePrologue(node.body)
this.next()
node.sourceType = this.options.sourceType
node.sourceType = this.options.sourceType === "commonjs" ? "script" : this.options.sourceType
return this.finishNode(node, "Program")
}

Expand Down
1 change: 1 addition & 0 deletions test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
require("./tests-module-string-names.js");
require("./tests-import-attributes.js");
require("./tests-using.js");
require("./tests-commonjs.js");
var acorn = require("../acorn")
var acorn_loose = require("../acorn-loose")

Expand Down
91 changes: 91 additions & 0 deletions test/tests-commonjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
if (typeof exports !== "undefined") {
var test = require("./driver.js").test
var testFail = require("./driver.js").testFail
}

// Top-level using declaration with commonjs
test("using x = resource;", {
type: "Program",
body: [{
type: "VariableDeclaration",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "x"
},
init: {
type: "Identifier",
name: "resource"
}
}],
kind: "using"
}],
sourceType: "script"
}, {ecmaVersion: 17, sourceType: "commonjs"});

// Top-level new.target with commonjs
test("new.target", {
type: "Program",
body: [{
type: "ExpressionStatement",
expression: {
type: "MetaProperty",
meta: {type: "Identifier", name: "new"},
property: {type: "Identifier", name: "target"}
}
}],
sourceType: "script"
}, {ecmaVersion: 6, sourceType: "commonjs"});

// new.target at top-level scope with commonjs
test("let y = () => new.target", {
type: "Program",
body: [{
type: "VariableDeclaration",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "y"
},
init: {
type: "ArrowFunctionExpression",
body: {
type: "MetaProperty",
meta: {type: "Identifier", name: "new"},
property: {type: "Identifier", name: "target"}
},
params: []
}
}],
kind: "let"
}],
sourceType: "script"
}, {ecmaVersion: 6, sourceType: "commonjs"});

// Top-level return statement with commonjs
test("return {} / 2", {
type: "Program",
body: [{
type: "ReturnStatement",
argument: {
type: "BinaryExpression",
left: {
type: "ObjectExpression",
properties: []
},
right: {
type: "Literal",
value: 2
},
operator: "/"
}
}],
sourceType: "script"
}, {sourceType: "commonjs"});

// Illegal return statement with commonjs
testFail(`class X { static { return; } }`, "'return' outside of function (1:19)", {ecmaVersion: 13, sourceType: "commonjs"});
// with allowReturnOutsideFunction option
test(`class X { static { return; } }`, {}, {allowReturnOutsideFunction: true, ecmaVersion: 13, sourceType: "commonjs"});