]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(sfc): inherit parent scopeId on child rooot (#756)
authorhareku <hareku908@gmail.com>
Fri, 21 Feb 2020 13:44:13 +0000 (22:44 +0900)
committerGitHub <noreply@github.com>
Fri, 21 Feb 2020 13:44:13 +0000 (14:44 +0100)
packages/runtime-core/__tests__/helpers/scopeId.spec.ts
packages/runtime-core/src/componentRenderUtils.ts
packages/server-renderer/__tests__/renderToString.spec.ts
packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts
packages/server-renderer/src/helpers/ssrRenderAttrs.ts

index 08f7b1e7d50fab1cf78252e8b9f3eecbaea84e56..b14d3acbc44ffb94bef773ad42e4c433b972d0e3 100644 (file)
@@ -17,6 +17,27 @@ describe('scopeId runtime support', () => {
     expect(serializeInner(root)).toBe(`<div parent><div parent></div></div>`)
   })
 
+  test('should attach scopeId to components in parent component', () => {
+    const Child = {
+      __scopeId: 'child',
+      render: withChildId(() => {
+        return h('div')
+      })
+    }
+    const App = {
+      __scopeId: 'parent',
+      render: withParentId(() => {
+        return h('div', [h(Child)])
+      })
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(App), root)
+    expect(serializeInner(root)).toBe(
+      `<div parent><div parent child></div></div>`
+    )
+  })
+
   test('should work on slots', () => {
     const Child = {
       __scopeId: 'child',
@@ -41,7 +62,7 @@ describe('scopeId runtime support', () => {
     // - scopeId from parent
     // - slotted scopeId (with `-s` postfix) from child (the tree owner)
     expect(serializeInner(root)).toBe(
-      `<div child><div parent child-s></div></div>`
+      `<div parent child><div parent child-s></div></div>`
     )
   })
 })
index 145a3697c5c385751d66c246678ecf01853a90aa..6b3be67279237ed3da9b6596152d8f1f13749dc4 100644 (file)
@@ -39,6 +39,7 @@ export function renderComponentRoot(
 ): VNode {
   const {
     type: Component,
+    parent,
     vnode,
     proxy,
     withProxy,
@@ -102,6 +103,11 @@ export function renderComponentRoot(
     if (vnodeHooks !== EMPTY_OBJ) {
       result = cloneVNode(result, vnodeHooks)
     }
+    // inherit scopeId
+    const parentScopeId = parent && parent.type.__scopeId
+    if (parentScopeId) {
+      result = cloneVNode(result, { [parentScopeId]: '' })
+    }
     // inherit directives
     if (vnode.dirs != null) {
       if (__DEV__ && !isElementRoot(result)) {
@@ -127,6 +133,7 @@ export function renderComponentRoot(
     result = createVNode(Comment)
   }
   currentRenderingInstance = null
+
   return result
 }
 
index 2ac929ac1c4a852170166bba23d24bea42a08778..c8bb79c8746ca32e4094149f47dbec8ae514a70b 100644 (file)
@@ -562,7 +562,7 @@ describe('ssr: renderToString', () => {
       }
 
       expect(await renderToString(h(Parent))).toBe(
-        `<div data-v-child><span data-v-test data-v-child-s>slot</span></div>`
+        `<div data-v-test data-v-child><span data-v-test data-v-child-s>slot</span></div>`
       )
     })
   })
index 87521a49aae412469dd67ecda27a62334af81ba5..38ca843c4db37dcc71bbba905ab782eb4fdeabde 100644 (file)
@@ -26,6 +26,14 @@ describe('ssr: renderAttrs', () => {
     ).toBe(` id="foo" title="bar"`)
   })
 
+  test('empty value attrs', () => {
+    expect(
+      ssrRenderAttrs({
+        'data-v-abc': ''
+      })
+    ).toBe(` data-v-abc`)
+  })
+
   test('escape attrs', () => {
     expect(
       ssrRenderAttrs({
index ef07bac30f1bbf2d15d3d5519262ae403c4f0ee3..d17c0dd11d63721d34e44858f6eb97bb48b63a86 100644 (file)
@@ -53,7 +53,9 @@ export function ssrRenderDynamicAttr(
   if (isBooleanAttr(attrKey)) {
     return value === false ? `` : ` ${attrKey}`
   } else if (isSSRSafeAttrName(attrKey)) {
-    return ` ${attrKey}="${escapeHtml(value)}"`
+    return value === ''
+      ? ` ${attrKey}`
+      : ` ${attrKey}="${escapeHtml(value)}"`
   } else {
     console.warn(
       `[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`