Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(runtime-core): use correct container for patch Teleport inside … #1703

Merged
merged 5 commits into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/compiler-core/src/transforms/transformElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import {
MERGE_PROPS,
TO_HANDLERS,
TELEPORT,
KEEP_ALIVE
KEEP_ALIVE,
SUSPENSE
} from '../runtimeHelpers'
import {
getInnerRange,
Expand Down Expand Up @@ -89,6 +90,8 @@ export const transformElement: NodeTransform = (node, context) => {
let shouldUseBlock =
// dynamic component may resolve to plain elements
isDynamicComponent ||
vnodeTag === TELEPORT ||
vnodeTag === SUSPENSE ||
(!isComponent &&
// <svg> and <foreignObject> must be forced into blocks so that block
// updates inside get proper isSVG flag at runtime. (#639, #643)
Expand Down
49 changes: 48 additions & 1 deletion packages/runtime-core/__tests__/components/Teleport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
Teleport,
Text,
ref,
nextTick
nextTick,
markRaw
} from '@vue/runtime-test'
import { createVNode, Fragment } from '../../src/vnode'
import { compile } from 'vue'

describe('renderer: teleport', () => {
test('should work', () => {
Expand Down Expand Up @@ -299,4 +301,49 @@ describe('renderer: teleport', () => {
)
expect(serializeInner(target)).toBe('')
})

test('should work with block tree', async () => {
const target = nodeOps.createElement('div')
const root = nodeOps.createElement('div')
const disabled = ref(false)

const App = {
setup() {
return {
target: markRaw(target),
disabled
}
},
render: compile(`
<teleport :to="target" :disabled="disabled">
<div>teleported</div><span>{{ disabled }}</span>
</teleport>
<div>root</div>
`)
}
render(h(App), root)
expect(serializeInner(root)).toMatchInlineSnapshot(
`"<!--teleport start--><!--teleport end--><div>root</div>"`
)
expect(serializeInner(target)).toMatchInlineSnapshot(
`"<div>teleported</div><span>false</span>"`
)

disabled.value = true
await nextTick()
expect(serializeInner(root)).toMatchInlineSnapshot(
`"<!--teleport start--><div>teleported</div><span>true</span><!--teleport end--><div>root</div>"`
)
expect(serializeInner(target)).toBe(``)

// toggle back
disabled.value = false
await nextTick()
expect(serializeInner(root)).toMatchInlineSnapshot(
`"<!--teleport start--><!--teleport end--><div>root</div>"`
)
expect(serializeInner(target)).toMatchInlineSnapshot(
`"<div>teleported</div><span>false</span>"`
)
})
})
2 changes: 0 additions & 2 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,6 @@ function finishComponentSetup(
if (__DEV__) {
endMeasure(instance, `compile`)
}
// mark the function as runtime compiled
;(Component.render as InternalRenderFunction)._rc = true
}

instance.render = (Component.render || NOOP) as InternalRenderFunction
Expand Down
7 changes: 7 additions & 0 deletions packages/runtime-core/src/components/Teleport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ export const TeleportImpl = {
parentSuspense,
isSVG
)
if (n2.patchFlag > 0 && n2.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
const oldChildren = n1.children as VNode[]
const children = n2.children as VNode[]
for (let i = 0; i < children.length; i++) {
children[i].el = oldChildren[i].el
}
}
} else if (!optimized) {
patchChildren(
n1,
Expand Down
3 changes: 2 additions & 1 deletion packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,8 @@ function baseCreateRenderer(
// which also requires the correct parent container
!isSameVNodeType(oldVNode, newVNode) ||
// - In the case of a component, it could contain anything.
oldVNode.shapeFlag & ShapeFlags.COMPONENT
oldVNode.shapeFlag & ShapeFlags.COMPONENT ||
oldVNode.shapeFlag & ShapeFlags.TELEPORT
? hostParentNode(oldVNode.el!)!
: // In other cases, the parent container is not actually used so we
// just pass the block element here to avoid a DOM parentNode call.
Expand Down
6 changes: 1 addition & 5 deletions packages/runtime-core/src/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,7 @@ function _createVNode(
// the EVENTS flag is only for hydration and if it is the only flag, the
// vnode should not be considered dynamic due to handler caching.
patchFlag !== PatchFlags.HYDRATE_EVENTS &&
(patchFlag > 0 ||
shapeFlag & ShapeFlags.SUSPENSE ||
shapeFlag & ShapeFlags.TELEPORT ||
shapeFlag & ShapeFlags.STATEFUL_COMPONENT ||
shapeFlag & ShapeFlags.FUNCTIONAL_COMPONENT)
(patchFlag > 0 || shapeFlag & ShapeFlags.COMPONENT)
) {
currentBlock.push(vnode)
}
Expand Down
5 changes: 5 additions & 0 deletions packages/vue/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { compile, CompilerOptions, CompilerError } from '@vue/compiler-dom'
import { registerRuntimeCompiler, RenderFunction, warn } from '@vue/runtime-dom'
import * as runtimeDom from '@vue/runtime-dom'
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
import { InternalRenderFunction } from 'packages/runtime-core/src/component'

__DEV__ && initDev()

Expand Down Expand Up @@ -74,6 +75,10 @@ function compileToFunction(
const render = (__GLOBAL__
? new Function(code)()
: new Function('Vue', code)(runtimeDom)) as RenderFunction

// mark the function as runtime compiled
;(render as InternalRenderFunction)._rc = true

return (compileCache[key] = render)
}

Expand Down