Skip to content

Commit 35c3608

Browse files
authored
Revert "fix(runtime-core): resolve kebab-case slot names from in-DOM template…" (#14331)
This reverts commit 7e554bf.
1 parent 7e554bf commit 35c3608

File tree

4 files changed

+15
-144
lines changed

4 files changed

+15
-144
lines changed

packages/runtime-core/__tests__/componentSlots.spec.ts

Lines changed: 0 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
} from '@vue/runtime-test'
1212
import { createBlock, normalizeVNode } from '../src/vnode'
1313
import { createSlots } from '../src/helpers/createSlots'
14-
import { renderSlot } from '../src/helpers/renderSlot'
15-
import { setCurrentRenderingInstance } from '../src/componentRenderContext'
1614

1715
describe('component: slots', () => {
1816
function renderWithSlots(slots: any): any {
@@ -463,118 +461,4 @@ describe('component: slots', () => {
463461
createApp(App).mount(root)
464462
expect(serializeInner(root)).toBe('foo')
465463
})
466-
467-
// in-DOM templates use kebab-case slot names
468-
describe('in-DOM template kebab-case slot name resolution', () => {
469-
beforeEach(() => {
470-
__BROWSER__ = true
471-
})
472-
473-
afterEach(() => {
474-
__BROWSER__ = false
475-
})
476-
477-
test('should resolve camelCase slot access to kebab-case via slots', () => {
478-
const Comp = {
479-
setup(_: any, { slots }: any) {
480-
// Access with camelCase, but slot is passed with kebab-case
481-
return () => slots.dropdownRender()
482-
},
483-
}
484-
485-
const App = {
486-
setup() {
487-
// Parent passes slot with kebab-case name (simulating in-DOM template)
488-
return () =>
489-
h(Comp, null, { 'dropdown-render': () => 'dropdown content' })
490-
},
491-
}
492-
493-
const root = nodeOps.createElement('div')
494-
createApp(App).mount(root)
495-
expect(serializeInner(root)).toBe('dropdown content')
496-
})
497-
498-
test('should resolve camelCase slot access to kebab-case via slots (PROD)', () => {
499-
__DEV__ = false
500-
try {
501-
const Comp = {
502-
setup(_: any, { slots }: any) {
503-
// Access with camelCase, but slot is passed with kebab-case
504-
return () => slots.dropdownRender()
505-
},
506-
}
507-
508-
const App = {
509-
setup() {
510-
// Parent passes slot with kebab-case name (simulating in-DOM template)
511-
return () =>
512-
h(Comp, null, { 'dropdown-render': () => 'dropdown content' })
513-
},
514-
}
515-
516-
const root = nodeOps.createElement('div')
517-
createApp(App).mount(root)
518-
expect(serializeInner(root)).toBe('dropdown content')
519-
} finally {
520-
__DEV__ = true
521-
}
522-
})
523-
524-
test('should prefer exact match over kebab-case conversion via slots', () => {
525-
const Comp = {
526-
setup(_: any, { slots }: any) {
527-
return () => slots.dropdownRender()
528-
},
529-
}
530-
531-
const App = {
532-
setup() {
533-
// Both exact match and kebab-case exist
534-
return () =>
535-
h(Comp, null, {
536-
'dropdown-render': () => 'kebab',
537-
dropdownRender: () => 'exact',
538-
})
539-
},
540-
}
541-
542-
const root = nodeOps.createElement('div')
543-
createApp(App).mount(root)
544-
// exact match should take priority
545-
expect(serializeInner(root)).toBe('exact')
546-
})
547-
548-
// renderSlot tests
549-
describe('renderSlot', () => {
550-
beforeEach(() => {
551-
setCurrentRenderingInstance({ type: {} } as any)
552-
})
553-
554-
afterEach(() => {
555-
setCurrentRenderingInstance(null)
556-
})
557-
558-
test('should resolve camelCase slot name to kebab-case via renderSlot', () => {
559-
let child: any
560-
const vnode = renderSlot(
561-
{ 'dropdown-render': () => [(child = h('child'))] },
562-
'dropdownRender',
563-
)
564-
expect(vnode.children).toEqual([child])
565-
})
566-
567-
test('should prefer exact match over kebab-case conversion via renderSlot', () => {
568-
let exactChild: any
569-
const vnode = renderSlot(
570-
{
571-
'dropdown-render': () => [h('kebab')],
572-
dropdownRender: () => [(exactChild = h('exact'))],
573-
},
574-
'dropdownRender',
575-
)
576-
expect(vnode.children).toEqual([exactChild])
577-
})
578-
})
579-
})
580464
})

packages/runtime-core/src/component.ts

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ import {
6666
ShapeFlags,
6767
extend,
6868
getGlobalThis,
69-
hyphenate,
7069
isArray,
7170
isFunction,
7271
isObject,
@@ -1111,20 +1110,17 @@ const attrsProxyHandlers = __DEV__
11111110
},
11121111
}
11131112

1114-
const createSlotsProxyHandlers = (
1115-
instance: ComponentInternalInstance,
1116-
): ProxyHandler<InternalSlots> => ({
1117-
get(target, key: string | symbol) {
1118-
if (__DEV__) {
1113+
/**
1114+
* Dev-only
1115+
*/
1116+
function getSlotsProxy(instance: ComponentInternalInstance): Slots {
1117+
return new Proxy(instance.slots, {
1118+
get(target, key: string) {
11191119
track(instance, TrackOpTypes.GET, '$slots')
1120-
}
1121-
// in-DOM templates use kebab-case slot names, only relevant in browser
1122-
return (
1123-
target[key as string] ||
1124-
(__BROWSER__ && typeof key === 'string' && target[hyphenate(key)])
1125-
)
1126-
},
1127-
})
1120+
return target[key]
1121+
},
1122+
})
1123+
}
11281124

11291125
export function createSetupContext(
11301126
instance: ComponentInternalInstance,
@@ -1166,13 +1162,7 @@ export function createSetupContext(
11661162
)
11671163
},
11681164
get slots() {
1169-
return (
1170-
slotsProxy ||
1171-
(slotsProxy = new Proxy(
1172-
instance.slots,
1173-
createSlotsProxyHandlers(instance),
1174-
))
1175-
)
1165+
return slotsProxy || (slotsProxy = getSlotsProxy(instance))
11761166
},
11771167
get emit() {
11781168
return (event: string, ...args: any[]) => instance.emit(event, ...args)
@@ -1182,9 +1172,7 @@ export function createSetupContext(
11821172
} else {
11831173
return {
11841174
attrs: new Proxy(instance.attrs, attrsProxyHandlers),
1185-
slots: __BROWSER__
1186-
? new Proxy(instance.slots, createSlotsProxyHandlers(instance))
1187-
: instance.slots,
1175+
slots: instance.slots,
11881176
emit: instance.emit,
11891177
expose,
11901178
}

packages/runtime-core/src/components/KeepAlive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ const KeepAliveImpl: ComponentOptions = {
189189
}
190190

191191
// for e2e test
192-
if (__DEV__ && __GLOBAL__) {
192+
if (__DEV__ && __BROWSER__) {
193193
;(instance as any).__keepAliveStorageContainer = storageContainer
194194
}
195195
}

packages/runtime-core/src/helpers/renderSlot.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
isVNode,
1515
openBlock,
1616
} from '../vnode'
17-
import { PatchFlags, SlotFlags, hyphenate, isSymbol } from '@vue/shared'
17+
import { PatchFlags, SlotFlags, isSymbol } from '@vue/shared'
1818
import { warn } from '../warning'
1919
import { isAsyncWrapper } from '../apiAsyncComponent'
2020

@@ -53,8 +53,7 @@ export function renderSlot(
5353
)
5454
}
5555

56-
// in-DOM templates use kebab-case slot names, only relevant in browser
57-
let slot = slots[name] || (__BROWSER__ && slots[hyphenate(name)])
56+
let slot = slots[name]
5857

5958
if (__DEV__ && slot && slot.length > 1) {
6059
warn(

0 commit comments

Comments
 (0)