fix(compiler-sfc): support export { default } from '...' (#5937)

fix #5935
This commit is contained in:
小刘(liulinboyi) 2022-05-19 07:51:44 +08:00 committed by GitHub
parent 991d62322f
commit 73e6523134
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 131 additions and 9 deletions

View File

@ -25,6 +25,17 @@ describe('compiler sfc: rewriteDefault', () => {
export { a as b, a as c}
const script = a"
`)
expect(
rewriteDefault(
`const a = 1 \n export { a as b, a as default , a as c}`,
'script'
)
).toMatchInlineSnapshot(`
"const a = 1
export { a as b, a as c}
const script = a"
`)
})
test('w/ comments', async () => {
@ -63,6 +74,81 @@ describe('compiler sfc: rewriteDefault', () => {
// export { myFunction as default }
const script = a"
`)
expect(
rewriteDefault(
`const a = 1 \n export {\n a as b,\n a as default ,\n a as c}\n` +
`// export { myFunction as default }`,
'script'
)
).toMatchInlineSnapshot(`
"const a = 1
export {
a as b,
a as c}
// export { myFunction as default }
const script = a"
`)
})
test(`export { default } from '...'`, async () => {
expect(
rewriteDefault(`export { default, foo } from './index.js'`, 'script')
).toMatchInlineSnapshot(`
"import { default as __VUE_DEFAULT__ } from './index.js'
export { foo } from './index.js'
const script = __VUE_DEFAULT__"
`)
expect(
rewriteDefault(`export { default , foo } from './index.js'`, 'script')
).toMatchInlineSnapshot(`
"import { default as __VUE_DEFAULT__ } from './index.js'
export { foo } from './index.js'
const script = __VUE_DEFAULT__"
`)
expect(
rewriteDefault(`export { foo, default } from './index.js'`, 'script')
).toMatchInlineSnapshot(`
"import { default as __VUE_DEFAULT__ } from './index.js'
export { foo, } from './index.js'
const script = __VUE_DEFAULT__"
`)
expect(
rewriteDefault(
`export { foo as default, bar } from './index.js'`,
'script'
)
).toMatchInlineSnapshot(`
"import { foo } from './index.js'
export { bar } from './index.js'
const script = foo"
`)
expect(
rewriteDefault(
`export { foo as default , bar } from './index.js'`,
'script'
)
).toMatchInlineSnapshot(`
"import { foo } from './index.js'
export { bar } from './index.js'
const script = foo"
`)
expect(
rewriteDefault(
`export { bar, foo as default } from './index.js'`,
'script'
)
).toMatchInlineSnapshot(`
"import { foo } from './index.js'
export { bar, } from './index.js'
const script = foo"
`)
})
test('export default class', async () => {

View File

@ -2,7 +2,7 @@ import { parse, ParserPlugin } from '@babel/parser'
import MagicString from 'magic-string'
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/s
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)(?:as)?(\s*)default/s
const exportDefaultClassRE =
/((?:^|\n|;)\s*)export\s+default\s+class\s+([\w$]+)/
@ -45,21 +45,39 @@ export function rewriteDefault(
s.overwrite(node.start!, node.declaration.start!, `const ${as} = `)
}
if (node.type === 'ExportNamedDeclaration') {
node.specifiers.forEach(specifier => {
for (const specifier of node.specifiers) {
if (
specifier.type === 'ExportSpecifier' &&
specifier.exported.type === 'Identifier' &&
specifier.exported.name === 'default'
) {
const end = specifier.end!
s.overwrite(
specifier.start!,
input.charAt(end) === ',' ? end + 1 : end,
``
)
if (node.source) {
if (specifier.local.name === 'default') {
const end = specifierEnd(input, specifier.local.end!, node.end)
s.prepend(
`import { default as __VUE_DEFAULT__ } from '${node.source.value}'\n`
)
s.overwrite(specifier.start!, end, ``)
s.append(`\nconst ${as} = __VUE_DEFAULT__`)
continue
} else {
const end = specifierEnd(input, specifier.exported.end!, node.end)
s.prepend(
`import { ${input.slice(
specifier.local.start!,
specifier.local.end!
)} } from '${node.source?.value}'\n`
)
s.overwrite(specifier.start!, end, ``)
s.append(`\nconst ${as} = ${specifier.local.name}`)
continue
}
}
const end = specifierEnd(input, specifier.end!, node.end)
s.overwrite(specifier.start!, end, ``)
s.append(`\nconst ${as} = ${specifier.local.name}`)
}
})
}
}
})
return s.toString()
@ -68,3 +86,21 @@ export function rewriteDefault(
export function hasDefaultExport(input: string): boolean {
return defaultExportRE.test(input) || namedDefaultExportRE.test(input)
}
function specifierEnd(input: string, end: number, nodeEnd: number | null) {
// export { default , foo } ...
let hasCommas = false
let oldEnd = end
while (end < nodeEnd!) {
if (/\s/.test(input.charAt(end))) {
end++
} else if (input.charAt(end) === ',') {
end++
hasCommas = true
break
} else if (input.charAt(end) === '}') {
break
}
}
return hasCommas ? end : oldEnd
}