mirror of https://github.com/vuejs/core.git
refactor(compiler-vapor): generate unique helper aliases to prevent collisions with user variables
This commit is contained in:
parent
ea397b7fa5
commit
ad525c43e2
|
@ -280,6 +280,18 @@ export function render(_ctx) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compile > helper alias > should avoid conflicts with existing variable names 1`] = `
|
||||
"import { child as _child2, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
|
||||
const t0 = _template("<div> </div>", true)
|
||||
|
||||
export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||
const n0 = t0()
|
||||
const x0 = _child2(n0)
|
||||
_renderEffect(() => _setText(x0, _toDisplayString(_ctx.foo)))
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compile > setInsertionState > next, child and nthChild should be above the setInsertionState 1`] = `
|
||||
"import { resolveComponent as _resolveComponent, child as _child, next as _next, setInsertionState as _setInsertionState, createComponentWithFallback as _createComponentWithFallback, nthChild as _nthChild, createIf as _createIf, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
|
||||
const t0 = _template("<div></div>")
|
||||
|
|
|
@ -268,4 +268,18 @@ describe('compile', () => {
|
|||
expect(code).matchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('helper alias', () => {
|
||||
test('should avoid conflicts with existing variable names', () => {
|
||||
const code = compile(`<div>{{ foo }}</div>`, {
|
||||
bindingMetadata: {
|
||||
_child: BindingTypes.LITERAL_CONST,
|
||||
_child1: BindingTypes.SETUP_REF,
|
||||
},
|
||||
})
|
||||
expect(code).matchSnapshot()
|
||||
expect(code).contains('child as _child2')
|
||||
expect(code).contains('const x0 = _child2(n0)')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -24,11 +24,31 @@ export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
|
|||
export class CodegenContext {
|
||||
options: Required<CodegenOptions>
|
||||
|
||||
helpers: Set<string> = new Set<string>([])
|
||||
bindingNames: Set<string> = new Set<string>()
|
||||
|
||||
helper = (name: CoreHelper | VaporHelper) => {
|
||||
this.helpers.add(name)
|
||||
return `_${name}`
|
||||
helpers: Map<string, string> = new Map()
|
||||
|
||||
helper = (name: CoreHelper | VaporHelper): string => {
|
||||
if (this.helpers.has(name)) {
|
||||
return this.helpers.get(name)!
|
||||
}
|
||||
|
||||
const base = `_${name}`
|
||||
if (this.bindingNames.size === 0) {
|
||||
this.helpers.set(name, base)
|
||||
return base
|
||||
}
|
||||
|
||||
// check whether an alias is already used bindings
|
||||
let alias = base
|
||||
let i = 0
|
||||
while (this.bindingNames.has(alias)) {
|
||||
i++
|
||||
alias = `${base}${i}`
|
||||
}
|
||||
|
||||
this.helpers.set(name, alias)
|
||||
return alias
|
||||
}
|
||||
|
||||
delegates: Set<string> = new Set<string>()
|
||||
|
@ -90,6 +110,11 @@ export class CodegenContext {
|
|||
}
|
||||
this.options = extend(defaultOptions, options)
|
||||
this.block = ir.block
|
||||
this.bindingNames = new Set<string>(
|
||||
this.options.bindingMetadata
|
||||
? Object.keys(this.options.bindingMetadata)
|
||||
: [],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +130,6 @@ export function generate(
|
|||
): VaporCodegenResult {
|
||||
const [frag, push] = buildCodeFragment()
|
||||
const context = new CodegenContext(ir, options)
|
||||
const { helpers } = context
|
||||
const { inline, bindingMetadata } = options
|
||||
const functionName = 'render'
|
||||
|
||||
|
@ -156,7 +180,7 @@ export function generate(
|
|||
ast: ir,
|
||||
preamble,
|
||||
map: map && map.toJSON(),
|
||||
helpers,
|
||||
helpers: new Set<string>(Array.from(context.helpers.keys())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,11 +193,11 @@ function genDelegates({ delegates, helper }: CodegenContext) {
|
|||
: ''
|
||||
}
|
||||
|
||||
function genHelperImports({ helpers, helper, options }: CodegenContext) {
|
||||
function genHelperImports({ helpers, options }: CodegenContext) {
|
||||
let imports = ''
|
||||
if (helpers.size) {
|
||||
imports += `import { ${[...helpers]
|
||||
.map(h => `${h} as _${h}`)
|
||||
imports += `import { ${Array.from(helpers)
|
||||
.map(([h, alias]) => `${h} as ${alias}`)
|
||||
.join(', ')} } from '${options.runtimeModuleName}';\n`
|
||||
}
|
||||
return imports
|
||||
|
|
Loading…
Reference in New Issue