From fbd0fe97595f759e12e445c713b732775589fabf Mon Sep 17 00:00:00 2001 From: Evan You Date: Sat, 11 Dec 2021 18:28:03 +0800 Subject: [PATCH] feat(reactivity-transform): support optionally importing macros --- .../__snapshots__/refTransform.spec.ts.snap | 12 +++ .../__tests__/refTransform.spec.ts | 16 ++++ packages/ref-transform/src/refTransform.ts | 79 +++++++++++++------ 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/packages/ref-transform/__tests__/__snapshots__/refTransform.spec.ts.snap b/packages/ref-transform/__tests__/__snapshots__/refTransform.spec.ts.snap index 5253bcce198..b120724ff6a 100644 --- a/packages/ref-transform/__tests__/__snapshots__/refTransform.spec.ts.snap +++ b/packages/ref-transform/__tests__/__snapshots__/refTransform.spec.ts.snap @@ -80,6 +80,18 @@ exports[`handle TS casting syntax 1`] = ` " `; +exports[`macro import alias and removal 1`] = ` +"import { ref as _ref, toRef as _toRef } from 'vue' + + + + let a = _ref(1) + const __$temp_1 = (useMouse()), + x = _toRef(__$temp_1, 'x'), + y = _toRef(__$temp_1, 'y') + " +`; + exports[`mixing $ref & $computed declarations 1`] = ` "import { ref as _ref, computed as _computed } from 'vue' diff --git a/packages/ref-transform/__tests__/refTransform.spec.ts b/packages/ref-transform/__tests__/refTransform.spec.ts index 712a234027a..5fffcd5d6d2 100644 --- a/packages/ref-transform/__tests__/refTransform.spec.ts +++ b/packages/ref-transform/__tests__/refTransform.spec.ts @@ -362,6 +362,22 @@ test('handle TS casting syntax', () => { assertCode(code) }) +test('macro import alias and removal', () => { + const { code } = transform( + ` + import { $ as fromRefs, $ref } from 'vue/macros' + + let a = $ref(1) + const { x, y } = fromRefs(useMouse()) + ` + ) + // should remove imports + expect(code).not.toMatch(`from 'vue/macros'`) + expect(code).toMatch(`let a = _ref(1)`) + expect(code).toMatch(`const __$temp_1 = (useMouse())`) + assertCode(code) +}) + describe('errors', () => { test('$ref w/ destructure', () => { expect(() => transform(`let { a } = $ref(1)`)).toThrow( diff --git a/packages/ref-transform/src/refTransform.ts b/packages/ref-transform/src/refTransform.ts index 1acdca74d1c..6a94f3b58a5 100644 --- a/packages/ref-transform/src/refTransform.ts +++ b/packages/ref-transform/src/refTransform.ts @@ -22,7 +22,7 @@ import { import { parse, ParserPlugin } from '@babel/parser' import { hasOwn, isArray, isString } from '@vue/shared' -const TO_VAR_SYMBOL = '$' +const CONVERT_SYMBOL = '$' const ESCAPE_SYMBOL = '$$' const shorthands = ['ref', 'computed', 'shallowRef', 'toRef', 'customRef'] const transformCheckRE = /[^\w]\$(?:\$|ref|computed|shallowRef)?\s*(\(|\<)/ @@ -114,10 +114,44 @@ export function transformAST( // TODO remove when out of experimental warnExperimental() + let convertSymbol = CONVERT_SYMBOL + let escapeSymbol = ESCAPE_SYMBOL + + // macro import handling + for (const node of ast.body) { + if ( + node.type === 'ImportDeclaration' && + node.source.value === 'vue/macros' + ) { + // remove macro imports + s.remove(node.start! + offset, node.end! + offset) + // check aliasing + for (const specifier of node.specifiers) { + if (specifier.type === 'ImportSpecifier') { + const imported = (specifier.imported as Identifier).name + const local = specifier.local.name + if (local !== imported) { + if (imported === ESCAPE_SYMBOL) { + escapeSymbol = local + } else if (imported === CONVERT_SYMBOL) { + convertSymbol = local + } else { + error( + `macro imports for ref-creating methods do not support aliasing.`, + specifier + ) + } + } + } + } + } + } + const importedHelpers = new Set() const rootScope: Scope = {} const scopeStack: Scope[] = [rootScope] let currentScope: Scope = rootScope + let escapeScope: CallExpression | undefined // inside $$() const excludedIds = new WeakSet() const parentStack: Node[] = [] const propsLocalToPublicMap = Object.create(null) @@ -135,6 +169,16 @@ export function transformAST( } } + function isRefCreationCall(callee: string): string | false { + if (callee === convertSymbol) { + return convertSymbol + } + if (callee[0] === '$' && shorthands.includes(callee.slice(1))) { + return callee + } + return false + } + function error(msg: string, node: Node) { const e = new Error(msg) ;(e as any).node = node @@ -174,20 +218,16 @@ export function transformAST( if (stmt.type === 'VariableDeclaration') { if (stmt.declare) continue for (const decl of stmt.declarations) { - let toVarCall + let refCall const isCall = decl.init && decl.init.type === 'CallExpression' && decl.init.callee.type === 'Identifier' if ( isCall && - (toVarCall = isToVarCall((decl as any).init.callee.name)) + (refCall = isRefCreationCall((decl as any).init.callee.name)) ) { - processRefDeclaration( - toVarCall, - decl.id, - decl.init as CallExpression - ) + processRefDeclaration(refCall, decl.id, decl.init as CallExpression) } else { const isProps = isRoot && @@ -220,7 +260,7 @@ export function transformAST( call: CallExpression ) { excludedIds.add(call.callee as Identifier) - if (method === TO_VAR_SYMBOL) { + if (method === convertSymbol) { // $ // remove macro s.remove(call.callee.start! + offset, call.callee.end! + offset) @@ -491,9 +531,6 @@ export function transformAST( // check root scope first walkScope(ast, true) - - // inside $$() - let escapeScope: CallExpression | undefined ;(walk as any)(ast, { enter(node: Node, parent?: Node) { parent && parentStack.push(parent) @@ -544,16 +581,16 @@ export function transformAST( if (node.type === 'CallExpression' && node.callee.type === 'Identifier') { const callee = node.callee.name - const toVarCall = isToVarCall(callee) - if (toVarCall && (!parent || parent.type !== 'VariableDeclarator')) { + const refCall = isRefCreationCall(callee) + if (refCall && (!parent || parent.type !== 'VariableDeclarator')) { return error( - `${toVarCall} can only be used as the initializer of ` + + `${refCall} can only be used as the initializer of ` + `a variable declaration.`, node ) } - if (callee === ESCAPE_SYMBOL) { + if (callee === escapeSymbol) { s.remove(node.callee.start! + offset, node.callee.end! + offset) escapeScope = node } @@ -596,16 +633,6 @@ export function transformAST( } } -function isToVarCall(callee: string): string | false { - if (callee === TO_VAR_SYMBOL) { - return TO_VAR_SYMBOL - } - if (callee[0] === TO_VAR_SYMBOL && shorthands.includes(callee.slice(1))) { - return callee - } - return false -} - const RFC_LINK = `https://github.com/vuejs/rfcs/discussions/369` const hasWarned: Record = {}