diff --git a/packages/babel-parser/data/schema.json b/packages/babel-parser/data/schema.json index 569e6747d1b3..ec354824d433 100644 --- a/packages/babel-parser/data/schema.json +++ b/packages/babel-parser/data/schema.json @@ -49,6 +49,10 @@ "description": "By default, a return statement at the top level raises an error.\nSet this to true to accept such code.", "type": "boolean" }, + "allowNewTargetOutsideFunction": { + "description": "By default, new.target use is not allowed outside of a function or class.\nSet this to true to accept such code.", + "type": "boolean" + }, "allowSuperOutsideMethod": { "type": "boolean" }, diff --git a/packages/babel-parser/src/options.ts b/packages/babel-parser/src/options.ts index 7abf8ba5d56a..91aaa2593026 100644 --- a/packages/babel-parser/src/options.ts +++ b/packages/babel-parser/src/options.ts @@ -12,6 +12,7 @@ export type Options = { startLine: number; allowAwaitOutsideFunction: boolean; allowReturnOutsideFunction: boolean; + allowNewTargetOutsideFunction: boolean; allowImportExportEverywhere: boolean; allowSuperOutsideMethod: boolean; allowUndeclaredExports: boolean; @@ -42,6 +43,9 @@ export const defaultOptions: Options = { // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, + // When enabled, new.target outside a function or class is not + // considered an error. + allowNewTargetOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts index 49f3eb5aa98a..60313e3d7138 100644 --- a/packages/babel-parser/src/parser/expression.ts +++ b/packages/babel-parser/src/parser/expression.ts @@ -1880,7 +1880,11 @@ export default abstract class ExpressionParser extends LValParser { "target", ); - if (!this.scope.inNonArrowFunction && !this.scope.inClass) { + if ( + !this.scope.inNonArrowFunction && + !this.scope.inClass && + !this.options.allowNewTargetOutsideFunction + ) { this.raise(Errors.UnexpectedNewTarget, { at: metaProp }); } diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false-2/input.js b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false-2/input.js new file mode 100644 index 000000000000..608666efc9bf --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false-2/input.js @@ -0,0 +1 @@ +const y = () => new.target; diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false-2/options.json b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false-2/options.json new file mode 100644 index 000000000000..88c709852466 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false-2/options.json @@ -0,0 +1,4 @@ +{ + "errorRecovery": false, + "throws": "`new.target` can only be used in functions or class properties. (1:16)" +} diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false/input.js b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false/input.js new file mode 100644 index 000000000000..85f7e4833373 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false/input.js @@ -0,0 +1 @@ +const x = new.target; diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false/options.json b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false/options.json new file mode 100644 index 000000000000..a090fd8b90d8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-false/options.json @@ -0,0 +1,4 @@ +{ + "errorRecovery": false, + "throws": "`new.target` can only be used in functions or class properties. (1:10)" +} diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/input.js b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/input.js new file mode 100644 index 000000000000..2896f435a2a3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/input.js @@ -0,0 +1,2 @@ +const x = new.target; +const y = () => new.target; diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/options.json b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/options.json new file mode 100644 index 000000000000..ec9099e4a969 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/options.json @@ -0,0 +1,4 @@ +{ + "allowNewTargetOutsideFunction": true, + "errorRecovery": false +} diff --git a/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/output.json b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/output.json new file mode 100644 index 000000000000..53eb2339ca5e --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/opts/allowNewTargetOutsideFunction-true/output.json @@ -0,0 +1,81 @@ +{ + "type": "File", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":27,"index":49}}, + "program": { + "type": "Program", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":27,"index":49}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":21,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":21,"index":21}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":20,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":20,"index":20}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":7,"index":7},"identifierName":"x"}, + "name": "x" + }, + "init": { + "type": "MetaProperty", + "start":10,"end":20,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":20,"index":20}}, + "meta": { + "type": "Identifier", + "start":10,"end":13,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":13,"index":13},"identifierName":"new"}, + "name": "new" + }, + "property": { + "type": "Identifier", + "start":14,"end":20,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":20,"index":20},"identifierName":"target"}, + "name": "target" + } + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "start":22,"end":49,"loc":{"start":{"line":2,"column":0,"index":22},"end":{"line":2,"column":27,"index":49}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":28,"end":48,"loc":{"start":{"line":2,"column":6,"index":28},"end":{"line":2,"column":26,"index":48}}, + "id": { + "type": "Identifier", + "start":28,"end":29,"loc":{"start":{"line":2,"column":6,"index":28},"end":{"line":2,"column":7,"index":29},"identifierName":"y"}, + "name": "y" + }, + "init": { + "type": "ArrowFunctionExpression", + "start":32,"end":48,"loc":{"start":{"line":2,"column":10,"index":32},"end":{"line":2,"column":26,"index":48}}, + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "MetaProperty", + "start":38,"end":48,"loc":{"start":{"line":2,"column":16,"index":38},"end":{"line":2,"column":26,"index":48}}, + "meta": { + "type": "Identifier", + "start":38,"end":41,"loc":{"start":{"line":2,"column":16,"index":38},"end":{"line":2,"column":19,"index":41},"identifierName":"new"}, + "name": "new" + }, + "property": { + "type": "Identifier", + "start":42,"end":48,"loc":{"start":{"line":2,"column":20,"index":42},"end":{"line":2,"column":26,"index":48},"identifierName":"target"}, + "name": "target" + } + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/typings/babel-parser.d.ts b/packages/babel-parser/typings/babel-parser.d.ts index b806352dbb35..e04fb4fb9459 100644 --- a/packages/babel-parser/typings/babel-parser.d.ts +++ b/packages/babel-parser/typings/babel-parser.d.ts @@ -122,6 +122,12 @@ interface ParserOptions { */ allowReturnOutsideFunction?: boolean; + /** + * By default, new.target use is not allowed outside of a function or class. + * Set this to true to accept such code. + */ + allowNewTargetOutsideFunction?: boolean; + allowSuperOutsideMethod?: boolean; /**