Skip to content

Commit b70fa18

Browse files
committed
feat(compiler-sfc): support module string names syntax
tc39/ecma262#2154
1 parent 7def8b1 commit b70fa18

File tree

7 files changed

+77
-20
lines changed

7 files changed

+77
-20
lines changed

packages/compiler-core/src/babelUtils.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import type {
66
Function,
77
ObjectProperty,
88
BlockStatement,
9-
Program
9+
Program,
10+
ImportDefaultSpecifier,
11+
ImportNamespaceSpecifier,
12+
ImportSpecifier
1013
} from '@babel/types'
1114
import { walk } from 'estree-walker'
1215

@@ -245,6 +248,17 @@ export const isStaticProperty = (node: Node): node is ObjectProperty =>
245248
export const isStaticPropertyKey = (node: Node, parent: Node) =>
246249
isStaticProperty(parent) && parent.key === node
247250

251+
export function getImportedName(
252+
specifier: ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier
253+
) {
254+
if (specifier.type === 'ImportSpecifier')
255+
return specifier.imported.type === 'Identifier'
256+
? specifier.imported.name
257+
: specifier.imported.value
258+
else if (specifier.type === 'ImportNamespaceSpecifier') return '*'
259+
return 'default'
260+
}
261+
248262
/**
249263
* Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts
250264
* To avoid runtime dependency on @babel/types (which includes process references)

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,20 @@ return { ref }
991991
}"
992992
`;
993993

994+
exports[`SFC compile <script setup> > imports > should support module string names syntax 1`] = `
995+
"import { \\"😏\\" as foo } from './foo'
996+
997+
export default {
998+
setup(__props, { expose }) {
999+
expose();
1000+
1001+
1002+
return { get foo() { return foo } }
1003+
}
1004+
1005+
}"
1006+
`;
1007+
9941008
exports[`SFC compile <script setup> > inlineTemplate mode > avoid unref() when necessary 1`] = `
9951009
"import { unref as _unref, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, withCtx as _withCtx, createVNode as _createVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
9961010

packages/compiler-sfc/__tests__/compileScript.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,21 @@ defineExpose({ foo: 123 })
471471
})
472472
})
473473
})
474+
475+
test('should support module string names syntax', () => {
476+
const { content, bindings } = compile(`
477+
<script>
478+
import { "😏" as foo } from './foo'
479+
</script>
480+
<script setup>
481+
import { "😏" as foo } from './foo'
482+
</script>
483+
`)
484+
assertCode(content)
485+
expect(bindings).toStrictEqual({
486+
foo: BindingTypes.SETUP_MAYBE_REF
487+
})
488+
})
474489
})
475490

476491
// in dev mode, declared bindings are returned as an object from setup()

packages/compiler-sfc/src/compileScript.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
UNREF,
1010
SimpleExpressionNode,
1111
isFunctionType,
12-
walkIdentifiers
12+
walkIdentifiers,
13+
getImportedName
1314
} from '@vue/compiler-dom'
1415
import { DEFAULT_FILENAME, SFCDescriptor, SFCScriptBlock } from './parse'
1516
import {
@@ -372,7 +373,7 @@ export function compileScript(
372373
function registerUserImport(
373374
source: string,
374375
local: string,
375-
imported: string | false,
376+
imported: string,
376377
isType: boolean,
377378
isFromSetup: boolean,
378379
needTemplateUsageCheck: boolean
@@ -392,7 +393,7 @@ export function compileScript(
392393

393394
userImports[local] = {
394395
isType,
395-
imported: imported || 'default',
396+
imported,
396397
local,
397398
source,
398399
isFromSetup,
@@ -994,10 +995,7 @@ export function compileScript(
994995
if (node.type === 'ImportDeclaration') {
995996
// record imports for dedupe
996997
for (const specifier of node.specifiers) {
997-
const imported =
998-
specifier.type === 'ImportSpecifier' &&
999-
specifier.imported.type === 'Identifier' &&
1000-
specifier.imported.name
998+
const imported = getImportedName(specifier)
1001999
registerUserImport(
10021000
node.source.value,
10031001
specifier.local.name,
@@ -1039,13 +1037,7 @@ export function compileScript(
10391037
for (let i = 0; i < node.specifiers.length; i++) {
10401038
const specifier = node.specifiers[i]
10411039
const local = specifier.local.name
1042-
let imported =
1043-
specifier.type === 'ImportSpecifier' &&
1044-
specifier.imported.type === 'Identifier' &&
1045-
specifier.imported.name
1046-
if (specifier.type === 'ImportNamespaceSpecifier') {
1047-
imported = '*'
1048-
}
1040+
const imported = getImportedName(specifier)
10491041
const source = node.source.value
10501042
const existing = userImports[local]
10511043
if (

packages/reactivity-transform/__tests__/__snapshots__/reactivityTransform.spec.ts.snap

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,15 @@ const props = defineProps<{msg: string; ids?: string[]}>()
280280
let ids = _ref([])"
281281
`;
282282
283+
exports[`should support module string names syntax 1`] = `
284+
"
285+
286+
287+
let a = (ref(0));
288+
console.log((a))
289+
"
290+
`;
291+
283292
exports[`using ref binding in property shorthand 1`] = `
284293
"import { ref as _ref } from 'vue'
285294

packages/reactivity-transform/__tests__/reactivityTransform.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,22 @@ test('macro import alias and removal', () => {
460460
assertCode(code)
461461
})
462462

463+
test('should support module string names syntax', () => {
464+
const { code } = transform(
465+
`
466+
import { "$" as fromRefs, "$$" as escapeRefs } from 'vue/macros'
467+
468+
let a = fromRefs(ref(0));
469+
console.log(escapeRefs(a))
470+
`
471+
)
472+
// should remove imports
473+
expect(code).not.toMatch(`from 'vue/macros'`)
474+
expect(code).toMatch(`let a = (ref(0))`)
475+
expect(code).toMatch(`console.log((a))`)
476+
assertCode(code)
477+
})
478+
463479
// #6838
464480
test('should not overwrite importing', () => {
465481
const { code } = transform(

packages/reactivity-transform/src/reactivityTransform.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import MagicString, { SourceMap } from 'magic-string'
1818
import { walk } from 'estree-walker'
1919
import {
2020
extractIdentifiers,
21+
getImportedName,
2122
isFunctionType,
2223
isInDestructureAssignment,
2324
isReferencedIdentifier,
@@ -198,11 +199,7 @@ export function transformAST(
198199

199200
for (const specifier of node.specifiers) {
200201
const local = specifier.local.name
201-
const imported =
202-
(specifier.type === 'ImportSpecifier' &&
203-
specifier.imported.type === 'Identifier' &&
204-
specifier.imported.name) ||
205-
'default'
202+
const imported = getImportedName(specifier)
206203
userImports[local] = {
207204
source,
208205
local,

0 commit comments

Comments
 (0)