Skip to content

Commit

Permalink
fix(runtime-core): registered custom elements should have all properi…
Browse files Browse the repository at this point in the history
…tes bound. fixes #7203
  • Loading branch information
steveworkman committed Jan 12, 2023
1 parent 510abf9 commit 81587b3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 12 deletions.
28 changes: 17 additions & 11 deletions packages/runtime-core/__tests__/hydration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,14 @@ describe('SSR hydration', () => {

test('element with text children', async () => {
const msg = ref('foo')
const { vnode, container } = mountWithHydration(
'<div class="foo">foo</div>',
() => h('div', { class: msg.value }, msg.value)
const app = mountWithHydration('<div class="foo">foo</div>', () =>
h('div', { class: msg.value }, msg.value)
)
expect(vnode.el).toBe(container.firstChild)
expect(container.firstChild!.textContent).toBe('foo')
expect(app.vnode.el).toBe(app.container.firstChild)
expect(app.container.firstChild!.textContent).toBe('foo')
msg.value = 'bar'
await nextTick()
expect(container.innerHTML).toBe(`<div class="bar">bar</div>`)
expect(app.container.innerHTML).toBe(`<div class="bar">bar</div>`)
})

test('element with elements children', async () => {
Expand Down Expand Up @@ -943,12 +942,19 @@ describe('SSR hydration', () => {
}
}
customElements.define('my-element', MyElement)

const msg = ref('bar')
const { container } = mountWithHydration(
'<my-element :foo="msg"></my-element>',
() => h('my-element', { foo: msg.value })
)
expect((container.firstChild as any).foo).toBe(msg.value)
const container = document.createElement('div')
container.innerHTML = '<my-element :foo="msg"></my-element>'
const app = createSSRApp({
render: () => h('my-element', { foo: msg.value })
})
// isCustomElement MUST be set at runtime
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('my-')
const vnode = app.mount(container).$.subTree as VNode<Node, Element> & {
el: Element
}
expect((vnode.el as any).foo).toBe(msg.value)
})

// #5728
Expand Down
7 changes: 6 additions & 1 deletion packages/runtime-core/src/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ export function createHydrationFunctions(
// #4006 for form elements with non-string v-model value bindings
// e.g. <option :value="obj">, <input type="checkbox" :true-value="1">
const forcePatchValue = (type === 'input' && dirs) || type === 'option'
// #7203 elements registered as custom elements should have all properties bound
const isCustomElement =
parentComponent?.appContext.config.compilerOptions.isCustomElement?.(
el.localName
)
// skip props & children if this is hoisted static nodes
// #5405 in dev, always hydrate children for HMR
if (__DEV__ || forcePatchValue || patchFlag !== PatchFlags.HOISTED) {
Expand All @@ -328,7 +333,7 @@ export function createHydrationFunctions(
if (
(forcePatchValue && key.endsWith('value')) ||
(isOn(key) && !isReservedProp(key)) ||
customElements.get(el.localName) // If the element is a custom element, apply vue props during hydration - See #7203
isCustomElement
) {
patchProp(
el,
Expand Down

0 comments on commit 81587b3

Please sign in to comment.