]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): support `export { default } from '...'` (#5937)
author小刘(liulinboyi) <814921718@qq.com>
Wed, 18 May 2022 23:51:44 +0000 (07:51 +0800)
committerGitHub <noreply@github.com>
Wed, 18 May 2022 23:51:44 +0000 (19:51 -0400)
fix #5935

packages/compiler-sfc/__tests__/rewriteDefault.spec.ts
packages/compiler-sfc/src/rewriteDefault.ts

index d44eeca0210dfce81b64e2dc689bf436927f48c6..ce198fbc23623729e18aa17f176f4dfc2b4bb8c6 100644 (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 () => {
index f4b2f2e87ae889e0e5000d991dccb4a1b5166ed9..53db1798b727c0941979819ce0353e98a99f2fd4 100644 (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
+}