Skip to content

Commit

Permalink
fix: 🐛 parse import specifier with keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
TyrealHu committed Oct 9, 2023
1 parent 3dfd46d commit 91a27a9
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 19 deletions.
94 changes: 94 additions & 0 deletions __test__/__snapshot__/import/normal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,100 @@ const NormalImportSnapshot = {
}
],
'sourceType': 'module'
},
Issue45: {
'type': 'Program',
'start': 0,
'end': 31,
'loc': {
'start': {
'line': 1,
'column': 0,
'index': 0
},
'end': {
'line': 1,
'column': 31,
'index': 31
}
},
'body': [
{
'type': 'ImportDeclaration',
'start': 0,
'end': 31,
'loc': {
'start': {
'line': 1,
'column': 0,
'index': 0
},
'end': {
'line': 1,
'column': 31,
'index': 31
}
},
'importKind': 'value',
'specifiers': [
{
'type': 'ImportDefaultSpecifier',
'start': 7,
'end': 13,
'loc': {
'start': {
'line': 1,
'column': 7,
'index': 7
},
'end': {
'line': 1,
'column': 13,
'index': 13
}
},
'local': {
'type': 'Identifier',
'start': 7,
'end': 13,
'loc': {
'start': {
'line': 1,
'column': 7,
'index': 7
},
'end': {
'line': 1,
'column': 13,
'index': 13
}
},
'name': 'assert'
}
}
],
'source': {
'type': 'Literal',
'start': 19,
'end': 31,
'loc': {
'start': {
'line': 1,
'column': 19,
'index': 19
},
'end': {
'line': 1,
'column': 31,
'index': 31
}
},
'value': './index.js',
'raw': '\'./index.js\''
}
}
],
'sourceType': 'module'
}
}

Expand Down
8 changes: 8 additions & 0 deletions __test__/import/normal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,12 @@ describe('normal syntax', () => {

equalNode(node, NormalImportSnapshot.ImportTypeSpecifierWithAsAsSomethings)
})

it('issue 45', function() {
const node = parseSource(generateSource([
`import assert from './index.js'`,
]))

equalNode(node, NormalImportSnapshot.Issue45)
})
})
60 changes: 41 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3049,6 +3049,28 @@ function tsPlugin(options?: {
return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec, forInit)
}

parseImportSpecifiers() {
let nodes = [], first = true
if (acornTypeScript.tokenIsIdentifier(this.type)) {
nodes.push(this.parseImportDefaultSpecifier())
if (!this.eat(tt.comma)) return nodes
}
if (this.type === tt.star) {
nodes.push(this.parseImportNamespaceSpecifier())
return nodes
}
this.expect(tt.braceL)
while (!this.eat(tt.braceR)) {
if (!first) {
this.expect(tt.comma)
if (this.afterTrailingComma(tt.braceR)) break
} else first = false

nodes.push(this.parseImportSpecifier())
}
return nodes
}

/**
* @param {Node} node this may be ImportDeclaration |
* TsImportEqualsDeclaration
Expand Down Expand Up @@ -3144,45 +3166,45 @@ function tsPlugin(options?: {

parseExportAllDeclaration(node, exports) {
if (this.options.ecmaVersion >= 11) {
if (this.eatContextual("as")) {
if (this.eatContextual('as')) {
node.exported = this.parseModuleExportName()
this.checkExport(exports, node.exported, this.lastTokStart)
} else {
node.exported = null
}
}
this.expectContextual("from")
this.expectContextual('from')
if (this.type !== tt.string) this.unexpected()
node.source = this.parseExprAtom()

this.parseMaybeImportAttributes(node)

this.semicolon()
return this.finishNode(node, "ExportAllDeclaration")
return this.finishNode(node, 'ExportAllDeclaration')
}

parseDynamicImport(node) {
this.next(); // skip `(`
this.next() // skip `(`

// Parse node.source.
node.source = this.parseMaybeAssign();
node.source = this.parseMaybeAssign()

if (this.eat(tt.comma)) {
const expr = this.parseExpression();
node.arguments = [expr];
const expr = this.parseExpression()
node.arguments = [expr]
}

// Verify ending.
if (!this.eat(tt.parenR)) {
const errorPos = this.start;
const errorPos = this.start
if (this.eat(tt.comma) && this.eat(tt.parenR)) {
this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
this.raiseRecoverable(errorPos, 'Trailing comma is not allowed in import()')
} else {
this.unexpected(errorPos);
this.unexpected(errorPos)
}
}

return this.finishNode(node, "ImportExpression")
return this.finishNode(node, 'ImportExpression')
}

parseExport(node: any, exports: any): any {
Expand Down Expand Up @@ -3241,14 +3263,14 @@ function tsPlugin(options?: {
return this.parseExportAllDeclaration(node, exports)
}
if (this.eat(tt._default)) { // export default ...
this.checkExport(exports, "default", this.lastTokStart)
this.checkExport(exports, 'default', this.lastTokStart)
node.declaration = this.parseExportDefaultDeclaration()
return this.finishNode(node, "ExportDefaultDeclaration")
return this.finishNode(node, 'ExportDefaultDeclaration')
}
// export var|const|let|function|class ...
if (this.shouldParseExportStatement()) {
node.declaration = this.parseExportDeclaration(node)
if (node.declaration.type === "VariableDeclaration")
if (node.declaration.type === 'VariableDeclaration')
this.checkVariableExport(exports, node.declaration.declarations)
else
this.checkExport(exports, node.declaration.id, node.declaration.id.start)
Expand All @@ -3257,7 +3279,7 @@ function tsPlugin(options?: {
} else { // export { x, y as z } [from '...']
node.declaration = null
node.specifiers = this.parseExportSpecifiers(exports)
if (this.eatContextual("from")) {
if (this.eatContextual('from')) {
if (this.type !== tt.string) this.unexpected()
node.source = this.parseExprAtom()

Expand All @@ -3269,16 +3291,16 @@ function tsPlugin(options?: {
// check if export is defined
this.checkLocalExport(spec.local)

if (spec.local.type === "Literal") {
this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`.")
if (spec.local.type === 'Literal') {
this.raise(spec.local.start, 'A string literal cannot be used as an exported binding without `from`.')
}
}

node.source = null
}
this.semicolon()
}
return this.finishNode(node, "ExportNamedDeclaration")
return this.finishNode(node, 'ExportNamedDeclaration')
// end
}
}
Expand Down Expand Up @@ -4394,7 +4416,7 @@ function tsPlugin(options?: {
}
return super.toAssignable(node, isBinding, refDestructuringErrors)
case 'TSTypeCastExpression': {
return this.typeCastToParameter(node);
return this.typeCastToParameter(node)
}
default:
return super.toAssignable(node, isBinding, refDestructuringErrors)
Expand Down
4 changes: 4 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ export declare class AcornParseClass extends Parser {

parseImportSpecifiers(): any

parseImportDefaultSpecifier(): any

parseImportNamespaceSpecifier(): any

parseImportAttributes(): any

parseMaybeImportAttributes(node: any): any
Expand Down

0 comments on commit 91a27a9

Please sign in to comment.