A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/vuejs/vue-next/commit/201060717d4498b4b7933bf8a8513866ab9347e4 below:

should not track dynamic children when the user ca… · vuejs/core@2010607 · GitHub

File tree Expand file treeCollapse file tree 7 files changed

+175

-34

lines changed

Filter options

Expand file treeCollapse file tree 7 files changed

+175

-34

lines changed Original file line number Diff line number Diff line change

@@ -2,6 +2,7 @@ import {

2 2

h,

3 3

Fragment,

4 4

createVNode,

5 +

createCommentVNode,

5 6

openBlock,

6 7

createBlock,

7 8

render,

@@ -576,4 +577,119 @@ describe('renderer: optimized mode', () => {

576 577

await nextTick()

577 578

expect(inner(root)).toBe('<div>World</div>')

578 579

})

580 + 581 +

// #3548

582 +

test('should not track dynamic children when the user calls a compiled slot inside template expression', () => {

583 +

const Comp = {

584 +

setup(props: any, { slots }: SetupContext) {

585 +

return () => {

586 +

return (

587 +

openBlock(),

588 +

(block = createBlock('section', null, [

589 +

renderSlot(slots, 'default')

590 +

]))

591 +

)

592 +

}

593 +

}

594 +

}

595 + 596 +

let dynamicVNode: VNode

597 +

const Wrapper = {

598 +

setup(props: any, { slots }: SetupContext) {

599 +

return () => {

600 +

return (

601 +

openBlock(),

602 +

createBlock(Comp, null, {

603 +

default: withCtx(() => {

604 +

return [

605 +

(dynamicVNode = createVNode(

606 +

'div',

607 +

{

608 +

class: {

609 +

foo: !!slots.default!()

610 +

}

611 +

},

612 +

null,

613 +

PatchFlags.CLASS

614 +

))

615 +

]

616 +

}),

617 +

_: 1

618 +

})

619 +

)

620 +

}

621 +

}

622 +

}

623 +

const app = createApp({

624 +

render() {

625 +

return (

626 +

openBlock(),

627 +

createBlock(Wrapper, null, {

628 +

default: withCtx(() => {

629 +

return [createVNode({}) /* component */]

630 +

}),

631 +

_: 1

632 +

})

633 +

)

634 +

}

635 +

})

636 + 637 +

app.mount(root)

638 +

expect(inner(root)).toBe('<section><div class="foo"></div></section>')

639 +

/**

640 +

* Block Tree:

641 +

* - block(div)

642 +

* - block(Fragment): renderSlots()

643 +

* - dynamicVNode

644 +

*/

645 +

expect(block!.dynamicChildren!.length).toBe(1)

646 +

expect(block!.dynamicChildren![0].dynamicChildren!.length).toBe(1)

647 +

expect(block!.dynamicChildren![0].dynamicChildren![0]).toEqual(

648 +

dynamicVNode!

649 +

)

650 +

})

651 + 652 +

// 3569

653 +

test('should force bailout when the user manually calls the slot function', async () => {

654 +

const index = ref(0)

655 +

const Foo = {

656 +

setup(props: any, { slots }: SetupContext) {

657 +

return () => {

658 +

return slots.default!()[index.value]

659 +

}

660 +

}

661 +

}

662 + 663 +

const app = createApp({

664 +

setup() {

665 +

return () => {

666 +

return (

667 +

openBlock(),

668 +

createBlock(Foo, null, {

669 +

default: withCtx(() => [

670 +

true

671 +

? (openBlock(), createBlock('p', { key: 0 }, '1'))

672 +

: createCommentVNode('v-if', true),

673 +

true

674 +

? (openBlock(), createBlock('p', { key: 0 }, '2'))

675 +

: createCommentVNode('v-if', true)

676 +

]),

677 +

_: 1 /* STABLE */

678 +

})

679 +

)

680 +

}

681 +

}

682 +

})

683 + 684 +

app.mount(root)

685 +

expect(inner(root)).toBe('<p>1</p>')

686 + 687 +

index.value = 1

688 +

await nextTick()

689 +

expect(inner(root)).toBe('<p>2</p>')

690 + 691 +

index.value = 0

692 +

await nextTick()

693 +

expect(inner(root)).toBe('<p>1</p>')

694 +

})

579 695

})

Original file line number Diff line number Diff line change

@@ -37,6 +37,7 @@ import {

37 37

import { resolveFilter } from '../helpers/resolveAssets'

38 38

import { resolveMergedOptions } from '../componentOptions'

39 39

import { InternalSlots, Slots } from '../componentSlots'

40 +

import { ContextualRenderFn } from '../componentRenderContext'

40 41 41 42

export type LegacyPublicInstance = ComponentPublicInstance &

42 43

LegacyPublicProperties

@@ -106,7 +107,7 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {

106 107

const res: InternalSlots = {}

107 108

for (const key in i.slots) {

108 109

const fn = i.slots[key]!

109 -

if (!(fn as any)._nonScoped) {

110 +

if (!(fn as ContextualRenderFn)._ns /* non-scoped slot */) {

110 111

res[key] = fn

111 112

}

112 113

}

Original file line number Diff line number Diff line change

@@ -281,7 +281,7 @@ function convertLegacySlots(vnode: VNode): VNode {

281 281

for (const key in slots) {

282 282

const slotChildren = slots[key]

283 283

slots[key] = () => slotChildren

284 -

slots[key]._nonScoped = true

284 +

slots[key]._ns = true /* non-scoped slot */

285 285

}

286 286

}

287 287

}

Original file line number Diff line number Diff line change

@@ -1,7 +1,6 @@

1 1

import { ComponentInternalInstance } from './component'

2 2

import { devtoolsComponentUpdated } from './devtools'

3 -

import { isRenderingCompiledSlot } from './helpers/renderSlot'

4 -

import { closeBlock, openBlock } from './vnode'

3 +

import { setBlockTracking } from './vnode'

5 4 6 5

/**

7 6

* mark the current rendering instance for asset resolution (e.g.

@@ -56,6 +55,14 @@ export function popScopeId() {

56 55

*/

57 56

export const withScopeId = (_id: string) => withCtx

58 57 58 +

export type ContextualRenderFn = {

59 +

(...args: any[]): any

60 +

_n: boolean /* already normalized */

61 +

_c: boolean /* compiled */

62 +

_d: boolean /* disableTracking */

63 +

_ns: boolean /* nonScoped */

64 +

}

65 + 59 66

/**

60 67

* Wrap a slot function to memoize current rendering instance

61 68

* @private compiler helper

@@ -66,18 +73,26 @@ export function withCtx(

66 73

isNonScopedSlot?: boolean // __COMPAT__ only

67 74

) {

68 75

if (!ctx) return fn

69 -

const renderFnWithContext = (...args: any[]) => {

76 + 77 +

// already normalized

78 +

if ((fn as ContextualRenderFn)._n) {

79 +

return fn

80 +

}

81 + 82 +

const renderFnWithContext: ContextualRenderFn = (...args: any[]) => {

70 83

// If a user calls a compiled slot inside a template expression (#1745), it

71 -

// can mess up block tracking, so by default we need to push a null block to

72 -

// avoid that. This isn't necessary if rendering a compiled `<slot>`.

73 -

if (!isRenderingCompiledSlot) {

74 -

openBlock(true /* null block that disables tracking */)

84 +

// can mess up block tracking, so by default we disable block tracking and

85 +

// force bail out when invoking a compiled slot (indicated by the ._d flag).

86 +

// This isn't necessary if rendering a compiled `<slot>`, so we flip the

87 +

// ._d flag off when invoking the wrapped fn inside `renderSlot`.

88 +

if (renderFnWithContext._d) {

89 +

setBlockTracking(-1)

75 90

}

76 91

const prevInstance = setCurrentRenderingInstance(ctx)

77 92

const res = fn(...args)

78 93

setCurrentRenderingInstance(prevInstance)

79 -

if (!isRenderingCompiledSlot) {

80 -

closeBlock()

94 +

if (renderFnWithContext._d) {

95 +

setBlockTracking(1)

81 96

}

82 97 83 98

if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {

@@ -86,13 +101,18 @@ export function withCtx(

86 101 87 102

return res

88 103

}

89 -

// mark this as a compiled slot function.

104 + 105 +

// mark normalized to avoid duplicated wrapping

106 +

renderFnWithContext._n = true

107 +

// mark this as compiled by default

90 108

// this is used in vnode.ts -> normalizeChildren() to set the slot

91 109

// rendering flag.

92 -

// also used to cache the normalized results to avoid repeated normalization

93 -

renderFnWithContext._c = renderFnWithContext

110 +

renderFnWithContext._c = true

111 +

// disable block tracking by default

112 +

renderFnWithContext._d = true

113 +

// compat build only flag to distinguish scoped slots from non-scoped ones

94 114

if (__COMPAT__ && isNonScopedSlot) {

95 -

renderFnWithContext._nonScoped = true

115 +

renderFnWithContext._ns = true

96 116

}

97 117

return renderFnWithContext

98 118

}

Original file line number Diff line number Diff line change

@@ -17,7 +17,7 @@ import {

17 17

} from '@vue/shared'

18 18

import { warn } from './warning'

19 19

import { isKeepAlive } from './components/KeepAlive'

20 -

import { withCtx } from './componentRenderContext'

20 +

import { ContextualRenderFn, withCtx } from './componentRenderContext'

21 21

import { isHmrUpdating } from './hmr'

22 22

import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'

23 23

import { toRaw } from '@vue/reactivity'

@@ -62,9 +62,8 @@ const normalizeSlot = (

62 62

key: string,

63 63

rawSlot: Function,

64 64

ctx: ComponentInternalInstance | null | undefined

65 -

): Slot =>

66 -

(rawSlot as any)._c ||

67 -

(withCtx((props: any) => {

65 +

): Slot => {

66 +

const normalized = withCtx((props: any) => {

68 67

if (__DEV__ && currentInstance) {

69 68

warn(

70 69

`Slot "${key}" invoked outside of the render function: ` +

@@ -73,7 +72,11 @@ const normalizeSlot = (

73 72

)

74 73

}

75 74

return normalizeSlotValue(rawSlot(props))

76 -

}, ctx) as Slot)

75 +

}, ctx) as Slot

76 +

// NOT a compiled slot

77 +

;(normalized as ContextualRenderFn)._c = false

78 +

return normalized

79 +

}

77 80 78 81

const normalizeObjectSlots = (

79 82

rawSlots: RawSlots,

Original file line number Diff line number Diff line change

@@ -1,5 +1,6 @@

1 1

import { Data } from '../component'

2 2

import { Slots, RawSlots } from '../componentSlots'

3 +

import { ContextualRenderFn } from '../componentRenderContext'

3 4

import { Comment, isVNode } from '../vnode'

4 5

import {

5 6

VNodeArrayChildren,

@@ -11,10 +12,6 @@ import {

11 12

import { PatchFlags, SlotFlags } from '@vue/shared'

12 13

import { warn } from '../warning'

13 14 14 -

export let isRenderingCompiledSlot = 0

15 -

export const setCompiledSlotRendering = (n: number) =>

16 -

(isRenderingCompiledSlot += n)

17 - 18 15

/**

19 16

* Compiler runtime helper for rendering `<slot/>`

20 17

* @private

@@ -43,7 +40,9 @@ export function renderSlot(

43 40

// invocation interfering with template-based block tracking, but in

44 41

// `renderSlot` we can be sure that it's template-based so we can force

45 42

// enable it.

46 -

isRenderingCompiledSlot++

43 +

if (slot && (slot as ContextualRenderFn)._c) {

44 +

;(slot as ContextualRenderFn)._d = false

45 +

}

47 46

openBlock()

48 47

const validSlotContent = slot && ensureValidVNode(slot(props))

49 48

const rendered = createBlock(

@@ -57,7 +56,9 @@ export function renderSlot(

57 56

if (!noSlotted && rendered.scopeId) {

58 57

rendered.slotScopeIds = [rendered.scopeId + '-s']

59 58

}

60 -

isRenderingCompiledSlot--

59 +

if (slot && (slot as ContextualRenderFn)._c) {

60 +

;(slot as ContextualRenderFn)._d = true

61 +

}

61 62

return rendered

62 63

}

63 64 Original file line number Diff line number Diff line change

@@ -40,7 +40,6 @@ import {

40 40

import { RendererNode, RendererElement } from './renderer'

41 41

import { NULL_DYNAMIC_COMPONENT } from './helpers/resolveAssets'

42 42

import { hmrDirtyComponents } from './hmr'

43 -

import { setCompiledSlotRendering } from './helpers/renderSlot'

44 43

import { convertLegacyComponent } from './compat/component'

45 44

import { convertLegacyVModelProps } from './compat/componentVModel'

46 45

import { defineLegacyVNodeProperties } from './compat/renderFn'

@@ -218,7 +217,7 @@ export function closeBlock() {

218 217

// Only tracks when this value is > 0

219 218

// We are not using a simple boolean because this value may need to be

220 219

// incremented/decremented by nested usage of v-once (see below)

221 -

let shouldTrack = 1

220 +

let isBlockTreeEnabled = 1

222 221 223 222

/**

224 223

* Block tracking sometimes needs to be disabled, for example during the

@@ -237,7 +236,7 @@ let shouldTrack = 1

237 236

* @private

238 237

*/

239 238

export function setBlockTracking(value: number) {

240 -

shouldTrack += value

239 +

isBlockTreeEnabled += value

241 240

}

242 241 243 242

/**

@@ -263,12 +262,13 @@ export function createBlock(

263 262

true /* isBlock: prevent a block from tracking itself */

264 263

)

265 264

// save current block children on the block vnode

266 -

vnode.dynamicChildren = currentBlock || (EMPTY_ARR as any)

265 +

vnode.dynamicChildren =

266 +

isBlockTreeEnabled > 0 ? currentBlock || (EMPTY_ARR as any) : null

267 267

// close block

268 268

closeBlock()

269 269

// a block is always going to be patched, so track it as a child of its

270 270

// parent block

271 -

if (shouldTrack > 0 && currentBlock) {

271 +

if (isBlockTreeEnabled > 0 && currentBlock) {

272 272

currentBlock.push(vnode)

273 273

}

274 274

return vnode

@@ -458,7 +458,7 @@ function _createVNode(

458 458

}

459 459 460 460

if (

461 -

shouldTrack > 0 &&

461 +

isBlockTreeEnabled > 0 &&

462 462

// avoid a block node from tracking itself

463 463

!isBlockNode &&

464 464

// has current parent block

@@ -635,9 +635,9 @@ export function normalizeChildren(vnode: VNode, children: unknown) {

635 635

const slot = (children as any).default

636 636

if (slot) {

637 637

// _c marker is added by withCtx() indicating this is a compiled slot

638 -

slot._c && setCompiledSlotRendering(1)

638 +

slot._c && (slot._d = false)

639 639

normalizeChildren(vnode, slot())

640 -

slot._c && setCompiledSlotRendering(-1)

640 +

slot._c && (slot._d = true)

641 641

}

642 642

return

643 643

} else {

You can’t perform that action at this time.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4