Skip to content

Commit

Permalink
fix: support string assertion key in assert entries (#12281)
Browse files Browse the repository at this point in the history
* fix: support string assertion key in assert entries

* Update packages/babel-parser/src/parser/statement.js

Co-authored-by: Sosuke Suzuki <aosukeke@gmail.com>

Co-authored-by: Sosuke Suzuki <aosukeke@gmail.com>
  • Loading branch information
JLHwung and sosukesuzuki committed Oct 29, 2020
1 parent 963537d commit 766df9c
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 23 deletions.
50 changes: 27 additions & 23 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -2182,9 +2182,14 @@ export default class StatementParser extends ExpressionParser {
node.specifiers.push(this.finishNode(specifier, type));
}
parseAssertEntries() {
this.expectPlugin("importAssertions");
/**
* parse assert entries
*
* @see {@link https://tc39.es/proposal-import-assertions/#prod-AssertEntries |AssertEntries}
* @returns {N.ImportAttribute[]}
* @memberof StatementParser
*/
parseAssertEntries(): N.ImportAttribute[] {
const attrs = [];
const attrNames = new Set();
Expand All @@ -2193,46 +2198,48 @@ export default class StatementParser extends ExpressionParser {
break;
}
const node = this.startNode();
const node = this.startNode<N.ImportAttribute>();
// parse AssertionKey : IdentifierName, StringLiteral
let assertionKeyNode;
const keyName = this.state.value;
if (this.match(tt.string)) {
assertionKeyNode = this.parseLiteral(this.state.value, "StringLiteral");
node.key = this.parseLiteral<N.StringLiteral>(keyName, "StringLiteral");
} else {
assertionKeyNode = this.parseIdentifier(true);
node.key = this.parseIdentifier(true);
}
this.next();
node.key = assertionKeyNode;
this.expect(tt.colon);
// for now we are only allowing `type` as the only allowed module attribute
if (node.key.name !== "type") {
if (keyName !== "type") {
this.raise(
node.key.start,
Errors.ModuleAttributeDifferentFromType,
node.key.name,
keyName,
);
}
// 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 (attrNames.has(node.key.name)) {
if (attrNames.has(keyName)) {
this.raise(
node.key.start,
Errors.ModuleAttributesWithDuplicateKeys,
node.key.name,
keyName,
);
}
attrNames.add(node.key.name);
attrNames.add(keyName);
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");
node.value = this.parseLiteral<N.StringLiteral>(
this.state.value,
"StringLiteral",
);
this.finishNode<N.ImportAttribute>(node, "ImportAttribute");
attrs.push(node);
} while (this.eat(tt.comma));
Expand Down Expand Up @@ -2291,18 +2298,15 @@ export default class StatementParser extends ExpressionParser {
}
maybeParseImportAssertions() {
if (
this.match(tt.name) &&
this.state.value === "assert" &&
!this.hasPrecedingLineBreak()
) {
// [no LineTerminator here] AssertClause
if (this.isContextual("assert") && !this.hasPrecedingLineBreak()) {
this.expectPlugin("importAssertions");
this.next();
this.next(); // eat `assert`
} else {
if (this.hasPlugin("importAssertions")) return [];
return null;
}
// https://tc39.es/proposal-import-assertions/#prod-AssertClause
this.eat(tt.braceL);
const attrs = this.parseAssertEntries();
this.eat(tt.braceR);
Expand Down
@@ -0,0 +1 @@
import "foo" assert { type, "json" };
@@ -0,0 +1,9 @@
{
"plugins": [
[
"importAssertions"
]
],
"sourceType": "module",
"throws": "Unexpected token, expected \":\" (1:26)"
}
@@ -0,0 +1 @@
import "foo" \u{61}ssert { type: "json" };
@@ -0,0 +1,9 @@
{
"plugins": [
[
"importAssertions"
]
],
"sourceType": "module",
"throws": "Unexpected token, expected \";\" (1:13)"
}
@@ -0,0 +1 @@
import foo from "foo.json" assert { "type": "json", type: "html", "type": "js" };
@@ -0,0 +1,105 @@
{
"type": "File",
"start":0,"end":81,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":81}},
"errors": [
"SyntaxError: Duplicate key \"type\" is not allowed in module attributes (1:52)",
"SyntaxError: Duplicate key \"type\" is not allowed in module attributes (1:66)"
],
"program": {
"type": "Program",
"start":0,"end":81,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":81}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ImportDeclaration",
"start":0,"end":81,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":81}},
"specifiers": [
{
"type": "ImportDefaultSpecifier",
"start":7,"end":10,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":10}},
"local": {
"type": "Identifier",
"start":7,"end":10,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":10},"identifierName":"foo"},
"name": "foo"
}
}
],
"source": {
"type": "StringLiteral",
"start":16,"end":26,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":26}},
"extra": {
"rawValue": "foo.json",
"raw": "\"foo.json\""
},
"value": "foo.json"
},
"assertions": [
{
"type": "ImportAttribute",
"start":36,"end":50,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":50}},
"key": {
"type": "StringLiteral",
"start":36,"end":42,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":42}},
"extra": {
"rawValue": "type",
"raw": "\"type\""
},
"value": "type"
},
"value": {
"type": "StringLiteral",
"start":44,"end":50,"loc":{"start":{"line":1,"column":44},"end":{"line":1,"column":50}},
"extra": {
"rawValue": "json",
"raw": "\"json\""
},
"value": "json"
}
},
{
"type": "ImportAttribute",
"start":52,"end":64,"loc":{"start":{"line":1,"column":52},"end":{"line":1,"column":64}},
"key": {
"type": "Identifier",
"start":52,"end":56,"loc":{"start":{"line":1,"column":52},"end":{"line":1,"column":56},"identifierName":"type"},
"name": "type"
},
"value": {
"type": "StringLiteral",
"start":58,"end":64,"loc":{"start":{"line":1,"column":58},"end":{"line":1,"column":64}},
"extra": {
"rawValue": "html",
"raw": "\"html\""
},
"value": "html"
}
},
{
"type": "ImportAttribute",
"start":66,"end":78,"loc":{"start":{"line":1,"column":66},"end":{"line":1,"column":78}},
"key": {
"type": "StringLiteral",
"start":66,"end":72,"loc":{"start":{"line":1,"column":66},"end":{"line":1,"column":72}},
"extra": {
"rawValue": "type",
"raw": "\"type\""
},
"value": "type"
},
"value": {
"type": "StringLiteral",
"start":74,"end":78,"loc":{"start":{"line":1,"column":74},"end":{"line":1,"column":78}},
"extra": {
"rawValue": "js",
"raw": "\"js\""
},
"value": "js"
}
}
]
}
],
"directives": []
}
}
@@ -0,0 +1 @@
import "foo" assert { "type": "json" };
@@ -0,0 +1,51 @@
{
"type": "File",
"start":0,"end":39,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":39}},
"program": {
"type": "Program",
"start":0,"end":39,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":39}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ImportDeclaration",
"start":0,"end":39,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":39}},
"specifiers": [],
"source": {
"type": "StringLiteral",
"start":7,"end":12,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":12}},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
},
"assertions": [
{
"type": "ImportAttribute",
"start":22,"end":36,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":36}},
"key": {
"type": "StringLiteral",
"start":22,"end":28,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":28}},
"extra": {
"rawValue": "type",
"raw": "\"type\""
},
"value": "type"
},
"value": {
"type": "StringLiteral",
"start":30,"end":36,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":36}},
"extra": {
"rawValue": "json",
"raw": "\"json\""
},
"value": "json"
}
}
]
}
],
"directives": []
}
}

0 comments on commit 766df9c

Please sign in to comment.