Skip to content

Commit

Permalink
Merge pull request #163 from vuejs/main
Browse files Browse the repository at this point in the history
update
  • Loading branch information
Tomxuetao authored Sep 23, 2024
2 parents 092d0d5 + a177092 commit 26e4168
Show file tree
Hide file tree
Showing 34 changed files with 398 additions and 62 deletions.
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
## [3.5.8](https://github.com/vuejs/core/compare/v3.5.7...v3.5.8) (2024-09-22)


### Bug Fixes

* **reactivity:** do not remove dep from depsMap when cleaning up deps of computed ([#11995](https://github.com/vuejs/core/issues/11995)) ([0267a58](https://github.com/vuejs/core/commit/0267a588017eee4951ac2a877fe1ccae84cad905))



## [3.5.7](https://github.com/vuejs/core/compare/v3.5.6...v3.5.7) (2024-09-20)


### Bug Fixes

* **compile-core:** fix v-model with newlines edge case ([#11960](https://github.com/vuejs/core/issues/11960)) ([6224288](https://github.com/vuejs/core/commit/62242886d705ece88dbcad45bb78072ecccad0ca)), closes [#8306](https://github.com/vuejs/core/issues/8306)
* **compiler-sfc:** initialize scope with null prototype object ([#11963](https://github.com/vuejs/core/issues/11963)) ([215e154](https://github.com/vuejs/core/commit/215e15407294bf667261360218f975b88c99c2e5))
* **hydration:** avoid observing non-Element node ([#11954](https://github.com/vuejs/core/issues/11954)) ([7257e6a](https://github.com/vuejs/core/commit/7257e6a34200409b3fc347d3bb807e11e2785974)), closes [#11952](https://github.com/vuejs/core/issues/11952)
* **reactivity:** do not remove dep from depsMap when unsubbed by computed ([960706e](https://github.com/vuejs/core/commit/960706eebf73f08ebc9d5dd853a05def05e2c153))
* **reactivity:** fix dev-only memory leak by updating dep.subsHead on sub removal ([5c8b76e](https://github.com/vuejs/core/commit/5c8b76ed6cfbbcee4cbaac0b72beab7291044e4f)), closes [#11956](https://github.com/vuejs/core/issues/11956)
* **reactivity:** fix memory leak from dep instances of garbage collected objects ([235ea47](https://github.com/vuejs/core/commit/235ea4772ed2972914cf142da8b7ac1fb04f7585)), closes [#11979](https://github.com/vuejs/core/issues/11979) [#11971](https://github.com/vuejs/core/issues/11971)
* **reactivity:** fix triggerRef call on ObjectRefImpl returned by toRef ([#11986](https://github.com/vuejs/core/issues/11986)) ([b030c8b](https://github.com/vuejs/core/commit/b030c8bc7327877efb98aa3d9a58eb287a6ff07a)), closes [#11982](https://github.com/vuejs/core/issues/11982)
* **scheduler:** ensure recursive jobs can't be queued twice ([#11955](https://github.com/vuejs/core/issues/11955)) ([d18d6aa](https://github.com/vuejs/core/commit/d18d6aa1b20dc57a8103c51ec4d61e8e53ed936d))
* **ssr:** don't render comments in TransitionGroup ([#11961](https://github.com/vuejs/core/issues/11961)) ([a2f6ede](https://github.com/vuejs/core/commit/a2f6edeb02faedbb673c4bc5c6a59d9a79a37d07)), closes [#11958](https://github.com/vuejs/core/issues/11958)
* **transition:** respect `duration` setting even when it is `0` ([#11967](https://github.com/vuejs/core/issues/11967)) ([f927a4a](https://github.com/vuejs/core/commit/f927a4ae6f7c453f70ba89498ee0c737dc9866fd))
* **types:** correct type inference of all-optional props ([#11644](https://github.com/vuejs/core/issues/11644)) ([9eca65e](https://github.com/vuejs/core/commit/9eca65ee9871d1ac878755afa9a3eb1b02030350)), closes [#11733](https://github.com/vuejs/core/issues/11733) [vuejs/language-tools#4704](https://github.com/vuejs/language-tools/issues/4704)


### Performance Improvements

* **hydration:** avoid observer if element is in viewport ([#11639](https://github.com/vuejs/core/issues/11639)) ([e075dfa](https://github.com/vuejs/core/commit/e075dfad5c7649c6045e3711687ec888e7aa1a39))



## [3.5.6](https://github.com/vuejs/core/compare/v3.5.5...v3.5.6) (2024-09-16)


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"private": true,
"version": "3.5.6",
"version": "3.5.8",
"packageManager": "pnpm@9.10.0",
"type": "module",
"scripts": {
Expand Down
3 changes: 2 additions & 1 deletion packages-private/sfc-playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ onMounted(() => {
@keydown.ctrl.s.prevent
@keydown.meta.s.prevent
:ssr="useSSRMode"
:autoSave="autoSave"
:model-value="autoSave"
:editorOptions="{ autoSaveText: false }"
:store="store"
:showCompileOutput="true"
:autoResize="true"
Expand Down
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.6",
"version": "3.5.8",
"description": "@vue/compiler-core",
"main": "index.js",
"module": "dist/compiler-core.esm-bundler.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-core/src/transforms/vModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {

// we assume v-model directives are always parsed
// (not artificially created by a transform)
const rawExp = exp.loc.source
const rawExp = exp.loc.source.trim()
const expString =
exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp

Expand Down
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.6",
"version": "3.5.8",
"description": "@vue/compiler-dom",
"main": "index.js",
"module": "dist/compiler-dom.esm-bundler.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,29 @@ return (_ctx, _cache) => {
}"
`;
exports[`SFC compile <script setup> > inlineTemplate mode > v-model w/ newlines codegen 1`] = `
"import { unref as _unref, isRef as _isRef, vModelText as _vModelText, withDirectives as _withDirectives, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export default {
setup(__props) {
const count = ref(0)
return (_ctx, _cache) => {
return _withDirectives((_openBlock(), _createElementBlock("input", {
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (_isRef(count) ? (count).value = $event : null))
}, null, 512 /* NEED_PATCH */)), [
[_vModelText,
_unref(count)
]
])
}
}
}"
`;
exports[`SFC compile <script setup> > inlineTemplate mode > with defineExpose() 1`] = `
"
export default {
Expand Down
17 changes: 17 additions & 0 deletions packages/compiler-sfc/__tests__/compileScript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,23 @@ describe('SFC compile <script setup>', () => {
assertCode(content)
})

test('v-model w/ newlines codegen', () => {
const { content } = compile(
`<script setup>
const count = ref(0)
</script>
<template>
<input v-model="
count
">
</template>
`,
{ inlineTemplate: true },
)
expect(content).toMatch(`_isRef(count) ? (count).value = $event : null`)
assertCode(content)
})

test('v-model should not generate ref assignment code for non-setup bindings', () => {
const { content } = compile(
`<script setup>
Expand Down
2 changes: 1 addition & 1 deletion 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.6",
"version": "3.5.8",
"description": "@vue/compiler-sfc",
"main": "dist/compiler-sfc.cjs.js",
"module": "dist/compiler-sfc.esm-browser.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-sfc/src/script/definePropsDestructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function transformDestructuredProps(
return
}

const rootScope: Scope = {}
const rootScope: Scope = Object.create(null)
const scopeStack: Scope[] = [rootScope]
let currentScope: Scope = rootScope
const excludedIds = new WeakSet<Identifier>()
Expand Down
21 changes: 20 additions & 1 deletion packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('transition-group', () => {
})

// #11514
test('with static tag + comment', () => {
test('with static tag + v-if comment', () => {
expect(
compile(
`<transition-group tag="ul"><div v-for="i in list"/><div v-if="false"></div></transition-group>`,
Expand All @@ -60,6 +60,25 @@ describe('transition-group', () => {
`)
})

// #11958
test('with static tag + comment', () => {
expect(
compile(
`<transition-group tag="ul"><div v-for="i in list"/><!--test--></transition-group>`,
).code,
).toMatchInlineSnapshot(`
"const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
return function ssrRender(_ctx, _push, _parent, _attrs) {
_push(\`<ul\${_ssrRenderAttrs(_attrs)}>\`)
_ssrRenderList(_ctx.list, (i) => {
_push(\`<div></div>\`)
})
_push(\`</ul>\`)
}"
`)
})

test('with dynamic tag', () => {
expect(
compile(
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-ssr/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/compiler-ssr",
"version": "3.5.6",
"version": "3.5.8",
"description": "@vue/compiler-ssr",
"main": "dist/compiler-ssr.cjs.js",
"types": "dist/compiler-ssr.d.ts",
Expand Down
13 changes: 5 additions & 8 deletions packages/compiler-ssr/src/ssrCodegenTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export function processChildren(
context: SSRTransformContext,
asFragment = false,
disableNestedFragments = false,
disableCommentAsIfAlternate = false,
disableComment = false,
): void {
if (asFragment) {
context.pushStringPart(`<!--[-->`)
Expand Down Expand Up @@ -197,7 +197,9 @@ export function processChildren(
case NodeTypes.COMMENT:
// no need to escape comment here because the AST can only
// contain valid comments.
context.pushStringPart(`<!--${child.content}-->`)
if (!disableComment) {
context.pushStringPart(`<!--${child.content}-->`)
}
break
case NodeTypes.INTERPOLATION:
context.pushStringPart(
Expand All @@ -207,12 +209,7 @@ export function processChildren(
)
break
case NodeTypes.IF:
ssrProcessIf(
child,
context,
disableNestedFragments,
disableCommentAsIfAlternate,
)
ssrProcessIf(child, context, disableNestedFragments, disableComment)
break
case NodeTypes.FOR:
ssrProcessFor(child, context, disableNestedFragments)
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-ssr/src/transforms/ssrVIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function ssrProcessIf(
node: IfNode,
context: SSRTransformContext,
disableNestedFragments = false,
disableCommentAsIfAlternate = false,
disableComment = false,
): void {
const [rootBranch] = node.branches
const ifStatement = createIfStatement(
Expand Down Expand Up @@ -56,7 +56,7 @@ export function ssrProcessIf(
}
}

if (!currentIf.alternate && !disableCommentAsIfAlternate) {
if (!currentIf.alternate && !disableComment) {
currentIf.alternate = createBlockStatement([
createCallExpression(`_push`, ['`<!---->`']),
])
Expand Down
28 changes: 27 additions & 1 deletion packages/reactivity/__tests__/computed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1006,9 +1006,35 @@ describe('reactivity/computed', () => {
expect(serializeInner(root)).toBe(`<button>Step</button><p>Step 2</p>`)
})

it('manual trigger computed', () => {
test('manual trigger computed', () => {
const cValue = computed(() => 1)
triggerRef(cValue)
expect(cValue.value).toBe(1)
})

test('computed should remain live after losing all subscribers', () => {
const state = reactive({ a: 1 })
const p = computed(() => state.a + 1)
const { effect: e } = effect(() => p.value)
e.stop()

expect(p.value).toBe(2)
state.a++
expect(p.value).toBe(3)
})

test('computed dep cleanup should not cause property dep to be deleted', () => {
const toggle = ref(true)
const state = reactive({ a: 1 })
const p = computed(() => {
return toggle.value ? state.a : 111
})
const pp = computed(() => state.a)
effect(() => p.value)

expect(pp.value).toBe(1)
toggle.value = false
state.a++
expect(pp.value).toBe(2)
})
})
2 changes: 1 addition & 1 deletion packages/reactivity/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue/reactivity",
"version": "3.5.6",
"version": "3.5.8",
"description": "@vue/reactivity",
"main": "index.js",
"module": "dist/reactivity.esm-bundler.js",
Expand Down
13 changes: 12 additions & 1 deletion packages/reactivity/src/dep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ export class Dep {
*/
subsHead?: Link

/**
* For object property deps cleanup
*/
target?: unknown = undefined
map?: KeyToDepMap = undefined
key?: unknown = undefined

constructor(public computed?: ComputedRefImpl | undefined) {
if (__DEV__) {
this.subsHead = undefined
Expand Down Expand Up @@ -218,7 +225,8 @@ function addSub(link: Link) {
// which maintains a Set of subscribers, but we simply store them as
// raw Maps to reduce memory overhead.
type KeyToDepMap = Map<any, Dep>
const targetMap = new WeakMap<object, KeyToDepMap>()

export const targetMap: WeakMap<object, KeyToDepMap> = new WeakMap()

export const ITERATE_KEY: unique symbol = Symbol(
__DEV__ ? 'Object iterate' : '',
Expand Down Expand Up @@ -249,6 +257,9 @@ export function track(target: object, type: TrackOpTypes, key: unknown): void {
let dep = depsMap.get(key)
if (!dep) {
depsMap.set(key, (dep = new Dep()))
dep.target = target
dep.map = depsMap
dep.key = key
}
if (__DEV__) {
dep.track({
Expand Down
32 changes: 21 additions & 11 deletions packages/reactivity/src/effect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { extend, hasChanged } from '@vue/shared'
import type { ComputedRefImpl } from './computed'
import type { TrackOpTypes, TriggerOpTypes } from './constants'
import { type Link, globalVersion } from './dep'
import { type Link, globalVersion, targetMap } from './dep'
import { activeEffectScope } from './effectScope'
import { warn } from './warning'

Expand Down Expand Up @@ -292,7 +292,7 @@ function prepareDeps(sub: Subscriber) {
}
}

function cleanupDeps(sub: Subscriber) {
function cleanupDeps(sub: Subscriber, fromComputed = false) {
// Cleanup unsued deps
let head
let tail = sub.depsTail
Expand All @@ -302,7 +302,7 @@ function cleanupDeps(sub: Subscriber) {
if (link.version === -1) {
if (link === tail) tail = prev
// unused - remove it from the dep's subscribing effect list
removeSub(link)
removeSub(link, fromComputed)
// also remove it from this effect's dep list
removeDep(link)
} else {
Expand Down Expand Up @@ -394,12 +394,12 @@ export function refreshComputed(computed: ComputedRefImpl): undefined {
} finally {
activeSub = prevSub
shouldTrack = prevShouldTrack
cleanupDeps(computed)
cleanupDeps(computed, true)
computed.flags &= ~EffectFlags.RUNNING
}
}

function removeSub(link: Link) {
function removeSub(link: Link, fromComputed = false) {
const { dep, prevSub, nextSub } = link
if (prevSub) {
prevSub.nextSub = nextSub
Expand All @@ -413,14 +413,24 @@ function removeSub(link: Link) {
// was previous tail, point new tail to prev
dep.subs = prevSub
}
if (__DEV__ && dep.subsHead === link) {
// was previous head, point new head to next
dep.subsHead = nextSub
}

if (!dep.subs && dep.computed) {
if (!dep.subs) {
// last subscriber removed
// if computed, unsubscribe it from all its deps so this computed and its
// value can be GCed
dep.computed.flags &= ~EffectFlags.TRACKING
for (let l = dep.computed.deps; l; l = l.nextDep) {
removeSub(l)
if (dep.computed) {
// if computed, unsubscribe it from all its deps so this computed and its
// value can be GCed
dep.computed.flags &= ~EffectFlags.TRACKING
for (let l = dep.computed.deps; l; l = l.nextDep) {
removeSub(l, true)
}
} else if (dep.map && !fromComputed) {
// property dep, remove it from the owner depsMap
dep.map.delete(dep.key)
if (!dep.map.size) targetMap.delete(dep.target!)
}
}
}
Expand Down
Loading

0 comments on commit 26e4168

Please sign in to comment.