Skip to content

Commit

Permalink
refactor(compiler-core): make ast.helpers a Set (vuejs#6774)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz authored and zhangzhonghe committed Apr 12, 2023
1 parent a404681 commit 2d810ab
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 107 deletions.
162 changes: 81 additions & 81 deletions packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions packages/compiler-core/__tests__/codegen.spec.ts
Expand Up @@ -41,7 +41,7 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
return {
type: NodeTypes.ROOT,
children: [],
helpers: [],
helpers: new Set(),
components: [],
directives: [],
imports: [],
Expand All @@ -57,7 +57,7 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
describe('compiler: codegen', () => {
test('module mode preamble', () => {
const root = createRoot({
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
})
const { code } = generate(root, { mode: 'module' })
expect(code).toMatch(
Expand All @@ -68,7 +68,7 @@ describe('compiler: codegen', () => {

test('module mode preamble w/ optimizeImports: true', () => {
const root = createRoot({
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
})
const { code } = generate(root, { mode: 'module', optimizeImports: true })
expect(code).toMatch(
Expand All @@ -82,7 +82,7 @@ describe('compiler: codegen', () => {

test('function mode preamble', () => {
const root = createRoot({
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
})
const { code } = generate(root, { mode: 'function' })
expect(code).toMatch(`const _Vue = Vue`)
Expand All @@ -94,7 +94,7 @@ describe('compiler: codegen', () => {

test('function mode preamble w/ prefixIdentifiers: true', () => {
const root = createRoot({
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
})
const { code } = generate(root, {
mode: 'function',
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-core/src/ast.ts
Expand Up @@ -100,7 +100,7 @@ export type TemplateChildNode =
export interface RootNode extends Node {
type: NodeTypes.ROOT
children: TemplateChildNode[]
helpers: symbol[]
helpers: Set<symbol>
components: string[]
directives: string[]
hoists: (JSChildNode | null)[]
Expand Down Expand Up @@ -556,7 +556,7 @@ export function createRoot(
return {
type: NodeTypes.ROOT,
children,
helpers: [],
helpers: new Set(),
components: [],
directives: [],
hoists: [],
Expand Down
26 changes: 14 additions & 12 deletions packages/compiler-core/src/codegen.ts
Expand Up @@ -208,7 +208,8 @@ export function generate(
ssr
} = context

const hasHelpers = ast.helpers.length > 0
const helpers = Array.from(ast.helpers)
const hasHelpers = helpers.length > 0
const useWithBlock = !prefixIdentifiers && mode !== 'module'
const genScopeId = !__BROWSER__ && scopeId != null && mode === 'module'
const isSetupInlined = !__BROWSER__ && !!options.inline
Expand Down Expand Up @@ -249,7 +250,7 @@ export function generate(
// function mode const declarations should be inside with block
// also they should be renamed to avoid collision with user properties
if (hasHelpers) {
push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = _Vue`)
push(`const { ${helpers.map(aliasHelper).join(', ')} } = _Vue`)
push(`\n`)
newline()
}
Expand Down Expand Up @@ -330,11 +331,10 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
// In prefix mode, we place the const declaration at top so it's done
// only once; But if we not prefixing, we place the declaration inside the
// with block so it doesn't incur the `in` check cost for every helper access.
if (ast.helpers.length > 0) {
const helpers = Array.from(ast.helpers)
if (helpers.length > 0) {
if (!__BROWSER__ && prefixIdentifiers) {
push(
`const { ${ast.helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`
)
push(`const { ${helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`)
} else {
// "with" mode.
// save Vue in a separate variable to avoid collision
Expand All @@ -350,7 +350,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
CREATE_TEXT,
CREATE_STATIC
]
.filter(helper => ast.helpers.includes(helper))
.filter(helper => helpers.includes(helper))
.map(aliasHelper)
.join(', ')
push(`const { ${staticHelpers} } = _Vue\n`)
Expand Down Expand Up @@ -386,30 +386,32 @@ function genModulePreamble(
} = context

if (genScopeId && ast.hoists.length) {
ast.helpers.push(PUSH_SCOPE_ID, POP_SCOPE_ID)
ast.helpers.add(PUSH_SCOPE_ID)
ast.helpers.add(POP_SCOPE_ID)
}

// generate import statements for helpers
if (ast.helpers.length) {
if (ast.helpers.size) {
const helpers = Array.from(ast.helpers)
if (optimizeImports) {
// when bundled with webpack with code-split, calling an import binding
// as a function leads to it being wrapped with `Object(a.b)` or `(0,a.b)`,
// incurring both payload size increase and potential perf overhead.
// therefore we assign the imports to variables (which is a constant ~50b
// cost per-component instead of scaling with template size)
push(
`import { ${ast.helpers
`import { ${helpers
.map(s => helperNameMap[s])
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`
)
push(
`\n// Binding optimization for webpack code-split\nconst ${ast.helpers
`\n// Binding optimization for webpack code-split\nconst ${helpers
.map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)
.join(', ')}\n`
)
} else {
push(
`import { ${ast.helpers
`import { ${helpers
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`
)
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-core/src/transform.ts
Expand Up @@ -324,7 +324,7 @@ export function transform(root: RootNode, options: TransformOptions) {
createRootCodegen(root, context)
}
// finalize meta information
root.helpers = [...context.helpers.keys()]
root.helpers = new Set([...context.helpers.keys()])
root.components = [...context.components]
root.directives = [...context.directives]
root.imports = context.imports
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/compileScript.ts
Expand Up @@ -1561,7 +1561,7 @@ export function compileScript(
// avoid duplicated unref import
// as this may get injected by the render function preamble OR the
// css vars codegen
if (ast && ast.helpers.includes(UNREF)) {
if (ast && ast.helpers.has(UNREF)) {
helperImports.delete('unref')
}
returned = code
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-ssr/__tests__/ssrInjectCssVars.spec.ts
Expand Up @@ -127,10 +127,10 @@ describe('ssr: inject <style vars>', () => {
}"
`)
expect(result.ast.helpers).toMatchInlineSnapshot(`
Array [
Set {
Symbol(mergeProps),
Symbol(unref),
]
}
`)
})
})
9 changes: 6 additions & 3 deletions packages/compiler-ssr/src/ssrCodegenTransform.ts
Expand Up @@ -49,7 +49,7 @@ export function ssrCodegenTransform(ast: RootNode, options: CompilerOptions) {
createCompoundExpression([`const _cssVars = { style: `, varsExp, `}`])
)
Array.from(cssContext.helpers.keys()).forEach(helper => {
if (!ast.helpers.includes(helper)) ast.helpers.push(helper)
ast.helpers.add(helper)
})
}

Expand All @@ -61,10 +61,13 @@ export function ssrCodegenTransform(ast: RootNode, options: CompilerOptions) {
// Finalize helpers.
// We need to separate helpers imported from 'vue' vs. '@vue/server-renderer'
ast.ssrHelpers = Array.from(
new Set([...ast.helpers.filter(h => h in ssrHelpers), ...context.helpers])
new Set([
...Array.from(ast.helpers).filter(h => h in ssrHelpers),
...context.helpers
])
)

ast.helpers = ast.helpers.filter(h => !(h in ssrHelpers))
ast.helpers = new Set(Array.from(ast.helpers).filter(h => !(h in ssrHelpers)))
}

export type SSRTransformContext = ReturnType<typeof createSSRTransformContext>
Expand Down

0 comments on commit 2d810ab

Please sign in to comment.