mirror of https://github.com/vuejs/core.git
fix(reactivity-transform): respect user defined symbols that conflict with macros (#6840)
closes #6838
This commit is contained in:
parent
bad3f3ce46
commit
7663a79a29
|
@ -199,6 +199,27 @@ exports[`object destructure w/ mid-path default values 1`] = `
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`should not overwrite current scope 1`] = `
|
||||
"
|
||||
const fn = () => {
|
||||
const $ = () => 'foo'
|
||||
const $ref = () => 'bar'
|
||||
const $$ = () => 'baz'
|
||||
console.log($())
|
||||
console.log($ref())
|
||||
console.log($$())
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`should not overwrite importing 1`] = `
|
||||
"
|
||||
import { $, $$ } from './foo'
|
||||
$('foo')
|
||||
$$('bar')
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`should not rewrite scope variable 1`] = `
|
||||
"import { ref as _ref } from 'vue'
|
||||
|
||||
|
|
|
@ -416,6 +416,35 @@ test('macro import alias and removal', () => {
|
|||
assertCode(code)
|
||||
})
|
||||
|
||||
// #6838
|
||||
test('should not overwrite importing', () => {
|
||||
const { code } = transform(
|
||||
`
|
||||
import { $, $$ } from './foo'
|
||||
$('foo')
|
||||
$$('bar')
|
||||
`
|
||||
)
|
||||
assertCode(code)
|
||||
})
|
||||
|
||||
// #6838
|
||||
test('should not overwrite current scope', () => {
|
||||
const { code } = transform(
|
||||
`
|
||||
const fn = () => {
|
||||
const $ = () => 'foo'
|
||||
const $ref = () => 'bar'
|
||||
const $$ = () => 'baz'
|
||||
console.log($())
|
||||
console.log($ref())
|
||||
console.log($$())
|
||||
}
|
||||
`
|
||||
)
|
||||
assertCode(code)
|
||||
})
|
||||
|
||||
describe('errors', () => {
|
||||
test('$ref w/ destructure', () => {
|
||||
expect(() => transform(`let { a } = $ref(1)`)).toThrow(
|
||||
|
|
|
@ -8,7 +8,11 @@ import {
|
|||
Program,
|
||||
VariableDeclarator,
|
||||
Expression,
|
||||
VariableDeclaration
|
||||
VariableDeclaration,
|
||||
ImportDeclaration,
|
||||
ImportSpecifier,
|
||||
ImportDefaultSpecifier,
|
||||
ImportNamespaceSpecifier
|
||||
} from '@babel/types'
|
||||
import MagicString, { SourceMap } from 'magic-string'
|
||||
import { walk } from 'estree-walker'
|
||||
|
@ -25,6 +29,7 @@ import { hasOwn, isArray, isString, genPropsAccessExp } from '@vue/shared'
|
|||
|
||||
const CONVERT_SYMBOL = '$'
|
||||
const ESCAPE_SYMBOL = '$$'
|
||||
const IMPORT_SOURCE = 'vue/macros'
|
||||
const shorthands = ['ref', 'computed', 'shallowRef', 'toRef', 'customRef']
|
||||
const transformCheckRE = /[^\w]\$(?:\$|ref|computed|shallowRef)?\s*(\(|\<)/
|
||||
|
||||
|
@ -48,6 +53,13 @@ export interface RefTransformResults {
|
|||
importedHelpers: string[]
|
||||
}
|
||||
|
||||
export interface ImportBinding {
|
||||
local: string
|
||||
imported: string
|
||||
source: string
|
||||
specifier: ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier
|
||||
}
|
||||
|
||||
export function transform(
|
||||
src: string,
|
||||
{
|
||||
|
@ -115,28 +127,24 @@ export function transformAST(
|
|||
// TODO remove when out of experimental
|
||||
warnExperimental()
|
||||
|
||||
let convertSymbol = CONVERT_SYMBOL
|
||||
let escapeSymbol = ESCAPE_SYMBOL
|
||||
const userImports: Record<string, ImportBinding> = Object.create(null)
|
||||
for (const node of ast.body) {
|
||||
if (node.type !== 'ImportDeclaration') continue
|
||||
walkImportDeclaration(node)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
let convertSymbol: string | undefined
|
||||
let escapeSymbol: string | undefined
|
||||
for (const { local, imported, source, specifier } of Object.values(
|
||||
userImports
|
||||
)) {
|
||||
if (source === IMPORT_SOURCE) {
|
||||
if (imported === ESCAPE_SYMBOL) {
|
||||
escapeSymbol = local
|
||||
} else if (imported === CONVERT_SYMBOL) {
|
||||
convertSymbol = local
|
||||
} else {
|
||||
} else if (imported !== local) {
|
||||
error(
|
||||
`macro imports for ref-creating methods do not support aliasing.`,
|
||||
specifier
|
||||
|
@ -144,8 +152,13 @@ export function transformAST(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default symbol
|
||||
if (!convertSymbol && !userImports[CONVERT_SYMBOL]) {
|
||||
convertSymbol = CONVERT_SYMBOL
|
||||
}
|
||||
}
|
||||
if (!escapeSymbol && !userImports[ESCAPE_SYMBOL]) {
|
||||
escapeSymbol = ESCAPE_SYMBOL
|
||||
}
|
||||
|
||||
const importedHelpers = new Set<string>()
|
||||
|
@ -170,7 +183,32 @@ export function transformAST(
|
|||
}
|
||||
}
|
||||
|
||||
function walkImportDeclaration(node: ImportDeclaration) {
|
||||
const source = node.source.value
|
||||
if (source === IMPORT_SOURCE) {
|
||||
s.remove(node.start! + offset, node.end! + offset)
|
||||
}
|
||||
|
||||
for (const specifier of node.specifiers) {
|
||||
const local = specifier.local.name
|
||||
const imported =
|
||||
(specifier.type === 'ImportSpecifier' &&
|
||||
specifier.imported.type === 'Identifier' &&
|
||||
specifier.imported.name) ||
|
||||
'default'
|
||||
userImports[local] = {
|
||||
source,
|
||||
local,
|
||||
imported,
|
||||
specifier
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isRefCreationCall(callee: string): string | false {
|
||||
if (!convertSymbol || currentScope[convertSymbol] !== undefined) {
|
||||
return false
|
||||
}
|
||||
if (callee === convertSymbol) {
|
||||
return convertSymbol
|
||||
}
|
||||
|
@ -628,7 +666,11 @@ export function transformAST(
|
|||
)
|
||||
}
|
||||
|
||||
if (callee === escapeSymbol) {
|
||||
if (
|
||||
escapeSymbol &&
|
||||
currentScope[escapeSymbol] === undefined &&
|
||||
callee === escapeSymbol
|
||||
) {
|
||||
s.remove(node.callee.start! + offset, node.callee.end! + offset)
|
||||
escapeScope = node
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue