@vue/compiler-ssr 3.2.34-beta.1 → 3.2.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -82,7 +82,7 @@ function processIfBranch(branch, context, disableNestedFragments = false) {
82
82
  (children.length !== 1 || children[0].type !== 1 /* ELEMENT */) &&
83
83
  // optimize away nested fragments when the only child is a ForNode
84
84
  !(children.length === 1 && children[0].type === 11 /* FOR */);
85
- return processChildrenAsStatement(children, context, needFragmentWrapper);
85
+ return processChildrenAsStatement(branch, context, needFragmentWrapper);
86
86
  }
87
87
 
88
88
  // Plugin for the first transform pass, which simply constructs the AST node
@@ -93,7 +93,7 @@ function ssrProcessFor(node, context, disableNestedFragments = false) {
93
93
  const needFragmentWrapper = !disableNestedFragments &&
94
94
  (node.children.length !== 1 || node.children[0].type !== 1 /* ELEMENT */);
95
95
  const renderLoop = compilerDom.createFunctionExpression(compilerDom.createForLoopParams(node.parseResult));
96
- renderLoop.body = processChildrenAsStatement(node.children, context, needFragmentWrapper);
96
+ renderLoop.body = processChildrenAsStatement(node, context, needFragmentWrapper);
97
97
  // v-for always renders a fragment unless explicitly disabled
98
98
  if (!disableNestedFragments) {
99
99
  context.pushStringPart(`<!--[-->`);
@@ -144,7 +144,7 @@ function ssrProcessSlotOutlet(node, context) {
144
144
  // has fallback content
145
145
  if (node.children.length) {
146
146
  const fallbackRenderFn = compilerDom.createFunctionExpression([]);
147
- fallbackRenderFn.body = processChildrenAsStatement(node.children, context);
147
+ fallbackRenderFn.body = processChildrenAsStatement(node, context);
148
148
  // _renderSlot(slots, name, props, fallback, ...)
149
149
  renderCall.arguments[3] = fallbackRenderFn;
150
150
  }
@@ -196,7 +196,7 @@ function ssrProcessTeleport(node, context) {
196
196
  true, // newline
197
197
  false, // isSlot
198
198
  node.loc);
199
- contentRenderFn.body = processChildrenAsStatement(node.children, context);
199
+ contentRenderFn.body = processChildrenAsStatement(node, context);
200
200
  context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_TELEPORT), [
201
201
  `_push`,
202
202
  contentRenderFn,
@@ -239,8 +239,8 @@ function ssrProcessSuspense(node, context) {
239
239
  }
240
240
  const { slotsExp, wipSlots } = wipEntry;
241
241
  for (let i = 0; i < wipSlots.length; i++) {
242
- const { fn, children } = wipSlots[i];
243
- fn.body = processChildrenAsStatement(children, context);
242
+ const slot = wipSlots[i];
243
+ slot.fn.body = processChildrenAsStatement(slot, context);
244
244
  }
245
245
  // _push(ssrRenderSuspense(slots))
246
246
  context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [
@@ -249,39 +249,6 @@ function ssrProcessSuspense(node, context) {
249
249
  ]));
250
250
  }
251
251
 
252
- function ssrProcessTransitionGroup(node, context) {
253
- const tag = compilerDom.findProp(node, 'tag');
254
- if (tag) {
255
- if (tag.type === 7 /* DIRECTIVE */) {
256
- // dynamic :tag
257
- context.pushStringPart(`<`);
258
- context.pushStringPart(tag.exp);
259
- context.pushStringPart(`>`);
260
- processChildren(node.children, context, false,
261
- /**
262
- * TransitionGroup has the special runtime behavior of flattening and
263
- * concatenating all children into a single fragment (in order for them to
264
- * be patched using the same key map) so we need to account for that here
265
- * by disabling nested fragment wrappers from being generated.
266
- */
267
- true);
268
- context.pushStringPart(`</`);
269
- context.pushStringPart(tag.exp);
270
- context.pushStringPart(`>`);
271
- }
272
- else {
273
- // static tag
274
- context.pushStringPart(`<${tag.value.content}>`);
275
- processChildren(node.children, context, false, true);
276
- context.pushStringPart(`</${tag.value.content}>`);
277
- }
278
- }
279
- else {
280
- // fragment
281
- processChildren(node.children, context, true, true);
282
- }
283
- }
284
-
285
252
  // for directives with children overwrite (e.g. v-html & v-text), we need to
286
253
  // store the raw children so that they can be added in the 2nd pass.
287
254
  const rawChildrenMap = new WeakMap();
@@ -303,7 +270,7 @@ const ssrTransformElement = (node, context) => {
303
270
  const hasCustomDir = node.props.some(p => p.type === 7 /* DIRECTIVE */ && !shared.isBuiltInDirective(p.name));
304
271
  const needMergeProps = hasDynamicVBind || hasCustomDir;
305
272
  if (needMergeProps) {
306
- const { props, directives } = compilerDom.buildProps(node, context, node.props, true /* ssr */);
273
+ const { props, directives } = compilerDom.buildProps(node, context, node.props, false /* isComponent */, false /* isDynamicComponent */, true /* ssr */);
307
274
  if (props || directives.length) {
308
275
  const mergedProps = buildSSRProps(props, directives, context);
309
276
  const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [mergedProps]);
@@ -382,7 +349,7 @@ const ssrTransformElement = (node, context) => {
382
349
  node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
383
350
  }
384
351
  }
385
- else if (!needMergeProps) {
352
+ else if (!needMergeProps && prop.name !== 'on') {
386
353
  // Directive transforms.
387
354
  const directiveTransform = context.directiveTransforms[prop.name];
388
355
  if (directiveTransform) {
@@ -547,7 +514,7 @@ function ssrProcessElement(node, context) {
547
514
  context.pushStringPart(rawChildren);
548
515
  }
549
516
  else if (node.children.length) {
550
- processChildren(node.children, context);
517
+ processChildren(node, context);
551
518
  }
552
519
  if (!isVoidTag(node.tag)) {
553
520
  // push closing tag
@@ -555,11 +522,75 @@ function ssrProcessElement(node, context) {
555
522
  }
556
523
  }
557
524
 
525
+ const wipMap$1 = new WeakMap();
526
+ // phase 1: build props
527
+ function ssrTransformTransitionGroup(node, context) {
528
+ return () => {
529
+ const tag = compilerDom.findProp(node, 'tag');
530
+ if (tag) {
531
+ const otherProps = node.props.filter(p => p !== tag);
532
+ const { props, directives } = compilerDom.buildProps(node, context, otherProps, true, /* isComponent */ false, /* isDynamicComponent */ true /* ssr (skip event listeners) */);
533
+ let propsExp = null;
534
+ if (props || directives.length) {
535
+ propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [
536
+ buildSSRProps(props, directives, context)
537
+ ]);
538
+ }
539
+ wipMap$1.set(node, {
540
+ tag,
541
+ propsExp
542
+ });
543
+ }
544
+ };
545
+ }
546
+ // phase 2: process children
547
+ function ssrProcessTransitionGroup(node, context) {
548
+ const entry = wipMap$1.get(node);
549
+ if (entry) {
550
+ const { tag, propsExp } = entry;
551
+ if (tag.type === 7 /* DIRECTIVE */) {
552
+ // dynamic :tag
553
+ context.pushStringPart(`<`);
554
+ context.pushStringPart(tag.exp);
555
+ if (propsExp) {
556
+ context.pushStringPart(propsExp);
557
+ }
558
+ context.pushStringPart(`>`);
559
+ processChildren(node, context, false,
560
+ /**
561
+ * TransitionGroup has the special runtime behavior of flattening and
562
+ * concatenating all children into a single fragment (in order for them to
563
+ * be patched using the same key map) so we need to account for that here
564
+ * by disabling nested fragment wrappers from being generated.
565
+ */
566
+ true);
567
+ context.pushStringPart(`</`);
568
+ context.pushStringPart(tag.exp);
569
+ context.pushStringPart(`>`);
570
+ }
571
+ else {
572
+ // static tag
573
+ context.pushStringPart(`<${tag.value.content}`);
574
+ if (propsExp) {
575
+ context.pushStringPart(propsExp);
576
+ }
577
+ context.pushStringPart(`>`);
578
+ processChildren(node, context, false, true);
579
+ context.pushStringPart(`</${tag.value.content}>`);
580
+ }
581
+ }
582
+ else {
583
+ // fragment
584
+ processChildren(node, context, true, true);
585
+ }
586
+ }
587
+
558
588
  // We need to construct the slot functions in the 1st pass to ensure proper
559
589
  // scope tracking, but the children of each slot cannot be processed until
560
590
  // the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
561
591
  // pass and complete them in the 2nd pass.
562
- const wipMap$1 = new WeakMap();
592
+ const wipMap$2 = new WeakMap();
593
+ const WIP_SLOT = Symbol();
563
594
  const componentTypeMap = new WeakMap();
564
595
  // ssr component transform is done in two phases:
565
596
  // In phase 1. we use `buildSlot` to analyze the children of the component into
@@ -573,12 +604,16 @@ const ssrTransformComponent = (node, context) => {
573
604
  return;
574
605
  }
575
606
  const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
607
+ const isDynamicComponent = shared.isObject(component) && component.callee === compilerDom.RESOLVE_DYNAMIC_COMPONENT;
576
608
  componentTypeMap.set(node, component);
577
609
  if (shared.isSymbol(component)) {
578
610
  if (component === compilerDom.SUSPENSE) {
579
611
  return ssrTransformSuspense(node, context);
580
612
  }
581
- return; // built-in component: fallthrough
613
+ if (component === compilerDom.TRANSITION_GROUP) {
614
+ return ssrTransformTransitionGroup(node, context);
615
+ }
616
+ return; // other built-in components: fallthrough
582
617
  }
583
618
  // Build the fallback vnode-based branch for the component's slots.
584
619
  // We need to clone the node into a fresh copy and use the buildSlots' logic
@@ -602,19 +637,20 @@ const ssrTransformComponent = (node, context) => {
602
637
  if (node.props.length) {
603
638
  // note we are not passing ssr: true here because for components, v-on
604
639
  // handlers should still be passed
605
- const { props, directives } = compilerDom.buildProps(node, context);
640
+ const { props, directives } = compilerDom.buildProps(node, context, undefined, true, isDynamicComponent);
606
641
  if (props || directives.length) {
607
642
  propsExp = buildSSRProps(props, directives, context);
608
643
  }
609
644
  }
610
645
  const wipEntries = [];
611
- wipMap$1.set(node, wipEntries);
646
+ wipMap$2.set(node, wipEntries);
612
647
  const buildSSRSlotFn = (props, children, loc) => {
613
648
  const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
614
649
  true, // newline
615
650
  true, // isSlot
616
651
  loc);
617
652
  wipEntries.push({
653
+ type: WIP_SLOT,
618
654
  fn,
619
655
  children,
620
656
  // also collect the corresponding vnode branch built earlier
@@ -644,7 +680,7 @@ const ssrTransformComponent = (node, context) => {
644
680
  }
645
681
  };
646
682
  };
647
- function ssrProcessComponent(node, context) {
683
+ function ssrProcessComponent(node, context, parent) {
648
684
  const component = componentTypeMap.get(node);
649
685
  if (!node.ssrCodegenNode) {
650
686
  // this is a built-in component that fell-through.
@@ -660,19 +696,29 @@ function ssrProcessComponent(node, context) {
660
696
  else {
661
697
  // real fall-through: Transition / KeepAlive
662
698
  // just render its children.
663
- processChildren(node.children, context);
699
+ // #5352: if is at root level of a slot, push an empty string.
700
+ // this does not affect the final output, but avoids all-comment slot
701
+ // content of being treated as empty by ssrRenderSlot().
702
+ if (parent.type === WIP_SLOT) {
703
+ context.pushStringPart(``);
704
+ }
705
+ // #5351: filter out comment children inside transition
706
+ if (component === compilerDom.TRANSITION) {
707
+ node.children = node.children.filter(c => c.type !== 3 /* COMMENT */);
708
+ }
709
+ processChildren(node, context);
664
710
  }
665
711
  }
666
712
  else {
667
713
  // finish up slot function expressions from the 1st pass.
668
- const wipEntries = wipMap$1.get(node) || [];
714
+ const wipEntries = wipMap$2.get(node) || [];
669
715
  for (let i = 0; i < wipEntries.length; i++) {
670
- const { fn, children, vnodeBranch } = wipEntries[i];
716
+ const { fn, vnodeBranch } = wipEntries[i];
671
717
  // For each slot, we generate two branches: one SSR-optimized branch and
672
718
  // one normal vnode-based branch. The branches are taken based on the
673
719
  // presence of the 2nd `_push` argument (which is only present if the slot
674
720
  // is called by `_ssrRenderSlot`.
675
- fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(children, context, false, true /* withSlotScopeId */), vnodeBranch);
721
+ fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(wipEntries[i], context, false, true /* withSlotScopeId */), vnodeBranch);
676
722
  }
677
723
  // component is inside a slot, inherit slot scope Id
678
724
  if (context.withSlotScopeId) {
@@ -801,7 +847,7 @@ function ssrCodegenTransform(ast, options) {
801
847
  context.body.push(compilerDom.createCompoundExpression([`const _cssVars = { style: `, varsExp, `}`]));
802
848
  }
803
849
  const isFragment = ast.children.length > 1 && ast.children.some(c => !compilerDom.isText(c));
804
- processChildren(ast.children, context, isFragment);
850
+ processChildren(ast, context, isFragment);
805
851
  ast.codegenNode = compilerDom.createBlockStatement(context.body);
806
852
  // Finalize helpers.
807
853
  // We need to separate helpers imported from 'vue' vs. '@vue/server-renderer'
@@ -852,10 +898,11 @@ function createChildContext(parent, withSlotScopeId = parent.withSlotScopeId) {
852
898
  // ensure child inherits parent helpers
853
899
  return createSSRTransformContext(parent.root, parent.options, parent.helpers, withSlotScopeId);
854
900
  }
855
- function processChildren(children, context, asFragment = false, disableNestedFragments = false) {
901
+ function processChildren(parent, context, asFragment = false, disableNestedFragments = false) {
856
902
  if (asFragment) {
857
903
  context.pushStringPart(`<!--[-->`);
858
904
  }
905
+ const { children } = parent;
859
906
  for (let i = 0; i < children.length; i++) {
860
907
  const child = children[i];
861
908
  switch (child.type) {
@@ -865,7 +912,7 @@ function processChildren(children, context, asFragment = false, disableNestedFra
865
912
  ssrProcessElement(child, context);
866
913
  break;
867
914
  case 1 /* COMPONENT */:
868
- ssrProcessComponent(child, context);
915
+ ssrProcessComponent(child, context, parent);
869
916
  break;
870
917
  case 2 /* SLOT */:
871
918
  ssrProcessSlotOutlet(child, context);
@@ -916,9 +963,9 @@ function processChildren(children, context, asFragment = false, disableNestedFra
916
963
  context.pushStringPart(`<!--]-->`);
917
964
  }
918
965
  }
919
- function processChildrenAsStatement(children, parentContext, asFragment = false, withSlotScopeId = parentContext.withSlotScopeId) {
966
+ function processChildrenAsStatement(parent, parentContext, asFragment = false, withSlotScopeId = parentContext.withSlotScopeId) {
920
967
  const childContext = createChildContext(parentContext, withSlotScopeId);
921
- processChildren(children, childContext, asFragment);
968
+ processChildren(parent, childContext, asFragment);
922
969
  return compilerDom.createBlockStatement(childContext.body);
923
970
  }
924
971
 
@@ -1037,7 +1084,8 @@ const ssrTransformShow = (dir, node, context) => {
1037
1084
  };
1038
1085
  };
1039
1086
 
1040
- const hasSingleChild = (node) => node.children.filter(n => n.type !== 3 /* COMMENT */).length === 1;
1087
+ const filterChild = (node) => node.children.filter(n => n.type !== 3 /* COMMENT */);
1088
+ const hasSingleChild = (node) => filterChild(node).length === 1;
1041
1089
  const ssrInjectFallthroughAttrs = (node, context) => {
1042
1090
  // _attrs is provided as a function argument.
1043
1091
  // mark it as a known identifier so that it doesn't get prefixed by
@@ -1049,16 +1097,37 @@ const ssrInjectFallthroughAttrs = (node, context) => {
1049
1097
  node.tagType === 1 /* COMPONENT */ &&
1050
1098
  (compilerDom.isBuiltInType(node.tag, 'Transition') ||
1051
1099
  compilerDom.isBuiltInType(node.tag, 'KeepAlive'))) {
1052
- if (hasSingleChild(node)) {
1053
- injectFallthroughAttrs(node.children[0]);
1100
+ const rootChildren = filterChild(context.root);
1101
+ if (rootChildren.length === 1 && rootChildren[0] === node) {
1102
+ if (hasSingleChild(node)) {
1103
+ injectFallthroughAttrs(node.children[0]);
1104
+ }
1105
+ return;
1054
1106
  }
1055
- return;
1056
1107
  }
1057
1108
  const parent = context.parent;
1058
1109
  if (!parent || parent.type !== 0 /* ROOT */) {
1059
1110
  return;
1060
1111
  }
1061
1112
  if (node.type === 10 /* IF_BRANCH */ && hasSingleChild(node)) {
1113
+ // detect cases where the parent v-if is not the only root level node
1114
+ let hasEncounteredIf = false;
1115
+ for (const c of filterChild(parent)) {
1116
+ if (c.type === 9 /* IF */ ||
1117
+ (c.type === 1 /* ELEMENT */ && compilerDom.findDir(c, 'if'))) {
1118
+ // multiple root v-if
1119
+ if (hasEncounteredIf)
1120
+ return;
1121
+ hasEncounteredIf = true;
1122
+ }
1123
+ else if (
1124
+ // node before v-if
1125
+ !hasEncounteredIf ||
1126
+ // non else nodes
1127
+ !(c.type === 1 /* ELEMENT */ && compilerDom.findDir(c, /else/, true))) {
1128
+ return;
1129
+ }
1130
+ }
1062
1131
  injectFallthroughAttrs(node.children[0]);
1063
1132
  }
1064
1133
  else if (hasSingleChild(parent)) {
@@ -1172,11 +1241,12 @@ function compile(template, options = {}) {
1172
1241
  directiveTransforms: {
1173
1242
  // reusing core v-bind
1174
1243
  bind: compilerDom.transformBind,
1244
+ on: compilerDom.transformOn,
1175
1245
  // model and show has dedicated SSR handling
1176
1246
  model: ssrTransformModel,
1177
1247
  show: ssrTransformShow,
1178
1248
  // the following are ignored during SSR
1179
- on: compilerDom.noopDirectiveTransform,
1249
+ // on: noopDirectiveTransform,
1180
1250
  cloak: compilerDom.noopDirectiveTransform,
1181
1251
  once: compilerDom.noopDirectiveTransform,
1182
1252
  memo: compilerDom.noopDirectiveTransform,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/compiler-ssr",
3
- "version": "3.2.34-beta.1",
3
+ "version": "3.2.34",
4
4
  "description": "@vue/compiler-ssr",
5
5
  "main": "dist/compiler-ssr.cjs.js",
6
6
  "types": "dist/compiler-ssr.d.ts",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-ssr#readme",
30
30
  "dependencies": {
31
- "@vue/shared": "3.2.34-beta.1",
32
- "@vue/compiler-dom": "3.2.34-beta.1"
31
+ "@vue/shared": "3.2.34",
32
+ "@vue/compiler-dom": "3.2.34"
33
33
  }
34
34
  }