Skip to content

Commit 14f102a

Browse files
authored
Merge branch 'vapor' into edison/feat/vaporTransition
2 parents e3f8ba4 + bce7164 commit 14f102a

File tree

16 files changed

+167
-72
lines changed

16 files changed

+167
-72
lines changed

packages-private/sfc-playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"vite": "catalog:"
1414
},
1515
"dependencies": {
16-
"@vue/repl": "^4.5.0",
16+
"@vue/repl": "^4.5.1",
1717
"file-saver": "^2.0.5",
1818
"jszip": "^3.10.1",
1919
"vue": "workspace:*"

packages/compiler-sfc/__tests__/parse.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,17 @@ h1 { color: red }
381381
})
382382
})
383383

384+
describe('vapor mode', () => {
385+
test('on empty script', () => {
386+
const { descriptor } = parse(`<script vapor></script>`)
387+
expect(descriptor.vapor).toBe(true)
388+
})
389+
test('on template', () => {
390+
const { descriptor } = parse(`<template vapor><div/></template>`)
391+
expect(descriptor.vapor).toBe(true)
392+
})
393+
})
394+
384395
describe('warnings', () => {
385396
function assertWarning(errors: Error[], msg: string) {
386397
expect(errors.some(e => e.message.match(msg))).toBe(true)

packages/compiler-sfc/src/parse.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@ export function parse(
162162
ignoreEmpty &&
163163
node.tag !== 'template' &&
164164
isEmpty(node) &&
165-
!hasSrc(node)
165+
!hasAttr(node, 'src')
166166
) {
167+
descriptor.vapor ||= hasAttr(node, 'vapor')
167168
return
168169
}
169170
switch (node.tag) {
@@ -409,13 +410,8 @@ function padContent(
409410
}
410411
}
411412

412-
function hasSrc(node: ElementNode) {
413-
return node.props.some(p => {
414-
if (p.type !== NodeTypes.ATTRIBUTE) {
415-
return false
416-
}
417-
return p.name === 'src'
418-
})
413+
function hasAttr(node: ElementNode, name: string) {
414+
return node.props.some(p => p.type === NodeTypes.ATTRIBUTE && p.name === name)
419415
}
420416

421417
/**

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`cache multiple access > cache variable used in both property shorthand and normal binding 1`] = `
4+
"import { setStyle as _setStyle, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
5+
const t0 = _template("<div></div>", true)
6+
7+
export function render(_ctx) {
8+
const n0 = t0()
9+
_renderEffect(() => {
10+
const _color = _ctx.color
11+
_setStyle(n0, {color: _color})
12+
_setProp(n0, "id", _color)
13+
})
14+
return n0
15+
}"
16+
`;
17+
318
exports[`cache multiple access > dynamic key bindings with expressions 1`] = `
419
"import { setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue';
520
const t0 = _template("<div></div>", true)
@@ -60,6 +75,17 @@ export function render(_ctx) {
6075
}"
6176
`;
6277

78+
exports[`cache multiple access > not cache variable only used in property shorthand 1`] = `
79+
"import { setStyle as _setStyle, renderEffect as _renderEffect, template as _template } from 'vue';
80+
const t0 = _template("<div></div>", true)
81+
82+
export function render(_ctx) {
83+
const n0 = t0()
84+
_renderEffect(() => _setStyle(n0, {color: _ctx.color}))
85+
return n0
86+
}"
87+
`;
88+
6389
exports[`cache multiple access > object property chain access 1`] = `
6490
"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
6591
const t0 = _template("<div></div>")

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,23 @@ describe('cache multiple access', () => {
785785
expect(code).contains('_setProp(n0, "id", _obj[1][_ctx.baz] + _obj.bar)')
786786
})
787787

788+
test('cache variable used in both property shorthand and normal binding', () => {
789+
const { code } = compileWithVBind(`
790+
<div :style="{color}" :id="color"/>
791+
`)
792+
expect(code).matchSnapshot()
793+
expect(code).contains('const _color = _ctx.color')
794+
expect(code).contains('_setStyle(n0, {color: _color})')
795+
})
796+
797+
test('not cache variable only used in property shorthand', () => {
798+
const { code } = compileWithVBind(`
799+
<div :style="{color}" />
800+
`)
801+
expect(code).matchSnapshot()
802+
expect(code).not.contains('const _color = _ctx.color')
803+
})
804+
788805
test('not cache variable and member expression with the same name', () => {
789806
const { code } = compileWithVBind(`
790807
<div :id="bar + obj.bar"></div>

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ function genIdentifier(
131131
if (idMap && idMap.length) {
132132
const replacement = idMap[0]
133133
if (isString(replacement)) {
134-
return [[replacement, NewlineType.None, loc]]
134+
if (parent && parent.type === 'ObjectProperty' && parent.shorthand) {
135+
return [[`${name}: ${replacement}`, NewlineType.None, loc]]
136+
} else {
137+
return [[replacement, NewlineType.None, loc]]
138+
}
135139
} else {
136140
// replacement is an expression - process it again
137141
return genExpression(replacement, context, assignment)
@@ -292,7 +296,7 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
292296
}
293297

294298
walk(exp.ast, {
295-
enter(currentNode: Node) {
299+
enter(currentNode: Node, parent: Node | null) {
296300
if (currentNode.type === 'MemberExpression') {
297301
const memberExp = extractMemberExpression(
298302
currentNode,
@@ -304,6 +308,16 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
304308
return this.skip()
305309
}
306310

311+
// skip shorthand or non-computed property keys
312+
if (
313+
parent &&
314+
parent.type === 'ObjectProperty' &&
315+
parent.key === currentNode &&
316+
(parent.shorthand || !parent.computed)
317+
) {
318+
return this.skip()
319+
}
320+
307321
if (currentNode.type === 'Identifier') {
308322
registerVariable(currentNode.name, exp, true)
309323
}

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ export function genSetText(
1414
context: CodegenContext,
1515
): CodeFragment[] {
1616
const { helper } = context
17-
const { element, values, generated } = oper
18-
const texts = combineValues(values, context)
17+
const { element, values, generated, jsx } = oper
18+
const texts = combineValues(values, context, jsx)
1919
return [
2020
NEWLINE,
2121
...genCall(helper('setText'), `${generated ? 'x' : 'n'}${element}`, texts),
@@ -27,29 +27,30 @@ export function genCreateTextNode(
2727
context: CodegenContext,
2828
): CodeFragment[] {
2929
const { helper } = context
30-
const { id, values } = oper
30+
const { id, values, jsx } = oper
3131
return [
3232
NEWLINE,
3333
`const n${id} = `,
3434
...genCall(
3535
helper('createTextNode'),
36-
values && combineValues(values, context),
36+
values && combineValues(values, context, jsx),
3737
),
3838
]
3939
}
4040

4141
function combineValues(
4242
values: SimpleExpressionNode[],
4343
context: CodegenContext,
44+
jsx?: boolean,
4445
): CodeFragment[] {
4546
return values.flatMap((value, i) => {
4647
let exp = genExpression(value, context)
47-
if (getLiteralExpressionValue(value) == null) {
48+
if (!jsx && getLiteralExpressionValue(value) == null) {
4849
// dynamic, wrap with toDisplayString
4950
exp = genCall(context.helper('toDisplayString'), exp)
5051
}
5152
if (i > 0) {
52-
exp.unshift(' + ')
53+
exp.unshift(jsx ? ', ' : ' + ')
5354
}
5455
return exp
5556
})

packages/compiler-vapor/src/ir/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export interface SetTextIRNode extends BaseIRNode {
123123
element: number
124124
values: SimpleExpressionNode[]
125125
generated?: boolean // whether this is a generated empty text node by `processTextLikeContainer`
126+
jsx?: boolean
126127
}
127128

128129
export type KeyOverride = [find: string, replacement: string]
@@ -163,6 +164,7 @@ export interface CreateTextNodeIRNode extends BaseIRNode {
163164
type: IRNodeTypes.CREATE_TEXT_NODE
164165
id: number
165166
values?: SimpleExpressionNode[]
167+
jsx?: boolean
166168
}
167169

168170
export interface InsertNodeIRNode extends BaseIRNode {

packages/reactivity/src/debug.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,8 @@ function setupFlagsHandler(target: Subscriber): void {
6969
},
7070
set(value) {
7171
if (
72-
!(
73-
(target as any)._flags &
74-
(SubscriberFlags.PendingComputed | SubscriberFlags.Dirty)
75-
) &&
76-
!!(value & (SubscriberFlags.PendingComputed | SubscriberFlags.Dirty))
72+
!((target as any)._flags & SubscriberFlags.Propagated) &&
73+
!!(value & SubscriberFlags.Propagated)
7774
) {
7875
onTrigger(this)
7976
}

packages/reactivity/src/system.ts

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable */
2-
// Ported from https://github.com/stackblitz/alien-signals/blob/v1.0.0/src/system.ts
2+
// Ported from https://github.com/stackblitz/alien-signals/blob/v1.0.4/src/system.ts
33
import type { ComputedRefImpl as Computed } from './computed.js'
44
import type { ReactiveEffect as Effect } from './effect.js'
55

@@ -35,7 +35,6 @@ export const enum SubscriberFlags {
3535
let batchDepth = 0
3636
let queuedEffects: Effect | undefined
3737
let queuedEffectsTail: Effect | undefined
38-
let linkPool: Link | undefined
3938

4039
export function startBatch(): void {
4140
++batchDepth
@@ -195,24 +194,18 @@ export function processComputedUpdate(
195194
computed: Computed,
196195
flags: SubscriberFlags,
197196
): void {
198-
if (flags & SubscriberFlags.Dirty) {
197+
if (
198+
flags & SubscriberFlags.Dirty ||
199+
(checkDirty(computed.deps!)
200+
? true
201+
: ((computed.flags = flags & ~SubscriberFlags.PendingComputed), false))
202+
) {
199203
if (computed.update()) {
200204
const subs = computed.subs
201205
if (subs !== undefined) {
202206
shallowPropagate(subs)
203207
}
204208
}
205-
} else if (flags & SubscriberFlags.PendingComputed) {
206-
if (checkDirty(computed.deps!)) {
207-
if (computed.update()) {
208-
const subs = computed.subs
209-
if (subs !== undefined) {
210-
shallowPropagate(subs)
211-
}
212-
}
213-
} else {
214-
computed.flags = flags & ~SubscriberFlags.PendingComputed
215-
}
216209
}
217210
}
218211

@@ -238,22 +231,12 @@ function linkNewDep(
238231
nextDep: Link | undefined,
239232
depsTail: Link | undefined,
240233
): Link {
241-
let newLink: Link
242-
243-
if (linkPool !== undefined) {
244-
newLink = linkPool
245-
linkPool = newLink.nextDep
246-
newLink.nextDep = nextDep
247-
newLink.dep = dep
248-
newLink.sub = sub
249-
} else {
250-
newLink = {
251-
dep,
252-
sub,
253-
nextDep,
254-
prevSub: undefined,
255-
nextSub: undefined,
256-
}
234+
const newLink: Link = {
235+
dep,
236+
sub,
237+
nextDep,
238+
prevSub: undefined,
239+
nextSub: undefined,
257240
}
258241

259242
if (depsTail === undefined) {
@@ -327,7 +310,7 @@ function checkDirty(link: Link): boolean {
327310
if (sub.update()) {
328311
if ((link = subSubs.prevSub!) !== undefined) {
329312
subSubs.prevSub = undefined
330-
shallowPropagate(sub.subs!)
313+
shallowPropagate(subSubs)
331314
sub = link.sub as Computed
332315
} else {
333316
sub = subSubs.sub as Computed
@@ -400,25 +383,16 @@ function clearTracking(link: Link): void {
400383

401384
if (nextSub !== undefined) {
402385
nextSub.prevSub = prevSub
403-
link.nextSub = undefined
404386
} else {
405387
dep.subsTail = prevSub
406388
}
407389

408390
if (prevSub !== undefined) {
409391
prevSub.nextSub = nextSub
410-
link.prevSub = undefined
411392
} else {
412393
dep.subs = nextSub
413394
}
414395

415-
// @ts-expect-error
416-
link.dep = undefined
417-
// @ts-expect-error
418-
link.sub = undefined
419-
link.nextDep = linkPool
420-
linkPool = link
421-
422396
if (dep.subs === undefined && 'deps' in dep) {
423397
const depFlags = dep.flags
424398
if (!(depFlags & SubscriberFlags.Dirty)) {

0 commit comments

Comments
 (0)