fix(compiler-core): handle template root and template v-if as stable fragments

This commit is contained in:
Evan You 2019-12-12 20:46:20 -05:00
parent f77ae132e5
commit 8ffd79c754
18 changed files with 106 additions and 60 deletions

View File

@ -5,6 +5,7 @@ module.exports = {
__TEST__: true, __TEST__: true,
__VERSION__: require('./package.json').version, __VERSION__: require('./package.json').version,
__BROWSER__: false, __BROWSER__: false,
__BUNDLER__: false,
__RUNTIME_COMPILE__: true, __RUNTIME_COMPILE__: true,
__FEATURE_OPTIONS__: true, __FEATURE_OPTIONS__: true,
__FEATURE_SUSPENSE__: true __FEATURE_SUSPENSE__: true

View File

@ -19,7 +19,7 @@ return function render() {
return (_openBlock(), _createBlock(\\"div\\", null, [ return (_openBlock(), _createBlock(\\"div\\", null, [
_createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */) _createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */)
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
], 2 /* CLASS */)) ], 2 /* CLASS */))
} }
}" }"
@ -42,7 +42,7 @@ return function render() {
return (openBlock(), createBlock(\\"div\\", null, [ return (openBlock(), createBlock(\\"div\\", null, [
createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */) createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */)
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
], 2 /* CLASS */)) ], 2 /* CLASS */))
}" }"
`; `;
@ -64,7 +64,7 @@ export default function render() {
return (openBlock(), createBlock(\\"div\\", null, [ return (openBlock(), createBlock(\\"div\\", null, [
createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */) createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */)
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
], 2 /* CLASS */)) ], 2 /* CLASS */))
}" }"
`; `;

View File

@ -21,6 +21,8 @@ import { transformFor } from '../src/transforms/vFor'
import { transformElement } from '../src/transforms/transformElement' import { transformElement } from '../src/transforms/transformElement'
import { transformSlotOutlet } from '../src/transforms/transformSlotOutlet' import { transformSlotOutlet } from '../src/transforms/transformSlotOutlet'
import { transformText } from '../src/transforms/transformText' import { transformText } from '../src/transforms/transformText'
import { genFlagText } from './testUtils'
import { PatchFlags } from '@vue/shared'
describe('compiler: transform', () => { describe('compiler: transform', () => {
test('context state', () => { test('context state', () => {
@ -352,7 +354,8 @@ describe('compiler: transform', () => {
[ [
{ type: NodeTypes.ELEMENT, tag: `div` }, { type: NodeTypes.ELEMENT, tag: `div` },
{ type: NodeTypes.ELEMENT, tag: `div` } { type: NodeTypes.ELEMENT, tag: `div` }
] ],
genFlagText(PatchFlags.STABLE_FRAGMENT)
]) ])
) )
}) })

View File

@ -235,7 +235,7 @@ return function render() {
return (_openBlock(), _createBlock(\\"p\\", null, [ return (_openBlock(), _createBlock(\\"p\\", null, [
_createVNode(\\"span\\", null, _toString(o + 'foo'), 1 /* TEXT */) _createVNode(\\"span\\", null, _toString(o + 'foo'), 1 /* TEXT */)
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
])) ]))
} }
}" }"
@ -270,7 +270,7 @@ return function render() {
return (_openBlock(), _createBlock(\\"p\\", null, [ return (_openBlock(), _createBlock(\\"p\\", null, [
_createVNode(\\"span\\", null, _toString(o), 1 /* TEXT */) _createVNode(\\"span\\", null, _toString(o), 1 /* TEXT */)
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
])) ]))
} }
}" }"
@ -362,7 +362,7 @@ return function render() {
return (_openBlock(), _createBlock(\\"div\\", _hoisted_1, [ return (_openBlock(), _createBlock(\\"div\\", _hoisted_1, [
_hoisted_2 _hoisted_2
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
])) ]))
} }
}" }"

View File

@ -23,7 +23,7 @@ return function render() {
_createVNode(\\"div\\"), _createVNode(\\"div\\"),
_createTextVNode(_toString(foo) + \\" bar \\" + _toString(baz), 1 /* TEXT */), _createTextVNode(_toString(foo) + \\" bar \\" + _toString(baz), 1 /* TEXT */),
_createVNode(\\"div\\") _createVNode(\\"div\\")
])) ], 64 /* STABLE_FRAGMENT */))
} }
}" }"
`; `;
@ -41,7 +41,7 @@ return function render() {
_createVNode(\\"div\\"), _createVNode(\\"div\\"),
_createTextVNode(\\"hello\\"), _createTextVNode(\\"hello\\"),
_createVNode(\\"div\\") _createVNode(\\"div\\")
])) ], 64 /* STABLE_FRAGMENT */))
} }
}" }"
`; `;
@ -69,7 +69,7 @@ return function render() {
_createVNode(\\"div\\"), _createVNode(\\"div\\"),
_createTextVNode(\\"hello\\"), _createTextVNode(\\"hello\\"),
_createVNode(\\"div\\") _createVNode(\\"div\\")
])) ], 64 /* STABLE_FRAGMENT */))
} }
}" }"
`; `;

View File

@ -9,7 +9,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => {
return (_openBlock(), _createBlock(\\"span\\")) return (_openBlock(), _createBlock(\\"span\\"))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -25,8 +25,8 @@ return function render() {
return (_openBlock(), _createBlock(_Fragment, { key: item }, [ return (_openBlock(), _createBlock(_Fragment, { key: item }, [
\\"hello\\", \\"hello\\",
_createVNode(\\"span\\") _createVNode(\\"span\\")
])) ], 64 /* STABLE_FRAGMENT */))
}), 64 /* KEYED_FRAGMENT */)) }), 128 /* KEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -40,7 +40,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => {
return (_openBlock(), _createBlock(\\"span\\", { key: item })) return (_openBlock(), _createBlock(\\"span\\", { key: item }))
}), 64 /* KEYED_FRAGMENT */)) }), 128 /* KEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -54,7 +54,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item, __, index) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item, __, index) => {
return (_openBlock(), _createBlock(\\"span\\")) return (_openBlock(), _createBlock(\\"span\\"))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -68,7 +68,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (_, __, index) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (_, __, index) => {
return (_openBlock(), _createBlock(\\"span\\")) return (_openBlock(), _createBlock(\\"span\\"))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -82,7 +82,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (_, key, index) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (_, key, index) => {
return (_openBlock(), _createBlock(\\"span\\")) return (_openBlock(), _createBlock(\\"span\\"))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -98,8 +98,8 @@ return function render() {
return (_openBlock(), _createBlock(_Fragment, null, [ return (_openBlock(), _createBlock(_Fragment, null, [
\\"hello\\", \\"hello\\",
_createVNode(\\"span\\") _createVNode(\\"span\\")
])) ], 64 /* STABLE_FRAGMENT */))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -113,7 +113,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => {
return _renderSlot($slots, \\"default\\") return _renderSlot($slots, \\"default\\")
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -127,7 +127,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item) => {
return _renderSlot($slots, \\"default\\") return _renderSlot($slots, \\"default\\")
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -145,7 +145,7 @@ return function render() {
return (_openBlock(), _withDirectives(_createBlock(\\"div\\", null, null, 32 /* NEED_PATCH */), [ return (_openBlock(), _withDirectives(_createBlock(\\"div\\", null, null, 32 /* NEED_PATCH */), [
[_directive_foo] [_directive_foo]
])) ]))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;
@ -160,7 +160,7 @@ return function render() {
return (_openBlock(), ok return (_openBlock(), ok
? _createBlock(_Fragment, { key: 0 }, _renderList(list, (i) => { ? _createBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {
return (_openBlock(), _createBlock(\\"div\\")) return (_openBlock(), _createBlock(\\"div\\"))
}), 128 /* UNKEYED_FRAGMENT */) }), 256 /* UNKEYED_FRAGMENT */)
: _createCommentVNode(\\"v-if\\", true)) : _createCommentVNode(\\"v-if\\", true))
} }
}" }"
@ -175,7 +175,7 @@ return function render() {
return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item, key, index) => { return (_openBlock(false), _createBlock(_Fragment, null, _renderList(items, (item, key, index) => {
return (_openBlock(), _createBlock(\\"span\\")) return (_openBlock(), _createBlock(\\"span\\"))
}), 128 /* UNKEYED_FRAGMENT */)) }), 256 /* UNKEYED_FRAGMENT */))
} }
}" }"
`; `;

View File

@ -11,7 +11,7 @@ return function render() {
[_ctx.one]: ({ foo }) => [toString(foo), toString(_ctx.bar)], [_ctx.one]: ({ foo }) => [toString(foo), toString(_ctx.bar)],
[_ctx.two]: ({ bar }) => [toString(_ctx.foo), toString(bar)], [_ctx.two]: ({ bar }) => [toString(_ctx.foo), toString(bar)],
_compiled: true _compiled: true
}, 256 /* DYNAMIC_SLOTS */)) }, 512 /* DYNAMIC_SLOTS */))
}" }"
`; `;
@ -59,7 +59,7 @@ return function render() {
fn: () => [toString(name)] fn: () => [toString(name)]
} }
}) })
]), 256 /* DYNAMIC_SLOTS */)) ]), 512 /* DYNAMIC_SLOTS */))
}" }"
`; `;
@ -77,7 +77,7 @@ return function render() {
fn: (props) => [toString(props)] fn: (props) => [toString(props)]
} }
: undefined : undefined
]), 256 /* DYNAMIC_SLOTS */)) ]), 512 /* DYNAMIC_SLOTS */))
}" }"
`; `;
@ -105,7 +105,7 @@ return function render() {
name: \\"one\\", name: \\"one\\",
fn: () => [\\"baz\\"] fn: () => [\\"baz\\"]
} }
]), 256 /* DYNAMIC_SLOTS */)) ]), 512 /* DYNAMIC_SLOTS */))
} }
}" }"
`; `;
@ -126,7 +126,7 @@ return function render() {
fn: () => [\\"hello\\"] fn: () => [\\"hello\\"]
} }
: undefined : undefined
]), 256 /* DYNAMIC_SLOTS */)) ]), 512 /* DYNAMIC_SLOTS */))
} }
}" }"
`; `;
@ -159,7 +159,7 @@ return function render() {
createVNode(_component_Inner, null, { createVNode(_component_Inner, null, {
default: ({ bar }) => [toString(foo), toString(bar), toString(_ctx.baz)], default: ({ bar }) => [toString(foo), toString(bar), toString(_ctx.baz)],
_compiled: true _compiled: true
}, 256 /* DYNAMIC_SLOTS */), }, 512 /* DYNAMIC_SLOTS */),
\\" \\", \\" \\",
toString(foo), toString(foo),
toString(_ctx.bar), toString(_ctx.bar),

View File

@ -25,7 +25,7 @@ import {
RENDER_SLOT, RENDER_SLOT,
WITH_DIRECTIVES WITH_DIRECTIVES
} from '../../src/runtimeHelpers' } from '../../src/runtimeHelpers'
import { PatchFlags } from '@vue/runtime-dom' import { PatchFlags } from '@vue/shared'
import { createObjectMatcher, genFlagText } from '../testUtils' import { createObjectMatcher, genFlagText } from '../testUtils'
function parseWithForTransform( function parseWithForTransform(
@ -704,7 +704,8 @@ describe('compiler: v-for', () => {
[ [
{ type: NodeTypes.TEXT, content: `hello` }, { type: NodeTypes.TEXT, content: `hello` },
{ type: NodeTypes.ELEMENT, tag: `span` } { type: NodeTypes.ELEMENT, tag: `span` }
] ],
genFlagText(PatchFlags.STABLE_FRAGMENT)
] ]
}) })
expect(generate(root).code).toMatchSnapshot() expect(generate(root).code).toMatchSnapshot()
@ -784,7 +785,8 @@ describe('compiler: v-for', () => {
[ [
{ type: NodeTypes.TEXT, content: `hello` }, { type: NodeTypes.TEXT, content: `hello` },
{ type: NodeTypes.ELEMENT, tag: `span` } { type: NodeTypes.ELEMENT, tag: `span` }
] ],
genFlagText(PatchFlags.STABLE_FRAGMENT)
] ]
}) })
expect(generate(root).code).toMatchSnapshot() expect(generate(root).code).toMatchSnapshot()

View File

@ -290,8 +290,8 @@ function finalizeRoot(root: RootNode, context: TransformContext) {
helper(FRAGMENT), helper(FRAGMENT),
`null`, `null`,
root.children, root.children,
`${PatchFlags.UNKEYED_FRAGMENT} /* ${ `${PatchFlags.STABLE_FRAGMENT} /* ${
PatchFlagNames[PatchFlags.UNKEYED_FRAGMENT] PatchFlagNames[PatchFlags.STABLE_FRAGMENT]
} */` } */`
]), ]),
context context

View File

@ -146,7 +146,10 @@ export const transformFor = createStructuralDirectiveTransform(
createCallExpression(helper(CREATE_BLOCK), [ createCallExpression(helper(CREATE_BLOCK), [
helper(FRAGMENT), helper(FRAGMENT),
keyProperty ? createObjectExpression([keyProperty]) : `null`, keyProperty ? createObjectExpression([keyProperty]) : `null`,
node.children node.children,
`${PatchFlags.STABLE_FRAGMENT} /* ${
PatchFlagNames[PatchFlags.STABLE_FRAGMENT]
} */`
]), ]),
context context
) )

View File

@ -16,7 +16,7 @@ return function render() {
_createVNode(\\"div\\", null, \\"test\\"), _createVNode(\\"div\\", null, \\"test\\"),
_createVNode(\\"div\\", { style: _hoisted_1 }, \\"red\\"), _createVNode(\\"div\\", { style: _hoisted_1 }, \\"red\\"),
_createVNode(\\"div\\", { style: {color: 'green'} }, null, 4 /* STYLE */) _createVNode(\\"div\\", { style: {color: 'green'} }, null, 4 /* STYLE */)
])) ], 64 /* STABLE_FRAGMENT */))
} }
}" }"
`; `;

View File

@ -34,6 +34,6 @@ export default function render() {
createVNode(\\"img\\", { src: _imports_0 }), createVNode(\\"img\\", { src: _imports_0 }),
createVNode(\\"img\\", { src: _imports_1 }), createVNode(\\"img\\", { src: _imports_1 }),
createVNode(\\"img\\", { src: _imports_1 }) createVNode(\\"img\\", { src: _imports_1 })
])) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;

View File

@ -44,6 +44,6 @@ export default function render() {
src: \\"./logo.png\\", src: \\"./logo.png\\",
srcset: _hoisted_7 srcset: _hoisted_7
}) })
])) ], 64 /* STABLE_FRAGMENT */))
}" }"
`; `;

View File

@ -10,7 +10,8 @@ import {
resetOps, resetOps,
dumpOps, dumpOps,
NodeOpTypes, NodeOpTypes,
serializeInner serializeInner,
createTextVNode
} from '@vue/runtime-test' } from '@vue/runtime-test'
describe('renderer: fragment', () => { describe('renderer: fragment', () => {
@ -110,7 +111,10 @@ describe('renderer: fragment', () => {
createVNode( createVNode(
Fragment, Fragment,
null, null,
[h('div', 'one'), 'two'], [
createVNode('div', null, 'one', PatchFlags.TEXT),
createTextVNode('two')
],
PatchFlags.UNKEYED_FRAGMENT PatchFlags.UNKEYED_FRAGMENT
), ),
root root
@ -121,7 +125,11 @@ describe('renderer: fragment', () => {
createVNode( createVNode(
Fragment, Fragment,
null, null,
[h('div', 'foo'), 'bar', 'baz'], [
createVNode('div', null, 'foo', PatchFlags.TEXT),
createTextVNode('bar'),
createTextVNode('baz')
],
PatchFlags.KEYED_FRAGMENT PatchFlags.KEYED_FRAGMENT
), ),
root root

View File

@ -44,6 +44,7 @@ export const PatchFlags = PublicPatchFlags as {
PROPS: number PROPS: number
NEED_PATCH: number NEED_PATCH: number
FULL_PROPS: number FULL_PROPS: number
STABLE_FRAGMENT: number
KEYED_FRAGMENT: number KEYED_FRAGMENT: number
UNKEYED_FRAGMENT: number UNKEYED_FRAGMENT: number
DYNAMIC_SLOTS: number DYNAMIC_SLOTS: number

View File

@ -654,10 +654,14 @@ export function createRenderer<
const fragmentEndAnchor = (n2.anchor = n1 const fragmentEndAnchor = (n2.anchor = n1
? n1.anchor ? n1.anchor
: hostCreateComment(showID ? `fragment-${devFragmentID}-end` : ''))! : hostCreateComment(showID ? `fragment-${devFragmentID}-end` : ''))!
if (showID) { const { patchFlag } = n2
devFragmentID++ if (patchFlag > 0) {
optimized = true
} }
if (n1 == null) { if (n1 == null) {
if (showID) {
devFragmentID++
}
hostInsert(fragmentStartAnchor, container, anchor) hostInsert(fragmentStartAnchor, container, anchor)
hostInsert(fragmentEndAnchor, container, anchor) hostInsert(fragmentEndAnchor, container, anchor)
// a fragment can only have array children // a fragment can only have array children
@ -673,16 +677,33 @@ export function createRenderer<
optimized optimized
) )
} else { } else {
patchChildren( if (patchFlag & PatchFlags.STABLE_FRAGMENT && n2.dynamicChildren) {
n1, // a stable fragment (template root or <template v-for>) doesn't need to
n2, // patch children order, but it may contain dynamicChildren.
container, patchBlockChildren(
fragmentEndAnchor, n1.dynamicChildren!,
parentComponent, n2.dynamicChildren,
parentSuspense, container,
isSVG, parentComponent,
optimized parentSuspense,
) isSVG
)
} else {
// keyed / unkeyed, or manual fragments.
// for keyed & unkeyed, since they are compiler generated from v-for,
// each child is guarunteed to be a block so the fragment will never
// have dynamicChildren.
patchChildren(
n1,
n2,
container,
fragmentEndAnchor,
parentComponent,
parentSuspense,
isSVG,
optimized
)
}
} }
} }
@ -1033,7 +1054,6 @@ export function createRenderer<
} }
// fast path // fast path
if (patchFlag > 0) { if (patchFlag > 0) {
optimized = true
if (patchFlag & PatchFlags.KEYED_FRAGMENT) { if (patchFlag & PatchFlags.KEYED_FRAGMENT) {
// this could be either fully-keyed or mixed (some keyed some not) // this could be either fully-keyed or mixed (some keyed some not)
// presence of patchFlag means children are guaranteed to be arrays // presence of patchFlag means children are guaranteed to be arrays
@ -1215,7 +1235,7 @@ export function createRenderer<
while (i <= e1 && i <= e2) { while (i <= e1 && i <= e2) {
const n1 = c1[e1] const n1 = c1[e1]
const n2 = optimized const n2 = optimized
? (c2[i] as HostVNode) ? (c2[e2] as HostVNode)
: (c2[e2] = normalizeVNode(c2[e2])) : (c2[e2] = normalizeVNode(c2[e2]))
if (isSameVNodeType(n1, n2)) { if (isSameVNodeType(n1, n2)) {
patch( patch(

View File

@ -47,16 +47,19 @@ export const enum PatchFlags {
// value. // value.
NEED_PATCH = 1 << 5, NEED_PATCH = 1 << 5,
// Indicates a fragment whose children order doesn't change.
STABLE_FRAGMENT = 1 << 6,
// Indicates a fragment with keyed or partially keyed children // Indicates a fragment with keyed or partially keyed children
KEYED_FRAGMENT = 1 << 6, KEYED_FRAGMENT = 1 << 7,
// Indicates a fragment with unkeyed children. // Indicates a fragment with unkeyed children.
UNKEYED_FRAGMENT = 1 << 7, UNKEYED_FRAGMENT = 1 << 8,
// Indicates a component with dynamic slots (e.g. slot that references a v-for // Indicates a component with dynamic slots (e.g. slot that references a v-for
// iterated value, or dynamic slot names). // iterated value, or dynamic slot names).
// Components with this flag are always force updated. // Components with this flag are always force updated.
DYNAMIC_SLOTS = 1 << 8, DYNAMIC_SLOTS = 1 << 9,
// A special flag that indicates that the diffing algorithm should bail out // A special flag that indicates that the diffing algorithm should bail out
// of optimized mode. This is only on block fragments created by renderSlot() // of optimized mode. This is only on block fragments created by renderSlot()
@ -87,6 +90,7 @@ export const PatchFlagNames = {
[PatchFlags.PROPS]: `PROPS`, [PatchFlags.PROPS]: `PROPS`,
[PatchFlags.NEED_PATCH]: `NEED_PATCH`, [PatchFlags.NEED_PATCH]: `NEED_PATCH`,
[PatchFlags.FULL_PROPS]: `FULL_PROPS`, [PatchFlags.FULL_PROPS]: `FULL_PROPS`,
[PatchFlags.STABLE_FRAGMENT]: `STABLE_FRAGMENT`,
[PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`, [PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`,
[PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`, [PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`,
[PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`, [PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`,

View File

@ -14,7 +14,11 @@ export function setupPuppeteer() {
page.on('console', e => { page.on('console', e => {
if (e.type() === 'error') { if (e.type() === 'error') {
console.error(`Error from Puppeteer-loaded page:`, e) const err = e.args()[0] as any
console.error(
`Error from Puppeteer-loaded page:\n`,
err._remoteObject.description
)
} }
}) })
}) })