Răsfoiți Sursa

fix(compiler-sfc): fix rewrite named export default (#1675)

underfin 5 ani în urmă
părinte
comite
452edb73cb

+ 29 - 0
packages/compiler-sfc/__tests__/rewriteDefault.spec.ts

@@ -0,0 +1,29 @@
+import { rewriteDefault } from '../src'
+
+describe('compiler sfc: rewriteDefault', () => {
+  test('without export default', () => {
+    expect(rewriteDefault(`export  a = {}`, 'script')).toMatchInlineSnapshot(`
+      "export  a = {}
+      const script = {}"
+    `)
+  })
+
+  test('rewrite export default', () => {
+    expect(
+      rewriteDefault(`export  default {}`, 'script')
+    ).toMatchInlineSnapshot(`"const script = {}"`)
+  })
+
+  test('rewrite export named default', () => {
+    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"
+    `)
+  })
+})

+ 25 - 3
packages/compiler-sfc/src/rewriteDefault.ts

@@ -1,7 +1,8 @@
 import { parse, ParserPlugin } from '@babel/parser'
 import MagicString from 'magic-string'
 
-const defaultExportRE = /((?:^|\n|;)\s*)export default/
+const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
+const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
 
 /**
  * Utility for rewriting `export default` in a script block into a varaible
@@ -12,12 +13,12 @@ export function rewriteDefault(
   as: string,
   parserPlugins?: ParserPlugin[]
 ): string {
-  if (!defaultExportRE.test(input)) {
+  if (!hasDefaultExport(input)) {
     return input + `\nconst ${as} = {}`
   }
 
   const replaced = input.replace(defaultExportRE, `$1const ${as} =`)
-  if (!defaultExportRE.test(replaced)) {
+  if (!hasDefaultExport(replaced)) {
     return replaced
   }
 
@@ -25,12 +26,33 @@ export function rewriteDefault(
   // multi-line comments or template strings. fallback to a full parse.
   const s = new MagicString(input)
   const ast = parse(input, {
+    sourceType: 'module',
     plugins: parserPlugins
   }).program.body
   ast.forEach(node => {
     if (node.type === 'ExportDefaultDeclaration') {
       s.overwrite(node.start!, node.declaration.start!, `const ${as} = `)
     }
+    if (node.type === 'ExportNamedDeclaration') {
+      node.specifiers.forEach(specifier => {
+        if (
+          specifier.type === 'ExportSpecifier' &&
+          specifier.exported.name === 'default'
+        ) {
+          const end = specifier.end!
+          s.overwrite(
+            specifier.start!,
+            input.charAt(end) === ',' ? end + 1 : end,
+            ``
+          )
+          s.append(`\nconst ${as} = ${specifier.local.name}`)
+        }
+      })
+    }
   })
   return s.toString()
 }
+
+export function hasDefaultExport(input: string): boolean {
+  return defaultExportRE.test(input) || namedDefaultExportRE.test(input)
+}