Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added basic support for module attributes and tests updated #10962

Merged
merged 71 commits into from May 24, 2020
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
7e1a783
:recycle: added basic support for module attributes and tests updated
Jan 5, 2020
b810e31
attributes should be set only if moduleAttributes plugin is enabled, …
Jan 5, 2020
c35b06e
Merge branch 'master' of https://github.com/babel/babel into proposal…
Jan 25, 2020
4243ec1
:recycle: use new AST Node ImportAttribute for module attributes, tes…
vivek12345 Jan 25, 2020
202af5a
Merge branch 'master' of https://github.com/babel/babel into proposal…
vivek12345 Mar 11, 2020
14aae84
chore: fixed the eslint issue and sorted the errors in ascending order
vivek12345 Mar 11, 2020
8c4ecf9
improvement: added support to throw error if duplicate attributes found
vivek12345 Mar 11, 2020
bbb6020
chore: fixed the failing test of babel plugin dotall regex
vivek12345 Mar 11, 2020
ba5482e
improvement: fixed error messages, confition to check presence of wit…
vivek12345 Mar 12, 2020
a038601
test: added a new test for allowing hasOwnProperty as one of the modu…
vivek12345 Mar 12, 2020
cde4f92
chore: added a mandatory version option to use along with module attr…
vivek12345 Mar 12, 2020
4f16179
improvement: replaced object create with set and renamed test folder …
vivek12345 Mar 13, 2020
a264662
Update packages/babel-parser/src/plugin-utils.js
vivek12345 Mar 13, 2020
c7c2c78
Update packages/babel-parser/src/parser/statement.js
vivek12345 Mar 13, 2020
2b5b437
chore: unnecesaary comment removed and tests updated
vivek12345 Mar 13, 2020
d36d314
improvement: using node.key.start instead of this.node.start to point…
vivek12345 Mar 13, 2020
0a0958d
improvement: added check for line terminator
vivek12345 Mar 14, 2020
f28f6ad
chore: renamed valid-syntax-with-attributes-multiple-lines to invalid…
vivek12345 Mar 14, 2020
7806809
improvement: changed the logic and tests to only support type as the …
vivek12345 Mar 15, 2020
a3c6a55
improvement: don't throw an error when attribute name is not type, ju…
vivek12345 Mar 15, 2020
65f9f5c
Revert output.js
nicolo-ribaudo Mar 15, 2020
1dacc99
improvement: removed the check for presence of tyep attribute as an e…
vivek12345 Mar 15, 2020
187d0d6
Merge branch 'proposal-module-attributes' of https://github.com/vivek…
vivek12345 Mar 15, 2020
5cb50ed
Merge branch 'master' of https://github.com/babel/babel into proposal…
vivek12345 Mar 15, 2020
40ddfab
feat: added syntax-import-module-attributes
vivek12345 Mar 16, 2020
41bb994
fix: fixed a message test in the readme for syntax-import-module-attr…
vivek12345 Mar 16, 2020
4030426
refactor: removed the error key ModuleAttributesWithoutType as it is …
vivek12345 Mar 16, 2020
792d096
refactor: renamed syntax-import-module-attributes to syntax-module-at…
vivek12345 Mar 16, 2020
a3c56ff
:recycle: added basic support for module attributes and tests updated
Jan 5, 2020
cbcdb3d
attributes should be set only if moduleAttributes plugin is enabled, …
Jan 5, 2020
e392984
:recycle: use new AST Node ImportAttribute for module attributes, tes…
vivek12345 Jan 25, 2020
256510b
chore: fixed the eslint issue and sorted the errors in ascending order
vivek12345 Mar 11, 2020
1ee26a7
improvement: added support to throw error if duplicate attributes found
vivek12345 Mar 11, 2020
2a708a5
improvement: fixed error messages, confition to check presence of wit…
vivek12345 Mar 12, 2020
f795d36
test: added a new test for allowing hasOwnProperty as one of the modu…
vivek12345 Mar 12, 2020
35a85e9
chore: added a mandatory version option to use along with module attr…
vivek12345 Mar 12, 2020
e3976f2
improvement: replaced object create with set and renamed test folder …
vivek12345 Mar 13, 2020
efacdaf
Update packages/babel-parser/src/plugin-utils.js
vivek12345 Mar 13, 2020
4202fa9
Update packages/babel-parser/src/parser/statement.js
vivek12345 Mar 13, 2020
e1016ad
chore: unnecesaary comment removed and tests updated
vivek12345 Mar 13, 2020
f89c15f
improvement: using node.key.start instead of this.node.start to point…
vivek12345 Mar 13, 2020
18dd064
improvement: added check for line terminator
vivek12345 Mar 14, 2020
31f6a38
chore: renamed valid-syntax-with-attributes-multiple-lines to invalid…
vivek12345 Mar 14, 2020
b98824f
improvement: changed the logic and tests to only support type as the …
vivek12345 Mar 15, 2020
1c2be01
improvement: don't throw an error when attribute name is not type, ju…
vivek12345 Mar 15, 2020
180b757
Revert output.js
nicolo-ribaudo Mar 15, 2020
ca2608f
improvement: removed the check for presence of tyep attribute as an e…
vivek12345 Mar 15, 2020
3581a82
feat: added syntax-import-module-attributes
vivek12345 Mar 16, 2020
b9d2939
fix: fixed a message test in the readme for syntax-import-module-attr…
vivek12345 Mar 16, 2020
24f7830
refactor: removed the error key ModuleAttributesWithoutType as it is …
vivek12345 Mar 16, 2020
b1270c6
refactor: renamed syntax-import-module-attributes to syntax-module-at…
vivek12345 Mar 16, 2020
b7280e2
Format output files
nicolo-ribaudo Apr 28, 2020
6e4e730
feb-2020 -> apr-2020
nicolo-ribaudo Apr 28, 2020
7a2f4f8
Revert output.js
nicolo-ribaudo Apr 28, 2020
69f153e
Revert expression.js
nicolo-ribaudo Apr 28, 2020
522bdc6
relaxed the argument condition on dynamic imports from 1 to 2 for pro…
vivek12345 Apr 30, 2020
2a3e3d0
merged with upstream master
vivek12345 Apr 30, 2020
b1e7ddc
merged with remote changes and merge conflicts resolved
vivek12345 Apr 30, 2020
2e243af
bug: fixed the version to apr-2020
vivek12345 Apr 30, 2020
f250937
polish: tune importArity error message
JLHwung May 20, 2020
dbf36f6
fix: allow trailing comma in import()
JLHwung May 20, 2020
0ce6e62
chore: update version to latest month
JLHwung May 20, 2020
9f80885
add moduleAttributes to parse typings
JLHwung May 20, 2020
aa22f1a
feat: add syntax-module-attributes to babel-standalone
JLHwung May 20, 2020
967a9be
fix: forbid spread element in second argument of import()
JLHwung May 20, 2020
d06d08b
expect moduleAttributes when there are two arguments of import()
JLHwung May 20, 2020
f051fa1
refactor: minor tweaks
JLHwung May 20, 2020
01933e4
Merge remote-tracking branch 'upstream/master' into proposal-module-a…
JLHwung May 20, 2020
dde6294
chore: rearrange tests
JLHwung May 20, 2020
907aacd
Update packages/babel-parser/src/parser/expression.js
JLHwung May 21, 2020
63b7c44
Merge remote-tracking branch 'upstream/master' into proposal-module-a…
nicolo-ribaudo May 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 20 additions & 6 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -765,12 +765,26 @@ export default class ExpressionParser extends LValParser {
optional: boolean,
): N.Expression {
if (node.callee.type === "Import") {
if (node.arguments.length !== 1) {
this.raise(node.start, Errors.ImportCallArity);
if (node.arguments.length === 2) {
this.expectPlugin("moduleAttributes");
}
if (node.arguments.length === 0 || node.arguments.length > 2) {
this.raise(
node.start,
Errors.ImportCallArity,
this.hasPlugin("moduleAttributes")
? "one or two arguments"
: "one argument",
);
} else {
const importArg = node.arguments[0];
if (importArg && importArg.type === "SpreadElement") {
this.raise(importArg.start, Errors.ImportCallSpreadArgument);
const importArgSpreadElement = node.arguments.find(
arg => arg.type === "SpreadElement",
);
if (importArgSpreadElement) {
this.raise(
importArgSpreadElement.start,
Errors.ImportCallSpreadArgument,
);
}
JLHwung marked this conversation as resolved.
Show resolved Hide resolved
}
}
Expand Down Expand Up @@ -799,7 +813,7 @@ export default class ExpressionParser extends LValParser {
} else {
this.expect(tt.comma);
if (this.match(close)) {
if (dynamicImport) {
if (dynamicImport && !this.hasPlugin("moduleAttributes")) {
this.raise(
this.state.lastTokStart,
Errors.ImportCallArgumentTrailingComma,
Expand Down
8 changes: 7 additions & 1 deletion packages/babel-parser/src/parser/location.js
Expand Up @@ -67,7 +67,7 @@ export const Errors = Object.freeze({
IllegalReturn: "'return' outside of function",
ImportCallArgumentTrailingComma:
"Trailing comma is disallowed inside import(...) arguments",
ImportCallArity: "import() requires exactly one argument",
ImportCallArity: "import() requires exactly %0",
JLHwung marked this conversation as resolved.
Show resolved Hide resolved
ImportCallArityLtOne: "Dynamic imports require a parameter: import('a.js')",
ImportCallNotNewExpression: "Cannot use new with import(...)",
ImportCallSpreadArgument: "... is not allowed in import()",
Expand Down Expand Up @@ -97,6 +97,12 @@ export const Errors = Object.freeze({
MissingUnicodeEscape: "Expecting Unicode escape sequence \\uXXXX",
MixingCoalesceWithLogical:
"Nullish coalescing operator(??) requires parens when mixing with logical operators",
ModuleAttributeDifferentFromType:
"The only accepted module attribute is `type`",
ModuleAttributeInvalidValue:
"Only string literals are allowed as module attribute values",
ModuleAttributesWithDuplicateKeys:
'Duplicate key "%0" is not allowed in module attributes',
ModuleExportUndefined: "Export '%0' is not defined",
MultipleDefaultsInSwitch: "Multiple default clauses",
NewlineAfterThrow: "Illegal newline after throw",
Expand Down
71 changes: 71 additions & 0 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -2041,13 +2041,31 @@ export default class StatementParser extends ExpressionParser {
// import '...'
node.specifiers = [];
if (!this.match(tt.string)) {
// check if we have a default import like
// import React from "react";
const hasDefault = this.maybeParseDefaultImportSpecifier(node);
/* we are checking if we do not have a default import, then it is obvious that we need named imports
* import { get } from "axios";
* but if we do have a default import
* we need to check if we have a comma after that and
* that is where this `|| this.eat` condition comes into play
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vivek12345 I don't know if I already thanked you, but I love these comments!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @nicolo-ribaudo . Means a lot 🙏

const parseNext = !hasDefault || this.eat(tt.comma);
// if we do have to parse the next set of specifiers, we first check for star imports
// import React, * from "react";
const hasStar = parseNext && this.maybeParseStarImportSpecifier(node);
// now we check if we need to parse the next imports
// but only if they are not importing * (everything)
if (parseNext && !hasStar) this.parseNamedImportSpecifiers(node);
this.expectContextual("from");
}
node.source = this.parseImportSource();
// https://github.com/tc39/proposal-module-attributes
// parse module attributes if the next token is `with` or ignore and finish the ImportDeclaration node.
const attributes = this.maybeParseModuleAttributes();
vivek12345 marked this conversation as resolved.
Show resolved Hide resolved
if (attributes) {
node.attributes = attributes;
}
xtuc marked this conversation as resolved.
Show resolved Hide resolved
this.semicolon();
return this.finishNode(node, "ImportDeclaration");
}
Expand Down Expand Up @@ -2078,6 +2096,59 @@ export default class StatementParser extends ExpressionParser {
node.specifiers.push(this.finishNode(specifier, type));
}

maybeParseModuleAttributes() {
if (this.match(tt._with) && !this.hasPrecedingLineBreak()) {
this.expectPlugin("moduleAttributes");
this.next();
} else {
if (this.hasPlugin("moduleAttributes")) return [];
xtuc marked this conversation as resolved.
Show resolved Hide resolved
return null;
}
const attrs = [];
const attributes = new Set();
do {
// we are trying to parse a node which has the following syntax
// with type: "json"
// [with -> keyword], [type -> Identifier], [":" -> token for colon], ["json" -> StringLiteral]
const node = this.startNode();
node.key = this.parseIdentifier(true);

// for now we are only allowing `type` as the only allowed module attribute
if (node.key.name !== "type") {
this.raise(
node.key.start,
Errors.ModuleAttributeDifferentFromType,
node.key.name,
);
}

// check if we already have an entry for an attribute
// if a duplicate entry is found, throw an error
// for now this logic will come into play only when someone declares `type` twice
if (attributes.has(node.key.name)) {
this.raise(
node.key.start,
Errors.ModuleAttributesWithDuplicateKeys,
node.key.name,
);
JLHwung marked this conversation as resolved.
Show resolved Hide resolved
}
attributes.add(node.key.name);
this.expect(tt.colon);
xtuc marked this conversation as resolved.
Show resolved Hide resolved
// check if the value set to the module attribute is a string as we only allow string literals
if (!this.match(tt.string)) {
throw this.unexpected(
this.state.start,
Errors.ModuleAttributeInvalidValue,
);
}
node.value = this.parseLiteral(this.state.value, "StringLiteral");
this.finishNode(node, "ImportAttribute");
attrs.push(node);
} while (this.eat(tt.comma));

return attrs;
}

maybeParseDefaultImportSpecifier(node: N.ImportDeclaration): boolean {
if (this.shouldParseDefaultImport(node)) {
// import defaultObj, { x, y as z } from '...'
Expand Down
14 changes: 14 additions & 0 deletions packages/babel-parser/src/plugin-utils.js
Expand Up @@ -86,6 +86,20 @@ export function validatePlugins(plugins: PluginList) {
);
}

if (hasPlugin(plugins, "moduleAttributes")) {
const moduleAttributesVerionPluginOption = getPluginOption(
plugins,
"moduleAttributes",
"version",
);
if (moduleAttributesVerionPluginOption !== "may-2020") {
throw new Error(
"The 'moduleAttributes' plugin requires a 'version' option," +
" representing the last proposal update. Currently, the" +
" only supported value is 'may-2020'.",
);
}
}
if (
hasPlugin(plugins, "recordAndTuple") &&
!RECORD_AND_TUPLE_SYNTAX_TYPES.includes(
Expand Down
@@ -1 +1 @@
import('hello', 'world');
import('hello', 'world', '!');
@@ -1,21 +1,21 @@
{
"type": "File",
"start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}},
"start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},
"errors": [
"SyntaxError: import() requires exactly one argument (1:0)"
],
"program": {
"type": "Program",
"start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}},
"start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}},
"start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},
"expression": {
"type": "CallExpression",
"start":0,"end":24,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},
"start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":29}},
"callee": {
"type": "Import",
"start":0,"end":6,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":6}}
Expand All @@ -38,6 +38,15 @@
"raw": "'world'"
},
"value": "world"
},
{
"type": "StringLiteral",
"start":25,"end":28,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":28}},
"extra": {
"rawValue": "!",
"raw": "'!'"
},
"value": "!"
}
]
}
Expand Down
@@ -0,0 +1 @@
import('hello', 'world');
@@ -0,0 +1,5 @@
{
"throws": "This experimental syntax requires enabling the parser plugin: 'moduleAttributes' (1:24)",
"sourceType": "module",
"plugins": []
}
@@ -0,0 +1 @@
import foo from "foo.json" with type: "json";
@@ -0,0 +1,5 @@
{
"throws": "This experimental syntax requires enabling the parser plugin: 'moduleAttributes' (1:27)",
"sourceType": "module",
"plugins": []
}
@@ -0,0 +1 @@
import("foo.json", { with: { type: "json" } })
@@ -0,0 +1,11 @@
{
"plugins": [
[
"moduleAttributes",
{
"version": "may-2020"
}
]
],
"sourceType": "module"
}