From 04d2c05054c26b02fbc1d84839b0ed5cd36455b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20L=C3=BCnborg?= Date: Sat, 16 Dec 2023 14:54:37 +0100 Subject: [PATCH 1/4] fix(runtime-dom): cache event handlers by key/modifiers (#9851) close #9849 --- .../__tests__/directives/vOn.spec.ts | 28 +++++++++++++++++++ packages/runtime-dom/src/directives/vOn.ts | 17 +++++++---- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/runtime-dom/__tests__/directives/vOn.spec.ts b/packages/runtime-dom/__tests__/directives/vOn.spec.ts index 2a4b02478f5..33ffec637df 100644 --- a/packages/runtime-dom/__tests__/directives/vOn.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vOn.spec.ts @@ -135,4 +135,32 @@ describe('runtime-dom: v-on directive', () => { handler(event, 'value', true) expect(fn).toBeCalledWith(event, 'value', true) }) + + it('withKeys cache wrapped listener separately for different modifiers', () => { + const el1 = document.createElement('button') + const el2 = document.createElement('button') + const fn = vi.fn() + const handler1 = withKeys(fn, ['a']) + const handler2 = withKeys(fn, ['b']) + expect(handler1 === handler2).toBe(false) + patchEvent(el1, 'onKeyup', null, handler1, null) + patchEvent(el2, 'onKeyup', null, handler2, null) + triggerEvent(el1, 'keyup', e => (e.key = 'a')) + triggerEvent(el2, 'keyup', e => (e.key = 'b')) + expect(fn).toBeCalledTimes(2) + }) + + it('withModifiers cache wrapped listener separately for different modifiers', () => { + const el1 = document.createElement('button') + const el2 = document.createElement('button') + const fn = vi.fn() + const handler1 = withModifiers(fn, ['ctrl']) + const handler2 = withModifiers(fn, ['shift']) + expect(handler1 === handler2).toBe(false) + patchEvent(el1, 'onClick', null, handler1, null) + patchEvent(el2, 'onClick', null, handler2, null) + triggerEvent(el1, 'click', e => (e.ctrlKey = true)) + triggerEvent(el2, 'click', e => (e.shiftKey = true)) + expect(fn).toBeCalledTimes(2) + }) }) diff --git a/packages/runtime-dom/src/directives/vOn.ts b/packages/runtime-dom/src/directives/vOn.ts index 8054efb9ea5..823c3fb4c41 100644 --- a/packages/runtime-dom/src/directives/vOn.ts +++ b/packages/runtime-dom/src/directives/vOn.ts @@ -35,12 +35,14 @@ const modifierGuards: Record< export const withModifiers = < T extends (event: Event, ...args: unknown[]) => any >( - fn: T & { _withMods?: T }, + fn: T & { _withMods?: { [key: string]: T } }, modifiers: string[] ) => { + const cache = fn._withMods || (fn._withMods = {}) + const cacheKey = modifiers.join('.') return ( - fn._withMods || - (fn._withMods = ((event, ...args) => { + cache[cacheKey] || + (cache[cacheKey] = ((event, ...args) => { for (let i = 0; i < modifiers.length; i++) { const guard = modifierGuards[modifiers[i]] if (guard && guard(event, modifiers)) return @@ -66,7 +68,7 @@ const keyNames: Record = { * @private */ export const withKeys = any>( - fn: T & { _withKeys?: T }, + fn: T & { _withKeys?: { [k: string]: T } }, modifiers: string[] ) => { let globalKeyCodes: LegacyConfig['keyCodes'] @@ -88,9 +90,12 @@ export const withKeys = any>( } } + const cache: { [k: string]: T } = fn._withKeys || (fn._withKeys = {}) + const cacheKey = modifiers.join('.') + return ( - fn._withKeys || - (fn._withKeys = (event => { + cache[cacheKey] || + (cache[cacheKey] = (event => { if (!('key' in event)) { return } From 24b1c1dd57fd55d998aa231a147500e010b10219 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 19 Dec 2023 10:05:29 +0100 Subject: [PATCH 2/4] fix(types): extract properties from extended collections (#9854) close #9852 --- packages/dts-test/reactivity.test-d.ts | 23 +++++++++++++++++++++++ packages/reactivity/src/ref.ts | 9 +++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/dts-test/reactivity.test-d.ts b/packages/dts-test/reactivity.test-d.ts index 431bbafbdf4..e0d8e207f0d 100644 --- a/packages/dts-test/reactivity.test-d.ts +++ b/packages/dts-test/reactivity.test-d.ts @@ -77,6 +77,18 @@ describe('should unwrap Map correctly', () => { expectType(wm2.get({})!.wrap) }) +describe('should unwrap extended Map correctly', () => { + class ExtendendMap1 extends Map }> { + foo = ref('foo') + bar = 1 + } + + const emap1 = reactive(new ExtendendMap1()) + expectType(emap1.foo) + expectType(emap1.bar) + expectType(emap1.get('a')!.wrap) +}) + describe('should unwrap Set correctly', () => { const set = reactive(new Set>()) expectType>>(set) @@ -90,3 +102,14 @@ describe('should unwrap Set correctly', () => { const ws2 = reactive(new WeakSet<{ wrap: Ref }>()) expectType>(ws2) }) + +describe('should unwrap extended Set correctly', () => { + class ExtendendSet1 extends Set<{ wrap: Ref }> { + foo = ref('foo') + bar = 1 + } + + const eset1 = reactive(new ExtendendSet1()) + expectType(eset1.foo) + expectType(eset1.bar) +}) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index a85c79c0bc6..e156a2e1134 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -500,13 +500,14 @@ export type UnwrapRefSimple = T extends | { [RawSymbol]?: true } ? T : T extends Map - ? Map> + ? Map> & UnwrapRef>> : T extends WeakMap - ? WeakMap> + ? WeakMap> & + UnwrapRef>> : T extends Set - ? Set> + ? Set> & UnwrapRef>> : T extends WeakSet - ? WeakSet> + ? WeakSet> & UnwrapRef>> : T extends ReadonlyArray ? { [K in keyof T]: UnwrapRefSimple } : T extends object & { [ShallowReactiveMarker]?: never } From bae79ddf8564a2da4a5365cfeb8d811990f42335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Tue, 19 Dec 2023 17:08:46 +0800 Subject: [PATCH 3/4] fix(compiler-core): fix v-on with modifiers on inline expression of undefined (#9866) close #9865 improve isMemberExpression check for undefined --- packages/compiler-core/__tests__/utils.spec.ts | 4 ++++ packages/compiler-core/src/utils.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/compiler-core/__tests__/utils.spec.ts b/packages/compiler-core/__tests__/utils.spec.ts index 45fa46fea7a..f2ea70cc51d 100644 --- a/packages/compiler-core/__tests__/utils.spec.ts +++ b/packages/compiler-core/__tests__/utils.spec.ts @@ -122,6 +122,10 @@ describe('isMemberExpression', () => { expect(fn(`123[a]`)).toBe(true) expect(fn(`foo() as string`)).toBe(false) expect(fn(`a + b as string`)).toBe(false) + // #9865 + expect(fn('""')).toBe(false) + expect(fn('undefined')).toBe(false) + expect(fn('null')).toBe(false) }) }) diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index baffe5086f6..fe4141507bc 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -163,7 +163,7 @@ export const isMemberExpressionNode = __BROWSER__ return ( ret.type === 'MemberExpression' || ret.type === 'OptionalMemberExpression' || - ret.type === 'Identifier' + (ret.type === 'Identifier' && ret.name !== 'undefined') ) } catch (e) { return false From 7c49a9c4d8adea88eb9af1d98437cf03ddc30128 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 19 Dec 2023 18:12:48 +0800 Subject: [PATCH 4/4] release: v3.3.13 --- CHANGELOG.md | 11 +++++++++++ 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-transform/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 +- 14 files changed, 24 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 697a618d82c..d71b7273754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [3.3.13](https://github.com/vuejs/core/compare/v3.3.12...v3.3.13) (2023-12-19) + + +### Bug Fixes + +* **compiler-core:** fix v-on with modifiers on inline expression of undefined ([#9866](https://github.com/vuejs/core/issues/9866)) ([bae79dd](https://github.com/vuejs/core/commit/bae79ddf8564a2da4a5365cfeb8d811990f42335)), closes [#9865](https://github.com/vuejs/core/issues/9865) +* **runtime-dom:** cache event handlers by key/modifiers ([#9851](https://github.com/vuejs/core/issues/9851)) ([04d2c05](https://github.com/vuejs/core/commit/04d2c05054c26b02fbc1d84839b0ed5cd36455b6)), closes [#9849](https://github.com/vuejs/core/issues/9849) +* **types:** extract properties from extended collections ([#9854](https://github.com/vuejs/core/issues/9854)) ([24b1c1d](https://github.com/vuejs/core/commit/24b1c1dd57fd55d998aa231a147500e010b10219)), closes [#9852](https://github.com/vuejs/core/issues/9852) + + + ## [3.3.12](https://github.com/vuejs/core/compare/v3.3.11...v3.3.12) (2023-12-16) diff --git a/package.json b/package.json index f5f09039247..61d41bfd85a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "3.3.12", + "version": "3.3.13", "packageManager": "pnpm@8.12.0", "type": "module", "scripts": { diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json index 3ef0bc597f7..6d9df3f06e1 100644 --- a/packages/compiler-core/package.json +++ b/packages/compiler-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-core", - "version": "3.3.12", + "version": "3.3.13", "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 d2de4b35ef2..2f052cd36e8 100644 --- a/packages/compiler-dom/package.json +++ b/packages/compiler-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-dom", - "version": "3.3.12", + "version": "3.3.13", "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 db05be865c7..f578317436e 100644 --- a/packages/compiler-sfc/package.json +++ b/packages/compiler-sfc/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-sfc", - "version": "3.3.12", + "version": "3.3.13", "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 70a8fbc2cac..0a653d18509 100644 --- a/packages/compiler-ssr/package.json +++ b/packages/compiler-ssr/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-ssr", - "version": "3.3.12", + "version": "3.3.13", "description": "@vue/compiler-ssr", "main": "dist/compiler-ssr.cjs.js", "types": "dist/compiler-ssr.d.ts", diff --git a/packages/reactivity-transform/package.json b/packages/reactivity-transform/package.json index c0268e9c4f0..2b684055606 100644 --- a/packages/reactivity-transform/package.json +++ b/packages/reactivity-transform/package.json @@ -1,6 +1,6 @@ { "name": "@vue/reactivity-transform", - "version": "3.3.12", + "version": "3.3.13", "description": "@vue/reactivity-transform", "main": "dist/reactivity-transform.cjs.js", "files": [ diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index 10e40f205c3..1a0a0e3b925 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@vue/reactivity", - "version": "3.3.12", + "version": "3.3.13", "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 46187a138d5..5744b2c0caf 100644 --- a/packages/runtime-core/package.json +++ b/packages/runtime-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-core", - "version": "3.3.12", + "version": "3.3.13", "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 7b4eb90607b..26109898aa9 100644 --- a/packages/runtime-dom/package.json +++ b/packages/runtime-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-dom", - "version": "3.3.12", + "version": "3.3.13", "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 e0bcfa42c1d..1210c1d02b2 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@vue/server-renderer", - "version": "3.3.12", + "version": "3.3.13", "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 8484847818e..ecf538cea0c 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@vue/shared", - "version": "3.3.12", + "version": "3.3.13", "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 cf6180b8863..a00acf24ae1 100644 --- a/packages/vue-compat/package.json +++ b/packages/vue-compat/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compat", - "version": "3.3.12", + "version": "3.3.13", "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 317e0754f4f..fbcfdd0a46c 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "3.3.12", + "version": "3.3.13", "description": "The progressive JavaScript framework for building modern web UI.", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js",