-
-
Notifications
You must be signed in to change notification settings - Fork 258
[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%)
|
@@ -300,7 +300,8 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) { | |||
let node = this.startNodeAt(startPos, startLoc); | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's probably a good idea, I can rework this to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@loganfsmyth Alright I updated the code to do that. Ended up being a pretty clean solution! Thanks for the recommendation.
@@ -394,6 +404,7 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this isn't needed now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, good catch! Fixed.
break; | ||
} else { | ||
this.state = state; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wondered that too, good question, curious to see what others think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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... |
@@ -385,6 +385,16 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { | |||
} | |||
return this.finishNode(node, "Super"); | |||
|
|||
case tt._import: | |||
if (!this.hasPlugin("importFunctions")) this.unexpected(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can do a
this.unexpected(null, `Unexpected token, expected (`);
https://github.com/babel/babylon/pull/150/files#diff-51a873a9697282bed0c15722a6ccf4e6R77
not sure if you can just use this.expect instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we can use #172
to do this.unexpected(null, tt.parenL);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add this to #172 after this lands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in #177.
There's a new stage-2 proposal that adds a new special
import()
function. This implements the syntax behind aimportFunctions
plugin.Here's the proposal: https://github.com/domenic/proposal-import-function
cc: @domenic