[dynamic-import] Implementing import() syntax#163
Conversation
|
Thanks so much for working on this; this'll be very helpful. As a nit, I think it might be better to name it importFunctionLike so people don't get the wrong idea. It's more like super() than it is like a function. I'll probably rename the proposal repo similarly (tc39/proposal-dynamic-import#14). |
|
Yeah I thought about that working on this, that's probably not a bad idea. I'm also not 💯 on |
Current coverage is 94.46% (diff: 90.00%)
|
| node.callee = base; | ||
| node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync); | ||
| base = this.finishNode(node, "CallExpression"); | ||
| base = this.finishNode(node, this.state.inImportCall ? "ImportCallExpression" : "CallExpression"); |
There was a problem hiding this comment.
Perhaps we'd be better off having this be its own node type, like super? super() for instance is just a normal CallExpression with callee being a Super node. Should we introduce an Import node as well?
There was a problem hiding this comment.
That's probably a good idea, I can rework this to do that.
There was a problem hiding this comment.
@loganfsmyth Alright I updated the code to do that. Ended up being a pretty clean solution! Thanks for the recommendation.
| if (this.state.inGenerator) this.unexpected(); | ||
|
|
||
| case tt.name: | ||
| if (!this.hasPlugin("importFunctions") && this.state.type === tt._import) this.unexpected(); |
There was a problem hiding this comment.
Looks like this isn't needed now?
There was a problem hiding this comment.
Yep, good catch! Fixed.
| break; | ||
| } else { | ||
| this.state = state; | ||
| } |
There was a problem hiding this comment.
I think this can be simplified to this, though I'm not an expert on Babylon.
if (this.hasPlugin("importFunctions") && this.lookahead().type === tt.parenL) break;
There was a problem hiding this comment.
Yep, looks like that handles this use-case perfectly.
|
Is it a good idea to ensure in the tests that it parses in both sloppy and strict mode, and in Scripts and Modules? |
|
@ljharb Not a bad idea. I can also add a test case for calling in module mode (right now I just run in script mode and assume that if it passes in script, it passes in module). EDIT: Added both of those cases! |
|
|
||
| node = this.startNode(); | ||
| this.next(); | ||
| if (!this.match(tt.parenL)) { |
There was a problem hiding this comment.
It looks like this case can never be hit, because the parser runs through statements first, and would throw unexpected trying to parse the import function.
Should I remove it knowing that, or keep it for safety?
There was a problem hiding this comment.
I wondered that too, good question, curious to see what others think.
There was a problem hiding this comment.
Also codecoverage says we never hit this block, but as we do the same for super maybe be consistent and leave it here?
There was a problem hiding this comment.
I figured out that this can be hit if you do something that parses as an expression first. For example, inside of a function return import.fails() hits this case.
I've added a test for this case to prevent any regressions and to bump the code coverage.
|
|
||
| node = this.startNode(); | ||
| this.next(); | ||
| if (!this.match(tt.parenL)) { |
There was a problem hiding this comment.
Also codecoverage says we never hit this block, but as we do the same for super maybe be consistent and leave it here?
|
@domenic Considering this: tc39/proposal-dynamic-import#15 do you think that we should enforce the single argument syntax in the parser now? |
|
Yeah, that's probably a good idea... not sure what the spec grammar will look like yet, which might impact your AST... |
| return this.finishNode(node, "Super"); | ||
|
|
||
| case tt._import: | ||
| if (!this.hasPlugin("importFunctions")) this.unexpected(); |
There was a problem hiding this comment.
Doesn't have to be done in this PR since it's a separate issue but we should make a better error message here (whenever we have a this.hasPlugin()
There was a problem hiding this comment.
I agree that would be nice. I did this because it seems like this is how the rest of the plugins handle it.
There was a problem hiding this comment.
Yeah it's totally fine just a note so I don't forget - I can just make an actual issue
|
Alright, I added a check to the arguments which fails parse on more than one argument. The only remaining line that I don't have code coverage for is the check for the plugin in expressions. If you folks think that'd be good to have I can do that. |
|
Updates from the spec side:
Exciting! |
|
I renamed the plugin |
|
Is there anything else that I can do to help get this out? |
|
Kind of trivial but maybe a test that we can do it later |
| node = this.startNode(); | ||
| this.next(); | ||
| if (!this.match(tt.parenL)) { | ||
| this.unexpected(); |
There was a problem hiding this comment.
Maybe we can do a
this.unexpected(null, `Unexpected token, expected (`);
not sure if you can just use this.expect instead
There was a problem hiding this comment.
Actually we can use #172
to do this.unexpected(null, tt.parenL);
There was a problem hiding this comment.
Should we add this to #172 after this lands?
There's a new stage-2 proposal that adds a new special
import()function. This implements the syntax behind aimportFunctionsplugin.Here's the proposal: https://github.com/domenic/proposal-import-function
cc: @domenic