@vue/compiler-ssr 3.2.29 → 3.2.30

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.
@@ -22,6 +22,7 @@ const SSR_RENDER_DYNAMIC_MODEL = Symbol(`ssrRenderDynamicModel`);
22
22
  const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`ssrGetDynamicModelProps`);
23
23
  const SSR_RENDER_TELEPORT = Symbol(`ssrRenderTeleport`);
24
24
  const SSR_RENDER_SUSPENSE = Symbol(`ssrRenderSuspense`);
25
+ const SSR_GET_DIRECTIVE_PROPS = Symbol(`ssrGetDirectiveProps`);
25
26
  const ssrHelpers = {
26
27
  [SSR_INTERPOLATE]: `ssrInterpolate`,
27
28
  [SSR_RENDER_VNODE]: `ssrRenderVNode`,
@@ -39,7 +40,8 @@ const ssrHelpers = {
39
40
  [SSR_RENDER_DYNAMIC_MODEL]: `ssrRenderDynamicModel`,
40
41
  [SSR_GET_DYNAMIC_MODEL_PROPS]: `ssrGetDynamicModelProps`,
41
42
  [SSR_RENDER_TELEPORT]: `ssrRenderTeleport`,
42
- [SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`
43
+ [SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`,
44
+ [SSR_GET_DIRECTIVE_PROPS]: `ssrGetDirectiveProps`
43
45
  };
44
46
  // Note: these are helpers imported from @vue/server-renderer
45
47
  // make sure the names match!
@@ -265,224 +267,6 @@ function ssrProcessTransitionGroup(node, context) {
265
267
  }
266
268
  }
267
269
 
268
- // We need to construct the slot functions in the 1st pass to ensure proper
269
- // scope tracking, but the children of each slot cannot be processed until
270
- // the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
271
- // pass and complete them in the 2nd pass.
272
- const wipMap$1 = new WeakMap();
273
- const componentTypeMap = new WeakMap();
274
- // ssr component transform is done in two phases:
275
- // In phase 1. we use `buildSlot` to analyze the children of the component into
276
- // WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
277
- // the core transform context).
278
- // In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
279
- // nodes.
280
- const ssrTransformComponent = (node, context) => {
281
- if (node.type !== 1 /* ELEMENT */ ||
282
- node.tagType !== 1 /* COMPONENT */) {
283
- return;
284
- }
285
- const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
286
- componentTypeMap.set(node, component);
287
- if (shared.isSymbol(component)) {
288
- if (component === compilerDom.SUSPENSE) {
289
- return ssrTransformSuspense(node, context);
290
- }
291
- return; // built-in component: fallthrough
292
- }
293
- // Build the fallback vnode-based branch for the component's slots.
294
- // We need to clone the node into a fresh copy and use the buildSlots' logic
295
- // to get access to the children of each slot. We then compile them with
296
- // a child transform pipeline using vnode-based transforms (instead of ssr-
297
- // based ones), and save the result branch (a ReturnStatement) in an array.
298
- // The branch is retrieved when processing slots again in ssr mode.
299
- const vnodeBranches = [];
300
- const clonedNode = clone(node);
301
- return function ssrPostTransformComponent() {
302
- // Using the cloned node, build the normal VNode-based branches (for
303
- // fallback in case the child is render-fn based). Store them in an array
304
- // for later use.
305
- if (clonedNode.children.length) {
306
- compilerDom.buildSlots(clonedNode, context, (props, children) => {
307
- vnodeBranches.push(createVNodeSlotBranch(props, children, context));
308
- return compilerDom.createFunctionExpression(undefined);
309
- });
310
- }
311
- const props = node.props.length > 0
312
- ? // note we are not passing ssr: true here because for components, v-on
313
- // handlers should still be passed
314
- compilerDom.buildProps(node, context).props || `null`
315
- : `null`;
316
- const wipEntries = [];
317
- wipMap$1.set(node, wipEntries);
318
- const buildSSRSlotFn = (props, children, loc) => {
319
- const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
320
- true, // newline
321
- true, // isSlot
322
- loc);
323
- wipEntries.push({
324
- fn,
325
- children,
326
- // also collect the corresponding vnode branch built earlier
327
- vnodeBranch: vnodeBranches[wipEntries.length]
328
- });
329
- return fn;
330
- };
331
- const slots = node.children.length
332
- ? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots
333
- : `null`;
334
- if (typeof component !== 'string') {
335
- // dynamic component that resolved to a `resolveDynamicComponent` call
336
- // expression - since the resolved result may be a plain element (string)
337
- // or a VNode, handle it with `renderVNode`.
338
- node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_VNODE), [
339
- `_push`,
340
- compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
341
- component,
342
- props,
343
- slots
344
- ]),
345
- `_parent`
346
- ]);
347
- }
348
- else {
349
- node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_COMPONENT), [component, props, slots, `_parent`]);
350
- }
351
- };
352
- };
353
- function ssrProcessComponent(node, context) {
354
- const component = componentTypeMap.get(node);
355
- if (!node.ssrCodegenNode) {
356
- // this is a built-in component that fell-through.
357
- if (component === compilerDom.TELEPORT) {
358
- return ssrProcessTeleport(node, context);
359
- }
360
- else if (component === compilerDom.SUSPENSE) {
361
- return ssrProcessSuspense(node, context);
362
- }
363
- else if (component === compilerDom.TRANSITION_GROUP) {
364
- return ssrProcessTransitionGroup(node, context);
365
- }
366
- else {
367
- // real fall-through: Transition / KeepAlive
368
- // just render its children.
369
- processChildren(node.children, context);
370
- }
371
- }
372
- else {
373
- // finish up slot function expressions from the 1st pass.
374
- const wipEntries = wipMap$1.get(node) || [];
375
- for (let i = 0; i < wipEntries.length; i++) {
376
- const { fn, children, vnodeBranch } = wipEntries[i];
377
- // For each slot, we generate two branches: one SSR-optimized branch and
378
- // one normal vnode-based branch. The branches are taken based on the
379
- // presence of the 2nd `_push` argument (which is only present if the slot
380
- // is called by `_ssrRenderSlot`.
381
- fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(children, context, false, true /* withSlotScopeId */), vnodeBranch);
382
- }
383
- // component is inside a slot, inherit slot scope Id
384
- if (context.withSlotScopeId) {
385
- node.ssrCodegenNode.arguments.push(`_scopeId`);
386
- }
387
- if (typeof component === 'string') {
388
- // static component
389
- context.pushStatement(compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode]));
390
- }
391
- else {
392
- // dynamic component (`resolveDynamicComponent` call)
393
- // the codegen node is a `renderVNode` call
394
- context.pushStatement(node.ssrCodegenNode);
395
- }
396
- }
397
- }
398
- const rawOptionsMap = new WeakMap();
399
- const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
400
- const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
401
- const vnodeDirectiveTransforms = Object.assign(Object.assign({}, baseDirectiveTransforms), compilerDom.DOMDirectiveTransforms);
402
- function createVNodeSlotBranch(props, children, parentContext) {
403
- // apply a sub-transform using vnode-based transforms.
404
- const rawOptions = rawOptionsMap.get(parentContext.root);
405
- const subOptions = Object.assign(Object.assign({}, rawOptions), {
406
- // overwrite with vnode-based transforms
407
- nodeTransforms: [
408
- ...vnodeNodeTransforms,
409
- ...(rawOptions.nodeTransforms || [])
410
- ], directiveTransforms: Object.assign(Object.assign({}, vnodeDirectiveTransforms), (rawOptions.directiveTransforms || {})) });
411
- // wrap the children with a wrapper template for proper children treatment.
412
- const wrapperNode = {
413
- type: 1 /* ELEMENT */,
414
- ns: 0 /* HTML */,
415
- tag: 'template',
416
- tagType: 3 /* TEMPLATE */,
417
- isSelfClosing: false,
418
- // important: provide v-slot="props" on the wrapper for proper
419
- // scope analysis
420
- props: [
421
- {
422
- type: 7 /* DIRECTIVE */,
423
- name: 'slot',
424
- exp: props,
425
- arg: undefined,
426
- modifiers: [],
427
- loc: compilerDom.locStub
428
- }
429
- ],
430
- children,
431
- loc: compilerDom.locStub,
432
- codegenNode: undefined
433
- };
434
- subTransform(wrapperNode, subOptions, parentContext);
435
- return compilerDom.createReturnStatement(children);
436
- }
437
- function subTransform(node, options, parentContext) {
438
- const childRoot = compilerDom.createRoot([node]);
439
- const childContext = compilerDom.createTransformContext(childRoot, options);
440
- // this sub transform is for vnode fallback branch so it should be handled
441
- // like normal render functions
442
- childContext.ssr = false;
443
- // inherit parent scope analysis state
444
- childContext.scopes = Object.assign({}, parentContext.scopes);
445
- childContext.identifiers = Object.assign({}, parentContext.identifiers);
446
- childContext.imports = parentContext.imports;
447
- // traverse
448
- compilerDom.traverseNode(childRoot, childContext);
449
- ['helpers', 'components', 'directives'].forEach(key => {
450
- childContext[key].forEach((value, helperKey) => {
451
- if (key === 'helpers') {
452
- const parentCount = parentContext.helpers.get(helperKey);
453
- if (parentCount === undefined) {
454
- parentContext.helpers.set(helperKey, value);
455
- }
456
- else {
457
- parentContext.helpers.set(helperKey, value + parentCount);
458
- }
459
- }
460
- else {
461
- parentContext[key].add(value);
462
- }
463
- });
464
- });
465
- // imports/hoists are not merged because:
466
- // - imports are only used for asset urls and should be consistent between
467
- // node/client branches
468
- // - hoists are not enabled for the client branch here
469
- }
470
- function clone(v) {
471
- if (shared.isArray(v)) {
472
- return v.map(clone);
473
- }
474
- else if (shared.isObject(v)) {
475
- const res = {};
476
- for (const key in v) {
477
- res[key] = clone(v[key]);
478
- }
479
- return res;
480
- }
481
- else {
482
- return v;
483
- }
484
- }
485
-
486
270
  // for directives with children overwrite (e.g. v-html & v-text), we need to
487
271
  // store the raw children so that they can be added in the 2nd pass.
488
272
  const rawChildrenMap = new WeakMap();
@@ -497,14 +281,17 @@ const ssrTransformElement = (node, context) => {
497
281
  const openTag = [`<${node.tag}`];
498
282
  // some tags need to be passed to runtime for special checks
499
283
  const needTagForRuntime = node.tag === 'textarea' || node.tag.indexOf('-') > 0;
500
- // v-bind="obj" or v-bind:[key] can potentially overwrite other static
501
- // attrs and can affect final rendering result, so when they are present
502
- // we need to bail out to full `renderAttrs`
284
+ // v-bind="obj", v-bind:[key] and custom directives can potentially
285
+ // overwrite other static attrs and can affect final rendering result,
286
+ // so when they are present we need to bail out to full `renderAttrs`
503
287
  const hasDynamicVBind = compilerDom.hasDynamicKeyVBind(node);
504
- if (hasDynamicVBind) {
505
- const { props } = compilerDom.buildProps(node, context, node.props, true /* ssr */);
506
- if (props) {
507
- const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [props]);
288
+ const hasCustomDir = node.props.some(p => p.type === 7 /* DIRECTIVE */ && !shared.isBuiltInDirective(p.name));
289
+ const needMergeProps = hasDynamicVBind || hasCustomDir;
290
+ if (needMergeProps) {
291
+ const { props, directives } = compilerDom.buildProps(node, context, node.props, true /* ssr */);
292
+ if (props || directives.length) {
293
+ const mergedProps = buildSSRProps(props, directives, context);
294
+ const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [mergedProps]);
508
295
  if (node.tag === 'textarea') {
509
296
  const existingText = node.children[0];
510
297
  // If interpolation, this is dynamic <textarea> content, potentially
@@ -516,7 +303,7 @@ const ssrTransformElement = (node, context) => {
516
303
  // it contains value (if yes, render is as children).
517
304
  const tempId = `_temp${context.temps++}`;
518
305
  propsExp.arguments = [
519
- compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false), props)
306
+ compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false), mergedProps)
520
307
  ];
521
308
  rawChildrenMap.set(node, compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [
522
309
  compilerDom.createConditionalExpression(compilerDom.createSimpleExpression(`"value" in ${tempId}`, false), compilerDom.createSimpleExpression(`${tempId}.value`, false), compilerDom.createSimpleExpression(existingText ? existingText.content : ``, true), false)
@@ -534,7 +321,7 @@ const ssrTransformElement = (node, context) => {
534
321
  const tempExp = compilerDom.createSimpleExpression(tempId, false);
535
322
  propsExp.arguments = [
536
323
  compilerDom.createSequenceExpression([
537
- compilerDom.createAssignmentExpression(tempExp, props),
324
+ compilerDom.createAssignmentExpression(tempExp, mergedProps),
538
325
  compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), [
539
326
  tempExp,
540
327
  compilerDom.createCallExpression(context.helper(SSR_GET_DYNAMIC_MODEL_PROPS), [
@@ -576,11 +363,11 @@ const ssrTransformElement = (node, context) => {
576
363
  context.onError(compilerDom.createCompilerError(40 /* X_V_SLOT_MISPLACED */, prop.loc));
577
364
  }
578
365
  else if (isTextareaWithValue(node, prop) && prop.exp) {
579
- if (!hasDynamicVBind) {
366
+ if (!needMergeProps) {
580
367
  node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
581
368
  }
582
369
  }
583
- else if (!hasDynamicVBind) {
370
+ else if (!needMergeProps) {
584
371
  // Directive transforms.
585
372
  const directiveTransform = context.directiveTransforms[prop.name];
586
373
  if (directiveTransform) {
@@ -646,7 +433,7 @@ const ssrTransformElement = (node, context) => {
646
433
  if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {
647
434
  rawChildrenMap.set(node, shared.escapeHtml(prop.value.content));
648
435
  }
649
- else if (!hasDynamicVBind) {
436
+ else if (!needMergeProps) {
650
437
  if (prop.name === 'key' || prop.name === 'ref') {
651
438
  continue;
652
439
  }
@@ -670,6 +457,30 @@ const ssrTransformElement = (node, context) => {
670
457
  node.ssrCodegenNode = compilerDom.createTemplateLiteral(openTag);
671
458
  };
672
459
  };
460
+ function buildSSRProps(props, directives, context) {
461
+ let mergePropsArgs = [];
462
+ if (props) {
463
+ if (props.type === 14 /* JS_CALL_EXPRESSION */) {
464
+ // already a mergeProps call
465
+ mergePropsArgs = props.arguments;
466
+ }
467
+ else {
468
+ mergePropsArgs.push(props);
469
+ }
470
+ }
471
+ if (directives.length) {
472
+ for (const dir of directives) {
473
+ context.directives.add(dir.name);
474
+ mergePropsArgs.push(compilerDom.createCallExpression(context.helper(SSR_GET_DIRECTIVE_PROPS), [
475
+ `_ctx`,
476
+ ...compilerDom.buildDirectiveArgs(dir, context).elements
477
+ ]));
478
+ }
479
+ }
480
+ return mergePropsArgs.length > 1
481
+ ? compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), mergePropsArgs)
482
+ : mergePropsArgs[0];
483
+ }
673
484
  function isTrueFalseValue(prop) {
674
485
  if (prop.type === 7 /* DIRECTIVE */) {
675
486
  return (prop.name === 'bind' &&
@@ -730,6 +541,228 @@ function ssrProcessElement(node, context) {
730
541
  }
731
542
  }
732
543
 
544
+ // We need to construct the slot functions in the 1st pass to ensure proper
545
+ // scope tracking, but the children of each slot cannot be processed until
546
+ // the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
547
+ // pass and complete them in the 2nd pass.
548
+ const wipMap$1 = new WeakMap();
549
+ const componentTypeMap = new WeakMap();
550
+ // ssr component transform is done in two phases:
551
+ // In phase 1. we use `buildSlot` to analyze the children of the component into
552
+ // WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
553
+ // the core transform context).
554
+ // In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
555
+ // nodes.
556
+ const ssrTransformComponent = (node, context) => {
557
+ if (node.type !== 1 /* ELEMENT */ ||
558
+ node.tagType !== 1 /* COMPONENT */) {
559
+ return;
560
+ }
561
+ const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
562
+ componentTypeMap.set(node, component);
563
+ if (shared.isSymbol(component)) {
564
+ if (component === compilerDom.SUSPENSE) {
565
+ return ssrTransformSuspense(node, context);
566
+ }
567
+ return; // built-in component: fallthrough
568
+ }
569
+ // Build the fallback vnode-based branch for the component's slots.
570
+ // We need to clone the node into a fresh copy and use the buildSlots' logic
571
+ // to get access to the children of each slot. We then compile them with
572
+ // a child transform pipeline using vnode-based transforms (instead of ssr-
573
+ // based ones), and save the result branch (a ReturnStatement) in an array.
574
+ // The branch is retrieved when processing slots again in ssr mode.
575
+ const vnodeBranches = [];
576
+ const clonedNode = clone(node);
577
+ return function ssrPostTransformComponent() {
578
+ // Using the cloned node, build the normal VNode-based branches (for
579
+ // fallback in case the child is render-fn based). Store them in an array
580
+ // for later use.
581
+ if (clonedNode.children.length) {
582
+ compilerDom.buildSlots(clonedNode, context, (props, children) => {
583
+ vnodeBranches.push(createVNodeSlotBranch(props, children, context));
584
+ return compilerDom.createFunctionExpression(undefined);
585
+ });
586
+ }
587
+ let propsExp = `null`;
588
+ if (node.props.length) {
589
+ // note we are not passing ssr: true here because for components, v-on
590
+ // handlers should still be passed
591
+ const { props, directives } = compilerDom.buildProps(node, context);
592
+ if (props || directives.length) {
593
+ propsExp = buildSSRProps(props, directives, context);
594
+ }
595
+ }
596
+ const wipEntries = [];
597
+ wipMap$1.set(node, wipEntries);
598
+ const buildSSRSlotFn = (props, children, loc) => {
599
+ const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
600
+ true, // newline
601
+ true, // isSlot
602
+ loc);
603
+ wipEntries.push({
604
+ fn,
605
+ children,
606
+ // also collect the corresponding vnode branch built earlier
607
+ vnodeBranch: vnodeBranches[wipEntries.length]
608
+ });
609
+ return fn;
610
+ };
611
+ const slots = node.children.length
612
+ ? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots
613
+ : `null`;
614
+ if (typeof component !== 'string') {
615
+ // dynamic component that resolved to a `resolveDynamicComponent` call
616
+ // expression - since the resolved result may be a plain element (string)
617
+ // or a VNode, handle it with `renderVNode`.
618
+ node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_VNODE), [
619
+ `_push`,
620
+ compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
621
+ component,
622
+ propsExp,
623
+ slots
624
+ ]),
625
+ `_parent`
626
+ ]);
627
+ }
628
+ else {
629
+ node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_COMPONENT), [component, propsExp, slots, `_parent`]);
630
+ }
631
+ };
632
+ };
633
+ function ssrProcessComponent(node, context) {
634
+ const component = componentTypeMap.get(node);
635
+ if (!node.ssrCodegenNode) {
636
+ // this is a built-in component that fell-through.
637
+ if (component === compilerDom.TELEPORT) {
638
+ return ssrProcessTeleport(node, context);
639
+ }
640
+ else if (component === compilerDom.SUSPENSE) {
641
+ return ssrProcessSuspense(node, context);
642
+ }
643
+ else if (component === compilerDom.TRANSITION_GROUP) {
644
+ return ssrProcessTransitionGroup(node, context);
645
+ }
646
+ else {
647
+ // real fall-through: Transition / KeepAlive
648
+ // just render its children.
649
+ processChildren(node.children, context);
650
+ }
651
+ }
652
+ else {
653
+ // finish up slot function expressions from the 1st pass.
654
+ const wipEntries = wipMap$1.get(node) || [];
655
+ for (let i = 0; i < wipEntries.length; i++) {
656
+ const { fn, children, vnodeBranch } = wipEntries[i];
657
+ // For each slot, we generate two branches: one SSR-optimized branch and
658
+ // one normal vnode-based branch. The branches are taken based on the
659
+ // presence of the 2nd `_push` argument (which is only present if the slot
660
+ // is called by `_ssrRenderSlot`.
661
+ fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(children, context, false, true /* withSlotScopeId */), vnodeBranch);
662
+ }
663
+ // component is inside a slot, inherit slot scope Id
664
+ if (context.withSlotScopeId) {
665
+ node.ssrCodegenNode.arguments.push(`_scopeId`);
666
+ }
667
+ if (typeof component === 'string') {
668
+ // static component
669
+ context.pushStatement(compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode]));
670
+ }
671
+ else {
672
+ // dynamic component (`resolveDynamicComponent` call)
673
+ // the codegen node is a `renderVNode` call
674
+ context.pushStatement(node.ssrCodegenNode);
675
+ }
676
+ }
677
+ }
678
+ const rawOptionsMap = new WeakMap();
679
+ const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
680
+ const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
681
+ const vnodeDirectiveTransforms = Object.assign(Object.assign({}, baseDirectiveTransforms), compilerDom.DOMDirectiveTransforms);
682
+ function createVNodeSlotBranch(props, children, parentContext) {
683
+ // apply a sub-transform using vnode-based transforms.
684
+ const rawOptions = rawOptionsMap.get(parentContext.root);
685
+ const subOptions = Object.assign(Object.assign({}, rawOptions), {
686
+ // overwrite with vnode-based transforms
687
+ nodeTransforms: [
688
+ ...vnodeNodeTransforms,
689
+ ...(rawOptions.nodeTransforms || [])
690
+ ], directiveTransforms: Object.assign(Object.assign({}, vnodeDirectiveTransforms), (rawOptions.directiveTransforms || {})) });
691
+ // wrap the children with a wrapper template for proper children treatment.
692
+ const wrapperNode = {
693
+ type: 1 /* ELEMENT */,
694
+ ns: 0 /* HTML */,
695
+ tag: 'template',
696
+ tagType: 3 /* TEMPLATE */,
697
+ isSelfClosing: false,
698
+ // important: provide v-slot="props" on the wrapper for proper
699
+ // scope analysis
700
+ props: [
701
+ {
702
+ type: 7 /* DIRECTIVE */,
703
+ name: 'slot',
704
+ exp: props,
705
+ arg: undefined,
706
+ modifiers: [],
707
+ loc: compilerDom.locStub
708
+ }
709
+ ],
710
+ children,
711
+ loc: compilerDom.locStub,
712
+ codegenNode: undefined
713
+ };
714
+ subTransform(wrapperNode, subOptions, parentContext);
715
+ return compilerDom.createReturnStatement(children);
716
+ }
717
+ function subTransform(node, options, parentContext) {
718
+ const childRoot = compilerDom.createRoot([node]);
719
+ const childContext = compilerDom.createTransformContext(childRoot, options);
720
+ // this sub transform is for vnode fallback branch so it should be handled
721
+ // like normal render functions
722
+ childContext.ssr = false;
723
+ // inherit parent scope analysis state
724
+ childContext.scopes = Object.assign({}, parentContext.scopes);
725
+ childContext.identifiers = Object.assign({}, parentContext.identifiers);
726
+ childContext.imports = parentContext.imports;
727
+ // traverse
728
+ compilerDom.traverseNode(childRoot, childContext);
729
+ ['helpers', 'components', 'directives'].forEach(key => {
730
+ childContext[key].forEach((value, helperKey) => {
731
+ if (key === 'helpers') {
732
+ const parentCount = parentContext.helpers.get(helperKey);
733
+ if (parentCount === undefined) {
734
+ parentContext.helpers.set(helperKey, value);
735
+ }
736
+ else {
737
+ parentContext.helpers.set(helperKey, value + parentCount);
738
+ }
739
+ }
740
+ else {
741
+ parentContext[key].add(value);
742
+ }
743
+ });
744
+ });
745
+ // imports/hoists are not merged because:
746
+ // - imports are only used for asset urls and should be consistent between
747
+ // node/client branches
748
+ // - hoists are not enabled for the client branch here
749
+ }
750
+ function clone(v) {
751
+ if (shared.isArray(v)) {
752
+ return v.map(clone);
753
+ }
754
+ else if (shared.isObject(v)) {
755
+ const res = {};
756
+ for (const key in v) {
757
+ res[key] = clone(v[key]);
758
+ }
759
+ return res;
760
+ }
761
+ else {
762
+ return v;
763
+ }
764
+ }
765
+
733
766
  // Because SSR codegen output is completely different from client-side output
734
767
  // (e.g. multiple elements can be concatenated into a single template literal
735
768
  // instead of each getting a corresponding call), we need to apply an extra
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/compiler-ssr",
3
- "version": "3.2.29",
3
+ "version": "3.2.30",
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.29",
32
- "@vue/compiler-dom": "3.2.29"
31
+ "@vue/shared": "3.2.30",
32
+ "@vue/compiler-dom": "3.2.30"
33
33
  }
34
34
  }