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`] = `
|
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';
|
"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>")
|
const t0 = _template("<div></div>")
|
||||||
|
|
|
@ -268,4 +268,18 @@ describe('compile', () => {
|
||||||
expect(code).matchSnapshot()
|
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 {
|
export class CodegenContext {
|
||||||
options: Required<CodegenOptions>
|
options: Required<CodegenOptions>
|
||||||
|
|
||||||
helpers: Set<string> = new Set<string>([])
|
bindingNames: Set<string> = new Set<string>()
|
||||||
|
|
||||||
helper = (name: CoreHelper | VaporHelper) => {
|
helpers: Map<string, string> = new Map()
|
||||||
this.helpers.add(name)
|
|
||||||
return `_${name}`
|
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>()
|
delegates: Set<string> = new Set<string>()
|
||||||
|
@ -90,6 +110,11 @@ export class CodegenContext {
|
||||||
}
|
}
|
||||||
this.options = extend(defaultOptions, options)
|
this.options = extend(defaultOptions, options)
|
||||||
this.block = ir.block
|
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 {
|
): VaporCodegenResult {
|
||||||
const [frag, push] = buildCodeFragment()
|
const [frag, push] = buildCodeFragment()
|
||||||
const context = new CodegenContext(ir, options)
|
const context = new CodegenContext(ir, options)
|
||||||
const { helpers } = context
|
|
||||||
const { inline, bindingMetadata } = options
|
const { inline, bindingMetadata } = options
|
||||||
const functionName = 'render'
|
const functionName = 'render'
|
||||||
|
|
||||||
|
@ -156,7 +180,7 @@ export function generate(
|
||||||
ast: ir,
|
ast: ir,
|
||||||
preamble,
|
preamble,
|
||||||
map: map && map.toJSON(),
|
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 = ''
|
let imports = ''
|
||||||
if (helpers.size) {
|
if (helpers.size) {
|
||||||
imports += `import { ${[...helpers]
|
imports += `import { ${Array.from(helpers)
|
||||||
.map(h => `${h} as _${h}`)
|
.map(([h, alias]) => `${h} as ${alias}`)
|
||||||
.join(', ')} } from '${options.runtimeModuleName}';\n`
|
.join(', ')} } from '${options.runtimeModuleName}';\n`
|
||||||
}
|
}
|
||||||
return imports
|
return imports
|
||||||
|
|
Loading…
Reference in New Issue