Skip to content

Commit dfe06f8

Browse files
committed
wip: cache setProp prev value on element, simplify codegen
Also separate `setClass`/`setClassIncremental` and `setStyle`/ `setStyleIncremental`
1 parent badd995 commit dfe06f8

File tree

23 files changed

+315
-608
lines changed

23 files changed

+315
-608
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap

+32
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,23 @@ export function render(_ctx) {
330330
}"
331331
`;
332332
333+
exports[`compiler v-bind > MathML global attributes should set as attribute 1`] = `
334+
"import { setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue';
335+
const t0 = _template("<math></math>")
336+
337+
export function render(_ctx) {
338+
const n0 = t0()
339+
_renderEffect(() => {
340+
_setAttr(n0, "autofucus", _ctx.autofucus)
341+
_setAttr(n0, "dir", _ctx.dir)
342+
_setAttr(n0, "displaystyle", _ctx.displaystyle)
343+
_setAttr(n0, "mathcolor", _ctx.mathcolor)
344+
_setAttr(n0, "tabindex", _ctx.tabindex)
345+
})
346+
return n0
347+
}"
348+
`;
349+
333350
exports[`compiler v-bind > MathML global attributes should set as dom prop 1`] = `
334351
"import { setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue';
335352
const t0 = _template("<math></math>")
@@ -348,6 +365,21 @@ export function render(_ctx) {
348365
}"
349366
`;
350367
368+
exports[`compiler v-bind > SVG global attributes should set as attribute 1`] = `
369+
"import { setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue';
370+
const t0 = _template("<svg></svg>")
371+
372+
export function render(_ctx) {
373+
const n0 = t0()
374+
_renderEffect(() => {
375+
_setAttr(n0, "id", _ctx.id)
376+
_setAttr(n0, "lang", _ctx.lang)
377+
_setAttr(n0, "tabindex", _ctx.tabindex)
378+
})
379+
return n0
380+
}"
381+
`;
382+
351383
exports[`compiler v-bind > SVG global attributes should set as dom prop 1`] = `
352384
"import { setDOMProp as _setDOMProp, renderEffect as _renderEffect, template as _template } from 'vue';
353385
const t0 = _template("<svg></svg>")

packages/compiler-vapor/__tests__/transforms/vBind.spec.ts

-63
Original file line numberDiff line numberDiff line change
@@ -686,69 +686,6 @@ describe('compiler v-bind', () => {
686686
expect(code).contains(' _setAttr(n6, "width", _ctx.width)')
687687
})
688688

689-
test('HTML global attributes should set as dom prop', () => {
690-
const { code } = compileWithVBind(`
691-
<div :id="id" :title="title" :lang="lang" :dir="dir" :tabindex="tabindex" />
692-
`)
693-
694-
expect(code).matchSnapshot()
695-
expect(code).contains(
696-
'_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))',
697-
)
698-
expect(code).contains(
699-
'_title !== _ctx.title && _setDOMProp(n0, "title", (_title = _ctx.title))',
700-
)
701-
expect(code).contains(
702-
'_lang !== _ctx.lang && _setDOMProp(n0, "lang", (_lang = _ctx.lang))',
703-
)
704-
expect(code).contains(
705-
'_dir !== _ctx.dir && _setDOMProp(n0, "dir", (_dir = _ctx.dir))',
706-
)
707-
expect(code).contains(
708-
'_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))',
709-
)
710-
})
711-
712-
test('SVG global attributes should set as dom prop', () => {
713-
const { code } = compileWithVBind(`
714-
<svg :id="id" :lang="lang" :tabindex="tabindex" />
715-
`)
716-
717-
expect(code).matchSnapshot()
718-
expect(code).contains(
719-
'_id !== _ctx.id && _setDOMProp(n0, "id", (_id = _ctx.id))',
720-
)
721-
expect(code).contains(
722-
'_lang !== _ctx.lang && _setDOMProp(n0, "lang", (_lang = _ctx.lang))',
723-
)
724-
expect(code).contains(
725-
'_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))',
726-
)
727-
})
728-
729-
test('MathML global attributes should set as dom prop', () => {
730-
const { code } = compileWithVBind(`
731-
<math :autofucus :dir :displaystyle :mathcolor :tabindex/>
732-
`)
733-
734-
expect(code).matchSnapshot()
735-
expect(code).contains(
736-
'_autofucus !== _ctx.autofucus && _setDOMProp(n0, "autofucus", (_autofucus = _ctx.autofucus))',
737-
)
738-
expect(code).contains(
739-
'_dir !== _ctx.dir && _setDOMProp(n0, "dir", (_dir = _ctx.dir))',
740-
)
741-
expect(code).contains(
742-
'_displaystyle !== _ctx.displaystyle && _setDOMProp(n0, "displaystyle", (_displaystyle = _ctx.displaystyle))',
743-
)
744-
expect(code).contains(
745-
'_mathcolor !== _ctx.mathcolor && _setDOMProp(n0, "mathcolor", (_mathcolor = _ctx.mathcolor))',
746-
)
747-
expect(code).contains(
748-
'_tabindex !== _ctx.tabindex && _setDOMProp(n0, "tabindex", (_tabindex = _ctx.tabindex))',
749-
)
750-
})
751-
752689
test(':innerHTML', () => {
753690
const { code } = compileWithVBind(`
754691
<div :innerHTML="foo"/>

packages/compiler-vapor/__tests__/transforms/vOn.spec.ts

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ describe('v-on', () => {
106106
},
107107
})
108108

109+
console.log(code)
110+
109111
expect(code).matchSnapshot()
110112
})
111113

packages/compiler-vapor/src/generate.ts

+1-16
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ import type {
22
CodegenOptions as BaseCodegenOptions,
33
BaseCodegenResult,
44
} from '@vue/compiler-dom'
5-
import type {
6-
BlockIRNode,
7-
CoreHelper,
8-
IREffect,
9-
RootIRNode,
10-
VaporHelper,
11-
} from './ir'
5+
import type { BlockIRNode, CoreHelper, RootIRNode, VaporHelper } from './ir'
126
import { extend, remove } from '@vue/shared'
137
import { genBlockContent } from './generators/block'
148
import { genTemplates } from './generators/template'
@@ -37,15 +31,6 @@ export class CodegenContext {
3731

3832
delegates: Set<string> = new Set<string>()
3933

40-
processingRenderEffect: IREffect | undefined = undefined
41-
allRenderEffectSeenNames: Record<string, number> = Object.create(null)
42-
shouldCacheRenderEffectDeps = (): boolean => {
43-
// only need to generate effect deps when it's not nested in v-for
44-
return !!(
45-
this.processingRenderEffect && !this.processingRenderEffect.inVFor
46-
)
47-
}
48-
4934
identifiers: Record<string, string[]> = Object.create(null)
5035

5136
block: BlockIRNode

packages/compiler-vapor/src/generators/expression.ts

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isArray, isGloballyAllowed } from '@vue/shared'
1+
import { isGloballyAllowed } from '@vue/shared'
22
import {
33
BindingTypes,
44
NewlineType,
@@ -95,14 +95,7 @@ export function genExpression(
9595
)
9696

9797
if (i === ids.length - 1 && end < content.length) {
98-
const rest = content.slice(end)
99-
const last = frag[frag.length - 1]
100-
if (hasMemberExpression && isArray(last)) {
101-
// merge rest content into the last identifier's generated name
102-
last[0] += rest
103-
} else {
104-
push([rest, NewlineType.Unknown])
105-
}
98+
push([content.slice(end), NewlineType.Unknown])
10699
}
107100
})
108101

packages/compiler-vapor/src/generators/html.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ import type { CodegenContext } from '../generate'
22
import type { SetHtmlIRNode } from '../ir'
33
import { genExpression } from './expression'
44
import { type CodeFragment, NEWLINE, genCall } from './utils'
5-
import { processValues } from './prop'
65

76
export function genSetHtml(
87
oper: SetHtmlIRNode,
98
context: CodegenContext,
109
): CodeFragment[] {
11-
const { helper, shouldCacheRenderEffectDeps } = context
10+
const { helper } = context
1211
const { value, element } = oper
13-
let html = genExpression(value, context)
14-
if (shouldCacheRenderEffectDeps()) {
15-
processValues(context, [html])
16-
}
17-
return [NEWLINE, ...genCall(helper('setHtml'), `n${element}`, html)]
12+
return [
13+
NEWLINE,
14+
...genCall(helper('setHtml'), `n${element}`, genExpression(value, context)),
15+
]
1816
}

packages/compiler-vapor/src/generators/operation.ts

+9-47
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,16 @@ export function genEffects(
7878
): CodeFragment[] {
7979
const { helper } = context
8080
const [frag, push, unshift] = buildCodeFragment()
81-
const declareNames = new Set<string>()
8281
let operationsCount = 0
8382
for (let i = 0; i < effects.length; i++) {
84-
const effect = (context.processingRenderEffect = effects[i])
83+
const effect = effects[i]
8584
operationsCount += effect.operations.length
86-
const frags = genEffect(effect, context, declareNames)
87-
const needSemi = frag[frag.length - 1] === ')' && frags[0] === '('
85+
const frags = genEffect(effect, context)
8886
i > 0 && push(NEWLINE)
89-
push(needSemi ? ';' : undefined, ...frags)
87+
if (frag[frag.length - 1] === ')' && frags[0] === '(') {
88+
push(';')
89+
}
90+
push(...frags)
9091
}
9192

9293
const newLineCount = frag.filter(frag => frag === NEWLINE).length
@@ -100,60 +101,21 @@ export function genEffects(
100101
push(`)`)
101102
}
102103

103-
// declare variables: let _foo, _bar
104-
if (declareNames.size) {
105-
frag.splice(1, 0, `let ${[...declareNames].join(', ')}`, NEWLINE)
106-
}
107104
return frag
108105
}
109106

110107
export function genEffect(
111108
{ operations }: IREffect,
112109
context: CodegenContext,
113-
allDeclareNames: Set<string>,
114110
): CodeFragment[] {
115-
const { processingRenderEffect } = context
116111
const [frag, push] = buildCodeFragment()
117-
const { declareNames, earlyCheckExps } = processingRenderEffect!
118112
const operationsExps = genOperations(operations, context)
119-
120-
if (declareNames.size) {
121-
allDeclareNames.add([...declareNames].join(', '))
122-
}
123-
124113
const newlineCount = operationsExps.filter(frag => frag === NEWLINE).length
114+
125115
if (newlineCount > 1) {
126-
// multiline check expression: if (_foo !== _ctx.foo || _bar !== _ctx.bar) {
127-
const checkExpsStart: CodeFragment[] =
128-
earlyCheckExps.length > 0
129-
? [`if(`, ...earlyCheckExps.join(' || '), `) {`, INDENT_START]
130-
: []
131-
const checkExpsEnd: CodeFragment[] =
132-
earlyCheckExps.length > 0 ? [INDENT_END, NEWLINE, '}'] : []
133-
// assignment: _foo = _ctx.foo; _bar = _ctx.bar
134-
const assignmentExps: CodeFragment[] =
135-
earlyCheckExps.length > 0
136-
? [NEWLINE, ...earlyCheckExps.map(c => c.replace('!==', '=')).join(';')]
137-
: []
138-
push(
139-
...checkExpsStart,
140-
...operationsExps,
141-
...assignmentExps,
142-
...checkExpsEnd,
143-
)
116+
push(...operationsExps)
144117
} else {
145-
// single line check expression: (_foo !== _ctx.foo || _bar !== _ctx.bar) &&
146-
const multiple = earlyCheckExps.length > 1
147-
const checkExps: CodeFragment[] =
148-
earlyCheckExps.length > 0
149-
? [
150-
multiple ? `(` : undefined,
151-
...earlyCheckExps.join(' || '),
152-
multiple ? `)` : undefined,
153-
' && ',
154-
]
155-
: []
156-
push(...checkExps, ...operationsExps.filter(frag => frag !== NEWLINE))
118+
push(...operationsExps.filter(frag => frag !== NEWLINE))
157119
}
158120

159121
return frag

0 commit comments

Comments
 (0)