From 76c024da5802f136889bac3102b564b09432ffad Mon Sep 17 00:00:00 2001 From: daiwei Date: Sun, 1 Dec 2024 15:11:40 +0800 Subject: [PATCH 1/2] wip: save --- packages-private/sfc-playground/src/App.vue | 2 +- .../compiler-vapor/src/generators/event.ts | 44 ++++++++++++++----- packages/runtime-vapor/src/dom/event.ts | 21 ++------- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/packages-private/sfc-playground/src/App.vue b/packages-private/sfc-playground/src/App.vue index 0389c8f51..ea3b3a9de 100644 --- a/packages-private/sfc-playground/src/App.vue +++ b/packages-private/sfc-playground/src/App.vue @@ -57,7 +57,7 @@ const importMap = computed(() => { 'vue/vapor': vapor, }, } - if (useVaporMode.value) vaporImportMap.imports!.vue = vapor + // if (useVaporMode.value) vaporImportMap.imports!.vue = vapor return mergeImportMap(vueImportMap.value, vaporImportMap) }) diff --git a/packages/compiler-vapor/src/generators/event.ts b/packages/compiler-vapor/src/generators/event.ts index 3be9ea4d6..e9c5f4568 100644 --- a/packages/compiler-vapor/src/generators/event.ts +++ b/packages/compiler-vapor/src/generators/event.ts @@ -22,7 +22,9 @@ export function genSetEvent( const { element, key, keyOverride, value, modifiers, delegate, effect } = oper const name = genName() - const handler = genEventHandler(context, value) + let handler = genEventHandler(context, value) + handler = genWithModifiers(context, handler, modifiers.nonKeys) + handler = genWithKeys(context, handler, modifiers.keys) const eventOptions = genEventOptions() if (delegate) { @@ -36,7 +38,7 @@ export function genSetEvent( vaporHelper(delegate ? 'delegate' : 'on'), `n${element}`, name, - handler, + ['() => ', ...handler], eventOptions, ), ] @@ -55,13 +57,11 @@ export function genSetEvent( } function genEventOptions(): CodeFragment[] | undefined { - let { options, keys, nonKeys } = modifiers - if (!options.length && !nonKeys.length && !keys.length && !effect) return + let { options } = modifiers + if (!options.length && !effect) return return genMulti( DELIMITERS_OBJECT_NEWLINE, - !!nonKeys.length && ['modifiers: ', genArrayExpression(nonKeys)], - !!keys.length && ['keys: ', genArrayExpression(keys)], effect && ['effect: true'], ...options.map((option): CodeFragment[] => [`${option}: true`]), ) @@ -83,10 +83,6 @@ export function genSetDynamicEvents( ] } -function genArrayExpression(elements: string[]) { - return `[${elements.map(it => JSON.stringify(it)).join(', ')}]` -} - export function genEventHandler( context: CodegenContext, value: SimpleExpressionNode | undefined, @@ -103,15 +99,39 @@ export function genEventHandler( }) const hasMultipleStatements = value.content.includes(`;`) return [ - '() => $event => ', + '$event => ', hasMultipleStatements ? '{' : '(', ...expr, hasMultipleStatements ? '}' : ')', ] } else { - return ['() => ', ...genExpression(value, context)] + return [...genExpression(value, context)] } } return ['() => {}'] } + +function genWithModifiers( + context: CodegenContext, + handler: CodeFragment[], + nonKeys: string[], +): CodeFragment[] { + if (!nonKeys.length) return handler + + return genCall( + context.helper('withModifiers'), + handler, + JSON.stringify(nonKeys), + ) +} + +function genWithKeys( + context: CodegenContext, + handler: CodeFragment[], + keys: string[], +): CodeFragment[] { + if (!keys.length) return handler + + return genCall(context.helper('withKeys'), handler, JSON.stringify(keys)) +} diff --git a/packages/runtime-vapor/src/dom/event.ts b/packages/runtime-vapor/src/dom/event.ts index caee1bcda..22be1eb87 100644 --- a/packages/runtime-vapor/src/dom/event.ts +++ b/packages/runtime-vapor/src/dom/event.ts @@ -8,7 +8,6 @@ import { getMetadata, recordEventMetadata, } from '../componentMetadata' -import { withKeys, withModifiers } from '@vue/runtime-dom' import { queuePostFlushCb } from '../scheduler' export function addEventListener( @@ -21,19 +20,13 @@ export function addEventListener( return (): void => el.removeEventListener(event, handler, options) } -interface ModifierOptions { - modifiers?: string[] - keys?: string[] -} - export function on( el: Element, event: string, handlerGetter: () => undefined | ((...args: any[]) => any), - options: AddEventListenerOptions & - ModifierOptions & { effect?: boolean } = {}, + options: AddEventListenerOptions & { effect?: boolean } = {}, ): void { - const handler: DelegatedHandler = eventHandler(handlerGetter, options) + const handler: DelegatedHandler = eventHandler(handlerGetter) let cleanupEvent: (() => void) | undefined queuePostFlushCb(() => { cleanupEvent = addEventListener(el, event, handler, options) @@ -59,23 +52,17 @@ export function delegate( el: HTMLElement, event: string, handlerGetter: () => undefined | ((...args: any[]) => any), - options: ModifierOptions = {}, ): void { - const handler: DelegatedHandler = eventHandler(handlerGetter, options) + const handler: DelegatedHandler = eventHandler(handlerGetter) handler.delegate = true recordEventMetadata(el, event, handler) } -function eventHandler( - getter: () => undefined | ((...args: any[]) => any), - { modifiers, keys }: ModifierOptions = {}, -) { +function eventHandler(getter: () => undefined | ((...args: any[]) => any)) { return (...args: any[]) => { let handler = getter() if (!handler) return - if (modifiers) handler = withModifiers(handler, modifiers as any[]) - if (keys) handler = withKeys(handler, keys) handler && handler(...args) } } From 95bd6864272c19e59cefb446ad01bf97deddb61e Mon Sep 17 00:00:00 2001 From: daiwei Date: Sun, 1 Dec 2024 15:33:27 +0800 Subject: [PATCH 2/2] wip: update test --- .../transformElement.spec.ts.snap | 11 +- .../transforms/__snapshots__/vOn.spec.ts.snap | 153 ++++++------------ .../__tests__/transforms/vOn.spec.ts | 13 +- .../compiler-vapor/src/generators/event.ts | 26 +-- 4 files changed, 76 insertions(+), 127 deletions(-) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap index 79b8fffbb..3d342a43c 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap @@ -309,18 +309,15 @@ export function render(_ctx) { `; exports[`compiler: element transform > props merging: event handlers 1`] = ` -"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withKeys as _withKeys } from 'vue'; +import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("
") _delegateEvents("click") export function render(_ctx) { const n0 = t0() - _delegate(n0, "click", () => _ctx.a, { - keys: ["foo"] - }) - _delegate(n0, "click", () => _ctx.b, { - keys: ["bar"] - }) + _delegate(n0, "click", () => _withKeys(_ctx.a, ["foo"])) + _delegate(n0, "click", () => _withKeys(_ctx.b, ["bar"])) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap index cbd195b83..bb88e89f7 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap @@ -58,7 +58,8 @@ export function render(_ctx) { `; exports[`v-on > event modifier 1`] = ` -"import { delegate as _delegate, on as _on, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers, withKeys as _withKeys } from 'vue'; +import { delegate as _delegate, on as _on, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("") const t1 = _template("
") const t2 = _template("
") @@ -88,18 +89,10 @@ export function render(_ctx, $props, $emit, $attrs, $slots) { const n19 = t3() const n20 = t3() const n21 = t3() - _delegate(n0, "click", () => _ctx.handleEvent, { - modifiers: ["stop"] - }) - _on(n1, "submit", () => _ctx.handleEvent, { - modifiers: ["prevent"] - }) - _delegate(n2, "click", () => _ctx.handleEvent, { - modifiers: ["stop", "prevent"] - }) - _delegate(n3, "click", () => _ctx.handleEvent, { - modifiers: ["self"] - }) + _delegate(n0, "click", () => _withModifiers(_ctx.handleEvent, ["stop"])) + _on(n1, "submit", () => _withModifiers(_ctx.handleEvent, ["prevent"])) + _delegate(n2, "click", () => _withModifiers(_ctx.handleEvent, ["stop","prevent"])) + _delegate(n3, "click", () => _withModifiers(_ctx.handleEvent, ["self"])) _on(n4, "click", () => _ctx.handleEvent, { capture: true }) @@ -109,53 +102,21 @@ export function render(_ctx, $props, $emit, $attrs, $slots) { _on(n6, "scroll", () => _ctx.handleEvent, { passive: true }) - _delegate(n7, "contextmenu", () => _ctx.handleEvent, { - modifiers: ["right"] - }) - _delegate(n8, "click", () => _ctx.handleEvent, { - modifiers: ["left"] - }) - _delegate(n9, "mouseup", () => _ctx.handleEvent, { - modifiers: ["middle"] - }) - _delegate(n10, "contextmenu", () => _ctx.handleEvent, { - modifiers: ["right"], - keys: ["enter"] - }) - _delegate(n11, "keyup", () => _ctx.handleEvent, { - keys: ["enter"] - }) - _delegate(n12, "keyup", () => _ctx.handleEvent, { - keys: ["tab"] - }) - _delegate(n13, "keyup", () => _ctx.handleEvent, { - keys: ["delete"] - }) - _delegate(n14, "keyup", () => _ctx.handleEvent, { - keys: ["esc"] - }) - _delegate(n15, "keyup", () => _ctx.handleEvent, { - keys: ["space"] - }) - _delegate(n16, "keyup", () => _ctx.handleEvent, { - keys: ["up"] - }) - _delegate(n17, "keyup", () => _ctx.handleEvent, { - keys: ["down"] - }) - _delegate(n18, "keyup", () => _ctx.handleEvent, { - keys: ["left"] - }) - _delegate(n19, "keyup", () => _ctx.submit, { - modifiers: ["middle"] - }) - _delegate(n20, "keyup", () => _ctx.submit, { - modifiers: ["middle", "self"] - }) - _delegate(n21, "keyup", () => _ctx.handleEvent, { - modifiers: ["self"], - keys: ["enter"] - }) + _delegate(n7, "contextmenu", () => _withModifiers(_ctx.handleEvent, ["right"])) + _delegate(n8, "click", () => _withModifiers(_ctx.handleEvent, ["left"])) + _delegate(n9, "mouseup", () => _withModifiers(_ctx.handleEvent, ["middle"])) + _delegate(n10, "contextmenu", () => _withKeys(_withModifiers(_ctx.handleEvent, ["right"]), ["enter"])) + _delegate(n11, "keyup", () => _withKeys(_ctx.handleEvent, ["enter"])) + _delegate(n12, "keyup", () => _withKeys(_ctx.handleEvent, ["tab"])) + _delegate(n13, "keyup", () => _withKeys(_ctx.handleEvent, ["delete"])) + _delegate(n14, "keyup", () => _withKeys(_ctx.handleEvent, ["esc"])) + _delegate(n15, "keyup", () => _withKeys(_ctx.handleEvent, ["space"])) + _delegate(n16, "keyup", () => _withKeys(_ctx.handleEvent, ["up"])) + _delegate(n17, "keyup", () => _withKeys(_ctx.handleEvent, ["down"])) + _delegate(n18, "keyup", () => _withKeys(_ctx.handleEvent, ["left"])) + _delegate(n19, "keyup", () => _withModifiers(_ctx.submit, ["middle"])) + _delegate(n20, "keyup", () => _withModifiers(_ctx.submit, ["middle","self"])) + _delegate(n21, "keyup", () => _withKeys(_withModifiers(_ctx.handleEvent, ["self"]), ["enter"])) return [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20, n21] }" `; @@ -312,44 +273,40 @@ export function render(_ctx) { `; exports[`v-on > should not wrap keys guard if no key modifier is present 1`] = ` -"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers } from 'vue'; +import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("
") _delegateEvents("keyup") export function render(_ctx) { const n0 = t0() - _delegate(n0, "keyup", () => _ctx.test, { - modifiers: ["exact"] - }) + _delegate(n0, "keyup", () => _withModifiers(_ctx.test, ["exact"])) return n0 }" `; exports[`v-on > should support multiple events and modifiers options w/ prefixIdentifiers: true 1`] = ` -"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers, withKeys as _withKeys } from 'vue'; +import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("
") _delegateEvents("click", "keyup") export function render(_ctx) { const n0 = t0() - _delegate(n0, "click", () => _ctx.test, { - modifiers: ["stop"] - }) - _delegate(n0, "keyup", () => _ctx.test, { - keys: ["enter"] - }) + _delegate(n0, "click", () => _withModifiers(_ctx.test, ["stop"])) + _delegate(n0, "keyup", () => _withKeys(_ctx.test, ["enter"])) return n0 }" `; exports[`v-on > should support multiple modifiers and event options w/ prefixIdentifiers: true 1`] = ` -"import { on as _on, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers } from 'vue'; +import { on as _on, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _on(n0, "click", () => _ctx.test, { - modifiers: ["stop", "prevent"], + _on(n0, "click", () => _withModifiers(_ctx.test, ["stop","prevent"]), { capture: true, once: true }) @@ -358,28 +315,27 @@ export function render(_ctx) { `; exports[`v-on > should transform click.middle 1`] = ` -"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers } from 'vue'; +import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("
") _delegateEvents("mouseup") export function render(_ctx) { const n0 = t0() - _delegate(n0, "mouseup", () => _ctx.test, { - modifiers: ["middle"] - }) + _delegate(n0, "mouseup", () => _withModifiers(_ctx.test, ["middle"])) return n0 }" `; exports[`v-on > should transform click.middle 2`] = ` -"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers } from 'vue'; +import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() _renderEffect(() => { - _on(n0, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _ctx.test, { - modifiers: ["middle"], + _on(n0, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _withModifiers(_ctx.test, ["middle"]), { effect: true }) }) @@ -388,29 +344,27 @@ export function render(_ctx) { `; exports[`v-on > should transform click.right 1`] = ` -"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers } from 'vue'; +import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("
") _delegateEvents("contextmenu") export function render(_ctx) { const n0 = t0() - _delegate(n0, "contextmenu", () => _ctx.test, { - modifiers: ["right"] - }) + _delegate(n0, "contextmenu", () => _withModifiers(_ctx.test, ["right"])) return n0 }" `; exports[`v-on > should transform click.right 2`] = ` -"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers, withKeys as _withKeys } from 'vue'; +import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() _renderEffect(() => { - _on(n0, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _ctx.test, { - modifiers: ["right"], - keys: ["right"], + _on(n0, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _withKeys(_withModifiers(_ctx.test, ["right"]), ["right"]), { effect: true }) }) @@ -431,15 +385,14 @@ export function render(_ctx) { `; exports[`v-on > should wrap both for dynamic key event w/ left/right modifiers 1`] = ` -"import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers, withKeys as _withKeys } from 'vue'; +import { renderEffect as _renderEffect, on as _on, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() _renderEffect(() => { - _on(n0, _ctx.e, () => _ctx.test, { - modifiers: ["left"], - keys: ["left"], + _on(n0, _ctx.e, () => _withKeys(_withModifiers(_ctx.test, ["left"]), ["left"]), { effect: true }) }) @@ -460,14 +413,13 @@ exports[`v-on > should wrap in unref if identifier is setup-maybe-ref w/ inline: `; exports[`v-on > should wrap keys guard for keyboard events or dynamic events 1`] = ` -"import { on as _on, template as _template } from 'vue/vapor'; +"import { withModifiers as _withModifiers, withKeys as _withKeys } from 'vue'; +import { on as _on, template as _template } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() - _on(n0, "keydown", () => _ctx.test, { - modifiers: ["stop", "ctrl"], - keys: ["a"], + _on(n0, "keydown", () => _withKeys(_withModifiers(_ctx.test, ["stop","ctrl"]), ["a"]), { capture: true }) return n0 @@ -475,15 +427,14 @@ export function render(_ctx) { `; exports[`v-on > should wrap keys guard for static key event w/ left/right modifiers 1`] = ` -"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; +"import { withKeys as _withKeys } from 'vue'; +import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue/vapor'; const t0 = _template("
") _delegateEvents("keyup") export function render(_ctx) { const n0 = t0() - _delegate(n0, "keyup", () => _ctx.test, { - keys: ["left"] - }) + _delegate(n0, "keyup", () => _withKeys(_ctx.test, ["left"])) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts index 3c74c1971..3555b8c67 100644 --- a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts @@ -481,8 +481,7 @@ describe('v-on', () => { }, ]) expect(code).contains( - `_on(n0, "click", () => _ctx.test, { - modifiers: ["stop", "prevent"], + `_on(n0, "click", () => _withModifiers(_ctx.test, ["stop","prevent"]), { capture: true, once: true })`, @@ -541,14 +540,12 @@ describe('v-on', () => { expect(code).matchSnapshot() expect(code).contains( - `_delegate(n0, "click", () => _ctx.test, { - modifiers: ["stop"] - })`, + `_delegate(n0, "click", () => _withModifiers(_ctx.test, ["stop"])`, ) - expect(code).contains(`_delegate(n0, "keyup", () => _ctx.test, { - keys: ["enter"] - })`) + expect(code).contains( + `_delegate(n0, "keyup", () => _withKeys(_ctx.test, ["enter"])`, + ) }) test('should wrap keys guard for keyboard events or dynamic events', () => { diff --git a/packages/compiler-vapor/src/generators/event.ts b/packages/compiler-vapor/src/generators/event.ts index e9c5f4568..a59969731 100644 --- a/packages/compiler-vapor/src/generators/event.ts +++ b/packages/compiler-vapor/src/generators/event.ts @@ -22,9 +22,7 @@ export function genSetEvent( const { element, key, keyOverride, value, modifiers, delegate, effect } = oper const name = genName() - let handler = genEventHandler(context, value) - handler = genWithModifiers(context, handler, modifiers.nonKeys) - handler = genWithKeys(context, handler, modifiers.keys) + const handler = genEventHandler(context, value, modifiers) const eventOptions = genEventOptions() if (delegate) { @@ -38,7 +36,7 @@ export function genSetEvent( vaporHelper(delegate ? 'delegate' : 'on'), `n${element}`, name, - ['() => ', ...handler], + handler, eventOptions, ), ] @@ -86,7 +84,12 @@ export function genSetDynamicEvents( export function genEventHandler( context: CodegenContext, value: SimpleExpressionNode | undefined, + modifiers: { + nonKeys: string[] + keys: string[] + } = { nonKeys: [], keys: [] }, ): CodeFragment[] { + let handlerExp: CodeFragment[] = [`{}`] if (value && value.content.trim()) { const isMemberExp = isMemberExpression(value, context.options) const isInlineStatement = !( @@ -98,18 +101,23 @@ export function genEventHandler( $event: null, }) const hasMultipleStatements = value.content.includes(`;`) - return [ + handlerExp = [ '$event => ', hasMultipleStatements ? '{' : '(', ...expr, hasMultipleStatements ? '}' : ')', ] } else { - return [...genExpression(value, context)] + handlerExp = [...genExpression(value, context)] } } - return ['() => {}'] + const { keys, nonKeys } = modifiers + if (nonKeys.length) + handlerExp = genWithModifiers(context, handlerExp, nonKeys) + if (keys.length) handlerExp = genWithKeys(context, handlerExp, keys) + + return [`() => `, ...handlerExp] } function genWithModifiers( @@ -117,8 +125,6 @@ function genWithModifiers( handler: CodeFragment[], nonKeys: string[], ): CodeFragment[] { - if (!nonKeys.length) return handler - return genCall( context.helper('withModifiers'), handler, @@ -131,7 +137,5 @@ function genWithKeys( handler: CodeFragment[], keys: string[], ): CodeFragment[] { - if (!keys.length) return handler - return genCall(context.helper('withKeys'), handler, JSON.stringify(keys)) }