Skip to content

Commit

Permalink
JSON modules should be imported with default (#14668)
Browse files Browse the repository at this point in the history
* fix: JSON module must be imported with default

* update test fixutres

* fix broken tests

* fix flow error

* Update packages/babel-parser/src/parse-error/standard-errors.js

Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>

* add assert {} test

* update test fixtures

* address review comment

Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
JLHwung and nicolo-ribaudo committed Jun 23, 2022
1 parent 87f26d5 commit e8dce41
Show file tree
Hide file tree
Showing 49 changed files with 963 additions and 176 deletions.
@@ -1,4 +1,4 @@
import foo1 from "foo.json" assert { type: "json" };
export { foo2 } from "foo.json" assert { type: "json" };
export { default as foo2 } from "foo.json" assert { type: "json" };
export * from "foo.json" assert { type: "json" };
export * as foo3 from "foo.json" assert { type: "json" };
@@ -1,4 +1,4 @@
import foo1 from "foo.json" assert { type: "json" };
export { foo2 } from "foo.json" assert { type: "json" };
export { default as foo2 } from "foo.json" assert { type: "json" };
export * from "foo.json" assert { type: "json" };
export * as foo3 from "foo.json" assert { type: "json" };
3 changes: 3 additions & 0 deletions packages/babel-parser/src/parse-error/standard-errors.js
Expand Up @@ -129,6 +129,9 @@ export default (_: typeof toParseErrorCredentials) => ({
),
ImportCallNotNewExpression: _("Cannot use new with import(...)."),
ImportCallSpreadArgument: _("`...` is not allowed in `import()`."),
ImportJSONBindingNotDefault: _(
"A JSON module can only be imported with `default`.",
),
IncompatibleRegExpUVFlags: _(
"The 'u' and 'v' regular expression flags cannot be enabled at the same time.",
),
Expand Down
52 changes: 52 additions & 0 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -2182,6 +2182,7 @@ export default class StatementParser extends ExpressionParser {
const assertions = this.maybeParseImportAssertions();
if (assertions) {
node.assertions = assertions;
this.checkJSONModuleImport(node);
}
} else if (expect) {
this.unexpected();
Expand Down Expand Up @@ -2399,6 +2400,56 @@ export default class StatementParser extends ExpressionParser {
return this.parseIdentifier(true);
}

isJSONModuleImport(
node:
| N.ExportAllDeclaration
| N.ExportNamedDeclaration
| N.ImportDeclaration,
): boolean {
if (node.assertions != null) {
return node.assertions.some(({ key, value }) => {
return (
value.value === "json" &&
(key.type === "Identifier"
? key.name === "type"
: key.value === "type")
);
});
}
return false;
}

checkJSONModuleImport(
node:
| N.ExportAllDeclaration
| N.ExportNamedDeclaration
| N.ImportDeclaration,
) {
if (this.isJSONModuleImport(node) && node.type !== "ExportAllDeclaration") {
const { specifiers } = node;
if (node.specifiers != null) {
const nonDefaultNamedSpecifier = specifiers.find(specifier => {
let imported;
if (specifier.type === "ExportSpecifier") {
imported = specifier.local;
} else if (specifier.type === "ImportSpecifier") {
imported = specifier.imported;
}
if (imported !== undefined) {
return imported.type === "Identifier"
? imported.name !== "default"
: imported.value !== "default";
}
});
if (nonDefaultNamedSpecifier !== undefined) {
this.raise(Errors.ImportJSONBindingNotDefault, {
at: nonDefaultNamedSpecifier.loc.start,
});
}
}
}
}

// Parses import declaration.
// https://tc39.es/ecma262/#prod-ImportDeclaration

Expand Down Expand Up @@ -2437,6 +2488,7 @@ export default class StatementParser extends ExpressionParser {
node.attributes = attributes;
}
}
this.checkJSONModuleImport(node);

this.semicolon();
return this.finishNode(node, "ImportDeclaration");
Expand Down
@@ -0,0 +1 @@
export { default as foo } from "foo.json" assert { type: "json", type: "html" };
@@ -0,0 +1,84 @@
{
"type": "File",
"start":0,"end":80,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":80,"index":80}},
"errors": [
"SyntaxError: Duplicate key \"type\" is not allowed in module attributes. (1:65)"
],
"program": {
"type": "Program",
"start":0,"end":80,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":80,"index":80}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start":0,"end":80,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":80,"index":80}},
"specifiers": [
{
"type": "ExportSpecifier",
"start":9,"end":23,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":23,"index":23}},
"local": {
"type": "Identifier",
"start":9,"end":16,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":16,"index":16},"identifierName":"default"},
"name": "default"
},
"exported": {
"type": "Identifier",
"start":20,"end":23,"loc":{"start":{"line":1,"column":20,"index":20},"end":{"line":1,"column":23,"index":23},"identifierName":"foo"},
"name": "foo"
}
}
],
"source": {
"type": "StringLiteral",
"start":31,"end":41,"loc":{"start":{"line":1,"column":31,"index":31},"end":{"line":1,"column":41,"index":41}},
"extra": {
"rawValue": "foo.json",
"raw": "\"foo.json\""
},
"value": "foo.json"
},
"declaration": null,
"assertions": [
{
"type": "ImportAttribute",
"start":51,"end":63,"loc":{"start":{"line":1,"column":51,"index":51},"end":{"line":1,"column":63,"index":63}},
"key": {
"type": "Identifier",
"start":51,"end":55,"loc":{"start":{"line":1,"column":51,"index":51},"end":{"line":1,"column":55,"index":55},"identifierName":"type"},
"name": "type"
},
"value": {
"type": "StringLiteral",
"start":57,"end":63,"loc":{"start":{"line":1,"column":57,"index":57},"end":{"line":1,"column":63,"index":63}},
"extra": {
"rawValue": "json",
"raw": "\"json\""
},
"value": "json"
}
},
{
"type": "ImportAttribute",
"start":65,"end":77,"loc":{"start":{"line":1,"column":65,"index":65},"end":{"line":1,"column":77,"index":77}},
"key": {
"type": "Identifier",
"start":65,"end":69,"loc":{"start":{"line":1,"column":65,"index":65},"end":{"line":1,"column":69,"index":69},"identifierName":"type"},
"name": "type"
},
"value": {
"type": "StringLiteral",
"start":71,"end":77,"loc":{"start":{"line":1,"column":71,"index":71},"end":{"line":1,"column":77,"index":77}},
"extra": {
"rawValue": "html",
"raw": "\"html\""
},
"value": "html"
}
}
]
}
],
"directives": []
}
}
@@ -1,2 +1,2 @@
import foo from "foo" assert { type: "json", }
export { foo } from "foo" assert { type: "json", }
export { default as foo } from "foo" assert { type: "json", }
@@ -1,9 +1,9 @@
{
"type": "File",
"start":0,"end":97,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":50,"index":97}},
"start":0,"end":108,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":61,"index":108}},
"program": {
"type": "Program",
"start":0,"end":97,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":50,"index":97}},
"start":0,"end":108,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":61,"index":108}},
"sourceType": "module",
"interpreter": null,
"body": [
Expand Down Expand Up @@ -53,26 +53,26 @@
},
{
"type": "ExportNamedDeclaration",
"start":47,"end":97,"loc":{"start":{"line":2,"column":0,"index":47},"end":{"line":2,"column":50,"index":97}},
"start":47,"end":108,"loc":{"start":{"line":2,"column":0,"index":47},"end":{"line":2,"column":61,"index":108}},
"specifiers": [
{
"type": "ExportSpecifier",
"start":56,"end":59,"loc":{"start":{"line":2,"column":9,"index":56},"end":{"line":2,"column":12,"index":59}},
"start":56,"end":70,"loc":{"start":{"line":2,"column":9,"index":56},"end":{"line":2,"column":23,"index":70}},
"local": {
"type": "Identifier",
"start":56,"end":59,"loc":{"start":{"line":2,"column":9,"index":56},"end":{"line":2,"column":12,"index":59},"identifierName":"foo"},
"name": "foo"
"start":56,"end":63,"loc":{"start":{"line":2,"column":9,"index":56},"end":{"line":2,"column":16,"index":63},"identifierName":"default"},
"name": "default"
},
"exported": {
"type": "Identifier",
"start":56,"end":59,"loc":{"start":{"line":2,"column":9,"index":56},"end":{"line":2,"column":12,"index":59},"identifierName":"foo"},
"start":67,"end":70,"loc":{"start":{"line":2,"column":20,"index":67},"end":{"line":2,"column":23,"index":70},"identifierName":"foo"},
"name": "foo"
}
}
],
"source": {
"type": "StringLiteral",
"start":67,"end":72,"loc":{"start":{"line":2,"column":20,"index":67},"end":{"line":2,"column":25,"index":72}},
"start":78,"end":83,"loc":{"start":{"line":2,"column":31,"index":78},"end":{"line":2,"column":36,"index":83}},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
Expand All @@ -83,15 +83,15 @@
"assertions": [
{
"type": "ImportAttribute",
"start":82,"end":94,"loc":{"start":{"line":2,"column":35,"index":82},"end":{"line":2,"column":47,"index":94}},
"start":93,"end":105,"loc":{"start":{"line":2,"column":46,"index":93},"end":{"line":2,"column":58,"index":105}},
"key": {
"type": "Identifier",
"start":82,"end":86,"loc":{"start":{"line":2,"column":35,"index":82},"end":{"line":2,"column":39,"index":86},"identifierName":"type"},
"start":93,"end":97,"loc":{"start":{"line":2,"column":46,"index":93},"end":{"line":2,"column":50,"index":97},"identifierName":"type"},
"name": "type"
},
"value": {
"type": "StringLiteral",
"start":88,"end":94,"loc":{"start":{"line":2,"column":41,"index":88},"end":{"line":2,"column":47,"index":94}},
"start":99,"end":105,"loc":{"start":{"line":2,"column":52,"index":99},"end":{"line":2,"column":58,"index":105}},
"extra": {
"rawValue": "json",
"raw": "\"json\""
Expand Down
@@ -0,0 +1,4 @@
import foo, { bar } from "foo" assert {};
import * as ns from "foo" assert {};
export { quux } from "foo" assert {};
export * as ns2 from "foo" assert {};
@@ -0,0 +1,133 @@
{
"type": "File",
"start":0,"end":154,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":37,"index":154}},
"program": {
"type": "Program",
"start":0,"end":154,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":37,"index":154}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ImportDeclaration",
"start":0,"end":41,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":41,"index":41}},
"specifiers": [
{
"type": "ImportDefaultSpecifier",
"start":7,"end":10,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":10,"index":10}},
"local": {
"type": "Identifier",
"start":7,"end":10,"loc":{"start":{"line":1,"column":7,"index":7},"end":{"line":1,"column":10,"index":10},"identifierName":"foo"},
"name": "foo"
}
},
{
"type": "ImportSpecifier",
"start":14,"end":17,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":17,"index":17}},
"imported": {
"type": "Identifier",
"start":14,"end":17,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":17,"index":17},"identifierName":"bar"},
"name": "bar"
},
"local": {
"type": "Identifier",
"start":14,"end":17,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":17,"index":17},"identifierName":"bar"},
"name": "bar"
}
}
],
"source": {
"type": "StringLiteral",
"start":25,"end":30,"loc":{"start":{"line":1,"column":25,"index":25},"end":{"line":1,"column":30,"index":30}},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
},
"assertions": []
},
{
"type": "ImportDeclaration",
"start":42,"end":78,"loc":{"start":{"line":2,"column":0,"index":42},"end":{"line":2,"column":36,"index":78}},
"specifiers": [
{
"type": "ImportNamespaceSpecifier",
"start":49,"end":56,"loc":{"start":{"line":2,"column":7,"index":49},"end":{"line":2,"column":14,"index":56}},
"local": {
"type": "Identifier",
"start":54,"end":56,"loc":{"start":{"line":2,"column":12,"index":54},"end":{"line":2,"column":14,"index":56},"identifierName":"ns"},
"name": "ns"
}
}
],
"source": {
"type": "StringLiteral",
"start":62,"end":67,"loc":{"start":{"line":2,"column":20,"index":62},"end":{"line":2,"column":25,"index":67}},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
},
"assertions": []
},
{
"type": "ExportNamedDeclaration",
"start":79,"end":116,"loc":{"start":{"line":3,"column":0,"index":79},"end":{"line":3,"column":37,"index":116}},
"specifiers": [
{
"type": "ExportSpecifier",
"start":88,"end":92,"loc":{"start":{"line":3,"column":9,"index":88},"end":{"line":3,"column":13,"index":92}},
"local": {
"type": "Identifier",
"start":88,"end":92,"loc":{"start":{"line":3,"column":9,"index":88},"end":{"line":3,"column":13,"index":92},"identifierName":"quux"},
"name": "quux"
},
"exported": {
"type": "Identifier",
"start":88,"end":92,"loc":{"start":{"line":3,"column":9,"index":88},"end":{"line":3,"column":13,"index":92},"identifierName":"quux"},
"name": "quux"
}
}
],
"source": {
"type": "StringLiteral",
"start":100,"end":105,"loc":{"start":{"line":3,"column":21,"index":100},"end":{"line":3,"column":26,"index":105}},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
},
"declaration": null,
"assertions": []
},
{
"type": "ExportNamedDeclaration",
"start":117,"end":154,"loc":{"start":{"line":4,"column":0,"index":117},"end":{"line":4,"column":37,"index":154}},
"specifiers": [
{
"type": "ExportNamespaceSpecifier",
"start":124,"end":132,"loc":{"start":{"line":4,"column":7,"index":124},"end":{"line":4,"column":15,"index":132}},
"exported": {
"type": "Identifier",
"start":129,"end":132,"loc":{"start":{"line":4,"column":12,"index":129},"end":{"line":4,"column":15,"index":132},"identifierName":"ns2"},
"name": "ns2"
}
}
],
"source": {
"type": "StringLiteral",
"start":138,"end":143,"loc":{"start":{"line":4,"column":21,"index":138},"end":{"line":4,"column":26,"index":143}},
"extra": {
"rawValue": "foo",
"raw": "\"foo\""
},
"value": "foo"
},
"assertions": []
}
],
"directives": []
}
}
@@ -1,2 +1,2 @@
export { x } from "foo" assert
export { default as x } from "foo" assert
{ type: "json" }

0 comments on commit e8dce41

Please sign in to comment.