Skip to content

Commit

Permalink
Merge tag 'v3.5.13'
Browse files Browse the repository at this point in the history
sxzz committed Nov 15, 2024
2 parents d845108 + 6eb29d3 commit f6ce3f9
Showing 69 changed files with 1,061 additions and 121 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -14,5 +14,6 @@
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"editor.formatOnSave": true
}
1 change: 1 addition & 0 deletions .well-known/funding-manifest-urls
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://vuejs.org/funding.json
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
## [3.5.13](https://github.com/vuejs/core/compare/v3.5.12...v3.5.13) (2024-11-15)


### Bug Fixes

* **compiler-core:** handle v-memo + v-for with functional key ([#12014](https://github.com/vuejs/core/issues/12014)) ([99009ee](https://github.com/vuejs/core/commit/99009eee0efc238392daba93792d478525b21afa)), closes [#12013](https://github.com/vuejs/core/issues/12013)
* **compiler-dom:** properly stringify template string style ([#12392](https://github.com/vuejs/core/issues/12392)) ([2d78539](https://github.com/vuejs/core/commit/2d78539da35322aea5f821b3cf9b02d006abac72)), closes [#12391](https://github.com/vuejs/core/issues/12391)
* **custom-element:** avoid triggering mutationObserver when relecting props ([352bc88](https://github.com/vuejs/core/commit/352bc88c1bd2fda09c61ab17ea1a5967ffcd7bc0)), closes [#12214](https://github.com/vuejs/core/issues/12214) [#12215](https://github.com/vuejs/core/issues/12215)
* **deps:** update dependency postcss to ^8.4.48 ([#12356](https://github.com/vuejs/core/issues/12356)) ([b5ff930](https://github.com/vuejs/core/commit/b5ff930089985a58c3553977ef999cec2a6708a4))
* **hydration:** the component vnode's el should be updated when a mismatch occurs. ([#12255](https://github.com/vuejs/core/issues/12255)) ([a20a4cb](https://github.com/vuejs/core/commit/a20a4cb36a3e717d1f8f259d0d59f133f508ff0a)), closes [#12253](https://github.com/vuejs/core/issues/12253)
* **reactiivty:** avoid unnecessary watcher effect removal from inactive scope ([2193284](https://github.com/vuejs/core/commit/21932840eae72ffcd357a62ec596aaecc7ec224a)), closes [#5783](https://github.com/vuejs/core/issues/5783) [#5806](https://github.com/vuejs/core/issues/5806)
* **reactivity:** release nested effects/scopes on effect scope stop ([#12373](https://github.com/vuejs/core/issues/12373)) ([bee2f5e](https://github.com/vuejs/core/commit/bee2f5ee62dc0cd04123b737779550726374dd0a)), closes [#12370](https://github.com/vuejs/core/issues/12370)
* **runtime-dom:** set css vars before user onMounted hooks ([2d5c5e2](https://github.com/vuejs/core/commit/2d5c5e25e9b7a56e883674fb434135ac514429b5)), closes [#11533](https://github.com/vuejs/core/issues/11533)
* **runtime-dom:** set css vars on update to handle child forcing reflow in onMount ([#11561](https://github.com/vuejs/core/issues/11561)) ([c4312f9](https://github.com/vuejs/core/commit/c4312f9c715c131a09e552ba46e9beb4b36d55e6))
* **ssr:** avoid updating subtree of async component if it is resolved ([#12363](https://github.com/vuejs/core/issues/12363)) ([da7ad5e](https://github.com/vuejs/core/commit/da7ad5e3d24f3e108401188d909d27a4910da095)), closes [#12362](https://github.com/vuejs/core/issues/12362)
* **ssr:** ensure v-text updates correctly with custom directives in SSR output ([#12311](https://github.com/vuejs/core/issues/12311)) ([1f75d4e](https://github.com/vuejs/core/commit/1f75d4e6dfe18121ebe443cd3e8105d54f727893)), closes [#12309](https://github.com/vuejs/core/issues/12309)
* **ssr:** handle initial selected state for select with v-model + v-for option ([#12399](https://github.com/vuejs/core/issues/12399)) ([4f8d807](https://github.com/vuejs/core/commit/4f8d8078221ee52deed266677a227ad2a6d8dd22)), closes [#12395](https://github.com/vuejs/core/issues/12395)
* **teleport:** handle deferred teleport update before mounted ([#12168](https://github.com/vuejs/core/issues/12168)) ([8bff142](https://github.com/vuejs/core/commit/8bff142f99b646e9dd15897ec75368fbf34f1534)), closes [#12161](https://github.com/vuejs/core/issues/12161)
* **templateRef:** set ref on cached async component which wrapped in KeepAlive ([#12290](https://github.com/vuejs/core/issues/12290)) ([983eb50](https://github.com/vuejs/core/commit/983eb50a17eac76f1bba4394ad0316c62b72191d)), closes [#4999](https://github.com/vuejs/core/issues/4999) [#5004](https://github.com/vuejs/core/issues/5004)
* **test:** update snapshot ([#12169](https://github.com/vuejs/core/issues/12169)) ([828d4a4](https://github.com/vuejs/core/commit/828d4a443919fa2aa4e2e92fbd03a5f04b258eea))
* **Transition:** fix transition memory leak edge case ([#12182](https://github.com/vuejs/core/issues/12182)) ([660132d](https://github.com/vuejs/core/commit/660132df6c6a8c14bf75e593dc47d2fdada30322)), closes [#12181](https://github.com/vuejs/core/issues/12181)
* **transition:** reflow before leave-active class after leave-from ([#12288](https://github.com/vuejs/core/issues/12288)) ([4b479db](https://github.com/vuejs/core/commit/4b479db61d233b054561402ae94ef08550073ea1)), closes [#2593](https://github.com/vuejs/core/issues/2593)
* **types:** defineEmits w/ interface declaration ([#12343](https://github.com/vuejs/core/issues/12343)) ([1022eab](https://github.com/vuejs/core/commit/1022eabaa1aaf8436876f5ec5573cb1e4b3959a6)), closes [#8457](https://github.com/vuejs/core/issues/8457)
* **v-once:** setting hasOnce to current block only when in v-once ([#12374](https://github.com/vuejs/core/issues/12374)) ([37300fc](https://github.com/vuejs/core/commit/37300fc26190a7299efddbf98800ffd96d5cad96)), closes [#12371](https://github.com/vuejs/core/issues/12371)


### Performance Improvements

* **reactivity:** do not track inner key `__v_skip`` ([#11690](https://github.com/vuejs/core/issues/11690)) ([d637bd6](https://github.com/vuejs/core/commit/d637bd6c0164c2883e6eabd3c2f1f8c258dedfb1))
* **runtime-core:** use feature flag for call to resolveMergedOptions ([#12163](https://github.com/vuejs/core/issues/12163)) ([1755ac0](https://github.com/vuejs/core/commit/1755ac0a108ba3486bd8397e56d3bdcd69196594))



## [3.5.12](https://github.com/vuejs/core/compare/v3.5.11...v3.5.12) (2024-10-11)


7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"private": true,
"version": "3.5.12",
"version": "3.5.13",
"packageManager": "pnpm@9.12.3",
"type": "module",
"scripts": {
@@ -22,7 +22,10 @@
"test-dts": "run-s build-dts test-dts-only",
"test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json",
"test-coverage": "vitest run --project unit --coverage",
"test-bench": "vitest bench",
"prebench": "node scripts/build.js -pf esm-browser reactivity",
"prebench-compare": "node scripts/build.js -pf esm-browser reactivity",
"bench": "vitest bench --project=unit --outputJson=temp/bench.json",
"bench-compare": "vitest bench --project=unit --compare=temp/bench.json",
"release": "node scripts/release.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"dev-esm": "node scripts/dev.js -if esm-bundler-runtime",
8 changes: 8 additions & 0 deletions packages-private/dts-test/setupHelpers.test-d.ts
Original file line number Diff line number Diff line change
@@ -306,6 +306,14 @@ describe('defineEmits w/ type declaration', () => {
emit2('baz')
})

describe('defineEmits w/ interface declaration', () => {
interface Emits {
foo: [value: string]
}
const emit = defineEmits<Emits>()
emit('foo', 'hi')
})

describe('defineEmits w/ alt type declaration', () => {
const emit = defineEmits<{
foo: [id: string]
1 change: 1 addition & 0 deletions packages-private/sfc-playground/src/Header.vue
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ function resetVueVersion() {
async function copyLink(e: MouseEvent) {
if (e.metaKey) {
resetVueVersion()
// hidden logic for going to local debug from play.vuejs.org
window.location.href = 'http://localhost:5173/' + window.location.hash
return
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`compiler: v-memo transform > element v-for key expression prefixing + v-memo 1`] = `
"import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, isMemoSame as _isMemoSame, withMemo as _withMemo } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.tableData, (data, __, ___, _cached) => {
const _memo = (_ctx.getLetter(data))
if (_cached && _cached.key === _ctx.getId(data) && _isMemoSame(_cached, _memo)) return _cached
const _item = (_openBlock(), _createElementBlock("span", {
key: _ctx.getId(data)
}))
_item.memo = _memo
return _item
}, _cache, 0), 128 /* KEYED_FRAGMENT */))
]))
}"
`;

exports[`compiler: v-memo transform > on component 1`] = `
"import { resolveComponent as _resolveComponent, createVNode as _createVNode, withMemo as _withMemo, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ return function render(_ctx, _cache) {
const { setBlockTracking: _setBlockTracking, createElementVNode: _createElementVNode } = _Vue
return _cache[0] || (
_setBlockTracking(-1),
_setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0,
_setBlockTracking(1),
_cache[0]
@@ -28,7 +28,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || (
_setBlockTracking(-1),
_setBlockTracking(-1, true),
(_cache[0] = _createVNode(_component_Comp, { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0,
_setBlockTracking(1),
_cache[0]
@@ -47,7 +47,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || (
_setBlockTracking(-1),
_setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div", { id: foo }, null, 8 /* PROPS */, ["id"])).cacheIndex = 0,
_setBlockTracking(1),
_cache[0]
@@ -66,7 +66,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || (
_setBlockTracking(-1),
_setBlockTracking(-1, true),
(_cache[0] = _renderSlot($slots, "default")).cacheIndex = 0,
_setBlockTracking(1),
_cache[0]
@@ -85,7 +85,7 @@ return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
_cache[0] || (
_setBlockTracking(-1),
_setBlockTracking(-1, true),
(_cache[0] = _createElementVNode("div")).cacheIndex = 0,
_setBlockTracking(1),
_cache[0]
8 changes: 8 additions & 0 deletions packages/compiler-core/__tests__/transforms/vMemo.spec.ts
Original file line number Diff line number Diff line change
@@ -53,4 +53,12 @@ describe('compiler: v-memo transform', () => {
),
).toMatchSnapshot()
})

test('element v-for key expression prefixing + v-memo', () => {
expect(
compile(
`<span v-for="data of tableData" :key="getId(data)" v-memo="getLetter(data)"></span>`,
),
).toMatchSnapshot()
})
})
2 changes: 1 addition & 1 deletion packages/compiler-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-core",
"version": "3.5.12",
"version": "3.5.13",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",
3 changes: 3 additions & 0 deletions packages/compiler-core/src/ast.ts
Original file line number Diff line number Diff line change
@@ -425,6 +425,7 @@ export interface CacheExpression extends Node {
index: number
value: JSChildNode
needPauseTracking: boolean
inVOnce: boolean
needArraySpread: boolean
}

@@ -781,12 +782,14 @@ export function createCacheExpression(
index: number,
value: JSChildNode,
needPauseTracking: boolean = false,
inVOnce: boolean = false,
): CacheExpression {
return {
type: NodeTypes.JS_CACHE_EXPRESSION,
index,
value,
needPauseTracking: needPauseTracking,
inVOnce,
needArraySpread: false,
loc: locStub,
}
4 changes: 3 additions & 1 deletion packages/compiler-core/src/codegen.ts
Original file line number Diff line number Diff line change
@@ -1034,7 +1034,9 @@ function genCacheExpression(node: CacheExpression, context: CodegenContext) {
push(`_cache[${node.index}] || (`)
if (needPauseTracking) {
indent()
push(`${helper(SET_BLOCK_TRACKING)}(-1),`)
push(`${helper(SET_BLOCK_TRACKING)}(-1`)
if (node.inVOnce) push(`, true`)
push(`),`)
newline()
push(`(`)
}
5 changes: 3 additions & 2 deletions packages/compiler-core/src/transform.ts
Original file line number Diff line number Diff line change
@@ -116,7 +116,7 @@ export interface TransformContext
addIdentifiers(exp: ExpressionNode | string): void
removeIdentifiers(exp: ExpressionNode | string): void
hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode
cache(exp: JSChildNode, isVNode?: boolean): CacheExpression
cache(exp: JSChildNode, isVNode?: boolean, inVOnce?: boolean): CacheExpression
constantCache: WeakMap<TemplateChildNode, ConstantTypes>

// 2.x Compat only
@@ -297,11 +297,12 @@ export function createTransformContext(
identifier.hoisted = exp
return identifier
},
cache(exp, isVNode = false) {
cache(exp, isVNode = false, inVOnce = false) {
const cacheExp = createCacheExpression(
context.cached.length,
exp,
isVNode,
inVOnce,
)
context.cached.push(cacheExp)
return cacheExp
12 changes: 10 additions & 2 deletions packages/compiler-core/src/transforms/transformExpression.ts
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ import {
isStaticPropertyKey,
walkIdentifiers,
} from '../babelUtils'
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
import { advancePositionWithClone, findDir, isSimpleIdentifier } from '../utils'
import {
genPropsAccessExp,
hasOwn,
@@ -55,6 +55,7 @@ export const transformExpression: NodeTransform = (node, context) => {
)
} else if (node.type === NodeTypes.ELEMENT) {
// handle directives on element
const memo = findDir(node, 'memo')
for (let i = 0; i < node.props.length; i++) {
const dir = node.props[i]
// do not process for v-on & v-for since they are special handled
@@ -66,7 +67,14 @@ export const transformExpression: NodeTransform = (node, context) => {
if (
exp &&
exp.type === NodeTypes.SIMPLE_EXPRESSION &&
!(dir.name === 'on' && arg)
!(dir.name === 'on' && arg) &&
// key has been processed in transformFor(vMemo + vFor)
!(
memo &&
arg &&
arg.type === NodeTypes.SIMPLE_EXPRESSION &&
arg.content === 'key'
)
) {
dir.exp = processExpression(
exp,
14 changes: 12 additions & 2 deletions packages/compiler-core/src/transforms/vFor.ts
Original file line number Diff line number Diff line change
@@ -63,17 +63,27 @@ export const transformFor: NodeTransform = createStructuralDirectiveTransform(
const isTemplate = isTemplateNode(node)
const memo = findDir(node, 'memo')
const keyProp = findProp(node, `key`, false, true)
if (keyProp && keyProp.type === NodeTypes.DIRECTIVE && !keyProp.exp) {
const isDirKey = keyProp && keyProp.type === NodeTypes.DIRECTIVE
if (isDirKey && !keyProp.exp) {
// resolve :key shorthand #10882
transformBindShorthand(keyProp, context)
}
const keyExp =
let keyExp =
keyProp &&
(keyProp.type === NodeTypes.ATTRIBUTE
? keyProp.value
? createSimpleExpression(keyProp.value.content, true)
: undefined
: keyProp.exp)

if (memo && keyExp && isDirKey) {
if (!__BROWSER__) {
keyProp.exp = keyExp = processExpression(
keyExp as SimpleExpressionNode,
context,
)
}
}
const keyProperty =
keyProp && keyExp ? createObjectProperty(`key`, keyExp) : null

6 changes: 5 additions & 1 deletion packages/compiler-core/src/transforms/vOnce.ts
Original file line number Diff line number Diff line change
@@ -17,7 +17,11 @@ export const transformOnce: NodeTransform = (node, context) => {
context.inVOnce = false
const cur = context.currentNode as ElementNode | IfNode | ForNode
if (cur.codegenNode) {
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */)
cur.codegenNode = context.cache(
cur.codegenNode,
true /* isVNode */,
true /* inVOnce */,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -32,6 +32,16 @@ return function render(_ctx, _cache) {
}"
`;

exports[`stringify static html > serializing template string style 1`] = `
"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
return function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, _cache[0] || (_cache[0] = [
_createStaticVNode("<div style=\\"color:red;\\"><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span><span class=\\"foo bar\\">1 + false</span></div>", 1)
])))
}"
`;

exports[`stringify static html > should bail for <option> elements with null values 1`] = `
"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
21 changes: 21 additions & 0 deletions packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts
Original file line number Diff line number Diff line change
@@ -162,6 +162,27 @@ describe('stringify static html', () => {
expect(code).toMatchSnapshot()
})

// #12391
test('serializing template string style', () => {
const { ast, code } = compileWithStringify(
`<div><div :style="\`color:red;\`">${repeat(
`<span :class="[{ foo: true }, { bar: true }]">{{ 1 }} + {{ false }}</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
)}</div></div>`,
)
// should be optimized now
expect(ast.cached).toMatchObject([
cachedArrayStaticNodeMatcher(
`<div style="color:red;">${repeat(
`<span class="foo bar">1 + false</span>`,
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
)}</div>`,
1,
),
])
expect(code).toMatchSnapshot()
})

test('escape', () => {
const { ast, code } = compileWithStringify(
`<div><div>${repeat(
2 changes: 1 addition & 1 deletion packages/compiler-dom/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-dom",
"version": "3.5.12",
"version": "3.5.13",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",
4 changes: 2 additions & 2 deletions packages/compiler-sfc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-sfc",
"version": "3.5.12",
"version": "3.5.13",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"module": "dist/compiler-sfc.esm-browser.js",
@@ -61,7 +61,7 @@
"merge-source-map": "^1.1.0",
"minimatch": "~9.0.5",
"postcss-modules": "^6.0.0",
"postcss-selector-parser": "^6.1.2",
"postcss-selector-parser": "^7.0.0",
"pug": "^3.0.3",
"sass": "^1.80.6"
}
3 changes: 1 addition & 2 deletions packages/compiler-sfc/src/style/pluginScoped.ts
Original file line number Diff line number Diff line change
@@ -189,8 +189,7 @@ function rewriteSelector(
// global: replace with inner selector and do not inject [id].
// ::v-global(.foo) -> .foo
if (value === ':global' || value === '::v-global') {
selectorRoot.insertAfter(selector, n.nodes[0])
selectorRoot.removeChild(selector)
selector.replaceWith(n.nodes[0])
return false
}
}
Loading

0 comments on commit f6ce3f9

Please sign in to comment.