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

RFC 0004: Add ImportExpression AST type #4

Merged
merged 11 commits into from May 2, 2024

Conversation

JLHwung
Copy link
Collaborator

@JLHwung JLHwung commented May 1, 2020

View Rendered Text

This RFC proposes to parse import() as a new AST node type ImportExpression instead of CallExpression.

Pinging a few people who may be interested in this:

@axetroy - vscode-npm-import-package-version
@devongovett - parcel
@flytam - babel-plugin-resolve-config-json
@kevinbarabash - eslint-plugin-khan
@ljharb - babel-plugin-dynamic-import-node, eslint-plugin-import
@suchipi - transform-imports
@swannodette - closurescript

Please share this RFC to anyone who can contribute to the discussion.

@ljharb
Copy link
Member

ljharb commented May 1, 2020

Note this will also likely impact eslint-plugin-import, which I also maintain.

Co-authored-by: Brian Ng <bng412@gmail.com>
@JLHwung
Copy link
Collaborator Author

JLHwung commented May 1, 2020

@ljharb I think any ESLint plugins that relies on CallExpression[callee=Import] will have to adapt to the new ImportExpression regardless of whether this RFC is accepted, because it has been included in ESTree and eslint should follow this path, too. In this way the RFC also aligns babel parser behaviour to ESTree.

Co-authored-by: Brian Ng <bng412@gmail.com>
Copy link
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

I like this proposal. Note that I don't think that aligning with ESTree should be a goal for us, but this AST shape is definitely better than our current one since it "automatically" disallows invalid states.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

@ljharb Currently, the @babel/plugin-proposal-dynamic-import when targeting CommonJS is just a proxy to babel-plugin-dynamic-import.

Since this AST change makes it harder to have a plugin working with Babel 6-7 and with Babel 8, I was thinking that it would be easier to only support Babel 6-7 in babel-plugin-dynamic-import and write the new logic for Babel 8 in our monorepo.

Does that sound good to you?

@ljharb
Copy link
Member

ljharb commented May 8, 2020

@nicolo-ribaudo that doesn't make sense to me; how does it make it harder? It seems like I just have to add an extra visitor.

If babel wants to inline the dependency, that's one thing, but otherwise it seems pretty trivial to support 6, 7, and 8?

More to the point, if it's not easy to support both babel 7 and 8 in the same transform, then imo the change is poorly designed and shouldn't happen at all.

}
```

When `@babel/parser` [supported](https://github.com/babel/babylon/pull/163) dynamic import, it was called `import-function` and shared similar syntax structure with `super` call that is parsed as `CallExpression[callee=Super]`. However, it encourages an incorrect mental model, as developers may think of `import()` as a function call. Besides, it was later syntactically limited to one argument, different from other call expressions. Last, it is also problematic when we extend the current AST shape to support stage-1 [module attributes](https://github.com/tc39/proposal-module-attributes) (`import(moduleName, attributes)`) since the arguments (`moduleName` and `attributes` respectively) share the same semantics in the AST.
Copy link
Member

Choose a reason for hiding this comment

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

There's a bit of discussion in tc39/proposal-import-attributes#52. Honestly, I'd rather we treat it as a regular function call, exactly the same as super().

Copy link
Member

@ljharb ljharb May 8, 2020

Choose a reason for hiding this comment

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

I very much doubt that import() will ever get consensus to be treated as a normal function call; there was a lot of discussion about that during its advancement. It’s syntax, and will likely always be special in a number of ways.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note that the ImportExpression is also created to be consistent with ImportDeclaration.

interface ImportDeclaration <: ModuleDeclaration {
  type: "ImportDeclaration";
  source: Literal;
}

interface ImportExpression <: Expression {
  type: "ImportExpression";
  source: Expression;
}

Although on the CST level an import expression shares similar syntax features with a function call, but on the AST level I think we should abstract them to common import interface.

@kliukovkin
Copy link

@JLHwung is there anything left before merging this PR?

@JLHwung
Copy link
Collaborator Author

JLHwung commented Aug 3, 2020

@ACSAIS

An RFC is considered as accepted if it receives at least 4 approving reviews, and no rejection from core team members. If the RFC is proposed by a core team member, this number is lowered to 3.

https://github.com/babel/rfcs#reviewing-rfcs

@kliukovkin
Copy link

Didn't know it, thanks for your answer @JLHwung !

@fisker
Copy link

fisker commented Aug 28, 2022

Progress?

@nicolo-ribaudo
Copy link
Member

This AST change would also make it easier to support https://github.com/tc39/proposal-import-reflection/. I wonder if we can start implementing it in Babel 7 as opt-in with a parser option.

@fisker
Copy link

fisker commented Jun 4, 2023

Though estree uses ImportExpression, and I hope babel aligh with them.

I wounder what the ast will look like for import.source("<specifier>").

{
  "type": "ImportExpression", 
  "phase": "source"
}

?

CallExpression seems easier to extend

{
  "type": "CallExpression", 
  "callee": {
    "type": "MetaProperty"
  }
}

@JLHwung
Copy link
Collaborator Author

JLHwung commented Jun 4, 2023

@fisker Good question. Currently the MetaProperty represents member-expression-like productions: function.sent and import.meta and they are expressions. However import.source() is different as import.source does not exist. If it were a MetaProperty, it will be inconsistent with other meta properties. If we extend Babel's current CallExpression approach for import.source(), we could use

{
  "type": "CallExpression", 
  "callee": {
    "type": "ImportSource"
  }
}

but popular matchers like CallExpression[callee.type = Import] now have to cover a new AST type. In this case, since either way we will need new AST type for import.source(), I think the ImportExpression approach is more compelling than before.

@fisker
Copy link

fisker commented Jun 4, 2023

That's reasonable. 👍

Introduce ImportSource for import.source() seems not a good idea to me, we'll need a new one for import.asset()...

What do you think {ImportExpression,Import}[phase="source" | "asset"]

@JLHwung
Copy link
Collaborator Author

JLHwung commented Jun 7, 2023

What do you think {ImportExpression,Import}[phase="source" | "asset"]?

@fisker The Babel AST of import phase will follow the ESTree proposal here. It will be built on top of the ImportExpression AST. Eventually we will phase out the current CallExpression(Import) model.

@nicolo-ribaudo
Copy link
Member

@JLHwung Can we enable the new mode by default for Babel 8, and then merge this RFC?

@nicolo-ribaudo
Copy link
Member

This is enabled by default in Babel 8 🎉

@nicolo-ribaudo nicolo-ribaudo changed the title Add ImportExpression AST type RFC 0004: Add ImportExpression AST type May 2, 2024
@nicolo-ribaudo nicolo-ribaudo merged commit f4ea1ed into babel:main May 2, 2024
@suchipi
Copy link
Member

suchipi commented May 3, 2024

Woo! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants