From 97716ae91a4fbc611a899bd9b2a256e4b91bd289 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 16 Apr 2024 19:49:52 +0800 Subject: [PATCH 1/4] chore: add security hall of fame [ci skip] --- SECURITY.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SECURITY.md b/SECURITY.md index dac6018b5bc..41a58da2970 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,3 +5,9 @@ To report a vulnerability, please email security@vuejs.org. While the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Vue and its official companion libraries to ensure your application remains as secure as possible. Please note that we do not consider XSS via template expressions a valid attack vector, because it can only happen if the user intentionally uses untrusted content as template compilation source. This is similar to knowingly pasting untrusted scripts into a browser console. We explicitly warn users against using untrusted content as template compilation source in our documentation. + +## Security Hall of Fame + +We would like to thank the following security researchers for responsibly disclosing security issues to us. + +- Jeet Pal - [GitHub](https://github.com/jeetpal2007) | [Email](jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290 ) From 6930e60787e4905a50417190263ae7dd46cf5409 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 16 Apr 2024 21:53:25 +0800 Subject: [PATCH 2/4] fix(runtime-core): fix regression for $attrs tracking in slots close #10710 --- .../rendererAttrsFallthrough.spec.ts | 28 +++++++++++++++++++ .../src/componentPublicInstance.ts | 3 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index 79e2867ad69..9c985379c1e 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -20,6 +20,7 @@ import { render, withModifiers, } from '@vue/runtime-dom' +import { createApp } from 'vue' import { PatchFlags } from '@vue/shared' describe('attribute fallthrough', () => { @@ -783,4 +784,31 @@ describe('attribute fallthrough', () => { expect(textBar).toBe('from GrandChild') expect(textFoo).toBe('from Child') }) + + // covers uncaught regression #10710 + it('should track this.$attrs access in slots', async () => { + const GrandChild = { + template: ``, + } + const Child = { + components: { GrandChild }, + template: `
{{ $attrs.foo }}
`, + } + + const obj = ref(1) + const App = { + render() { + return h(Child, { foo: obj.value }) + }, + } + + const root = document.createElement('div') + createApp(App).mount(root) + + expect(root.innerHTML).toBe('
1
') + + obj.value = 2 + await nextTick() + expect(root.innerHTML).toBe('
2
') + }) }) diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index a1b45e4f9cc..b43accfa0a3 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -368,9 +368,10 @@ export const PublicInstanceProxyHandlers: ProxyHandler = { // public $xxx properties if (publicGetter) { if (key === '$attrs') { - track(instance, TrackOpTypes.GET, key) + track(instance.attrs, TrackOpTypes.GET, '') __DEV__ && markAttrsAccessed() } else if (__DEV__ && key === '$slots') { + // for HMR only track(instance, TrackOpTypes.GET, key) } return publicGetter(instance) From 6df53d85a207986128159d88565e6e7045db2add Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 16 Apr 2024 22:47:24 +0800 Subject: [PATCH 3/4] fix(runtime-core): use same internal object mechanism for slots close #10709 --- packages/runtime-core/src/componentProps.ts | 10 ++-------- packages/runtime-core/src/componentSlots.ts | 5 +++-- packages/runtime-core/src/internalObject.ts | 12 ++++++++++++ packages/runtime-core/src/vnode.ts | 8 +++----- 4 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 packages/runtime-core/src/internalObject.ts diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 1c87304185c..5a4292b6f36 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -38,6 +38,7 @@ import { createPropsDefaultThis } from './compat/props' import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig' import { DeprecationTypes } from './compat/compatConfig' import { shouldSkipAttr } from './compat/attrsFallthrough' +import { createInternalObject } from './internalObject' export type ComponentPropsOptions

= | ComponentObjectPropsOptions

@@ -185,13 +186,6 @@ type NormalizedProp = export type NormalizedProps = Record export type NormalizedPropsOptions = [NormalizedProps, string[]] | [] -/** - * Used during vnode props normalization to check if the vnode props is the - * attrs object of a component via `Object.getPrototypeOf`. This is more - * performant than defining a non-enumerable property. - */ -export const attrsProto = {} - export function initProps( instance: ComponentInternalInstance, rawProps: Data | null, @@ -199,7 +193,7 @@ export function initProps( isSSR = false, ) { const props: Data = {} - const attrs: Data = Object.create(attrsProto) + const attrs: Data = createInternalObject() instance.propsDefaults = Object.create(null) diff --git a/packages/runtime-core/src/componentSlots.ts b/packages/runtime-core/src/componentSlots.ts index e0f051b3984..66a09e5fa1a 100644 --- a/packages/runtime-core/src/componentSlots.ts +++ b/packages/runtime-core/src/componentSlots.ts @@ -24,6 +24,7 @@ import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig' import { toRaw } from '@vue/reactivity' import { trigger } from '@vue/reactivity' import { TriggerOpTypes } from '@vue/reactivity' +import { createInternalObject } from './internalObject' export type Slot = ( ...args: IfAny @@ -177,12 +178,12 @@ export const initSlots = ( } else { normalizeObjectSlots( children as RawSlots, - (instance.slots = {}), + (instance.slots = createInternalObject()), instance, ) } } else { - instance.slots = {} + instance.slots = createInternalObject() if (children) { normalizeVNodeSlots(instance, children) } diff --git a/packages/runtime-core/src/internalObject.ts b/packages/runtime-core/src/internalObject.ts new file mode 100644 index 00000000000..0c0c39bef6d --- /dev/null +++ b/packages/runtime-core/src/internalObject.ts @@ -0,0 +1,12 @@ +/** + * Used during vnode props/slots normalization to check if the vnode props/slots + * are the internal attrs / slots object of a component via + * `Object.getPrototypeOf`. This is more performant than defining a + * non-enumerable property. (one of the optimizations done for ssr-benchmark) + */ +const internalObjectProto = Object.create(null) + +export const createInternalObject = () => Object.create(internalObjectProto) + +export const isInternalObject = (obj: object) => + Object.getPrototypeOf(obj) === internalObjectProto diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 28b60be78f2..a1a6a908d2a 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -55,7 +55,7 @@ import { convertLegacyVModelProps } from './compat/componentVModel' import { defineLegacyVNodeProperties } from './compat/renderFn' import { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling' import type { ComponentPublicInstance } from './componentPublicInstance' -import { attrsProto } from './componentProps' +import { isInternalObject } from './internalObject' export const Fragment = Symbol.for('v-fgt') as any as { __isFragment: true @@ -617,9 +617,7 @@ function _createVNode( export function guardReactiveProps(props: (Data & VNodeProps) | null) { if (!props) return null - return isProxy(props) || Object.getPrototypeOf(props) === attrsProto - ? extend({}, props) - : props + return isProxy(props) || isInternalObject(props) ? extend({}, props) : props } export function cloneVNode( @@ -791,7 +789,7 @@ export function normalizeChildren(vnode: VNode, children: unknown) { } else { type = ShapeFlags.SLOTS_CHILDREN const slotFlag = (children as RawSlots)._ - if (!slotFlag) { + if (!slotFlag && !isInternalObject(children)) { // if slots are not normalized, attach context instance // (compiled / normalized slots already have context) ;(children as RawSlots)._ctx = currentRenderingInstance From 46c2b63981b8321be2d8bb1892b74d7e50bdd668 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 16 Apr 2024 22:55:56 +0800 Subject: [PATCH 4/4] release: v3.4.23 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- packages/compiler-core/package.json | 2 +- packages/compiler-dom/package.json | 2 +- packages/compiler-sfc/package.json | 2 +- packages/compiler-ssr/package.json | 2 +- packages/reactivity/package.json | 2 +- packages/runtime-core/package.json | 2 +- packages/runtime-dom/package.json | 2 +- packages/server-renderer/package.json | 2 +- packages/shared/package.json | 2 +- packages/vue-compat/package.json | 2 +- packages/vue/package.json | 2 +- 13 files changed, 22 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0d590a5b8b..4eae200db69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [3.4.23](https://github.com/vuejs/core/compare/v3.4.22...v3.4.23) (2024-04-16) + + +### Bug Fixes + +* **runtime-core:** fix regression for $attrs tracking in slots ([6930e60](https://github.com/vuejs/core/commit/6930e60787e4905a50417190263ae7dd46cf5409)), closes [#10710](https://github.com/vuejs/core/issues/10710) +* **runtime-core:** use same internal object mechanism for slots ([6df53d8](https://github.com/vuejs/core/commit/6df53d85a207986128159d88565e6e7045db2add)), closes [#10709](https://github.com/vuejs/core/issues/10709) + + + ## [3.4.22](https://github.com/vuejs/core/compare/v3.4.21...v3.4.22) (2024-04-15) diff --git a/package.json b/package.json index acb12ffc926..66c831a7b8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "3.4.22", + "version": "3.4.23", "packageManager": "pnpm@8.15.6", "type": "module", "scripts": { diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json index 19d0a416a98..f671478659a 100644 --- a/packages/compiler-core/package.json +++ b/packages/compiler-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-core", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/compiler-core", "main": "index.js", "module": "dist/compiler-core.esm-bundler.js", diff --git a/packages/compiler-dom/package.json b/packages/compiler-dom/package.json index 3826fb2c60c..1b7700aa9ba 100644 --- a/packages/compiler-dom/package.json +++ b/packages/compiler-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-dom", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/compiler-dom", "main": "index.js", "module": "dist/compiler-dom.esm-bundler.js", diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json index 9e732550000..d4f2cb4c717 100644 --- a/packages/compiler-sfc/package.json +++ b/packages/compiler-sfc/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-sfc", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/compiler-sfc", "main": "dist/compiler-sfc.cjs.js", "module": "dist/compiler-sfc.esm-browser.js", diff --git a/packages/compiler-ssr/package.json b/packages/compiler-ssr/package.json index 6e9648f5400..a4972e5c014 100644 --- a/packages/compiler-ssr/package.json +++ b/packages/compiler-ssr/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-ssr", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/compiler-ssr", "main": "dist/compiler-ssr.cjs.js", "types": "dist/compiler-ssr.d.ts", diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index 414083ef6f1..7966c34e412 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@vue/reactivity", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/reactivity", "main": "index.js", "module": "dist/reactivity.esm-bundler.js", diff --git a/packages/runtime-core/package.json b/packages/runtime-core/package.json index 8edddcc32c8..134080b1012 100644 --- a/packages/runtime-core/package.json +++ b/packages/runtime-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-core", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/runtime-core", "main": "index.js", "module": "dist/runtime-core.esm-bundler.js", diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json index 17712da8eed..2f579ff7b13 100644 --- a/packages/runtime-dom/package.json +++ b/packages/runtime-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-dom", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/runtime-dom", "main": "index.js", "module": "dist/runtime-dom.esm-bundler.js", diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index 8cd53da98b5..cc5ea9ad902 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@vue/server-renderer", - "version": "3.4.22", + "version": "3.4.23", "description": "@vue/server-renderer", "main": "index.js", "module": "dist/server-renderer.esm-bundler.js", diff --git a/packages/shared/package.json b/packages/shared/package.json index a227ded9ecb..5d05a5371d9 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@vue/shared", - "version": "3.4.22", + "version": "3.4.23", "description": "internal utils shared across @vue packages", "main": "index.js", "module": "dist/shared.esm-bundler.js", diff --git a/packages/vue-compat/package.json b/packages/vue-compat/package.json index 4c5dd04e3cc..70f9f23b1ba 100644 --- a/packages/vue-compat/package.json +++ b/packages/vue-compat/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compat", - "version": "3.4.22", + "version": "3.4.23", "description": "Vue 3 compatibility build for Vue 2", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js", diff --git a/packages/vue/package.json b/packages/vue/package.json index 1a297293d06..41dd36385b8 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "3.4.22", + "version": "3.4.23", "description": "The progressive JavaScript framework for building modern web UI.", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js",