diff --git a/packages/babel-generator/src/generators/expressions.ts b/packages/babel-generator/src/generators/expressions.ts index 0ee7f1ead7..160ca32995 100644 --- a/packages/babel-generator/src/generators/expressions.ts +++ b/packages/babel-generator/src/generators/expressions.ts @@ -300,3 +300,16 @@ export function V8IntrinsicIdentifier( this.token("%"); this.word(node.name); } + +export function ModuleExpression(node: t.ModuleExpression) { + this.word("module"); + this.space(); + this.token("{"); + if (node.body.body.length === 0) { + this.token("}"); + } else { + this.newline(); + this.printSequence(node.body.body, node, { indent: true }); + this.rightBrace(); + } +} diff --git a/packages/babel-generator/test/fixtures/types/ModuleExpression/input.js b/packages/babel-generator/test/fixtures/types/ModuleExpression/input.js new file mode 100644 index 0000000000..28f5488c73 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/ModuleExpression/input.js @@ -0,0 +1,6 @@ +const m = module { export const foo = "foo" }; +module { + foo; + bar; +}; +foo(module {}); diff --git a/packages/babel-generator/test/fixtures/types/ModuleExpression/options.json b/packages/babel-generator/test/fixtures/types/ModuleExpression/options.json new file mode 100644 index 0000000000..9c33cc7763 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/ModuleExpression/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["moduleBlocks"], + "sourceType": "module" +} diff --git a/packages/babel-generator/test/fixtures/types/ModuleExpression/output.js b/packages/babel-generator/test/fixtures/types/ModuleExpression/output.js new file mode 100644 index 0000000000..0a069dd6ff --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/ModuleExpression/output.js @@ -0,0 +1,8 @@ +const m = module { + export const foo = "foo"; +}; +module { + foo; + bar; +}; +foo(module {}); \ No newline at end of file diff --git a/packages/babel-parser/ast/spec.md b/packages/babel-parser/ast/spec.md index 6caadbc449..48d37a300e 100644 --- a/packages/babel-parser/ast/spec.md +++ b/packages/babel-parser/ast/spec.md @@ -87,6 +87,7 @@ These are the core @babel/parser (babylon) AST node types. - [SequenceExpression](#sequenceexpression) - [ParenthesizedExpression](#parenthesizedexpression) - [DoExpression](#doexpression) + - [ModuleExpression](#moduleexpression) - [Template Literals](#template-literals) - [TemplateLiteral](#templateliteral) - [TaggedTemplateExpression](#taggedtemplateexpression) @@ -1086,6 +1087,17 @@ interface DoExpression <: Expression { } ``` +## ModuleExpression + +```js +interface ModuleExpression <: Expression { + type: "ModuleExpression"; + body: Program +} +``` + +A inline module expression proposed in https://github.com/tc39/proposal-js-module-blocks. + # Template Literals ## TemplateLiteral diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 3c52a4f229..dbc9bdc5e8 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -56,6 +56,10 @@ import { } from "../util/expression-scope"; import { Errors } from "./error"; +/*:: +import type { SourceType } from "../options"; +*/ + export default class ExpressionParser extends LValParser { // Forward-declaration: defined in statement.js /*:: @@ -78,6 +82,16 @@ export default class ExpressionParser extends LValParser { ) => T; +parseFunctionParams: (node: N.Function, allowModifiers?: boolean) => void; +takeDecorators: (node: N.HasDecorators) => void; + +parseBlockOrModuleBlockBody: ( + body: N.Statement[], + directives: ?(N.Directive[]), + topLevel: boolean, + end: TokenType, + afterBlockParse?: (hasStrictModeDirective: boolean) => void + ) => void + +parseProgram: ( + program: N.Program, end: TokenType, sourceType?: SourceType + ) => N.Program */ // For object literal, check if property __proto__ has been used more than once. @@ -500,7 +514,13 @@ export default class ExpressionParser extends LValParser { this.next(); return this.parseAwait(startPos, startLoc); } - + if ( + this.isContextual("module") && + this.lookaheadCharCode() === charCodes.leftCurlyBrace && + !this.hasFollowingLineBreak() + ) { + return this.parseModuleExpression(); + } const update = this.match(tt.incDec); const node = this.startNode(); if (this.state.type.prefix) { @@ -2630,4 +2650,24 @@ export default class ExpressionParser extends LValParser { return ret; } + + // https://github.com/tc39/proposal-js-module-blocks + parseModuleExpression(): N.ModuleExpression { + this.expectPlugin("moduleBlocks"); + const node = this.startNode(); + this.next(); // eat "module" + this.eat(tt.braceL); + + const revertScopes = this.initializeScopes(/** inModule */ true); + this.enterInitialScopes(); + + const program = this.startNode(); + try { + node.body = this.parseProgram(program, tt.braceR, "module"); + } finally { + revertScopes(); + } + this.eat(tt.braceR); + return this.finishNode(node, "ModuleExpression"); + } } diff --git a/packages/babel-parser/src/parser/index.js b/packages/babel-parser/src/parser/index.js index 6e94469075..2db11faf49 100644 --- a/packages/babel-parser/src/parser/index.js +++ b/packages/babel-parser/src/parser/index.js @@ -5,14 +5,7 @@ import type { File /*::, JSXOpeningElement */ } from "../types"; import type { PluginList } from "../plugin-utils"; import { getOptions } from "../options"; import StatementParser from "./statement"; -import { SCOPE_PROGRAM } from "../util/scopeflags"; import ScopeHandler from "../util/scope"; -import ClassScopeHandler from "../util/class-scope"; -import ExpressionScopeHandler from "../util/expression-scope"; -import ProductionParameterHandler, { - PARAM_AWAIT, - PARAM, -} from "../util/production-parameter"; export type PluginsMap = Map; @@ -28,14 +21,8 @@ export default class Parser extends StatementParser { options = getOptions(options); super(options, input); - const ScopeHandler = this.getScopeHandler(); - this.options = options; - this.inModule = this.options.sourceType === "module"; - this.scope = new ScopeHandler(this.raise.bind(this), this.inModule); - this.prodParam = new ProductionParameterHandler(); - this.classScope = new ClassScopeHandler(this.raise.bind(this)); - this.expressionScope = new ExpressionScopeHandler(this.raise.bind(this)); + this.initializeScopes(); this.plugins = pluginsMap(this.options.plugins); this.filename = options.sourceFilename; } @@ -46,12 +33,7 @@ export default class Parser extends StatementParser { } parse(): File { - let paramFlags = PARAM; - if (this.hasPlugin("topLevelAwait") && this.inModule) { - paramFlags |= PARAM_AWAIT; - } - this.scope.enter(SCOPE_PROGRAM); - this.prodParam.enter(paramFlags); + this.enterInitialScopes(); const file = this.startNode(); const program = this.startNode(); this.nextToken(); diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 13ef7ee36d..de23bfb0cd 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -35,6 +35,7 @@ import { newExpressionScope, newParameterDeclarationScope, } from "../util/expression-scope"; +import type { SourceType } from "../options"; const loopLabel = { kind: "loop" }, switchLabel = { kind: "switch" }; @@ -55,12 +56,22 @@ export default class StatementParser extends ExpressionParser { // to its body instead of creating a new node. parseTopLevel(file: N.File, program: N.Program): N.File { - program.sourceType = this.options.sourceType; + file.program = this.parseProgram(program); + file.comments = this.state.comments; + if (this.options.tokens) file.tokens = this.tokens; + + return this.finishNode(file, "File"); + } + + parseProgram( + program: N.Program, + end: TokenType = tt.eof, + sourceType: SourceType = this.options.sourceType, + ): N.Program { + program.sourceType = sourceType; program.interpreter = this.parseInterpreterDirective(); - - this.parseBlockBody(program, true, true, tt.eof); - + this.parseBlockBody(program, true, true, end); if ( this.inModule && !this.options.allowUndeclaredExports && @@ -72,13 +83,7 @@ export default class StatementParser extends ExpressionParser { this.raise(pos, Errors.ModuleExportUndefined, name); } } - - file.program = this.finishNode(program, "Program"); - file.comments = this.state.comments; - - if (this.options.tokens) file.tokens = this.tokens; - - return this.finishNode(file, "File"); + return this.finishNode(program, "Program"); } // TODO diff --git a/packages/babel-parser/src/parser/util.js b/packages/babel-parser/src/parser/util.js index d3a83b18c2..53156c577f 100644 --- a/packages/babel-parser/src/parser/util.js +++ b/packages/babel-parser/src/parser/util.js @@ -6,7 +6,17 @@ import State from "../tokenizer/state"; import type { Node } from "../types"; import { lineBreak } from "../util/whitespace"; import { isIdentifierChar } from "../util/identifier"; +import ClassScopeHandler from "../util/class-scope"; +import ExpressionScopeHandler from "../util/expression-scope"; +import { SCOPE_PROGRAM } from "../util/scopeflags"; +import ProductionParameterHandler, { + PARAM_AWAIT, + PARAM, +} from "../util/production-parameter"; import { Errors } from "./error"; +/*:: +import type ScopeHandler from "../util/scope"; +*/ type TryParse = { node: Node, @@ -19,6 +29,11 @@ type TryParse = { // ## Parser utilities export default class UtilParser extends Tokenizer { + // Forward-declaration: defined in parser/index.js + /*:: + +getScopeHandler: () => Class>; + */ + // TODO addExtra(node: Node, key: string, val: any): void { @@ -304,6 +319,56 @@ export default class UtilParser extends Tokenizer { isObjectMethod(node: Node): boolean { return node.type === "ObjectMethod"; } + + initializeScopes( + inModule: boolean = this.options.sourceType === "module", + ): () => void { + // Initialize state + const oldLabels = this.state.labels; + this.state.labels = []; + + const oldExportedIdentifiers = this.state.exportedIdentifiers; + this.state.exportedIdentifiers = []; + + // initialize scopes + const oldInModule = this.inModule; + this.inModule = inModule; + + const oldScope = this.scope; + const ScopeHandler = this.getScopeHandler(); + this.scope = new ScopeHandler(this.raise.bind(this), this.inModule); + + const oldProdParam = this.prodParam; + this.prodParam = new ProductionParameterHandler(); + + const oldClassScope = this.classScope; + this.classScope = new ClassScopeHandler(this.raise.bind(this)); + + const oldExpressionScope = this.expressionScope; + this.expressionScope = new ExpressionScopeHandler(this.raise.bind(this)); + + return () => { + // Revert state + this.state.labels = oldLabels; + this.state.exportedIdentifiers = oldExportedIdentifiers; + + // Revert scopes + this.inModule = oldInModule; + this.scope = oldScope; + this.prodParam = oldProdParam; + this.classScope = oldClassScope; + this.expressionScope = oldExpressionScope; + }; + } + + enterInitialScopes() { + let paramFlags = PARAM; + if (this.hasPlugin("topLevelAwait") && this.inModule) { + paramFlags |= PARAM_AWAIT; + } + this.scope.enter(SCOPE_PROGRAM); + this.prodParam.enter(paramFlags); + } } /** diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index 1c9d4c02c6..b190b4bde7 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -655,6 +655,11 @@ export type TemplateElement = NodeBase & { }, }; +export type ModuleExpression = NodeBase & { + type: "ModuleExpression", + body: Program, +}; + // Patterns // TypeScript access modifiers diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/input.js new file mode 100644 index 0000000000..11c5bcbc35 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/input.js @@ -0,0 +1 @@ +module { await: 3 }; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/options.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/options.json new file mode 100644 index 0000000000..3282864d94 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "script", + "plugins": ["moduleBlocks"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/output.json new file mode 100644 index 0000000000..5b7d9f6731 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-await-label-in-module-blocks/output.json @@ -0,0 +1,55 @@ +{ + "type": "File", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "errors": [ + "SyntaxError: Unexpected reserved word 'await' (1:9)" + ], + "program": { + "type": "Program", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "expression": { + "type": "ModuleExpression", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "body": { + "type": "Program", + "start":9,"end":19,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":19}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "LabeledStatement", + "start":9,"end":17,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":17}}, + "body": { + "type": "ExpressionStatement", + "start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}}, + "expression": { + "type": "NumericLiteral", + "start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}}, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + }, + "label": { + "type": "Identifier", + "start":9,"end":14,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":14},"identifierName":"await"}, + "name": "await" + } + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/input.js new file mode 100644 index 0000000000..04f0c7aab1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/input.js @@ -0,0 +1,7 @@ +class B { + #p() { + module { + class C { [this.#p]; } + }; + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/options.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/options.json new file mode 100644 index 0000000000..5a36d4e0d5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/options.json @@ -0,0 +1,9 @@ +{ + "sourceType": "module", + "plugins": [ + "moduleBlocks", + "classPrivateProperties", + "classPrivateMethods", + "classProperties" + ] +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/output.json new file mode 100644 index 0000000000..86b7e8c0c9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-class-in-module-blocks/output.json @@ -0,0 +1,116 @@ +{ + "type": "File", + "start":0,"end":73,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":1}}, + "errors": [ + "SyntaxError: Private name #p is not defined (4:22)" + ], + "program": { + "type": "Program", + "start":0,"end":73,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":73,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"B"}, + "name": "B" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":8,"end":73,"loc":{"start":{"line":1,"column":8},"end":{"line":7,"column":1}}, + "body": [ + { + "type": "ClassPrivateMethod", + "start":12,"end":71,"loc":{"start":{"line":2,"column":2},"end":{"line":6,"column":3}}, + "static": false, + "key": { + "type": "PrivateName", + "start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}}, + "id": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"p"}, + "name": "p" + } + }, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":17,"end":71,"loc":{"start":{"line":2,"column":7},"end":{"line":6,"column":3}}, + "body": [ + { + "type": "ExpressionStatement", + "start":23,"end":67,"loc":{"start":{"line":3,"column":4},"end":{"line":5,"column":6}}, + "expression": { + "type": "ModuleExpression", + "start":23,"end":66,"loc":{"start":{"line":3,"column":4},"end":{"line":5,"column":5}}, + "body": { + "type": "Program", + "start":38,"end":66,"loc":{"start":{"line":4,"column":6},"end":{"line":5,"column":5}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":38,"end":60,"loc":{"start":{"line":4,"column":6},"end":{"line":4,"column":28}}, + "id": { + "type": "Identifier", + "start":44,"end":45,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":13},"identifierName":"C"}, + "name": "C" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":46,"end":60,"loc":{"start":{"line":4,"column":14},"end":{"line":4,"column":28}}, + "body": [ + { + "type": "ClassProperty", + "start":48,"end":58,"loc":{"start":{"line":4,"column":16},"end":{"line":4,"column":26}}, + "static": false, + "computed": true, + "key": { + "type": "MemberExpression", + "start":49,"end":56,"loc":{"start":{"line":4,"column":17},"end":{"line":4,"column":24}}, + "object": { + "type": "ThisExpression", + "start":49,"end":53,"loc":{"start":{"line":4,"column":17},"end":{"line":4,"column":21}} + }, + "computed": false, + "property": { + "type": "PrivateName", + "start":54,"end":56,"loc":{"start":{"line":4,"column":22},"end":{"line":4,"column":24}}, + "id": { + "type": "Identifier", + "start":55,"end":56,"loc":{"start":{"line":4,"column":23},"end":{"line":4,"column":24},"identifierName":"p"}, + "name": "p" + } + } + }, + "value": null + } + ] + } + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-duplicated-exports-in-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-duplicated-exports-in-blocks/input.js new file mode 100644 index 0000000000..6615af79d4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-duplicated-exports-in-blocks/input.js @@ -0,0 +1,4 @@ +const m = module { + export const foo = "foo"; + export { foo }; +}; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-duplicated-exports-in-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-duplicated-exports-in-blocks/output.json new file mode 100644 index 0000000000..b8619d5810 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-duplicated-exports-in-blocks/output.json @@ -0,0 +1,98 @@ +{ + "type": "File", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":2}}, + "errors": [ + "SyntaxError: `foo` has already been exported. Exported identifiers must be unique. (3:11)" + ], + "program": { + "type": "Program", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":67,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":2}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":66,"loc":{"start":{"line":1,"column":6},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "ModuleExpression", + "start":10,"end":66,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": { + "type": "Program", + "start":21,"end":66,"loc":{"start":{"line":2,"column":2},"end":{"line":4,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":21,"end":46,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":27}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":28,"end":46,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":27}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":34,"end":45,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":26}}, + "id": { + "type": "Identifier", + "start":34,"end":37,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":18},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":40,"end":45,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + }, + { + "type": "ExportNamedDeclaration", + "start":49,"end":64,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":17}}, + "specifiers": [ + { + "type": "ExportSpecifier", + "start":58,"end":61,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":14}}, + "local": { + "type": "Identifier", + "start":58,"end":61,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":14},"identifierName":"foo"}, + "name": "foo" + }, + "exported": { + "type": "Identifier", + "start":58,"end":61,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":14},"identifierName":"foo"}, + "name": "foo" + } + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-linebreak-between-module-keyword-and-braces/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-linebreak-between-module-keyword-and-braces/input.js new file mode 100644 index 0000000000..b52c515adc --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-linebreak-between-module-keyword-and-braces/input.js @@ -0,0 +1,2 @@ +const m = module +{} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-linebreak-between-module-keyword-and-braces/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-linebreak-between-module-keyword-and-braces/output.json new file mode 100644 index 0000000000..37e6d7a5ec --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-linebreak-between-module-keyword-and-braces/output.json @@ -0,0 +1,40 @@ +{ + "type": "File", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":2}}, + "program": { + "type": "Program", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":16,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":16}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "Identifier", + "start":10,"end":16,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":16},"identifierName":"module"}, + "name": "module" + } + } + ], + "kind": "const" + }, + { + "type": "BlockStatement", + "start":17,"end":19,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":2}}, + "body": [], + "directives": [] + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks01/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks01/input.js new file mode 100644 index 0000000000..e878e46aeb --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks01/input.js @@ -0,0 +1,3 @@ +module { + export { foo } +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks01/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks01/output.json new file mode 100644 index 0000000000..571c2383d6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks01/output.json @@ -0,0 +1,55 @@ +{ + "type": "File", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Export 'foo' is not defined (2:11)" + ], + "program": { + "type": "Program", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "expression": { + "type": "ModuleExpression", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "body": { + "type": "Program", + "start":11,"end":27,"loc":{"start":{"line":2,"column":2},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":11,"end":25,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":16}}, + "specifiers": [ + { + "type": "ExportSpecifier", + "start":20,"end":23,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14}}, + "local": { + "type": "Identifier", + "start":20,"end":23,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14},"identifierName":"foo"}, + "name": "foo" + }, + "exported": { + "type": "Identifier", + "start":20,"end":23,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14},"identifierName":"foo"}, + "name": "foo" + } + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks02/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks02/input.js new file mode 100644 index 0000000000..d2dcc8371b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks02/input.js @@ -0,0 +1,4 @@ +let foo; +module { + export { foo }; +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks02/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks02/output.json new file mode 100644 index 0000000000..bd11a6632a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/invalid-undefined-export-in-module-blocks02/output.json @@ -0,0 +1,72 @@ +{ + "type": "File", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "errors": [ + "SyntaxError: Export 'foo' is not defined (3:11)" + ], + "program": { + "type": "Program", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":8,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":8}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":4,"end":7,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":7}}, + "id": { + "type": "Identifier", + "start":4,"end":7,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":7},"identifierName":"foo"}, + "name": "foo" + }, + "init": null + } + ], + "kind": "let" + }, + { + "type": "ExpressionStatement", + "start":9,"end":37,"loc":{"start":{"line":2,"column":0},"end":{"line":4,"column":1}}, + "expression": { + "type": "ModuleExpression", + "start":9,"end":37,"loc":{"start":{"line":2,"column":0},"end":{"line":4,"column":1}}, + "body": { + "type": "Program", + "start":20,"end":37,"loc":{"start":{"line":3,"column":2},"end":{"line":4,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":20,"end":35,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":17}}, + "specifiers": [ + { + "type": "ExportSpecifier", + "start":29,"end":32,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":14}}, + "local": { + "type": "Identifier", + "start":29,"end":32,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":14},"identifierName":"foo"}, + "name": "foo" + }, + "exported": { + "type": "Identifier", + "start":29,"end":32,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":14},"identifierName":"foo"}, + "name": "foo" + } + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/options.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/options.json new file mode 100644 index 0000000000..6fdc8aa523 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "module", + "plugins": ["moduleBlocks"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-assign-module-blocks-to-variables/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-assign-module-blocks-to-variables/input.js new file mode 100644 index 0000000000..584705a796 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-assign-module-blocks-to-variables/input.js @@ -0,0 +1,3 @@ +const m = module { + export const foo = "foo"; +}; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-assign-module-blocks-to-variables/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-assign-module-blocks-to-variables/output.json new file mode 100644 index 0000000000..fb701f8cce --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-assign-module-blocks-to-variables/output.json @@ -0,0 +1,73 @@ +{ + "type": "File", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "program": { + "type": "Program", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":48,"loc":{"start":{"line":1,"column":6},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "ModuleExpression", + "start":10,"end":48,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": { + "type": "Program", + "start":21,"end":48,"loc":{"start":{"line":2,"column":2},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":21,"end":46,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":27}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":28,"end":46,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":27}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":34,"end":45,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":26}}, + "id": { + "type": "Identifier", + "start":34,"end":37,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":18},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":40,"end":45,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/input.js new file mode 100644 index 0000000000..3ca87a5894 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/input.js @@ -0,0 +1,11 @@ +class B { + #p() { + module { + class C { + [this.#p]; + #p = 3; + } + }; + } +} + \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/options.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/options.json new file mode 100644 index 0000000000..02815f9893 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/options.json @@ -0,0 +1,9 @@ +{ + "sourceType": "module", + "plugins": [ + "moduleBlocks", + "classPrivateProperties", + "classPrivateMethods", + "classProperties" + ] +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/output.json new file mode 100644 index 0000000000..8f9f254397 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-class-in-module-blocks/output.json @@ -0,0 +1,136 @@ +{ + "type": "File", + "start":0,"end":103,"loc":{"start":{"line":1,"column":0},"end":{"line":10,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":103,"loc":{"start":{"line":1,"column":0},"end":{"line":10,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":103,"loc":{"start":{"line":1,"column":0},"end":{"line":10,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"B"}, + "name": "B" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":8,"end":103,"loc":{"start":{"line":1,"column":8},"end":{"line":10,"column":1}}, + "body": [ + { + "type": "ClassPrivateMethod", + "start":12,"end":101,"loc":{"start":{"line":2,"column":2},"end":{"line":9,"column":3}}, + "static": false, + "key": { + "type": "PrivateName", + "start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}}, + "id": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"p"}, + "name": "p" + } + }, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":17,"end":101,"loc":{"start":{"line":2,"column":7},"end":{"line":9,"column":3}}, + "body": [ + { + "type": "ExpressionStatement", + "start":23,"end":97,"loc":{"start":{"line":3,"column":4},"end":{"line":8,"column":6}}, + "expression": { + "type": "ModuleExpression", + "start":23,"end":96,"loc":{"start":{"line":3,"column":4},"end":{"line":8,"column":5}}, + "body": { + "type": "Program", + "start":38,"end":96,"loc":{"start":{"line":4,"column":6},"end":{"line":8,"column":5}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":38,"end":90,"loc":{"start":{"line":4,"column":6},"end":{"line":7,"column":7}}, + "id": { + "type": "Identifier", + "start":44,"end":45,"loc":{"start":{"line":4,"column":12},"end":{"line":4,"column":13},"identifierName":"C"}, + "name": "C" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":46,"end":90,"loc":{"start":{"line":4,"column":14},"end":{"line":7,"column":7}}, + "body": [ + { + "type": "ClassProperty", + "start":56,"end":66,"loc":{"start":{"line":5,"column":8},"end":{"line":5,"column":18}}, + "static": false, + "computed": true, + "key": { + "type": "MemberExpression", + "start":57,"end":64,"loc":{"start":{"line":5,"column":9},"end":{"line":5,"column":16}}, + "object": { + "type": "ThisExpression", + "start":57,"end":61,"loc":{"start":{"line":5,"column":9},"end":{"line":5,"column":13}} + }, + "computed": false, + "property": { + "type": "PrivateName", + "start":62,"end":64,"loc":{"start":{"line":5,"column":14},"end":{"line":5,"column":16}}, + "id": { + "type": "Identifier", + "start":63,"end":64,"loc":{"start":{"line":5,"column":15},"end":{"line":5,"column":16},"identifierName":"p"}, + "name": "p" + } + } + }, + "value": null + }, + { + "type": "ClassPrivateProperty", + "start":75,"end":82,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":15}}, + "static": false, + "key": { + "type": "PrivateName", + "start":75,"end":77,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":10}}, + "id": { + "type": "Identifier", + "start":76,"end":77,"loc":{"start":{"line":6,"column":9},"end":{"line":6,"column":10},"identifierName":"p"}, + "name": "p" + } + }, + "value": { + "type": "NumericLiteral", + "start":80,"end":81,"loc":{"start":{"line":6,"column":13},"end":{"line":6,"column":14}}, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + } + ] + } + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-exports-between-other-modules/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-exports-between-other-modules/input.js new file mode 100644 index 0000000000..3a1edfbf3d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-exports-between-other-modules/input.js @@ -0,0 +1,3 @@ +export const foo = "foo"; +const m1 = module { export const foo = "foo" }; +const m2 = module { export const foo = "foo" }; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-exports-between-other-modules/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-exports-between-other-modules/output.json new file mode 100644 index 0000000000..212ed8a2f6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-exports-between-other-modules/output.json @@ -0,0 +1,164 @@ +{ + "type": "File", + "start":0,"end":121,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":47}}, + "program": { + "type": "Program", + "start":0,"end":121,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":47}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":7,"end":25,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":25}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":13,"end":24,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":24}}, + "id": { + "type": "Identifier", + "start":13,"end":16,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":16},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":19,"end":24,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":24}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + }, + { + "type": "VariableDeclaration", + "start":26,"end":73,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":47}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":32,"end":72,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":46}}, + "id": { + "type": "Identifier", + "start":32,"end":34,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":8},"identifierName":"m1"}, + "name": "m1" + }, + "init": { + "type": "ModuleExpression", + "start":37,"end":72,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":46}}, + "body": { + "type": "Program", + "start":46,"end":72,"loc":{"start":{"line":2,"column":20},"end":{"line":2,"column":46}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":46,"end":70,"loc":{"start":{"line":2,"column":20},"end":{"line":2,"column":44}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":53,"end":70,"loc":{"start":{"line":2,"column":27},"end":{"line":2,"column":44}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":59,"end":70,"loc":{"start":{"line":2,"column":33},"end":{"line":2,"column":44}}, + "id": { + "type": "Identifier", + "start":59,"end":62,"loc":{"start":{"line":2,"column":33},"end":{"line":2,"column":36},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":65,"end":70,"loc":{"start":{"line":2,"column":39},"end":{"line":2,"column":44}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "start":74,"end":121,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":47}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":80,"end":120,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":46}}, + "id": { + "type": "Identifier", + "start":80,"end":82,"loc":{"start":{"line":3,"column":6},"end":{"line":3,"column":8},"identifierName":"m2"}, + "name": "m2" + }, + "init": { + "type": "ModuleExpression", + "start":85,"end":120,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":46}}, + "body": { + "type": "Program", + "start":94,"end":120,"loc":{"start":{"line":3,"column":20},"end":{"line":3,"column":46}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":94,"end":118,"loc":{"start":{"line":3,"column":20},"end":{"line":3,"column":44}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":101,"end":118,"loc":{"start":{"line":3,"column":27},"end":{"line":3,"column":44}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":107,"end":118,"loc":{"start":{"line":3,"column":33},"end":{"line":3,"column":44}}, + "id": { + "type": "Identifier", + "start":107,"end":110,"loc":{"start":{"line":3,"column":33},"end":{"line":3,"column":36},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":113,"end":118,"loc":{"start":{"line":3,"column":39},"end":{"line":3,"column":44}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-variables-in-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-variables-in-module-blocks/input.js new file mode 100644 index 0000000000..b9f1c1c91d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-variables-in-module-blocks/input.js @@ -0,0 +1,4 @@ +const foo = "foo"; +const m = module { + const foo = "foo"; +}; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-variables-in-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-variables-in-module-blocks/output.json new file mode 100644 index 0000000000..2bf04ffeb8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-duplicated-variables-in-module-blocks/output.json @@ -0,0 +1,92 @@ +{ + "type": "File", + "start":0,"end":61,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":2}}, + "program": { + "type": "Program", + "start":0,"end":61,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":17,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":17}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":12,"end":17,"loc":{"start":{"line":1,"column":12},"end":{"line":1,"column":17}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + }, + { + "type": "VariableDeclaration", + "start":19,"end":61,"loc":{"start":{"line":2,"column":0},"end":{"line":4,"column":2}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":25,"end":60,"loc":{"start":{"line":2,"column":6},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":25,"end":26,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":7},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "ModuleExpression", + "start":29,"end":60,"loc":{"start":{"line":2,"column":10},"end":{"line":4,"column":1}}, + "body": { + "type": "Program", + "start":40,"end":60,"loc":{"start":{"line":3,"column":2},"end":{"line":4,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":40,"end":58,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":20}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":46,"end":57,"loc":{"start":{"line":3,"column":8},"end":{"line":3,"column":19}}, + "id": { + "type": "Identifier", + "start":46,"end":49,"loc":{"start":{"line":3,"column":8},"end":{"line":3,"column":11},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":52,"end":57,"loc":{"start":{"line":3,"column":14},"end":{"line":3,"column":19}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-empty-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-empty-module-blocks/input.js new file mode 100644 index 0000000000..ee74db7f8f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-empty-module-blocks/input.js @@ -0,0 +1 @@ +module {}; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-empty-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-empty-module-blocks/output.json new file mode 100644 index 0000000000..945e41366b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-empty-module-blocks/output.json @@ -0,0 +1,29 @@ +{ + "type": "File", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "program": { + "type": "Program", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "expression": { + "type": "ModuleExpression", + "start":0,"end":9,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":9}}, + "body": { + "type": "Program", + "start":8,"end":9,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":9}}, + "sourceType": "module", + "interpreter": null, + "body": [], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-import-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-import-module-blocks/input.js new file mode 100644 index 0000000000..a0c4e38151 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-import-module-blocks/input.js @@ -0,0 +1,4 @@ +const m = module { + export const foo = "foo"; +}; +import(module); diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-import-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-import-module-blocks/output.json new file mode 100644 index 0000000000..bf4fc88736 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-import-module-blocks/output.json @@ -0,0 +1,92 @@ +{ + "type": "File", + "start":0,"end":65,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":15}}, + "program": { + "type": "Program", + "start":0,"end":65,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":15}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":48,"loc":{"start":{"line":1,"column":6},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "ModuleExpression", + "start":10,"end":48,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": { + "type": "Program", + "start":21,"end":48,"loc":{"start":{"line":2,"column":2},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":21,"end":46,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":27}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":28,"end":46,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":27}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":34,"end":45,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":26}}, + "id": { + "type": "Identifier", + "start":34,"end":37,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":18},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":40,"end":45,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + }, + { + "type": "ExpressionStatement", + "start":50,"end":65,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":15}}, + "expression": { + "type": "CallExpression", + "start":50,"end":64,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":14}}, + "callee": { + "type": "Import", + "start":50,"end":56,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":6}} + }, + "arguments": [ + { + "type": "Identifier", + "start":57,"end":63,"loc":{"start":{"line":4,"column":7},"end":{"line":4,"column":13},"identifierName":"module"}, + "name": "module" + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-module-blocks-as-arguments/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-module-blocks-as-arguments/input.js new file mode 100644 index 0000000000..d443912a2c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-module-blocks-as-arguments/input.js @@ -0,0 +1,3 @@ +const worker = new Worker(module { + export const foo = "foo"; +}); diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-module-blocks-as-arguments/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-module-blocks-as-arguments/output.json new file mode 100644 index 0000000000..2e86931034 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-module-blocks-as-arguments/output.json @@ -0,0 +1,84 @@ +{ + "type": "File", + "start":0,"end":68,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":3}}, + "program": { + "type": "Program", + "start":0,"end":68,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":3}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":68,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":3}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":67,"loc":{"start":{"line":1,"column":6},"end":{"line":3,"column":2}}, + "id": { + "type": "Identifier", + "start":6,"end":12,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":12},"identifierName":"worker"}, + "name": "worker" + }, + "init": { + "type": "NewExpression", + "start":15,"end":67,"loc":{"start":{"line":1,"column":15},"end":{"line":3,"column":2}}, + "callee": { + "type": "Identifier", + "start":19,"end":25,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":25},"identifierName":"Worker"}, + "name": "Worker" + }, + "arguments": [ + { + "type": "ModuleExpression", + "start":26,"end":66,"loc":{"start":{"line":1,"column":26},"end":{"line":3,"column":1}}, + "body": { + "type": "Program", + "start":39,"end":66,"loc":{"start":{"line":2,"column":4},"end":{"line":3,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":39,"end":64,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":29}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":46,"end":64,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":29}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":52,"end":63,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":28}}, + "id": { + "type": "Identifier", + "start":52,"end":55,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":20},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":58,"end":63,"loc":{"start":{"line":2,"column":23},"end":{"line":2,"column":28}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-nested-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-nested-module-blocks/input.js new file mode 100644 index 0000000000..baf30bb569 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-nested-module-blocks/input.js @@ -0,0 +1,5 @@ +let m = module { + module { + export let foo = "foo"; + }; +}; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-nested-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-nested-module-blocks/output.json new file mode 100644 index 0000000000..988aee5d5e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-nested-module-blocks/output.json @@ -0,0 +1,90 @@ +{ + "type": "File", + "start":0,"end":63,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":2}}, + "program": { + "type": "Program", + "start":0,"end":63,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":63,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":2}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":4,"end":62,"loc":{"start":{"line":1,"column":4},"end":{"line":5,"column":1}}, + "id": { + "type": "Identifier", + "start":4,"end":5,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":5},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "ModuleExpression", + "start":8,"end":62,"loc":{"start":{"line":1,"column":8},"end":{"line":5,"column":1}}, + "body": { + "type": "Program", + "start":19,"end":62,"loc":{"start":{"line":2,"column":2},"end":{"line":5,"column":1}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":19,"end":60,"loc":{"start":{"line":2,"column":2},"end":{"line":4,"column":4}}, + "expression": { + "type": "ModuleExpression", + "start":19,"end":59,"loc":{"start":{"line":2,"column":2},"end":{"line":4,"column":3}}, + "body": { + "type": "Program", + "start":32,"end":59,"loc":{"start":{"line":3,"column":4},"end":{"line":4,"column":3}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":32,"end":55,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":27}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":39,"end":55,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":27}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":43,"end":54,"loc":{"start":{"line":3,"column":15},"end":{"line":3,"column":26}}, + "id": { + "type": "Identifier", + "start":43,"end":46,"loc":{"start":{"line":3,"column":15},"end":{"line":3,"column":18},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":49,"end":54,"loc":{"start":{"line":3,"column":21},"end":{"line":3,"column":26}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "let" + } + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } + } + } + ], + "kind": "let" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-singleline-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-singleline-module-blocks/input.js new file mode 100644 index 0000000000..4b7bd35ec1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-singleline-module-blocks/input.js @@ -0,0 +1 @@ +const m = module { export const foo = "foo" }; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-singleline-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-singleline-module-blocks/output.json new file mode 100644 index 0000000000..d872a3275f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-singleline-module-blocks/output.json @@ -0,0 +1,73 @@ +{ + "type": "File", + "start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":46}}, + "program": { + "type": "Program", + "start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":46}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":46}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":45,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":45}}, + "id": { + "type": "Identifier", + "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"m"}, + "name": "m" + }, + "init": { + "type": "ModuleExpression", + "start":10,"end":45,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":45}}, + "body": { + "type": "Program", + "start":19,"end":45,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":45}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":19,"end":43,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":43}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start":26,"end":43,"loc":{"start":{"line":1,"column":26},"end":{"line":1,"column":43}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":32,"end":43,"loc":{"start":{"line":1,"column":32},"end":{"line":1,"column":43}}, + "id": { + "type": "Identifier", + "start":32,"end":35,"loc":{"start":{"line":1,"column":32},"end":{"line":1,"column":35},"identifierName":"foo"}, + "name": "foo" + }, + "init": { + "type": "StringLiteral", + "start":38,"end":43,"loc":{"start":{"line":1,"column":38},"end":{"line":1,"column":43}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "kind": "const" + } + } + ], + "directives": [] + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/input.js b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/input.js new file mode 100644 index 0000000000..3eb8123ffe --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/input.js @@ -0,0 +1 @@ +module { await 3 }; diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/options.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/options.json new file mode 100644 index 0000000000..92bd836fbb --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/options.json @@ -0,0 +1,4 @@ +{ + "sourceType": "module", + "plugins": ["moduleBlocks", "topLevelAwait"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/output.json b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/output.json new file mode 100644 index 0000000000..0a547ef93a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/module-blocks/valid-top-level-await-in-module-blocks/output.json @@ -0,0 +1,47 @@ +{ + "type": "File", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "program": { + "type": "Program", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "expression": { + "type": "ModuleExpression", + "start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}, + "body": { + "type": "Program", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":9,"end":16,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":16}}, + "expression": { + "type": "AwaitExpression", + "start":9,"end":16,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":16}}, + "argument": { + "type": "NumericLiteral", + "start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}}, + "extra": { + "rawValue": 3, + "raw": "3" + }, + "value": 3 + } + } + } + ], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-plugin-syntax-module-blocks/.npmignore b/packages/babel-plugin-syntax-module-blocks/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-syntax-module-blocks/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-syntax-module-blocks/README.md b/packages/babel-plugin-syntax-module-blocks/README.md new file mode 100644 index 0000000000..90eb1ba051 --- /dev/null +++ b/packages/babel-plugin-syntax-module-blocks/README.md @@ -0,0 +1,19 @@ +# @babel/plugin-syntax-module-blocks + +> Allow parsing of module blocks + +See our website [@babel/plugin-syntax-module-blocks](https://babeljs.io/docs/en/babel-plugin-syntax-module-blocks) for more information. + +## Install + +Using npm: + +```sh +npm install --save-dev @babel/plugin-syntax-module-blocks +``` + +or using yarn: + +```sh +yarn add @babel/plugin-syntax-module-blocks --dev +``` diff --git a/packages/babel-plugin-syntax-module-blocks/package.json b/packages/babel-plugin-syntax-module-blocks/package.json new file mode 100644 index 0000000000..dbe37522c1 --- /dev/null +++ b/packages/babel-plugin-syntax-module-blocks/package.json @@ -0,0 +1,27 @@ +{ + "name": "@babel/plugin-syntax-module-blocks", + "version": "7.11.0", + "description": "Allow parsing of JS Module Blocks", + "repository": { + "type": "git", + "url": "https://github.com/babel/babel.git", + "directory": "packages/babel-plugin-syntax-module-blocks" + }, + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "lib/index.js", + "exports": { + ".": "./lib/index.js" + }, + "keywords": [ + "babel-plugin" + ], + "dependencies": { + "@babel/helper-plugin-utils": "workspace:^7.10.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } +} diff --git a/packages/babel-plugin-syntax-module-blocks/src/index.js b/packages/babel-plugin-syntax-module-blocks/src/index.js new file mode 100644 index 0000000000..0cce13f321 --- /dev/null +++ b/packages/babel-plugin-syntax-module-blocks/src/index.js @@ -0,0 +1,13 @@ +import { declare } from "@babel/helper-plugin-utils"; + +export default declare(api => { + api.assertVersion(7); + + return { + name: "syntax-module-blocks", + + manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("moduleBlocks"); + }, + }; +}); diff --git a/packages/babel-standalone/package.json b/packages/babel-standalone/package.json index f191a4a8c6..ad0d981ad2 100644 --- a/packages/babel-standalone/package.json +++ b/packages/babel-standalone/package.json @@ -45,6 +45,7 @@ "@babel/plugin-syntax-import-assertions": "workspace:*", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-jsx": "workspace:*", + "@babel/plugin-syntax-module-blocks": "workspace:*", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", "@babel/plugin-syntax-pipeline-operator": "workspace:*", diff --git a/packages/babel-standalone/scripts/pluginConfig.json b/packages/babel-standalone/scripts/pluginConfig.json index 11b25e193c..7fd28384f6 100644 --- a/packages/babel-standalone/scripts/pluginConfig.json +++ b/packages/babel-standalone/scripts/pluginConfig.json @@ -10,6 +10,7 @@ "syntax-flow", "syntax-function-bind", "syntax-function-sent", + "syntax-module-blocks", "syntax-import-meta", "syntax-jsx", "syntax-import-assertions", diff --git a/packages/babel-standalone/src/generated/plugins.js b/packages/babel-standalone/src/generated/plugins.js index 889f6a494e..bcf2a29fb3 100644 --- a/packages/babel-standalone/src/generated/plugins.js +++ b/packages/babel-standalone/src/generated/plugins.js @@ -13,6 +13,7 @@ import syntaxExportDefaultFrom from "@babel/plugin-syntax-export-default-from"; import syntaxFlow from "@babel/plugin-syntax-flow"; import syntaxFunctionBind from "@babel/plugin-syntax-function-bind"; import syntaxFunctionSent from "@babel/plugin-syntax-function-sent"; +import syntaxModuleBlocks from "@babel/plugin-syntax-module-blocks"; import syntaxImportMeta from "@babel/plugin-syntax-import-meta"; import syntaxJsx from "@babel/plugin-syntax-jsx"; import syntaxImportAssertions from "@babel/plugin-syntax-import-assertions"; @@ -107,6 +108,7 @@ export { syntaxFlow, syntaxFunctionBind, syntaxFunctionSent, + syntaxModuleBlocks, syntaxImportMeta, syntaxJsx, syntaxImportAssertions, @@ -202,6 +204,7 @@ export const all = { "syntax-flow": syntaxFlow, "syntax-function-bind": syntaxFunctionBind, "syntax-function-sent": syntaxFunctionSent, + "syntax-module-blocks": syntaxModuleBlocks, "syntax-import-meta": syntaxImportMeta, "syntax-jsx": syntaxJsx, "syntax-import-assertions": syntaxImportAssertions, diff --git a/packages/babel-standalone/src/preset-stage-1.js b/packages/babel-standalone/src/preset-stage-1.js index eaf640f6cc..a3b891743a 100644 --- a/packages/babel-standalone/src/preset-stage-1.js +++ b/packages/babel-standalone/src/preset-stage-1.js @@ -22,6 +22,7 @@ export default (_: any, opts: Object = {}) => { plugins: [ babelPlugins.syntaxDecimal, [babelPlugins.syntaxRecordAndTuple, { syntaxType: recordAndTupleSyntax }], + babelPlugins.syntaxModuleBlocks, babelPlugins.proposalExportDefaultFrom, [babelPlugins.proposalPipelineOperator, { proposal: pipelineProposal }], babelPlugins.proposalDoExpressions, diff --git a/packages/babel-traverse/src/path/generated/asserts.ts b/packages/babel-traverse/src/path/generated/asserts.ts index cf912c0d63..b0e6e22ccf 100755 --- a/packages/babel-traverse/src/path/generated/asserts.ts +++ b/packages/babel-traverse/src/path/generated/asserts.ts @@ -331,6 +331,9 @@ export interface NodePathAssetions { assertModuleDeclaration( opts?: object, ): asserts this is NodePath; + assertModuleExpression( + opts?: object, + ): asserts this is NodePath; assertModuleSpecifier( opts?: object, ): asserts this is NodePath; diff --git a/packages/babel-traverse/src/path/generated/validators.ts b/packages/babel-traverse/src/path/generated/validators.ts index 985a24d4e7..ced5e53907 100755 --- a/packages/babel-traverse/src/path/generated/validators.ts +++ b/packages/babel-traverse/src/path/generated/validators.ts @@ -191,6 +191,7 @@ export interface NodePathValidators { isMethod(opts?: object): this is NodePath; isMixedTypeAnnotation(opts?: object): this is NodePath; isModuleDeclaration(opts?: object): this is NodePath; + isModuleExpression(opts?: object): this is NodePath; isModuleSpecifier(opts?: object): this is NodePath; isNewExpression(opts?: object): this is NodePath; isNoop(opts?: object): this is NodePath; diff --git a/packages/babel-types/src/asserts/generated/index.ts b/packages/babel-types/src/asserts/generated/index.ts index 2744f4c6bf..04cf3195f1 100755 --- a/packages/babel-types/src/asserts/generated/index.ts +++ b/packages/babel-types/src/asserts/generated/index.ts @@ -1088,6 +1088,12 @@ export function assertStaticBlock( ): asserts node is t.StaticBlock { assert("StaticBlock", node, opts); } +export function assertModuleExpression( + node: object | null | undefined, + opts?: object | null, +): asserts node is t.ModuleExpression { + assert("ModuleExpression", node, opts); +} export function assertTSParameterProperty( node: object | null | undefined, opts?: object | null, diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index a47bdb0c72..4d1cf3922f 100755 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -182,6 +182,7 @@ export type Node = | Method | MixedTypeAnnotation | ModuleDeclaration + | ModuleExpression | ModuleSpecifier | NewExpression | Noop @@ -1621,6 +1622,11 @@ export interface StaticBlock extends BaseNode { body: Array; } +export interface ModuleExpression extends BaseNode { + type: "ModuleExpression"; + body: Program; +} + export interface TSParameterProperty extends BaseNode { type: "TSParameterProperty"; parameter: Identifier | AssignmentPattern; @@ -2046,6 +2052,7 @@ export type Expression = | RecordExpression | TupleExpression | DecimalLiteral + | ModuleExpression | TSAsExpression | TSTypeAssertion | TSNonNullExpression; diff --git a/packages/babel-types/src/builders/generated/index.ts b/packages/babel-types/src/builders/generated/index.ts index 3328c722a3..2ade185393 100755 --- a/packages/babel-types/src/builders/generated/index.ts +++ b/packages/babel-types/src/builders/generated/index.ts @@ -1066,6 +1066,9 @@ export function decimalLiteral(value: string): t.DecimalLiteral { export function staticBlock(body: Array): t.StaticBlock { return builder("StaticBlock", ...arguments); } +export function moduleExpression(body: t.Program): t.ModuleExpression { + return builder("ModuleExpression", ...arguments); +} export function tsParameterProperty( parameter: t.Identifier | t.AssignmentPattern, ): t.TSParameterProperty { diff --git a/packages/babel-types/src/builders/generated/uppercase.js b/packages/babel-types/src/builders/generated/uppercase.js index f217d2532a..3e25736a38 100755 --- a/packages/babel-types/src/builders/generated/uppercase.js +++ b/packages/babel-types/src/builders/generated/uppercase.js @@ -188,6 +188,7 @@ export { tupleExpression as TupleExpression, decimalLiteral as DecimalLiteral, staticBlock as StaticBlock, + moduleExpression as ModuleExpression, tsParameterProperty as TSParameterProperty, tsDeclareFunction as TSDeclareFunction, tsDeclareMethod as TSDeclareMethod, diff --git a/packages/babel-types/src/definitions/experimental.ts b/packages/babel-types/src/definitions/experimental.ts index 95be90585e..4dd41acd13 100644 --- a/packages/babel-types/src/definitions/experimental.ts +++ b/packages/babel-types/src/definitions/experimental.ts @@ -262,3 +262,14 @@ defineType("StaticBlock", { }, aliases: ["Scopable", "BlockParent"], }); + +// https://github.com/tc39/proposal-js-module-blocks +defineType("ModuleExpression", { + visitor: ["body"], + fields: { + body: { + validate: assertNodeType("Program"), + }, + }, + aliases: ["Expression"], +}); diff --git a/packages/babel-types/src/validators/generated/index.ts b/packages/babel-types/src/validators/generated/index.ts index d839e1f62b..d24f3f81bf 100755 --- a/packages/babel-types/src/validators/generated/index.ts +++ b/packages/babel-types/src/validators/generated/index.ts @@ -3048,6 +3048,23 @@ export function isStaticBlock( return false; } +export function isModuleExpression( + node: object | null | undefined, + opts?: object | null, +): node is t.ModuleExpression { + if (!node) return false; + + const nodeType = (node as t.Node).type; + if (nodeType === "ModuleExpression") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isTSParameterProperty( node: object | null | undefined, opts?: object | null, @@ -4169,6 +4186,7 @@ export function isExpression( "RecordExpression" === nodeType || "TupleExpression" === nodeType || "DecimalLiteral" === nodeType || + "ModuleExpression" === nodeType || "TSAsExpression" === nodeType || "TSTypeAssertion" === nodeType || "TSNonNullExpression" === nodeType || diff --git a/yarn.lock b/yarn.lock index 59efd04ebb..33fa28266d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1656,6 +1656,16 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-module-blocks@workspace:*, @babel/plugin-syntax-module-blocks@workspace:packages/babel-plugin-syntax-module-blocks": + version: 0.0.0-use.local + resolution: "@babel/plugin-syntax-module-blocks@workspace:packages/babel-plugin-syntax-module-blocks" + dependencies: + "@babel/helper-plugin-utils": "workspace:^7.10.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + languageName: unknown + linkType: soft + "@babel/plugin-syntax-module-string-names@workspace:packages/babel-plugin-syntax-module-string-names": version: 0.0.0-use.local resolution: "@babel/plugin-syntax-module-string-names@workspace:packages/babel-plugin-syntax-module-string-names" @@ -3258,6 +3268,7 @@ __metadata: "@babel/plugin-syntax-import-assertions": "workspace:*" "@babel/plugin-syntax-import-meta": ^7.10.4 "@babel/plugin-syntax-jsx": "workspace:*" + "@babel/plugin-syntax-module-blocks": "workspace:*" "@babel/plugin-syntax-object-rest-spread": ^7.8.0 "@babel/plugin-syntax-optional-catch-binding": ^7.8.0 "@babel/plugin-syntax-pipeline-operator": "workspace:*"