@vue/compiler-ssr 3.2.40 → 3.2.41

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.
Files changed (2) hide show
  1. package/dist/compiler-ssr.cjs.js +1231 -1231
  2. package/package.json +3 -3
@@ -5,1267 +5,1267 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var compilerDom = require('@vue/compiler-dom');
6
6
  var shared = require('@vue/shared');
7
7
 
8
- const SSR_INTERPOLATE = Symbol(`ssrInterpolate`);
9
- const SSR_RENDER_VNODE = Symbol(`ssrRenderVNode`);
10
- const SSR_RENDER_COMPONENT = Symbol(`ssrRenderComponent`);
11
- const SSR_RENDER_SLOT = Symbol(`ssrRenderSlot`);
12
- const SSR_RENDER_SLOT_INNER = Symbol(`ssrRenderSlotInner`);
13
- const SSR_RENDER_CLASS = Symbol(`ssrRenderClass`);
14
- const SSR_RENDER_STYLE = Symbol(`ssrRenderStyle`);
15
- const SSR_RENDER_ATTRS = Symbol(`ssrRenderAttrs`);
16
- const SSR_RENDER_ATTR = Symbol(`ssrRenderAttr`);
17
- const SSR_RENDER_DYNAMIC_ATTR = Symbol(`ssrRenderDynamicAttr`);
18
- const SSR_RENDER_LIST = Symbol(`ssrRenderList`);
19
- const SSR_INCLUDE_BOOLEAN_ATTR = Symbol(`ssrIncludeBooleanAttr`);
20
- const SSR_LOOSE_EQUAL = Symbol(`ssrLooseEqual`);
21
- const SSR_LOOSE_CONTAIN = Symbol(`ssrLooseContain`);
22
- const SSR_RENDER_DYNAMIC_MODEL = Symbol(`ssrRenderDynamicModel`);
23
- const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`ssrGetDynamicModelProps`);
24
- const SSR_RENDER_TELEPORT = Symbol(`ssrRenderTeleport`);
25
- const SSR_RENDER_SUSPENSE = Symbol(`ssrRenderSuspense`);
26
- const SSR_GET_DIRECTIVE_PROPS = Symbol(`ssrGetDirectiveProps`);
27
- const ssrHelpers = {
28
- [SSR_INTERPOLATE]: `ssrInterpolate`,
29
- [SSR_RENDER_VNODE]: `ssrRenderVNode`,
30
- [SSR_RENDER_COMPONENT]: `ssrRenderComponent`,
31
- [SSR_RENDER_SLOT]: `ssrRenderSlot`,
32
- [SSR_RENDER_SLOT_INNER]: `ssrRenderSlotInner`,
33
- [SSR_RENDER_CLASS]: `ssrRenderClass`,
34
- [SSR_RENDER_STYLE]: `ssrRenderStyle`,
35
- [SSR_RENDER_ATTRS]: `ssrRenderAttrs`,
36
- [SSR_RENDER_ATTR]: `ssrRenderAttr`,
37
- [SSR_RENDER_DYNAMIC_ATTR]: `ssrRenderDynamicAttr`,
38
- [SSR_RENDER_LIST]: `ssrRenderList`,
39
- [SSR_INCLUDE_BOOLEAN_ATTR]: `ssrIncludeBooleanAttr`,
40
- [SSR_LOOSE_EQUAL]: `ssrLooseEqual`,
41
- [SSR_LOOSE_CONTAIN]: `ssrLooseContain`,
42
- [SSR_RENDER_DYNAMIC_MODEL]: `ssrRenderDynamicModel`,
43
- [SSR_GET_DYNAMIC_MODEL_PROPS]: `ssrGetDynamicModelProps`,
44
- [SSR_RENDER_TELEPORT]: `ssrRenderTeleport`,
45
- [SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`,
46
- [SSR_GET_DIRECTIVE_PROPS]: `ssrGetDirectiveProps`
47
- };
48
- // Note: these are helpers imported from @vue/server-renderer
49
- // make sure the names match!
8
+ const SSR_INTERPOLATE = Symbol(`ssrInterpolate`);
9
+ const SSR_RENDER_VNODE = Symbol(`ssrRenderVNode`);
10
+ const SSR_RENDER_COMPONENT = Symbol(`ssrRenderComponent`);
11
+ const SSR_RENDER_SLOT = Symbol(`ssrRenderSlot`);
12
+ const SSR_RENDER_SLOT_INNER = Symbol(`ssrRenderSlotInner`);
13
+ const SSR_RENDER_CLASS = Symbol(`ssrRenderClass`);
14
+ const SSR_RENDER_STYLE = Symbol(`ssrRenderStyle`);
15
+ const SSR_RENDER_ATTRS = Symbol(`ssrRenderAttrs`);
16
+ const SSR_RENDER_ATTR = Symbol(`ssrRenderAttr`);
17
+ const SSR_RENDER_DYNAMIC_ATTR = Symbol(`ssrRenderDynamicAttr`);
18
+ const SSR_RENDER_LIST = Symbol(`ssrRenderList`);
19
+ const SSR_INCLUDE_BOOLEAN_ATTR = Symbol(`ssrIncludeBooleanAttr`);
20
+ const SSR_LOOSE_EQUAL = Symbol(`ssrLooseEqual`);
21
+ const SSR_LOOSE_CONTAIN = Symbol(`ssrLooseContain`);
22
+ const SSR_RENDER_DYNAMIC_MODEL = Symbol(`ssrRenderDynamicModel`);
23
+ const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`ssrGetDynamicModelProps`);
24
+ const SSR_RENDER_TELEPORT = Symbol(`ssrRenderTeleport`);
25
+ const SSR_RENDER_SUSPENSE = Symbol(`ssrRenderSuspense`);
26
+ const SSR_GET_DIRECTIVE_PROPS = Symbol(`ssrGetDirectiveProps`);
27
+ const ssrHelpers = {
28
+ [SSR_INTERPOLATE]: `ssrInterpolate`,
29
+ [SSR_RENDER_VNODE]: `ssrRenderVNode`,
30
+ [SSR_RENDER_COMPONENT]: `ssrRenderComponent`,
31
+ [SSR_RENDER_SLOT]: `ssrRenderSlot`,
32
+ [SSR_RENDER_SLOT_INNER]: `ssrRenderSlotInner`,
33
+ [SSR_RENDER_CLASS]: `ssrRenderClass`,
34
+ [SSR_RENDER_STYLE]: `ssrRenderStyle`,
35
+ [SSR_RENDER_ATTRS]: `ssrRenderAttrs`,
36
+ [SSR_RENDER_ATTR]: `ssrRenderAttr`,
37
+ [SSR_RENDER_DYNAMIC_ATTR]: `ssrRenderDynamicAttr`,
38
+ [SSR_RENDER_LIST]: `ssrRenderList`,
39
+ [SSR_INCLUDE_BOOLEAN_ATTR]: `ssrIncludeBooleanAttr`,
40
+ [SSR_LOOSE_EQUAL]: `ssrLooseEqual`,
41
+ [SSR_LOOSE_CONTAIN]: `ssrLooseContain`,
42
+ [SSR_RENDER_DYNAMIC_MODEL]: `ssrRenderDynamicModel`,
43
+ [SSR_GET_DYNAMIC_MODEL_PROPS]: `ssrGetDynamicModelProps`,
44
+ [SSR_RENDER_TELEPORT]: `ssrRenderTeleport`,
45
+ [SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`,
46
+ [SSR_GET_DIRECTIVE_PROPS]: `ssrGetDirectiveProps`
47
+ };
48
+ // Note: these are helpers imported from @vue/server-renderer
49
+ // make sure the names match!
50
50
  compilerDom.registerRuntimeHelpers(ssrHelpers);
51
51
 
52
- // Plugin for the first transform pass, which simply constructs the AST node
53
- const ssrTransformIf = compilerDom.createStructuralDirectiveTransform(/^(if|else|else-if)$/, compilerDom.processIf);
54
- // This is called during the 2nd transform pass to construct the SSR-specific
55
- // codegen nodes.
56
- function ssrProcessIf(node, context, disableNestedFragments = false) {
57
- const [rootBranch] = node.branches;
58
- const ifStatement = compilerDom.createIfStatement(rootBranch.condition, processIfBranch(rootBranch, context, disableNestedFragments));
59
- context.pushStatement(ifStatement);
60
- let currentIf = ifStatement;
61
- for (let i = 1; i < node.branches.length; i++) {
62
- const branch = node.branches[i];
63
- const branchBlockStatement = processIfBranch(branch, context, disableNestedFragments);
64
- if (branch.condition) {
65
- // else-if
66
- currentIf = currentIf.alternate = compilerDom.createIfStatement(branch.condition, branchBlockStatement);
67
- }
68
- else {
69
- // else
70
- currentIf.alternate = branchBlockStatement;
71
- }
72
- }
73
- if (!currentIf.alternate) {
74
- currentIf.alternate = compilerDom.createBlockStatement([
75
- compilerDom.createCallExpression(`_push`, ['`<!---->`'])
76
- ]);
77
- }
78
- }
79
- function processIfBranch(branch, context, disableNestedFragments = false) {
80
- const { children } = branch;
81
- const needFragmentWrapper = !disableNestedFragments &&
82
- (children.length !== 1 || children[0].type !== 1 /* NodeTypes.ELEMENT */) &&
83
- // optimize away nested fragments when the only child is a ForNode
84
- !(children.length === 1 && children[0].type === 11 /* NodeTypes.FOR */);
85
- return processChildrenAsStatement(branch, context, needFragmentWrapper);
52
+ // Plugin for the first transform pass, which simply constructs the AST node
53
+ const ssrTransformIf = compilerDom.createStructuralDirectiveTransform(/^(if|else|else-if)$/, compilerDom.processIf);
54
+ // This is called during the 2nd transform pass to construct the SSR-specific
55
+ // codegen nodes.
56
+ function ssrProcessIf(node, context, disableNestedFragments = false) {
57
+ const [rootBranch] = node.branches;
58
+ const ifStatement = compilerDom.createIfStatement(rootBranch.condition, processIfBranch(rootBranch, context, disableNestedFragments));
59
+ context.pushStatement(ifStatement);
60
+ let currentIf = ifStatement;
61
+ for (let i = 1; i < node.branches.length; i++) {
62
+ const branch = node.branches[i];
63
+ const branchBlockStatement = processIfBranch(branch, context, disableNestedFragments);
64
+ if (branch.condition) {
65
+ // else-if
66
+ currentIf = currentIf.alternate = compilerDom.createIfStatement(branch.condition, branchBlockStatement);
67
+ }
68
+ else {
69
+ // else
70
+ currentIf.alternate = branchBlockStatement;
71
+ }
72
+ }
73
+ if (!currentIf.alternate) {
74
+ currentIf.alternate = compilerDom.createBlockStatement([
75
+ compilerDom.createCallExpression(`_push`, ['`<!---->`'])
76
+ ]);
77
+ }
78
+ }
79
+ function processIfBranch(branch, context, disableNestedFragments = false) {
80
+ const { children } = branch;
81
+ const needFragmentWrapper = !disableNestedFragments &&
82
+ (children.length !== 1 || children[0].type !== 1 /* NodeTypes.ELEMENT */) &&
83
+ // optimize away nested fragments when the only child is a ForNode
84
+ !(children.length === 1 && children[0].type === 11 /* NodeTypes.FOR */);
85
+ return processChildrenAsStatement(branch, context, needFragmentWrapper);
86
86
  }
87
87
 
88
- // Plugin for the first transform pass, which simply constructs the AST node
89
- const ssrTransformFor = compilerDom.createStructuralDirectiveTransform('for', compilerDom.processFor);
90
- // This is called during the 2nd transform pass to construct the SSR-specific
91
- // codegen nodes.
92
- function ssrProcessFor(node, context, disableNestedFragments = false) {
93
- const needFragmentWrapper = !disableNestedFragments &&
94
- (node.children.length !== 1 || node.children[0].type !== 1 /* NodeTypes.ELEMENT */);
95
- const renderLoop = compilerDom.createFunctionExpression(compilerDom.createForLoopParams(node.parseResult));
96
- renderLoop.body = processChildrenAsStatement(node, context, needFragmentWrapper);
97
- // v-for always renders a fragment unless explicitly disabled
98
- if (!disableNestedFragments) {
99
- context.pushStringPart(`<!--[-->`);
100
- }
101
- context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_LIST), [
102
- node.source,
103
- renderLoop
104
- ]));
105
- if (!disableNestedFragments) {
106
- context.pushStringPart(`<!--]-->`);
107
- }
88
+ // Plugin for the first transform pass, which simply constructs the AST node
89
+ const ssrTransformFor = compilerDom.createStructuralDirectiveTransform('for', compilerDom.processFor);
90
+ // This is called during the 2nd transform pass to construct the SSR-specific
91
+ // codegen nodes.
92
+ function ssrProcessFor(node, context, disableNestedFragments = false) {
93
+ const needFragmentWrapper = !disableNestedFragments &&
94
+ (node.children.length !== 1 || node.children[0].type !== 1 /* NodeTypes.ELEMENT */);
95
+ const renderLoop = compilerDom.createFunctionExpression(compilerDom.createForLoopParams(node.parseResult));
96
+ renderLoop.body = processChildrenAsStatement(node, context, needFragmentWrapper);
97
+ // v-for always renders a fragment unless explicitly disabled
98
+ if (!disableNestedFragments) {
99
+ context.pushStringPart(`<!--[-->`);
100
+ }
101
+ context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_LIST), [
102
+ node.source,
103
+ renderLoop
104
+ ]));
105
+ if (!disableNestedFragments) {
106
+ context.pushStringPart(`<!--]-->`);
107
+ }
108
108
  }
109
109
 
110
- const ssrTransformSlotOutlet = (node, context) => {
111
- if (compilerDom.isSlotOutlet(node)) {
112
- const { slotName, slotProps } = compilerDom.processSlotOutlet(node, context);
113
- const args = [
114
- `_ctx.$slots`,
115
- slotName,
116
- slotProps || `{}`,
117
- // fallback content placeholder. will be replaced in the process phase
118
- `null`,
119
- `_push`,
120
- `_parent`
121
- ];
122
- // inject slot scope id if current template uses :slotted
123
- if (context.scopeId && context.slotted !== false) {
124
- args.push(`"${context.scopeId}-s"`);
125
- }
126
- let method = SSR_RENDER_SLOT;
127
- // #3989
128
- // check if this is a single slot inside a transition wrapper - since
129
- // transition will unwrap the slot fragment into a single vnode at runtime,
130
- // we need to avoid rendering the slot as a fragment.
131
- const parent = context.parent;
132
- if (parent &&
133
- parent.type === 1 /* NodeTypes.ELEMENT */ &&
134
- parent.tagType === 1 /* ElementTypes.COMPONENT */ &&
135
- compilerDom.resolveComponentType(parent, context, true) === compilerDom.TRANSITION &&
136
- parent.children.filter(c => c.type === 1 /* NodeTypes.ELEMENT */).length === 1) {
137
- method = SSR_RENDER_SLOT_INNER;
138
- if (!(context.scopeId && context.slotted !== false)) {
139
- args.push('null');
140
- }
141
- args.push('true');
142
- }
143
- node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(method), args);
144
- }
145
- };
146
- function ssrProcessSlotOutlet(node, context) {
147
- const renderCall = node.ssrCodegenNode;
148
- // has fallback content
149
- if (node.children.length) {
150
- const fallbackRenderFn = compilerDom.createFunctionExpression([]);
151
- fallbackRenderFn.body = processChildrenAsStatement(node, context);
152
- // _renderSlot(slots, name, props, fallback, ...)
153
- renderCall.arguments[3] = fallbackRenderFn;
154
- }
155
- // Forwarded <slot/>. Merge slot scope ids
156
- if (context.withSlotScopeId) {
157
- const slotScopeId = renderCall.arguments[6];
158
- renderCall.arguments[6] = slotScopeId
159
- ? `${slotScopeId} + _scopeId`
160
- : `_scopeId`;
161
- }
162
- context.pushStatement(node.ssrCodegenNode);
110
+ const ssrTransformSlotOutlet = (node, context) => {
111
+ if (compilerDom.isSlotOutlet(node)) {
112
+ const { slotName, slotProps } = compilerDom.processSlotOutlet(node, context);
113
+ const args = [
114
+ `_ctx.$slots`,
115
+ slotName,
116
+ slotProps || `{}`,
117
+ // fallback content placeholder. will be replaced in the process phase
118
+ `null`,
119
+ `_push`,
120
+ `_parent`
121
+ ];
122
+ // inject slot scope id if current template uses :slotted
123
+ if (context.scopeId && context.slotted !== false) {
124
+ args.push(`"${context.scopeId}-s"`);
125
+ }
126
+ let method = SSR_RENDER_SLOT;
127
+ // #3989
128
+ // check if this is a single slot inside a transition wrapper - since
129
+ // transition will unwrap the slot fragment into a single vnode at runtime,
130
+ // we need to avoid rendering the slot as a fragment.
131
+ const parent = context.parent;
132
+ if (parent &&
133
+ parent.type === 1 /* NodeTypes.ELEMENT */ &&
134
+ parent.tagType === 1 /* ElementTypes.COMPONENT */ &&
135
+ compilerDom.resolveComponentType(parent, context, true) === compilerDom.TRANSITION &&
136
+ parent.children.filter(c => c.type === 1 /* NodeTypes.ELEMENT */).length === 1) {
137
+ method = SSR_RENDER_SLOT_INNER;
138
+ if (!(context.scopeId && context.slotted !== false)) {
139
+ args.push('null');
140
+ }
141
+ args.push('true');
142
+ }
143
+ node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(method), args);
144
+ }
145
+ };
146
+ function ssrProcessSlotOutlet(node, context) {
147
+ const renderCall = node.ssrCodegenNode;
148
+ // has fallback content
149
+ if (node.children.length) {
150
+ const fallbackRenderFn = compilerDom.createFunctionExpression([]);
151
+ fallbackRenderFn.body = processChildrenAsStatement(node, context);
152
+ // _renderSlot(slots, name, props, fallback, ...)
153
+ renderCall.arguments[3] = fallbackRenderFn;
154
+ }
155
+ // Forwarded <slot/>. Merge slot scope ids
156
+ if (context.withSlotScopeId) {
157
+ const slotScopeId = renderCall.arguments[6];
158
+ renderCall.arguments[6] = slotScopeId
159
+ ? `${slotScopeId} + _scopeId`
160
+ : `_scopeId`;
161
+ }
162
+ context.pushStatement(node.ssrCodegenNode);
163
163
  }
164
164
 
165
- function createSSRCompilerError(code, loc) {
166
- return compilerDom.createCompilerError(code, loc, SSRErrorMessages);
167
- }
168
- const SSRErrorMessages = {
169
- [61 /* SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME */]: `Unsafe attribute name for SSR.`,
170
- [62 /* SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET */]: `Missing the 'to' prop on teleport element.`,
171
- [63 /* SSRErrorCodes.X_SSR_INVALID_AST_NODE */]: `Invalid AST node during SSR transform.`
165
+ function createSSRCompilerError(code, loc) {
166
+ return compilerDom.createCompilerError(code, loc, SSRErrorMessages);
167
+ }
168
+ const SSRErrorMessages = {
169
+ [61 /* SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME */]: `Unsafe attribute name for SSR.`,
170
+ [62 /* SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET */]: `Missing the 'to' prop on teleport element.`,
171
+ [63 /* SSRErrorCodes.X_SSR_INVALID_AST_NODE */]: `Invalid AST node during SSR transform.`
172
172
  };
173
173
 
174
- // Note: this is a 2nd-pass codegen transform.
175
- function ssrProcessTeleport(node, context) {
176
- const targetProp = compilerDom.findProp(node, 'to');
177
- if (!targetProp) {
178
- context.onError(createSSRCompilerError(62 /* SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET */, node.loc));
179
- return;
180
- }
181
- let target;
182
- if (targetProp.type === 6 /* NodeTypes.ATTRIBUTE */) {
183
- target =
184
- targetProp.value && compilerDom.createSimpleExpression(targetProp.value.content, true);
185
- }
186
- else {
187
- target = targetProp.exp;
188
- }
189
- if (!target) {
190
- context.onError(createSSRCompilerError(62 /* SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET */, targetProp.loc));
191
- return;
192
- }
193
- const disabledProp = compilerDom.findProp(node, 'disabled', false, true /* allow empty */);
194
- const disabled = disabledProp
195
- ? disabledProp.type === 6 /* NodeTypes.ATTRIBUTE */
196
- ? `true`
197
- : disabledProp.exp || `false`
198
- : `false`;
199
- const contentRenderFn = compilerDom.createFunctionExpression([`_push`], undefined, // Body is added later
200
- true, // newline
201
- false, // isSlot
202
- node.loc);
203
- contentRenderFn.body = processChildrenAsStatement(node, context);
204
- context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_TELEPORT), [
205
- `_push`,
206
- contentRenderFn,
207
- target,
208
- disabled,
209
- `_parent`
210
- ]));
174
+ // Note: this is a 2nd-pass codegen transform.
175
+ function ssrProcessTeleport(node, context) {
176
+ const targetProp = compilerDom.findProp(node, 'to');
177
+ if (!targetProp) {
178
+ context.onError(createSSRCompilerError(62 /* SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET */, node.loc));
179
+ return;
180
+ }
181
+ let target;
182
+ if (targetProp.type === 6 /* NodeTypes.ATTRIBUTE */) {
183
+ target =
184
+ targetProp.value && compilerDom.createSimpleExpression(targetProp.value.content, true);
185
+ }
186
+ else {
187
+ target = targetProp.exp;
188
+ }
189
+ if (!target) {
190
+ context.onError(createSSRCompilerError(62 /* SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET */, targetProp.loc));
191
+ return;
192
+ }
193
+ const disabledProp = compilerDom.findProp(node, 'disabled', false, true /* allow empty */);
194
+ const disabled = disabledProp
195
+ ? disabledProp.type === 6 /* NodeTypes.ATTRIBUTE */
196
+ ? `true`
197
+ : disabledProp.exp || `false`
198
+ : `false`;
199
+ const contentRenderFn = compilerDom.createFunctionExpression([`_push`], undefined, // Body is added later
200
+ true, // newline
201
+ false, // isSlot
202
+ node.loc);
203
+ contentRenderFn.body = processChildrenAsStatement(node, context);
204
+ context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_TELEPORT), [
205
+ `_push`,
206
+ contentRenderFn,
207
+ target,
208
+ disabled,
209
+ `_parent`
210
+ ]));
211
211
  }
212
212
 
213
- const wipMap = new WeakMap();
214
- // phase 1
215
- function ssrTransformSuspense(node, context) {
216
- return () => {
217
- if (node.children.length) {
218
- const wipEntry = {
219
- slotsExp: null,
220
- wipSlots: []
221
- };
222
- wipMap.set(node, wipEntry);
223
- wipEntry.slotsExp = compilerDom.buildSlots(node, context, (_props, children, loc) => {
224
- const fn = compilerDom.createFunctionExpression([], undefined, // no return, assign body later
225
- true, // newline
226
- false, // suspense slots are not treated as normal slots
227
- loc);
228
- wipEntry.wipSlots.push({
229
- fn,
230
- children
231
- });
232
- return fn;
233
- }).slots;
234
- }
235
- };
236
- }
237
- // phase 2
238
- function ssrProcessSuspense(node, context) {
239
- // complete wip slots with ssr code
240
- const wipEntry = wipMap.get(node);
241
- if (!wipEntry) {
242
- return;
243
- }
244
- const { slotsExp, wipSlots } = wipEntry;
245
- for (let i = 0; i < wipSlots.length; i++) {
246
- const slot = wipSlots[i];
247
- slot.fn.body = processChildrenAsStatement(slot, context);
248
- }
249
- // _push(ssrRenderSuspense(slots))
250
- context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [
251
- `_push`,
252
- slotsExp
253
- ]));
213
+ const wipMap = new WeakMap();
214
+ // phase 1
215
+ function ssrTransformSuspense(node, context) {
216
+ return () => {
217
+ if (node.children.length) {
218
+ const wipEntry = {
219
+ slotsExp: null,
220
+ wipSlots: []
221
+ };
222
+ wipMap.set(node, wipEntry);
223
+ wipEntry.slotsExp = compilerDom.buildSlots(node, context, (_props, children, loc) => {
224
+ const fn = compilerDom.createFunctionExpression([], undefined, // no return, assign body later
225
+ true, // newline
226
+ false, // suspense slots are not treated as normal slots
227
+ loc);
228
+ wipEntry.wipSlots.push({
229
+ fn,
230
+ children
231
+ });
232
+ return fn;
233
+ }).slots;
234
+ }
235
+ };
236
+ }
237
+ // phase 2
238
+ function ssrProcessSuspense(node, context) {
239
+ // complete wip slots with ssr code
240
+ const wipEntry = wipMap.get(node);
241
+ if (!wipEntry) {
242
+ return;
243
+ }
244
+ const { slotsExp, wipSlots } = wipEntry;
245
+ for (let i = 0; i < wipSlots.length; i++) {
246
+ const slot = wipSlots[i];
247
+ slot.fn.body = processChildrenAsStatement(slot, context);
248
+ }
249
+ // _push(ssrRenderSuspense(slots))
250
+ context.pushStatement(compilerDom.createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [
251
+ `_push`,
252
+ slotsExp
253
+ ]));
254
254
  }
255
255
 
256
- // for directives with children overwrite (e.g. v-html & v-text), we need to
257
- // store the raw children so that they can be added in the 2nd pass.
258
- const rawChildrenMap = new WeakMap();
259
- const ssrTransformElement = (node, context) => {
260
- if (node.type !== 1 /* NodeTypes.ELEMENT */ ||
261
- node.tagType !== 0 /* ElementTypes.ELEMENT */) {
262
- return;
263
- }
264
- return function ssrPostTransformElement() {
265
- // element
266
- // generate the template literal representing the open tag.
267
- const openTag = [`<${node.tag}`];
268
- // some tags need to be passed to runtime for special checks
269
- const needTagForRuntime = node.tag === 'textarea' || node.tag.indexOf('-') > 0;
270
- // v-bind="obj", v-bind:[key] and custom directives can potentially
271
- // overwrite other static attrs and can affect final rendering result,
272
- // so when they are present we need to bail out to full `renderAttrs`
273
- const hasDynamicVBind = compilerDom.hasDynamicKeyVBind(node);
274
- const hasCustomDir = node.props.some(p => p.type === 7 /* NodeTypes.DIRECTIVE */ && !shared.isBuiltInDirective(p.name));
275
- const needMergeProps = hasDynamicVBind || hasCustomDir;
276
- if (needMergeProps) {
277
- const { props, directives } = compilerDom.buildProps(node, context, node.props, false /* isComponent */, false /* isDynamicComponent */, true /* ssr */);
278
- if (props || directives.length) {
279
- const mergedProps = buildSSRProps(props, directives, context);
280
- const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [mergedProps]);
281
- if (node.tag === 'textarea') {
282
- const existingText = node.children[0];
283
- // If interpolation, this is dynamic <textarea> content, potentially
284
- // injected by v-model and takes higher priority than v-bind value
285
- if (!existingText || existingText.type !== 5 /* NodeTypes.INTERPOLATION */) {
286
- // <textarea> with dynamic v-bind. We don't know if the final props
287
- // will contain .value, so we will have to do something special:
288
- // assign the merged props to a temp variable, and check whether
289
- // it contains value (if yes, render is as children).
290
- const tempId = `_temp${context.temps++}`;
291
- propsExp.arguments = [
292
- compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false), mergedProps)
293
- ];
294
- rawChildrenMap.set(node, compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [
295
- compilerDom.createConditionalExpression(compilerDom.createSimpleExpression(`"value" in ${tempId}`, false), compilerDom.createSimpleExpression(`${tempId}.value`, false), compilerDom.createSimpleExpression(existingText ? existingText.content : ``, true), false)
296
- ]));
297
- }
298
- }
299
- else if (node.tag === 'input') {
300
- // <input v-bind="obj" v-model>
301
- // we need to determine the props to render for the dynamic v-model
302
- // and merge it with the v-bind expression.
303
- const vModel = findVModel(node);
304
- if (vModel) {
305
- // 1. save the props (san v-model) in a temp variable
306
- const tempId = `_temp${context.temps++}`;
307
- const tempExp = compilerDom.createSimpleExpression(tempId, false);
308
- propsExp.arguments = [
309
- compilerDom.createSequenceExpression([
310
- compilerDom.createAssignmentExpression(tempExp, mergedProps),
311
- compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), [
312
- tempExp,
313
- compilerDom.createCallExpression(context.helper(SSR_GET_DYNAMIC_MODEL_PROPS), [
314
- tempExp,
315
- vModel.exp // model
316
- ])
317
- ])
318
- ])
319
- ];
320
- }
321
- }
322
- if (needTagForRuntime) {
323
- propsExp.arguments.push(`"${node.tag}"`);
324
- }
325
- openTag.push(propsExp);
326
- }
327
- }
328
- // book keeping static/dynamic class merging.
329
- let dynamicClassBinding = undefined;
330
- let staticClassBinding = undefined;
331
- // all style bindings are converted to dynamic by transformStyle.
332
- // but we need to make sure to merge them.
333
- let dynamicStyleBinding = undefined;
334
- for (let i = 0; i < node.props.length; i++) {
335
- const prop = node.props[i];
336
- // ignore true-value/false-value on input
337
- if (node.tag === 'input' && isTrueFalseValue(prop)) {
338
- continue;
339
- }
340
- // special cases with children override
341
- if (prop.type === 7 /* NodeTypes.DIRECTIVE */) {
342
- if (prop.name === 'html' && prop.exp) {
343
- rawChildrenMap.set(node, prop.exp);
344
- }
345
- else if (prop.name === 'text' && prop.exp) {
346
- node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
347
- }
348
- else if (prop.name === 'slot') {
349
- context.onError(compilerDom.createCompilerError(40 /* ErrorCodes.X_V_SLOT_MISPLACED */, prop.loc));
350
- }
351
- else if (isTextareaWithValue(node, prop) && prop.exp) {
352
- if (!needMergeProps) {
353
- node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
354
- }
355
- }
356
- else if (!needMergeProps && prop.name !== 'on') {
357
- // Directive transforms.
358
- const directiveTransform = context.directiveTransforms[prop.name];
359
- if (directiveTransform) {
360
- const { props, ssrTagParts } = directiveTransform(prop, node, context);
361
- if (ssrTagParts) {
362
- openTag.push(...ssrTagParts);
363
- }
364
- for (let j = 0; j < props.length; j++) {
365
- const { key, value } = props[j];
366
- if (compilerDom.isStaticExp(key)) {
367
- let attrName = key.content;
368
- // static key attr
369
- if (attrName === 'key' || attrName === 'ref') {
370
- continue;
371
- }
372
- if (attrName === 'class') {
373
- openTag.push(` class="`, (dynamicClassBinding = compilerDom.createCallExpression(context.helper(SSR_RENDER_CLASS), [value])), `"`);
374
- }
375
- else if (attrName === 'style') {
376
- if (dynamicStyleBinding) {
377
- // already has style binding, merge into it.
378
- mergeCall(dynamicStyleBinding, value);
379
- }
380
- else {
381
- openTag.push(` style="`, (dynamicStyleBinding = compilerDom.createCallExpression(context.helper(SSR_RENDER_STYLE), [value])), `"`);
382
- }
383
- }
384
- else {
385
- attrName =
386
- node.tag.indexOf('-') > 0
387
- ? attrName // preserve raw name on custom elements
388
- : shared.propsToAttrMap[attrName] || attrName.toLowerCase();
389
- if (shared.isBooleanAttr(attrName)) {
390
- openTag.push(compilerDom.createConditionalExpression(compilerDom.createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [value]), compilerDom.createSimpleExpression(' ' + attrName, true), compilerDom.createSimpleExpression('', true), false /* no newline */));
391
- }
392
- else if (shared.isSSRSafeAttrName(attrName)) {
393
- openTag.push(compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTR), [
394
- key,
395
- value
396
- ]));
397
- }
398
- else {
399
- context.onError(createSSRCompilerError(61 /* SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME */, key.loc));
400
- }
401
- }
402
- }
403
- else {
404
- // dynamic key attr
405
- // this branch is only encountered for custom directive
406
- // transforms that returns properties with dynamic keys
407
- const args = [key, value];
408
- if (needTagForRuntime) {
409
- args.push(`"${node.tag}"`);
410
- }
411
- openTag.push(compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_ATTR), args));
412
- }
413
- }
414
- }
415
- }
416
- }
417
- else {
418
- // special case: value on <textarea>
419
- if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {
420
- rawChildrenMap.set(node, shared.escapeHtml(prop.value.content));
421
- }
422
- else if (!needMergeProps) {
423
- if (prop.name === 'key' || prop.name === 'ref') {
424
- continue;
425
- }
426
- // static prop
427
- if (prop.name === 'class' && prop.value) {
428
- staticClassBinding = JSON.stringify(prop.value.content);
429
- }
430
- openTag.push(` ${prop.name}` +
431
- (prop.value ? `="${shared.escapeHtml(prop.value.content)}"` : ``));
432
- }
433
- }
434
- }
435
- // handle co-existence of dynamic + static class bindings
436
- if (dynamicClassBinding && staticClassBinding) {
437
- mergeCall(dynamicClassBinding, staticClassBinding);
438
- removeStaticBinding(openTag, 'class');
439
- }
440
- if (context.scopeId) {
441
- openTag.push(` ${context.scopeId}`);
442
- }
443
- node.ssrCodegenNode = compilerDom.createTemplateLiteral(openTag);
444
- };
445
- };
446
- function buildSSRProps(props, directives, context) {
447
- let mergePropsArgs = [];
448
- if (props) {
449
- if (props.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
450
- // already a mergeProps call
451
- mergePropsArgs = props.arguments;
452
- }
453
- else {
454
- mergePropsArgs.push(props);
455
- }
456
- }
457
- if (directives.length) {
458
- for (const dir of directives) {
459
- mergePropsArgs.push(compilerDom.createCallExpression(context.helper(SSR_GET_DIRECTIVE_PROPS), [
460
- `_ctx`,
461
- ...compilerDom.buildDirectiveArgs(dir, context).elements
462
- ]));
463
- }
464
- }
465
- return mergePropsArgs.length > 1
466
- ? compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), mergePropsArgs)
467
- : mergePropsArgs[0];
468
- }
469
- function isTrueFalseValue(prop) {
470
- if (prop.type === 7 /* NodeTypes.DIRECTIVE */) {
471
- return (prop.name === 'bind' &&
472
- prop.arg &&
473
- compilerDom.isStaticExp(prop.arg) &&
474
- (prop.arg.content === 'true-value' || prop.arg.content === 'false-value'));
475
- }
476
- else {
477
- return prop.name === 'true-value' || prop.name === 'false-value';
478
- }
479
- }
480
- function isTextareaWithValue(node, prop) {
481
- return !!(node.tag === 'textarea' &&
482
- prop.name === 'bind' &&
483
- compilerDom.isStaticArgOf(prop.arg, 'value'));
484
- }
485
- function mergeCall(call, arg) {
486
- const existing = call.arguments[0];
487
- if (existing.type === 17 /* NodeTypes.JS_ARRAY_EXPRESSION */) {
488
- existing.elements.push(arg);
489
- }
490
- else {
491
- call.arguments[0] = compilerDom.createArrayExpression([existing, arg]);
492
- }
493
- }
494
- function removeStaticBinding(tag, binding) {
495
- const regExp = new RegExp(`^ ${binding}=".+"$`);
496
- const i = tag.findIndex(e => typeof e === 'string' && regExp.test(e));
497
- if (i > -1) {
498
- tag.splice(i, 1);
499
- }
500
- }
501
- function findVModel(node) {
502
- return node.props.find(p => p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'model' && p.exp);
503
- }
504
- function ssrProcessElement(node, context) {
505
- const isVoidTag = context.options.isVoidTag || shared.NO;
506
- const elementsToAdd = node.ssrCodegenNode.elements;
507
- for (let j = 0; j < elementsToAdd.length; j++) {
508
- context.pushStringPart(elementsToAdd[j]);
509
- }
510
- // Handle slot scopeId
511
- if (context.withSlotScopeId) {
512
- context.pushStringPart(compilerDom.createSimpleExpression(`_scopeId`, false));
513
- }
514
- // close open tag
515
- context.pushStringPart(`>`);
516
- const rawChildren = rawChildrenMap.get(node);
517
- if (rawChildren) {
518
- context.pushStringPart(rawChildren);
519
- }
520
- else if (node.children.length) {
521
- processChildren(node, context);
522
- }
523
- if (!isVoidTag(node.tag)) {
524
- // push closing tag
525
- context.pushStringPart(`</${node.tag}>`);
526
- }
256
+ // for directives with children overwrite (e.g. v-html & v-text), we need to
257
+ // store the raw children so that they can be added in the 2nd pass.
258
+ const rawChildrenMap = new WeakMap();
259
+ const ssrTransformElement = (node, context) => {
260
+ if (node.type !== 1 /* NodeTypes.ELEMENT */ ||
261
+ node.tagType !== 0 /* ElementTypes.ELEMENT */) {
262
+ return;
263
+ }
264
+ return function ssrPostTransformElement() {
265
+ // element
266
+ // generate the template literal representing the open tag.
267
+ const openTag = [`<${node.tag}`];
268
+ // some tags need to be passed to runtime for special checks
269
+ const needTagForRuntime = node.tag === 'textarea' || node.tag.indexOf('-') > 0;
270
+ // v-bind="obj", v-bind:[key] and custom directives can potentially
271
+ // overwrite other static attrs and can affect final rendering result,
272
+ // so when they are present we need to bail out to full `renderAttrs`
273
+ const hasDynamicVBind = compilerDom.hasDynamicKeyVBind(node);
274
+ const hasCustomDir = node.props.some(p => p.type === 7 /* NodeTypes.DIRECTIVE */ && !shared.isBuiltInDirective(p.name));
275
+ const needMergeProps = hasDynamicVBind || hasCustomDir;
276
+ if (needMergeProps) {
277
+ const { props, directives } = compilerDom.buildProps(node, context, node.props, false /* isComponent */, false /* isDynamicComponent */, true /* ssr */);
278
+ if (props || directives.length) {
279
+ const mergedProps = buildSSRProps(props, directives, context);
280
+ const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [mergedProps]);
281
+ if (node.tag === 'textarea') {
282
+ const existingText = node.children[0];
283
+ // If interpolation, this is dynamic <textarea> content, potentially
284
+ // injected by v-model and takes higher priority than v-bind value
285
+ if (!existingText || existingText.type !== 5 /* NodeTypes.INTERPOLATION */) {
286
+ // <textarea> with dynamic v-bind. We don't know if the final props
287
+ // will contain .value, so we will have to do something special:
288
+ // assign the merged props to a temp variable, and check whether
289
+ // it contains value (if yes, render is as children).
290
+ const tempId = `_temp${context.temps++}`;
291
+ propsExp.arguments = [
292
+ compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false), mergedProps)
293
+ ];
294
+ rawChildrenMap.set(node, compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [
295
+ compilerDom.createConditionalExpression(compilerDom.createSimpleExpression(`"value" in ${tempId}`, false), compilerDom.createSimpleExpression(`${tempId}.value`, false), compilerDom.createSimpleExpression(existingText ? existingText.content : ``, true), false)
296
+ ]));
297
+ }
298
+ }
299
+ else if (node.tag === 'input') {
300
+ // <input v-bind="obj" v-model>
301
+ // we need to determine the props to render for the dynamic v-model
302
+ // and merge it with the v-bind expression.
303
+ const vModel = findVModel(node);
304
+ if (vModel) {
305
+ // 1. save the props (san v-model) in a temp variable
306
+ const tempId = `_temp${context.temps++}`;
307
+ const tempExp = compilerDom.createSimpleExpression(tempId, false);
308
+ propsExp.arguments = [
309
+ compilerDom.createSequenceExpression([
310
+ compilerDom.createAssignmentExpression(tempExp, mergedProps),
311
+ compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), [
312
+ tempExp,
313
+ compilerDom.createCallExpression(context.helper(SSR_GET_DYNAMIC_MODEL_PROPS), [
314
+ tempExp,
315
+ vModel.exp // model
316
+ ])
317
+ ])
318
+ ])
319
+ ];
320
+ }
321
+ }
322
+ if (needTagForRuntime) {
323
+ propsExp.arguments.push(`"${node.tag}"`);
324
+ }
325
+ openTag.push(propsExp);
326
+ }
327
+ }
328
+ // book keeping static/dynamic class merging.
329
+ let dynamicClassBinding = undefined;
330
+ let staticClassBinding = undefined;
331
+ // all style bindings are converted to dynamic by transformStyle.
332
+ // but we need to make sure to merge them.
333
+ let dynamicStyleBinding = undefined;
334
+ for (let i = 0; i < node.props.length; i++) {
335
+ const prop = node.props[i];
336
+ // ignore true-value/false-value on input
337
+ if (node.tag === 'input' && isTrueFalseValue(prop)) {
338
+ continue;
339
+ }
340
+ // special cases with children override
341
+ if (prop.type === 7 /* NodeTypes.DIRECTIVE */) {
342
+ if (prop.name === 'html' && prop.exp) {
343
+ rawChildrenMap.set(node, prop.exp);
344
+ }
345
+ else if (prop.name === 'text' && prop.exp) {
346
+ node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
347
+ }
348
+ else if (prop.name === 'slot') {
349
+ context.onError(compilerDom.createCompilerError(40 /* ErrorCodes.X_V_SLOT_MISPLACED */, prop.loc));
350
+ }
351
+ else if (isTextareaWithValue(node, prop) && prop.exp) {
352
+ if (!needMergeProps) {
353
+ node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
354
+ }
355
+ }
356
+ else if (!needMergeProps && prop.name !== 'on') {
357
+ // Directive transforms.
358
+ const directiveTransform = context.directiveTransforms[prop.name];
359
+ if (directiveTransform) {
360
+ const { props, ssrTagParts } = directiveTransform(prop, node, context);
361
+ if (ssrTagParts) {
362
+ openTag.push(...ssrTagParts);
363
+ }
364
+ for (let j = 0; j < props.length; j++) {
365
+ const { key, value } = props[j];
366
+ if (compilerDom.isStaticExp(key)) {
367
+ let attrName = key.content;
368
+ // static key attr
369
+ if (attrName === 'key' || attrName === 'ref') {
370
+ continue;
371
+ }
372
+ if (attrName === 'class') {
373
+ openTag.push(` class="`, (dynamicClassBinding = compilerDom.createCallExpression(context.helper(SSR_RENDER_CLASS), [value])), `"`);
374
+ }
375
+ else if (attrName === 'style') {
376
+ if (dynamicStyleBinding) {
377
+ // already has style binding, merge into it.
378
+ mergeCall(dynamicStyleBinding, value);
379
+ }
380
+ else {
381
+ openTag.push(` style="`, (dynamicStyleBinding = compilerDom.createCallExpression(context.helper(SSR_RENDER_STYLE), [value])), `"`);
382
+ }
383
+ }
384
+ else {
385
+ attrName =
386
+ node.tag.indexOf('-') > 0
387
+ ? attrName // preserve raw name on custom elements
388
+ : shared.propsToAttrMap[attrName] || attrName.toLowerCase();
389
+ if (shared.isBooleanAttr(attrName)) {
390
+ openTag.push(compilerDom.createConditionalExpression(compilerDom.createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [value]), compilerDom.createSimpleExpression(' ' + attrName, true), compilerDom.createSimpleExpression('', true), false /* no newline */));
391
+ }
392
+ else if (shared.isSSRSafeAttrName(attrName)) {
393
+ openTag.push(compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTR), [
394
+ key,
395
+ value
396
+ ]));
397
+ }
398
+ else {
399
+ context.onError(createSSRCompilerError(61 /* SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME */, key.loc));
400
+ }
401
+ }
402
+ }
403
+ else {
404
+ // dynamic key attr
405
+ // this branch is only encountered for custom directive
406
+ // transforms that returns properties with dynamic keys
407
+ const args = [key, value];
408
+ if (needTagForRuntime) {
409
+ args.push(`"${node.tag}"`);
410
+ }
411
+ openTag.push(compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_ATTR), args));
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
417
+ else {
418
+ // special case: value on <textarea>
419
+ if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {
420
+ rawChildrenMap.set(node, shared.escapeHtml(prop.value.content));
421
+ }
422
+ else if (!needMergeProps) {
423
+ if (prop.name === 'key' || prop.name === 'ref') {
424
+ continue;
425
+ }
426
+ // static prop
427
+ if (prop.name === 'class' && prop.value) {
428
+ staticClassBinding = JSON.stringify(prop.value.content);
429
+ }
430
+ openTag.push(` ${prop.name}` +
431
+ (prop.value ? `="${shared.escapeHtml(prop.value.content)}"` : ``));
432
+ }
433
+ }
434
+ }
435
+ // handle co-existence of dynamic + static class bindings
436
+ if (dynamicClassBinding && staticClassBinding) {
437
+ mergeCall(dynamicClassBinding, staticClassBinding);
438
+ removeStaticBinding(openTag, 'class');
439
+ }
440
+ if (context.scopeId) {
441
+ openTag.push(` ${context.scopeId}`);
442
+ }
443
+ node.ssrCodegenNode = compilerDom.createTemplateLiteral(openTag);
444
+ };
445
+ };
446
+ function buildSSRProps(props, directives, context) {
447
+ let mergePropsArgs = [];
448
+ if (props) {
449
+ if (props.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
450
+ // already a mergeProps call
451
+ mergePropsArgs = props.arguments;
452
+ }
453
+ else {
454
+ mergePropsArgs.push(props);
455
+ }
456
+ }
457
+ if (directives.length) {
458
+ for (const dir of directives) {
459
+ mergePropsArgs.push(compilerDom.createCallExpression(context.helper(SSR_GET_DIRECTIVE_PROPS), [
460
+ `_ctx`,
461
+ ...compilerDom.buildDirectiveArgs(dir, context).elements
462
+ ]));
463
+ }
464
+ }
465
+ return mergePropsArgs.length > 1
466
+ ? compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), mergePropsArgs)
467
+ : mergePropsArgs[0];
468
+ }
469
+ function isTrueFalseValue(prop) {
470
+ if (prop.type === 7 /* NodeTypes.DIRECTIVE */) {
471
+ return (prop.name === 'bind' &&
472
+ prop.arg &&
473
+ compilerDom.isStaticExp(prop.arg) &&
474
+ (prop.arg.content === 'true-value' || prop.arg.content === 'false-value'));
475
+ }
476
+ else {
477
+ return prop.name === 'true-value' || prop.name === 'false-value';
478
+ }
479
+ }
480
+ function isTextareaWithValue(node, prop) {
481
+ return !!(node.tag === 'textarea' &&
482
+ prop.name === 'bind' &&
483
+ compilerDom.isStaticArgOf(prop.arg, 'value'));
484
+ }
485
+ function mergeCall(call, arg) {
486
+ const existing = call.arguments[0];
487
+ if (existing.type === 17 /* NodeTypes.JS_ARRAY_EXPRESSION */) {
488
+ existing.elements.push(arg);
489
+ }
490
+ else {
491
+ call.arguments[0] = compilerDom.createArrayExpression([existing, arg]);
492
+ }
493
+ }
494
+ function removeStaticBinding(tag, binding) {
495
+ const regExp = new RegExp(`^ ${binding}=".+"$`);
496
+ const i = tag.findIndex(e => typeof e === 'string' && regExp.test(e));
497
+ if (i > -1) {
498
+ tag.splice(i, 1);
499
+ }
500
+ }
501
+ function findVModel(node) {
502
+ return node.props.find(p => p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'model' && p.exp);
503
+ }
504
+ function ssrProcessElement(node, context) {
505
+ const isVoidTag = context.options.isVoidTag || shared.NO;
506
+ const elementsToAdd = node.ssrCodegenNode.elements;
507
+ for (let j = 0; j < elementsToAdd.length; j++) {
508
+ context.pushStringPart(elementsToAdd[j]);
509
+ }
510
+ // Handle slot scopeId
511
+ if (context.withSlotScopeId) {
512
+ context.pushStringPart(compilerDom.createSimpleExpression(`_scopeId`, false));
513
+ }
514
+ // close open tag
515
+ context.pushStringPart(`>`);
516
+ const rawChildren = rawChildrenMap.get(node);
517
+ if (rawChildren) {
518
+ context.pushStringPart(rawChildren);
519
+ }
520
+ else if (node.children.length) {
521
+ processChildren(node, context);
522
+ }
523
+ if (!isVoidTag(node.tag)) {
524
+ // push closing tag
525
+ context.pushStringPart(`</${node.tag}>`);
526
+ }
527
527
  }
528
528
 
529
- const wipMap$1 = new WeakMap();
530
- // phase 1: build props
531
- function ssrTransformTransitionGroup(node, context) {
532
- return () => {
533
- const tag = compilerDom.findProp(node, 'tag');
534
- if (tag) {
535
- const otherProps = node.props.filter(p => p !== tag);
536
- const { props, directives } = compilerDom.buildProps(node, context, otherProps, true, /* isComponent */ false, /* isDynamicComponent */ true /* ssr (skip event listeners) */);
537
- let propsExp = null;
538
- if (props || directives.length) {
539
- propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [
540
- buildSSRProps(props, directives, context)
541
- ]);
542
- }
543
- wipMap$1.set(node, {
544
- tag,
545
- propsExp
546
- });
547
- }
548
- };
549
- }
550
- // phase 2: process children
551
- function ssrProcessTransitionGroup(node, context) {
552
- const entry = wipMap$1.get(node);
553
- if (entry) {
554
- const { tag, propsExp } = entry;
555
- if (tag.type === 7 /* NodeTypes.DIRECTIVE */) {
556
- // dynamic :tag
557
- context.pushStringPart(`<`);
558
- context.pushStringPart(tag.exp);
559
- if (propsExp) {
560
- context.pushStringPart(propsExp);
561
- }
562
- context.pushStringPart(`>`);
563
- processChildren(node, context, false,
564
- /**
565
- * TransitionGroup has the special runtime behavior of flattening and
566
- * concatenating all children into a single fragment (in order for them to
567
- * be patched using the same key map) so we need to account for that here
568
- * by disabling nested fragment wrappers from being generated.
569
- */
570
- true);
571
- context.pushStringPart(`</`);
572
- context.pushStringPart(tag.exp);
573
- context.pushStringPart(`>`);
574
- }
575
- else {
576
- // static tag
577
- context.pushStringPart(`<${tag.value.content}`);
578
- if (propsExp) {
579
- context.pushStringPart(propsExp);
580
- }
581
- context.pushStringPart(`>`);
582
- processChildren(node, context, false, true);
583
- context.pushStringPart(`</${tag.value.content}>`);
584
- }
585
- }
586
- else {
587
- // fragment
588
- processChildren(node, context, true, true);
589
- }
529
+ const wipMap$1 = new WeakMap();
530
+ // phase 1: build props
531
+ function ssrTransformTransitionGroup(node, context) {
532
+ return () => {
533
+ const tag = compilerDom.findProp(node, 'tag');
534
+ if (tag) {
535
+ const otherProps = node.props.filter(p => p !== tag);
536
+ const { props, directives } = compilerDom.buildProps(node, context, otherProps, true /* isComponent */, false /* isDynamicComponent */, true /* ssr (skip event listeners) */);
537
+ let propsExp = null;
538
+ if (props || directives.length) {
539
+ propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [
540
+ buildSSRProps(props, directives, context)
541
+ ]);
542
+ }
543
+ wipMap$1.set(node, {
544
+ tag,
545
+ propsExp
546
+ });
547
+ }
548
+ };
549
+ }
550
+ // phase 2: process children
551
+ function ssrProcessTransitionGroup(node, context) {
552
+ const entry = wipMap$1.get(node);
553
+ if (entry) {
554
+ const { tag, propsExp } = entry;
555
+ if (tag.type === 7 /* NodeTypes.DIRECTIVE */) {
556
+ // dynamic :tag
557
+ context.pushStringPart(`<`);
558
+ context.pushStringPart(tag.exp);
559
+ if (propsExp) {
560
+ context.pushStringPart(propsExp);
561
+ }
562
+ context.pushStringPart(`>`);
563
+ processChildren(node, context, false,
564
+ /**
565
+ * TransitionGroup has the special runtime behavior of flattening and
566
+ * concatenating all children into a single fragment (in order for them to
567
+ * be patched using the same key map) so we need to account for that here
568
+ * by disabling nested fragment wrappers from being generated.
569
+ */
570
+ true);
571
+ context.pushStringPart(`</`);
572
+ context.pushStringPart(tag.exp);
573
+ context.pushStringPart(`>`);
574
+ }
575
+ else {
576
+ // static tag
577
+ context.pushStringPart(`<${tag.value.content}`);
578
+ if (propsExp) {
579
+ context.pushStringPart(propsExp);
580
+ }
581
+ context.pushStringPart(`>`);
582
+ processChildren(node, context, false, true);
583
+ context.pushStringPart(`</${tag.value.content}>`);
584
+ }
585
+ }
586
+ else {
587
+ // fragment
588
+ processChildren(node, context, true, true);
589
+ }
590
590
  }
591
591
 
592
- // We need to construct the slot functions in the 1st pass to ensure proper
593
- // scope tracking, but the children of each slot cannot be processed until
594
- // the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
595
- // pass and complete them in the 2nd pass.
596
- const wipMap$2 = new WeakMap();
597
- const WIP_SLOT = Symbol();
598
- const componentTypeMap = new WeakMap();
599
- // ssr component transform is done in two phases:
600
- // In phase 1. we use `buildSlot` to analyze the children of the component into
601
- // WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
602
- // the core transform context).
603
- // In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
604
- // nodes.
605
- const ssrTransformComponent = (node, context) => {
606
- if (node.type !== 1 /* NodeTypes.ELEMENT */ ||
607
- node.tagType !== 1 /* ElementTypes.COMPONENT */) {
608
- return;
609
- }
610
- const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
611
- const isDynamicComponent = shared.isObject(component) && component.callee === compilerDom.RESOLVE_DYNAMIC_COMPONENT;
612
- componentTypeMap.set(node, component);
613
- if (shared.isSymbol(component)) {
614
- if (component === compilerDom.SUSPENSE) {
615
- return ssrTransformSuspense(node, context);
616
- }
617
- if (component === compilerDom.TRANSITION_GROUP) {
618
- return ssrTransformTransitionGroup(node, context);
619
- }
620
- return; // other built-in components: fallthrough
621
- }
622
- // Build the fallback vnode-based branch for the component's slots.
623
- // We need to clone the node into a fresh copy and use the buildSlots' logic
624
- // to get access to the children of each slot. We then compile them with
625
- // a child transform pipeline using vnode-based transforms (instead of ssr-
626
- // based ones), and save the result branch (a ReturnStatement) in an array.
627
- // The branch is retrieved when processing slots again in ssr mode.
628
- const vnodeBranches = [];
629
- const clonedNode = clone(node);
630
- return function ssrPostTransformComponent() {
631
- // Using the cloned node, build the normal VNode-based branches (for
632
- // fallback in case the child is render-fn based). Store them in an array
633
- // for later use.
634
- if (clonedNode.children.length) {
635
- compilerDom.buildSlots(clonedNode, context, (props, children) => {
636
- vnodeBranches.push(createVNodeSlotBranch(props, children, context));
637
- return compilerDom.createFunctionExpression(undefined);
638
- });
639
- }
640
- let propsExp = `null`;
641
- if (node.props.length) {
642
- // note we are not passing ssr: true here because for components, v-on
643
- // handlers should still be passed
644
- const { props, directives } = compilerDom.buildProps(node, context, undefined, true, isDynamicComponent);
645
- if (props || directives.length) {
646
- propsExp = buildSSRProps(props, directives, context);
647
- }
648
- }
649
- const wipEntries = [];
650
- wipMap$2.set(node, wipEntries);
651
- const buildSSRSlotFn = (props, children, loc) => {
652
- const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
653
- true, // newline
654
- true, // isSlot
655
- loc);
656
- wipEntries.push({
657
- type: WIP_SLOT,
658
- fn,
659
- children,
660
- // also collect the corresponding vnode branch built earlier
661
- vnodeBranch: vnodeBranches[wipEntries.length]
662
- });
663
- return fn;
664
- };
665
- const slots = node.children.length
666
- ? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots
667
- : `null`;
668
- if (typeof component !== 'string') {
669
- // dynamic component that resolved to a `resolveDynamicComponent` call
670
- // expression - since the resolved result may be a plain element (string)
671
- // or a VNode, handle it with `renderVNode`.
672
- node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_VNODE), [
673
- `_push`,
674
- compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
675
- component,
676
- propsExp,
677
- slots
678
- ]),
679
- `_parent`
680
- ]);
681
- }
682
- else {
683
- node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_COMPONENT), [component, propsExp, slots, `_parent`]);
684
- }
685
- };
686
- };
687
- function ssrProcessComponent(node, context, parent) {
688
- const component = componentTypeMap.get(node);
689
- if (!node.ssrCodegenNode) {
690
- // this is a built-in component that fell-through.
691
- if (component === compilerDom.TELEPORT) {
692
- return ssrProcessTeleport(node, context);
693
- }
694
- else if (component === compilerDom.SUSPENSE) {
695
- return ssrProcessSuspense(node, context);
696
- }
697
- else if (component === compilerDom.TRANSITION_GROUP) {
698
- return ssrProcessTransitionGroup(node, context);
699
- }
700
- else {
701
- // real fall-through: Transition / KeepAlive
702
- // just render its children.
703
- // #5352: if is at root level of a slot, push an empty string.
704
- // this does not affect the final output, but avoids all-comment slot
705
- // content of being treated as empty by ssrRenderSlot().
706
- if (parent.type === WIP_SLOT) {
707
- context.pushStringPart(``);
708
- }
709
- // #5351: filter out comment children inside transition
710
- if (component === compilerDom.TRANSITION) {
711
- node.children = node.children.filter(c => c.type !== 3 /* NodeTypes.COMMENT */);
712
- }
713
- processChildren(node, context);
714
- }
715
- }
716
- else {
717
- // finish up slot function expressions from the 1st pass.
718
- const wipEntries = wipMap$2.get(node) || [];
719
- for (let i = 0; i < wipEntries.length; i++) {
720
- const { fn, vnodeBranch } = wipEntries[i];
721
- // For each slot, we generate two branches: one SSR-optimized branch and
722
- // one normal vnode-based branch. The branches are taken based on the
723
- // presence of the 2nd `_push` argument (which is only present if the slot
724
- // is called by `_ssrRenderSlot`.
725
- fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(wipEntries[i], context, false, true /* withSlotScopeId */), vnodeBranch);
726
- }
727
- // component is inside a slot, inherit slot scope Id
728
- if (context.withSlotScopeId) {
729
- node.ssrCodegenNode.arguments.push(`_scopeId`);
730
- }
731
- if (typeof component === 'string') {
732
- // static component
733
- context.pushStatement(compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode]));
734
- }
735
- else {
736
- // dynamic component (`resolveDynamicComponent` call)
737
- // the codegen node is a `renderVNode` call
738
- context.pushStatement(node.ssrCodegenNode);
739
- }
740
- }
741
- }
742
- const rawOptionsMap = new WeakMap();
743
- const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
744
- const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
745
- const vnodeDirectiveTransforms = {
746
- ...baseDirectiveTransforms,
747
- ...compilerDom.DOMDirectiveTransforms
748
- };
749
- function createVNodeSlotBranch(props, children, parentContext) {
750
- // apply a sub-transform using vnode-based transforms.
751
- const rawOptions = rawOptionsMap.get(parentContext.root);
752
- const subOptions = {
753
- ...rawOptions,
754
- // overwrite with vnode-based transforms
755
- nodeTransforms: [
756
- ...vnodeNodeTransforms,
757
- ...(rawOptions.nodeTransforms || [])
758
- ],
759
- directiveTransforms: {
760
- ...vnodeDirectiveTransforms,
761
- ...(rawOptions.directiveTransforms || {})
762
- }
763
- };
764
- // wrap the children with a wrapper template for proper children treatment.
765
- const wrapperNode = {
766
- type: 1 /* NodeTypes.ELEMENT */,
767
- ns: 0 /* Namespaces.HTML */,
768
- tag: 'template',
769
- tagType: 3 /* ElementTypes.TEMPLATE */,
770
- isSelfClosing: false,
771
- // important: provide v-slot="props" on the wrapper for proper
772
- // scope analysis
773
- props: [
774
- {
775
- type: 7 /* NodeTypes.DIRECTIVE */,
776
- name: 'slot',
777
- exp: props,
778
- arg: undefined,
779
- modifiers: [],
780
- loc: compilerDom.locStub
781
- }
782
- ],
783
- children,
784
- loc: compilerDom.locStub,
785
- codegenNode: undefined
786
- };
787
- subTransform(wrapperNode, subOptions, parentContext);
788
- return compilerDom.createReturnStatement(children);
789
- }
790
- function subTransform(node, options, parentContext) {
791
- const childRoot = compilerDom.createRoot([node]);
792
- const childContext = compilerDom.createTransformContext(childRoot, options);
793
- // this sub transform is for vnode fallback branch so it should be handled
794
- // like normal render functions
795
- childContext.ssr = false;
796
- // inherit parent scope analysis state
797
- childContext.scopes = { ...parentContext.scopes };
798
- childContext.identifiers = { ...parentContext.identifiers };
799
- childContext.imports = parentContext.imports;
800
- // traverse
801
- compilerDom.traverseNode(childRoot, childContext);
802
- ['helpers', 'components', 'directives'].forEach(key => {
803
- childContext[key].forEach((value, helperKey) => {
804
- if (key === 'helpers') {
805
- const parentCount = parentContext.helpers.get(helperKey);
806
- if (parentCount === undefined) {
807
- parentContext.helpers.set(helperKey, value);
808
- }
809
- else {
810
- parentContext.helpers.set(helperKey, value + parentCount);
811
- }
812
- }
813
- else {
814
- parentContext[key].add(value);
815
- }
816
- });
817
- });
818
- // imports/hoists are not merged because:
819
- // - imports are only used for asset urls and should be consistent between
820
- // node/client branches
821
- // - hoists are not enabled for the client branch here
822
- }
823
- function clone(v) {
824
- if (shared.isArray(v)) {
825
- return v.map(clone);
826
- }
827
- else if (shared.isObject(v)) {
828
- const res = {};
829
- for (const key in v) {
830
- res[key] = clone(v[key]);
831
- }
832
- return res;
833
- }
834
- else {
835
- return v;
836
- }
592
+ // We need to construct the slot functions in the 1st pass to ensure proper
593
+ // scope tracking, but the children of each slot cannot be processed until
594
+ // the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st
595
+ // pass and complete them in the 2nd pass.
596
+ const wipMap$2 = new WeakMap();
597
+ const WIP_SLOT = Symbol();
598
+ const componentTypeMap = new WeakMap();
599
+ // ssr component transform is done in two phases:
600
+ // In phase 1. we use `buildSlot` to analyze the children of the component into
601
+ // WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
602
+ // the core transform context).
603
+ // In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
604
+ // nodes.
605
+ const ssrTransformComponent = (node, context) => {
606
+ if (node.type !== 1 /* NodeTypes.ELEMENT */ ||
607
+ node.tagType !== 1 /* ElementTypes.COMPONENT */) {
608
+ return;
609
+ }
610
+ const component = compilerDom.resolveComponentType(node, context, true /* ssr */);
611
+ const isDynamicComponent = shared.isObject(component) && component.callee === compilerDom.RESOLVE_DYNAMIC_COMPONENT;
612
+ componentTypeMap.set(node, component);
613
+ if (shared.isSymbol(component)) {
614
+ if (component === compilerDom.SUSPENSE) {
615
+ return ssrTransformSuspense(node, context);
616
+ }
617
+ if (component === compilerDom.TRANSITION_GROUP) {
618
+ return ssrTransformTransitionGroup(node, context);
619
+ }
620
+ return; // other built-in components: fallthrough
621
+ }
622
+ // Build the fallback vnode-based branch for the component's slots.
623
+ // We need to clone the node into a fresh copy and use the buildSlots' logic
624
+ // to get access to the children of each slot. We then compile them with
625
+ // a child transform pipeline using vnode-based transforms (instead of ssr-
626
+ // based ones), and save the result branch (a ReturnStatement) in an array.
627
+ // The branch is retrieved when processing slots again in ssr mode.
628
+ const vnodeBranches = [];
629
+ const clonedNode = clone(node);
630
+ return function ssrPostTransformComponent() {
631
+ // Using the cloned node, build the normal VNode-based branches (for
632
+ // fallback in case the child is render-fn based). Store them in an array
633
+ // for later use.
634
+ if (clonedNode.children.length) {
635
+ compilerDom.buildSlots(clonedNode, context, (props, children) => {
636
+ vnodeBranches.push(createVNodeSlotBranch(props, children, context));
637
+ return compilerDom.createFunctionExpression(undefined);
638
+ });
639
+ }
640
+ let propsExp = `null`;
641
+ if (node.props.length) {
642
+ // note we are not passing ssr: true here because for components, v-on
643
+ // handlers should still be passed
644
+ const { props, directives } = compilerDom.buildProps(node, context, undefined, true, isDynamicComponent);
645
+ if (props || directives.length) {
646
+ propsExp = buildSSRProps(props, directives, context);
647
+ }
648
+ }
649
+ const wipEntries = [];
650
+ wipMap$2.set(node, wipEntries);
651
+ const buildSSRSlotFn = (props, children, loc) => {
652
+ const fn = compilerDom.createFunctionExpression([props || `_`, `_push`, `_parent`, `_scopeId`], undefined, // no return, assign body later
653
+ true, // newline
654
+ true, // isSlot
655
+ loc);
656
+ wipEntries.push({
657
+ type: WIP_SLOT,
658
+ fn,
659
+ children,
660
+ // also collect the corresponding vnode branch built earlier
661
+ vnodeBranch: vnodeBranches[wipEntries.length]
662
+ });
663
+ return fn;
664
+ };
665
+ const slots = node.children.length
666
+ ? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots
667
+ : `null`;
668
+ if (typeof component !== 'string') {
669
+ // dynamic component that resolved to a `resolveDynamicComponent` call
670
+ // expression - since the resolved result may be a plain element (string)
671
+ // or a VNode, handle it with `renderVNode`.
672
+ node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_VNODE), [
673
+ `_push`,
674
+ compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
675
+ component,
676
+ propsExp,
677
+ slots
678
+ ]),
679
+ `_parent`
680
+ ]);
681
+ }
682
+ else {
683
+ node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(SSR_RENDER_COMPONENT), [component, propsExp, slots, `_parent`]);
684
+ }
685
+ };
686
+ };
687
+ function ssrProcessComponent(node, context, parent) {
688
+ const component = componentTypeMap.get(node);
689
+ if (!node.ssrCodegenNode) {
690
+ // this is a built-in component that fell-through.
691
+ if (component === compilerDom.TELEPORT) {
692
+ return ssrProcessTeleport(node, context);
693
+ }
694
+ else if (component === compilerDom.SUSPENSE) {
695
+ return ssrProcessSuspense(node, context);
696
+ }
697
+ else if (component === compilerDom.TRANSITION_GROUP) {
698
+ return ssrProcessTransitionGroup(node, context);
699
+ }
700
+ else {
701
+ // real fall-through: Transition / KeepAlive
702
+ // just render its children.
703
+ // #5352: if is at root level of a slot, push an empty string.
704
+ // this does not affect the final output, but avoids all-comment slot
705
+ // content of being treated as empty by ssrRenderSlot().
706
+ if (parent.type === WIP_SLOT) {
707
+ context.pushStringPart(``);
708
+ }
709
+ // #5351: filter out comment children inside transition
710
+ if (component === compilerDom.TRANSITION) {
711
+ node.children = node.children.filter(c => c.type !== 3 /* NodeTypes.COMMENT */);
712
+ }
713
+ processChildren(node, context);
714
+ }
715
+ }
716
+ else {
717
+ // finish up slot function expressions from the 1st pass.
718
+ const wipEntries = wipMap$2.get(node) || [];
719
+ for (let i = 0; i < wipEntries.length; i++) {
720
+ const { fn, vnodeBranch } = wipEntries[i];
721
+ // For each slot, we generate two branches: one SSR-optimized branch and
722
+ // one normal vnode-based branch. The branches are taken based on the
723
+ // presence of the 2nd `_push` argument (which is only present if the slot
724
+ // is called by `_ssrRenderSlot`.
725
+ fn.body = compilerDom.createIfStatement(compilerDom.createSimpleExpression(`_push`, false), processChildrenAsStatement(wipEntries[i], context, false, true /* withSlotScopeId */), vnodeBranch);
726
+ }
727
+ // component is inside a slot, inherit slot scope Id
728
+ if (context.withSlotScopeId) {
729
+ node.ssrCodegenNode.arguments.push(`_scopeId`);
730
+ }
731
+ if (typeof component === 'string') {
732
+ // static component
733
+ context.pushStatement(compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode]));
734
+ }
735
+ else {
736
+ // dynamic component (`resolveDynamicComponent` call)
737
+ // the codegen node is a `renderVNode` call
738
+ context.pushStatement(node.ssrCodegenNode);
739
+ }
740
+ }
741
+ }
742
+ const rawOptionsMap = new WeakMap();
743
+ const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
744
+ const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
745
+ const vnodeDirectiveTransforms = {
746
+ ...baseDirectiveTransforms,
747
+ ...compilerDom.DOMDirectiveTransforms
748
+ };
749
+ function createVNodeSlotBranch(props, children, parentContext) {
750
+ // apply a sub-transform using vnode-based transforms.
751
+ const rawOptions = rawOptionsMap.get(parentContext.root);
752
+ const subOptions = {
753
+ ...rawOptions,
754
+ // overwrite with vnode-based transforms
755
+ nodeTransforms: [
756
+ ...vnodeNodeTransforms,
757
+ ...(rawOptions.nodeTransforms || [])
758
+ ],
759
+ directiveTransforms: {
760
+ ...vnodeDirectiveTransforms,
761
+ ...(rawOptions.directiveTransforms || {})
762
+ }
763
+ };
764
+ // wrap the children with a wrapper template for proper children treatment.
765
+ const wrapperNode = {
766
+ type: 1 /* NodeTypes.ELEMENT */,
767
+ ns: 0 /* Namespaces.HTML */,
768
+ tag: 'template',
769
+ tagType: 3 /* ElementTypes.TEMPLATE */,
770
+ isSelfClosing: false,
771
+ // important: provide v-slot="props" on the wrapper for proper
772
+ // scope analysis
773
+ props: [
774
+ {
775
+ type: 7 /* NodeTypes.DIRECTIVE */,
776
+ name: 'slot',
777
+ exp: props,
778
+ arg: undefined,
779
+ modifiers: [],
780
+ loc: compilerDom.locStub
781
+ }
782
+ ],
783
+ children,
784
+ loc: compilerDom.locStub,
785
+ codegenNode: undefined
786
+ };
787
+ subTransform(wrapperNode, subOptions, parentContext);
788
+ return compilerDom.createReturnStatement(children);
789
+ }
790
+ function subTransform(node, options, parentContext) {
791
+ const childRoot = compilerDom.createRoot([node]);
792
+ const childContext = compilerDom.createTransformContext(childRoot, options);
793
+ // this sub transform is for vnode fallback branch so it should be handled
794
+ // like normal render functions
795
+ childContext.ssr = false;
796
+ // inherit parent scope analysis state
797
+ childContext.scopes = { ...parentContext.scopes };
798
+ childContext.identifiers = { ...parentContext.identifiers };
799
+ childContext.imports = parentContext.imports;
800
+ // traverse
801
+ compilerDom.traverseNode(childRoot, childContext);
802
+ ['helpers', 'components', 'directives'].forEach(key => {
803
+ childContext[key].forEach((value, helperKey) => {
804
+ if (key === 'helpers') {
805
+ const parentCount = parentContext.helpers.get(helperKey);
806
+ if (parentCount === undefined) {
807
+ parentContext.helpers.set(helperKey, value);
808
+ }
809
+ else {
810
+ parentContext.helpers.set(helperKey, value + parentCount);
811
+ }
812
+ }
813
+ else {
814
+ parentContext[key].add(value);
815
+ }
816
+ });
817
+ });
818
+ // imports/hoists are not merged because:
819
+ // - imports are only used for asset urls and should be consistent between
820
+ // node/client branches
821
+ // - hoists are not enabled for the client branch here
822
+ }
823
+ function clone(v) {
824
+ if (shared.isArray(v)) {
825
+ return v.map(clone);
826
+ }
827
+ else if (shared.isObject(v)) {
828
+ const res = {};
829
+ for (const key in v) {
830
+ res[key] = clone(v[key]);
831
+ }
832
+ return res;
833
+ }
834
+ else {
835
+ return v;
836
+ }
837
837
  }
838
838
 
839
- // Because SSR codegen output is completely different from client-side output
840
- // (e.g. multiple elements can be concatenated into a single template literal
841
- // instead of each getting a corresponding call), we need to apply an extra
842
- // transform pass to convert the template AST into a fresh JS AST before
843
- // passing it to codegen.
844
- function ssrCodegenTransform(ast, options) {
845
- const context = createSSRTransformContext(ast, options);
846
- // inject SFC <style> CSS variables
847
- // we do this instead of inlining the expression to ensure the vars are
848
- // only resolved once per render
849
- if (options.ssrCssVars) {
850
- const cssContext = compilerDom.createTransformContext(compilerDom.createRoot([]), options);
851
- const varsExp = compilerDom.processExpression(compilerDom.createSimpleExpression(options.ssrCssVars, false), cssContext);
852
- context.body.push(compilerDom.createCompoundExpression([`const _cssVars = { style: `, varsExp, `}`]));
853
- Array.from(cssContext.helpers.keys()).forEach(helper => {
854
- if (!ast.helpers.includes(helper))
855
- ast.helpers.push(helper);
856
- });
857
- }
858
- const isFragment = ast.children.length > 1 && ast.children.some(c => !compilerDom.isText(c));
859
- processChildren(ast, context, isFragment);
860
- ast.codegenNode = compilerDom.createBlockStatement(context.body);
861
- // Finalize helpers.
862
- // We need to separate helpers imported from 'vue' vs. '@vue/server-renderer'
863
- ast.ssrHelpers = Array.from(new Set([...ast.helpers.filter(h => h in ssrHelpers), ...context.helpers]));
864
- ast.helpers = ast.helpers.filter(h => !(h in ssrHelpers));
865
- }
866
- function createSSRTransformContext(root, options, helpers = new Set(), withSlotScopeId = false) {
867
- const body = [];
868
- let currentString = null;
869
- return {
870
- root,
871
- options,
872
- body,
873
- helpers,
874
- withSlotScopeId,
875
- onError: options.onError ||
876
- (e => {
877
- throw e;
878
- }),
879
- helper(name) {
880
- helpers.add(name);
881
- return name;
882
- },
883
- pushStringPart(part) {
884
- if (!currentString) {
885
- const currentCall = compilerDom.createCallExpression(`_push`);
886
- body.push(currentCall);
887
- currentString = compilerDom.createTemplateLiteral([]);
888
- currentCall.arguments.push(currentString);
889
- }
890
- const bufferedElements = currentString.elements;
891
- const lastItem = bufferedElements[bufferedElements.length - 1];
892
- if (shared.isString(part) && shared.isString(lastItem)) {
893
- bufferedElements[bufferedElements.length - 1] += part;
894
- }
895
- else {
896
- bufferedElements.push(part);
897
- }
898
- },
899
- pushStatement(statement) {
900
- // close current string
901
- currentString = null;
902
- body.push(statement);
903
- }
904
- };
905
- }
906
- function createChildContext(parent, withSlotScopeId = parent.withSlotScopeId) {
907
- // ensure child inherits parent helpers
908
- return createSSRTransformContext(parent.root, parent.options, parent.helpers, withSlotScopeId);
909
- }
910
- function processChildren(parent, context, asFragment = false, disableNestedFragments = false) {
911
- if (asFragment) {
912
- context.pushStringPart(`<!--[-->`);
913
- }
914
- const { children } = parent;
915
- for (let i = 0; i < children.length; i++) {
916
- const child = children[i];
917
- switch (child.type) {
918
- case 1 /* NodeTypes.ELEMENT */:
919
- switch (child.tagType) {
920
- case 0 /* ElementTypes.ELEMENT */:
921
- ssrProcessElement(child, context);
922
- break;
923
- case 1 /* ElementTypes.COMPONENT */:
924
- ssrProcessComponent(child, context, parent);
925
- break;
926
- case 2 /* ElementTypes.SLOT */:
927
- ssrProcessSlotOutlet(child, context);
928
- break;
929
- case 3 /* ElementTypes.TEMPLATE */:
930
- // TODO
931
- break;
932
- default:
933
- context.onError(createSSRCompilerError(63 /* SSRErrorCodes.X_SSR_INVALID_AST_NODE */, child.loc));
934
- // make sure we exhaust all possible types
935
- const exhaustiveCheck = child;
936
- return exhaustiveCheck;
937
- }
938
- break;
939
- case 2 /* NodeTypes.TEXT */:
940
- context.pushStringPart(shared.escapeHtml(child.content));
941
- break;
942
- case 3 /* NodeTypes.COMMENT */:
943
- // no need to escape comment here because the AST can only
944
- // contain valid comments.
945
- context.pushStringPart(`<!--${child.content}-->`);
946
- break;
947
- case 5 /* NodeTypes.INTERPOLATION */:
948
- context.pushStringPart(compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [child.content]));
949
- break;
950
- case 9 /* NodeTypes.IF */:
951
- ssrProcessIf(child, context, disableNestedFragments);
952
- break;
953
- case 11 /* NodeTypes.FOR */:
954
- ssrProcessFor(child, context, disableNestedFragments);
955
- break;
956
- case 10 /* NodeTypes.IF_BRANCH */:
957
- // no-op - handled by ssrProcessIf
958
- break;
959
- case 12 /* NodeTypes.TEXT_CALL */:
960
- case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
961
- // no-op - these two types can never appear as template child node since
962
- // `transformText` is not used during SSR compile.
963
- break;
964
- default:
965
- context.onError(createSSRCompilerError(63 /* SSRErrorCodes.X_SSR_INVALID_AST_NODE */, child.loc));
966
- // make sure we exhaust all possible types
967
- const exhaustiveCheck = child;
968
- return exhaustiveCheck;
969
- }
970
- }
971
- if (asFragment) {
972
- context.pushStringPart(`<!--]-->`);
973
- }
974
- }
975
- function processChildrenAsStatement(parent, parentContext, asFragment = false, withSlotScopeId = parentContext.withSlotScopeId) {
976
- const childContext = createChildContext(parentContext, withSlotScopeId);
977
- processChildren(parent, childContext, asFragment);
978
- return compilerDom.createBlockStatement(childContext.body);
839
+ // Because SSR codegen output is completely different from client-side output
840
+ // (e.g. multiple elements can be concatenated into a single template literal
841
+ // instead of each getting a corresponding call), we need to apply an extra
842
+ // transform pass to convert the template AST into a fresh JS AST before
843
+ // passing it to codegen.
844
+ function ssrCodegenTransform(ast, options) {
845
+ const context = createSSRTransformContext(ast, options);
846
+ // inject SFC <style> CSS variables
847
+ // we do this instead of inlining the expression to ensure the vars are
848
+ // only resolved once per render
849
+ if (options.ssrCssVars) {
850
+ const cssContext = compilerDom.createTransformContext(compilerDom.createRoot([]), options);
851
+ const varsExp = compilerDom.processExpression(compilerDom.createSimpleExpression(options.ssrCssVars, false), cssContext);
852
+ context.body.push(compilerDom.createCompoundExpression([`const _cssVars = { style: `, varsExp, `}`]));
853
+ Array.from(cssContext.helpers.keys()).forEach(helper => {
854
+ if (!ast.helpers.includes(helper))
855
+ ast.helpers.push(helper);
856
+ });
857
+ }
858
+ const isFragment = ast.children.length > 1 && ast.children.some(c => !compilerDom.isText(c));
859
+ processChildren(ast, context, isFragment);
860
+ ast.codegenNode = compilerDom.createBlockStatement(context.body);
861
+ // Finalize helpers.
862
+ // We need to separate helpers imported from 'vue' vs. '@vue/server-renderer'
863
+ ast.ssrHelpers = Array.from(new Set([...ast.helpers.filter(h => h in ssrHelpers), ...context.helpers]));
864
+ ast.helpers = ast.helpers.filter(h => !(h in ssrHelpers));
865
+ }
866
+ function createSSRTransformContext(root, options, helpers = new Set(), withSlotScopeId = false) {
867
+ const body = [];
868
+ let currentString = null;
869
+ return {
870
+ root,
871
+ options,
872
+ body,
873
+ helpers,
874
+ withSlotScopeId,
875
+ onError: options.onError ||
876
+ (e => {
877
+ throw e;
878
+ }),
879
+ helper(name) {
880
+ helpers.add(name);
881
+ return name;
882
+ },
883
+ pushStringPart(part) {
884
+ if (!currentString) {
885
+ const currentCall = compilerDom.createCallExpression(`_push`);
886
+ body.push(currentCall);
887
+ currentString = compilerDom.createTemplateLiteral([]);
888
+ currentCall.arguments.push(currentString);
889
+ }
890
+ const bufferedElements = currentString.elements;
891
+ const lastItem = bufferedElements[bufferedElements.length - 1];
892
+ if (shared.isString(part) && shared.isString(lastItem)) {
893
+ bufferedElements[bufferedElements.length - 1] += part;
894
+ }
895
+ else {
896
+ bufferedElements.push(part);
897
+ }
898
+ },
899
+ pushStatement(statement) {
900
+ // close current string
901
+ currentString = null;
902
+ body.push(statement);
903
+ }
904
+ };
905
+ }
906
+ function createChildContext(parent, withSlotScopeId = parent.withSlotScopeId) {
907
+ // ensure child inherits parent helpers
908
+ return createSSRTransformContext(parent.root, parent.options, parent.helpers, withSlotScopeId);
909
+ }
910
+ function processChildren(parent, context, asFragment = false, disableNestedFragments = false) {
911
+ if (asFragment) {
912
+ context.pushStringPart(`<!--[-->`);
913
+ }
914
+ const { children } = parent;
915
+ for (let i = 0; i < children.length; i++) {
916
+ const child = children[i];
917
+ switch (child.type) {
918
+ case 1 /* NodeTypes.ELEMENT */:
919
+ switch (child.tagType) {
920
+ case 0 /* ElementTypes.ELEMENT */:
921
+ ssrProcessElement(child, context);
922
+ break;
923
+ case 1 /* ElementTypes.COMPONENT */:
924
+ ssrProcessComponent(child, context, parent);
925
+ break;
926
+ case 2 /* ElementTypes.SLOT */:
927
+ ssrProcessSlotOutlet(child, context);
928
+ break;
929
+ case 3 /* ElementTypes.TEMPLATE */:
930
+ // TODO
931
+ break;
932
+ default:
933
+ context.onError(createSSRCompilerError(63 /* SSRErrorCodes.X_SSR_INVALID_AST_NODE */, child.loc));
934
+ // make sure we exhaust all possible types
935
+ const exhaustiveCheck = child;
936
+ return exhaustiveCheck;
937
+ }
938
+ break;
939
+ case 2 /* NodeTypes.TEXT */:
940
+ context.pushStringPart(shared.escapeHtml(child.content));
941
+ break;
942
+ case 3 /* NodeTypes.COMMENT */:
943
+ // no need to escape comment here because the AST can only
944
+ // contain valid comments.
945
+ context.pushStringPart(`<!--${child.content}-->`);
946
+ break;
947
+ case 5 /* NodeTypes.INTERPOLATION */:
948
+ context.pushStringPart(compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [child.content]));
949
+ break;
950
+ case 9 /* NodeTypes.IF */:
951
+ ssrProcessIf(child, context, disableNestedFragments);
952
+ break;
953
+ case 11 /* NodeTypes.FOR */:
954
+ ssrProcessFor(child, context, disableNestedFragments);
955
+ break;
956
+ case 10 /* NodeTypes.IF_BRANCH */:
957
+ // no-op - handled by ssrProcessIf
958
+ break;
959
+ case 12 /* NodeTypes.TEXT_CALL */:
960
+ case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
961
+ // no-op - these two types can never appear as template child node since
962
+ // `transformText` is not used during SSR compile.
963
+ break;
964
+ default:
965
+ context.onError(createSSRCompilerError(63 /* SSRErrorCodes.X_SSR_INVALID_AST_NODE */, child.loc));
966
+ // make sure we exhaust all possible types
967
+ const exhaustiveCheck = child;
968
+ return exhaustiveCheck;
969
+ }
970
+ }
971
+ if (asFragment) {
972
+ context.pushStringPart(`<!--]-->`);
973
+ }
974
+ }
975
+ function processChildrenAsStatement(parent, parentContext, asFragment = false, withSlotScopeId = parentContext.withSlotScopeId) {
976
+ const childContext = createChildContext(parentContext, withSlotScopeId);
977
+ processChildren(parent, childContext, asFragment);
978
+ return compilerDom.createBlockStatement(childContext.body);
979
979
  }
980
980
 
981
- const ssrTransformModel = (dir, node, context) => {
982
- const model = dir.exp;
983
- function checkDuplicatedValue() {
984
- const value = compilerDom.findProp(node, 'value');
985
- if (value) {
986
- context.onError(compilerDom.createDOMCompilerError(57 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */, value.loc));
987
- }
988
- }
989
- if (node.tagType === 0 /* ElementTypes.ELEMENT */) {
990
- const res = { props: [] };
991
- const defaultProps = [
992
- // default value binding for text type inputs
993
- compilerDom.createObjectProperty(`value`, model)
994
- ];
995
- if (node.tag === 'input') {
996
- const type = compilerDom.findProp(node, 'type');
997
- if (type) {
998
- const value = findValueBinding(node);
999
- if (type.type === 7 /* NodeTypes.DIRECTIVE */) {
1000
- // dynamic type
1001
- res.ssrTagParts = [
1002
- compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_MODEL), [
1003
- type.exp,
1004
- model,
1005
- value
1006
- ])
1007
- ];
1008
- }
1009
- else if (type.value) {
1010
- // static type
1011
- switch (type.value.content) {
1012
- case 'radio':
1013
- res.props = [
1014
- compilerDom.createObjectProperty(`checked`, compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
1015
- model,
1016
- value
1017
- ]))
1018
- ];
1019
- break;
1020
- case 'checkbox':
1021
- const trueValueBinding = compilerDom.findProp(node, 'true-value');
1022
- if (trueValueBinding) {
1023
- const trueValue = trueValueBinding.type === 6 /* NodeTypes.ATTRIBUTE */
1024
- ? JSON.stringify(trueValueBinding.value.content)
1025
- : trueValueBinding.exp;
1026
- res.props = [
1027
- compilerDom.createObjectProperty(`checked`, compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
1028
- model,
1029
- trueValue
1030
- ]))
1031
- ];
1032
- }
1033
- else {
1034
- res.props = [
1035
- compilerDom.createObjectProperty(`checked`, compilerDom.createConditionalExpression(compilerDom.createCallExpression(`Array.isArray`, [model]), compilerDom.createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
1036
- model,
1037
- value
1038
- ]), model))
1039
- ];
1040
- }
1041
- break;
1042
- case 'file':
1043
- context.onError(compilerDom.createDOMCompilerError(56 /* DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));
1044
- break;
1045
- default:
1046
- checkDuplicatedValue();
1047
- res.props = defaultProps;
1048
- break;
1049
- }
1050
- }
1051
- }
1052
- else if (compilerDom.hasDynamicKeyVBind(node)) ;
1053
- else {
1054
- // text type
1055
- checkDuplicatedValue();
1056
- res.props = defaultProps;
1057
- }
1058
- }
1059
- else if (node.tag === 'textarea') {
1060
- checkDuplicatedValue();
1061
- node.children = [compilerDom.createInterpolation(model, model.loc)];
1062
- }
1063
- else if (node.tag === 'select') ;
1064
- else {
1065
- context.onError(compilerDom.createDOMCompilerError(54 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));
1066
- }
1067
- return res;
1068
- }
1069
- else {
1070
- // component v-model
1071
- return compilerDom.transformModel(dir, node, context);
1072
- }
1073
- };
1074
- function findValueBinding(node) {
1075
- const valueBinding = compilerDom.findProp(node, 'value');
1076
- return valueBinding
1077
- ? valueBinding.type === 7 /* NodeTypes.DIRECTIVE */
1078
- ? valueBinding.exp
1079
- : compilerDom.createSimpleExpression(valueBinding.value.content, true)
1080
- : compilerDom.createSimpleExpression(`null`, false);
981
+ const ssrTransformModel = (dir, node, context) => {
982
+ const model = dir.exp;
983
+ function checkDuplicatedValue() {
984
+ const value = compilerDom.findProp(node, 'value');
985
+ if (value) {
986
+ context.onError(compilerDom.createDOMCompilerError(57 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */, value.loc));
987
+ }
988
+ }
989
+ if (node.tagType === 0 /* ElementTypes.ELEMENT */) {
990
+ const res = { props: [] };
991
+ const defaultProps = [
992
+ // default value binding for text type inputs
993
+ compilerDom.createObjectProperty(`value`, model)
994
+ ];
995
+ if (node.tag === 'input') {
996
+ const type = compilerDom.findProp(node, 'type');
997
+ if (type) {
998
+ const value = findValueBinding(node);
999
+ if (type.type === 7 /* NodeTypes.DIRECTIVE */) {
1000
+ // dynamic type
1001
+ res.ssrTagParts = [
1002
+ compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_MODEL), [
1003
+ type.exp,
1004
+ model,
1005
+ value
1006
+ ])
1007
+ ];
1008
+ }
1009
+ else if (type.value) {
1010
+ // static type
1011
+ switch (type.value.content) {
1012
+ case 'radio':
1013
+ res.props = [
1014
+ compilerDom.createObjectProperty(`checked`, compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
1015
+ model,
1016
+ value
1017
+ ]))
1018
+ ];
1019
+ break;
1020
+ case 'checkbox':
1021
+ const trueValueBinding = compilerDom.findProp(node, 'true-value');
1022
+ if (trueValueBinding) {
1023
+ const trueValue = trueValueBinding.type === 6 /* NodeTypes.ATTRIBUTE */
1024
+ ? JSON.stringify(trueValueBinding.value.content)
1025
+ : trueValueBinding.exp;
1026
+ res.props = [
1027
+ compilerDom.createObjectProperty(`checked`, compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
1028
+ model,
1029
+ trueValue
1030
+ ]))
1031
+ ];
1032
+ }
1033
+ else {
1034
+ res.props = [
1035
+ compilerDom.createObjectProperty(`checked`, compilerDom.createConditionalExpression(compilerDom.createCallExpression(`Array.isArray`, [model]), compilerDom.createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
1036
+ model,
1037
+ value
1038
+ ]), model))
1039
+ ];
1040
+ }
1041
+ break;
1042
+ case 'file':
1043
+ context.onError(compilerDom.createDOMCompilerError(56 /* DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));
1044
+ break;
1045
+ default:
1046
+ checkDuplicatedValue();
1047
+ res.props = defaultProps;
1048
+ break;
1049
+ }
1050
+ }
1051
+ }
1052
+ else if (compilerDom.hasDynamicKeyVBind(node)) ;
1053
+ else {
1054
+ // text type
1055
+ checkDuplicatedValue();
1056
+ res.props = defaultProps;
1057
+ }
1058
+ }
1059
+ else if (node.tag === 'textarea') {
1060
+ checkDuplicatedValue();
1061
+ node.children = [compilerDom.createInterpolation(model, model.loc)];
1062
+ }
1063
+ else if (node.tag === 'select') ;
1064
+ else {
1065
+ context.onError(compilerDom.createDOMCompilerError(54 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));
1066
+ }
1067
+ return res;
1068
+ }
1069
+ else {
1070
+ // component v-model
1071
+ return compilerDom.transformModel(dir, node, context);
1072
+ }
1073
+ };
1074
+ function findValueBinding(node) {
1075
+ const valueBinding = compilerDom.findProp(node, 'value');
1076
+ return valueBinding
1077
+ ? valueBinding.type === 7 /* NodeTypes.DIRECTIVE */
1078
+ ? valueBinding.exp
1079
+ : compilerDom.createSimpleExpression(valueBinding.value.content, true)
1080
+ : compilerDom.createSimpleExpression(`null`, false);
1081
1081
  }
1082
1082
 
1083
- const ssrTransformShow = (dir, node, context) => {
1084
- if (!dir.exp) {
1085
- context.onError(compilerDom.createDOMCompilerError(58 /* DOMErrorCodes.X_V_SHOW_NO_EXPRESSION */));
1086
- }
1087
- return {
1088
- props: [
1089
- compilerDom.createObjectProperty(`style`, compilerDom.createConditionalExpression(dir.exp, compilerDom.createSimpleExpression(`null`, false), compilerDom.createObjectExpression([
1090
- compilerDom.createObjectProperty(`display`, compilerDom.createSimpleExpression(`none`, true))
1091
- ]), false /* no newline */))
1092
- ]
1093
- };
1083
+ const ssrTransformShow = (dir, node, context) => {
1084
+ if (!dir.exp) {
1085
+ context.onError(compilerDom.createDOMCompilerError(58 /* DOMErrorCodes.X_V_SHOW_NO_EXPRESSION */));
1086
+ }
1087
+ return {
1088
+ props: [
1089
+ compilerDom.createObjectProperty(`style`, compilerDom.createConditionalExpression(dir.exp, compilerDom.createSimpleExpression(`null`, false), compilerDom.createObjectExpression([
1090
+ compilerDom.createObjectProperty(`display`, compilerDom.createSimpleExpression(`none`, true))
1091
+ ]), false /* no newline */))
1092
+ ]
1093
+ };
1094
1094
  };
1095
1095
 
1096
- const filterChild = (node) => node.children.filter(n => n.type !== 3 /* NodeTypes.COMMENT */);
1097
- const hasSingleChild = (node) => filterChild(node).length === 1;
1098
- const ssrInjectFallthroughAttrs = (node, context) => {
1099
- // _attrs is provided as a function argument.
1100
- // mark it as a known identifier so that it doesn't get prefixed by
1101
- // transformExpression.
1102
- if (node.type === 0 /* NodeTypes.ROOT */) {
1103
- context.identifiers._attrs = 1;
1104
- }
1105
- if (node.type === 1 /* NodeTypes.ELEMENT */ &&
1106
- node.tagType === 1 /* ElementTypes.COMPONENT */ &&
1107
- (compilerDom.isBuiltInType(node.tag, 'Transition') ||
1108
- compilerDom.isBuiltInType(node.tag, 'KeepAlive'))) {
1109
- const rootChildren = filterChild(context.root);
1110
- if (rootChildren.length === 1 && rootChildren[0] === node) {
1111
- if (hasSingleChild(node)) {
1112
- injectFallthroughAttrs(node.children[0]);
1113
- }
1114
- return;
1115
- }
1116
- }
1117
- const parent = context.parent;
1118
- if (!parent || parent.type !== 0 /* NodeTypes.ROOT */) {
1119
- return;
1120
- }
1121
- if (node.type === 10 /* NodeTypes.IF_BRANCH */ && hasSingleChild(node)) {
1122
- // detect cases where the parent v-if is not the only root level node
1123
- let hasEncounteredIf = false;
1124
- for (const c of filterChild(parent)) {
1125
- if (c.type === 9 /* NodeTypes.IF */ ||
1126
- (c.type === 1 /* NodeTypes.ELEMENT */ && compilerDom.findDir(c, 'if'))) {
1127
- // multiple root v-if
1128
- if (hasEncounteredIf)
1129
- return;
1130
- hasEncounteredIf = true;
1131
- }
1132
- else if (
1133
- // node before v-if
1134
- !hasEncounteredIf ||
1135
- // non else nodes
1136
- !(c.type === 1 /* NodeTypes.ELEMENT */ && compilerDom.findDir(c, /else/, true))) {
1137
- return;
1138
- }
1139
- }
1140
- injectFallthroughAttrs(node.children[0]);
1141
- }
1142
- else if (hasSingleChild(parent)) {
1143
- injectFallthroughAttrs(node);
1144
- }
1145
- };
1146
- function injectFallthroughAttrs(node) {
1147
- if (node.type === 1 /* NodeTypes.ELEMENT */ &&
1148
- (node.tagType === 0 /* ElementTypes.ELEMENT */ ||
1149
- node.tagType === 1 /* ElementTypes.COMPONENT */) &&
1150
- !compilerDom.findDir(node, 'for')) {
1151
- node.props.push({
1152
- type: 7 /* NodeTypes.DIRECTIVE */,
1153
- name: 'bind',
1154
- arg: undefined,
1155
- exp: compilerDom.createSimpleExpression(`_attrs`, false),
1156
- modifiers: [],
1157
- loc: compilerDom.locStub
1158
- });
1159
- }
1096
+ const filterChild = (node) => node.children.filter(n => n.type !== 3 /* NodeTypes.COMMENT */);
1097
+ const hasSingleChild = (node) => filterChild(node).length === 1;
1098
+ const ssrInjectFallthroughAttrs = (node, context) => {
1099
+ // _attrs is provided as a function argument.
1100
+ // mark it as a known identifier so that it doesn't get prefixed by
1101
+ // transformExpression.
1102
+ if (node.type === 0 /* NodeTypes.ROOT */) {
1103
+ context.identifiers._attrs = 1;
1104
+ }
1105
+ if (node.type === 1 /* NodeTypes.ELEMENT */ &&
1106
+ node.tagType === 1 /* ElementTypes.COMPONENT */ &&
1107
+ (compilerDom.isBuiltInType(node.tag, 'Transition') ||
1108
+ compilerDom.isBuiltInType(node.tag, 'KeepAlive'))) {
1109
+ const rootChildren = filterChild(context.root);
1110
+ if (rootChildren.length === 1 && rootChildren[0] === node) {
1111
+ if (hasSingleChild(node)) {
1112
+ injectFallthroughAttrs(node.children[0]);
1113
+ }
1114
+ return;
1115
+ }
1116
+ }
1117
+ const parent = context.parent;
1118
+ if (!parent || parent.type !== 0 /* NodeTypes.ROOT */) {
1119
+ return;
1120
+ }
1121
+ if (node.type === 10 /* NodeTypes.IF_BRANCH */ && hasSingleChild(node)) {
1122
+ // detect cases where the parent v-if is not the only root level node
1123
+ let hasEncounteredIf = false;
1124
+ for (const c of filterChild(parent)) {
1125
+ if (c.type === 9 /* NodeTypes.IF */ ||
1126
+ (c.type === 1 /* NodeTypes.ELEMENT */ && compilerDom.findDir(c, 'if'))) {
1127
+ // multiple root v-if
1128
+ if (hasEncounteredIf)
1129
+ return;
1130
+ hasEncounteredIf = true;
1131
+ }
1132
+ else if (
1133
+ // node before v-if
1134
+ !hasEncounteredIf ||
1135
+ // non else nodes
1136
+ !(c.type === 1 /* NodeTypes.ELEMENT */ && compilerDom.findDir(c, /else/, true))) {
1137
+ return;
1138
+ }
1139
+ }
1140
+ injectFallthroughAttrs(node.children[0]);
1141
+ }
1142
+ else if (hasSingleChild(parent)) {
1143
+ injectFallthroughAttrs(node);
1144
+ }
1145
+ };
1146
+ function injectFallthroughAttrs(node) {
1147
+ if (node.type === 1 /* NodeTypes.ELEMENT */ &&
1148
+ (node.tagType === 0 /* ElementTypes.ELEMENT */ ||
1149
+ node.tagType === 1 /* ElementTypes.COMPONENT */) &&
1150
+ !compilerDom.findDir(node, 'for')) {
1151
+ node.props.push({
1152
+ type: 7 /* NodeTypes.DIRECTIVE */,
1153
+ name: 'bind',
1154
+ arg: undefined,
1155
+ exp: compilerDom.createSimpleExpression(`_attrs`, false),
1156
+ modifiers: [],
1157
+ loc: compilerDom.locStub
1158
+ });
1159
+ }
1160
1160
  }
1161
1161
 
1162
- const ssrInjectCssVars = (node, context) => {
1163
- if (!context.ssrCssVars) {
1164
- return;
1165
- }
1166
- // _cssVars is initialized once per render function
1167
- // the code is injected in ssrCodegenTransform when creating the
1168
- // ssr transform context
1169
- if (node.type === 0 /* NodeTypes.ROOT */) {
1170
- context.identifiers._cssVars = 1;
1171
- }
1172
- const parent = context.parent;
1173
- if (!parent || parent.type !== 0 /* NodeTypes.ROOT */) {
1174
- return;
1175
- }
1176
- if (node.type === 10 /* NodeTypes.IF_BRANCH */) {
1177
- for (const child of node.children) {
1178
- injectCssVars(child);
1179
- }
1180
- }
1181
- else {
1182
- injectCssVars(node);
1183
- }
1184
- };
1185
- function injectCssVars(node) {
1186
- if (node.type === 1 /* NodeTypes.ELEMENT */ &&
1187
- (node.tagType === 0 /* ElementTypes.ELEMENT */ ||
1188
- node.tagType === 1 /* ElementTypes.COMPONENT */) &&
1189
- !compilerDom.findDir(node, 'for')) {
1190
- if (compilerDom.isBuiltInType(node.tag, 'Suspense')) {
1191
- for (const child of node.children) {
1192
- if (child.type === 1 /* NodeTypes.ELEMENT */ &&
1193
- child.tagType === 3 /* ElementTypes.TEMPLATE */) {
1194
- // suspense slot
1195
- child.children.forEach(injectCssVars);
1196
- }
1197
- else {
1198
- injectCssVars(child);
1199
- }
1200
- }
1201
- }
1202
- else {
1203
- node.props.push({
1204
- type: 7 /* NodeTypes.DIRECTIVE */,
1205
- name: 'bind',
1206
- arg: undefined,
1207
- exp: compilerDom.createSimpleExpression(`_cssVars`, false),
1208
- modifiers: [],
1209
- loc: compilerDom.locStub
1210
- });
1211
- }
1212
- }
1162
+ const ssrInjectCssVars = (node, context) => {
1163
+ if (!context.ssrCssVars) {
1164
+ return;
1165
+ }
1166
+ // _cssVars is initialized once per render function
1167
+ // the code is injected in ssrCodegenTransform when creating the
1168
+ // ssr transform context
1169
+ if (node.type === 0 /* NodeTypes.ROOT */) {
1170
+ context.identifiers._cssVars = 1;
1171
+ }
1172
+ const parent = context.parent;
1173
+ if (!parent || parent.type !== 0 /* NodeTypes.ROOT */) {
1174
+ return;
1175
+ }
1176
+ if (node.type === 10 /* NodeTypes.IF_BRANCH */) {
1177
+ for (const child of node.children) {
1178
+ injectCssVars(child);
1179
+ }
1180
+ }
1181
+ else {
1182
+ injectCssVars(node);
1183
+ }
1184
+ };
1185
+ function injectCssVars(node) {
1186
+ if (node.type === 1 /* NodeTypes.ELEMENT */ &&
1187
+ (node.tagType === 0 /* ElementTypes.ELEMENT */ ||
1188
+ node.tagType === 1 /* ElementTypes.COMPONENT */) &&
1189
+ !compilerDom.findDir(node, 'for')) {
1190
+ if (compilerDom.isBuiltInType(node.tag, 'Suspense')) {
1191
+ for (const child of node.children) {
1192
+ if (child.type === 1 /* NodeTypes.ELEMENT */ &&
1193
+ child.tagType === 3 /* ElementTypes.TEMPLATE */) {
1194
+ // suspense slot
1195
+ child.children.forEach(injectCssVars);
1196
+ }
1197
+ else {
1198
+ injectCssVars(child);
1199
+ }
1200
+ }
1201
+ }
1202
+ else {
1203
+ node.props.push({
1204
+ type: 7 /* NodeTypes.DIRECTIVE */,
1205
+ name: 'bind',
1206
+ arg: undefined,
1207
+ exp: compilerDom.createSimpleExpression(`_cssVars`, false),
1208
+ modifiers: [],
1209
+ loc: compilerDom.locStub
1210
+ });
1211
+ }
1212
+ }
1213
1213
  }
1214
1214
 
1215
- function compile(template, options = {}) {
1216
- options = {
1217
- ...options,
1218
- // apply DOM-specific parsing options
1219
- ...compilerDom.parserOptions,
1220
- ssr: true,
1221
- inSSR: true,
1222
- scopeId: options.mode === 'function' ? null : options.scopeId,
1223
- // always prefix since compiler-ssr doesn't have size concern
1224
- prefixIdentifiers: true,
1225
- // disable optimizations that are unnecessary for ssr
1226
- cacheHandlers: false,
1227
- hoistStatic: false
1228
- };
1229
- const ast = compilerDom.baseParse(template, options);
1230
- // Save raw options for AST. This is needed when performing sub-transforms
1231
- // on slot vnode branches.
1232
- rawOptionsMap.set(ast, options);
1233
- compilerDom.transform(ast, {
1234
- ...options,
1235
- hoistStatic: false,
1236
- nodeTransforms: [
1237
- ssrTransformIf,
1238
- ssrTransformFor,
1239
- compilerDom.trackVForSlotScopes,
1240
- compilerDom.transformExpression,
1241
- ssrTransformSlotOutlet,
1242
- ssrInjectFallthroughAttrs,
1243
- ssrInjectCssVars,
1244
- ssrTransformElement,
1245
- ssrTransformComponent,
1246
- compilerDom.trackSlotScopes,
1247
- compilerDom.transformStyle,
1248
- ...(options.nodeTransforms || []) // user transforms
1249
- ],
1250
- directiveTransforms: {
1251
- // reusing core v-bind
1252
- bind: compilerDom.transformBind,
1253
- on: compilerDom.transformOn,
1254
- // model and show has dedicated SSR handling
1255
- model: ssrTransformModel,
1256
- show: ssrTransformShow,
1257
- // the following are ignored during SSR
1258
- // on: noopDirectiveTransform,
1259
- cloak: compilerDom.noopDirectiveTransform,
1260
- once: compilerDom.noopDirectiveTransform,
1261
- memo: compilerDom.noopDirectiveTransform,
1262
- ...(options.directiveTransforms || {}) // user transforms
1263
- }
1264
- });
1265
- // traverse the template AST and convert into SSR codegen AST
1266
- // by replacing ast.codegenNode.
1267
- ssrCodegenTransform(ast, options);
1268
- return compilerDom.generate(ast, options);
1215
+ function compile(template, options = {}) {
1216
+ options = {
1217
+ ...options,
1218
+ // apply DOM-specific parsing options
1219
+ ...compilerDom.parserOptions,
1220
+ ssr: true,
1221
+ inSSR: true,
1222
+ scopeId: options.mode === 'function' ? null : options.scopeId,
1223
+ // always prefix since compiler-ssr doesn't have size concern
1224
+ prefixIdentifiers: true,
1225
+ // disable optimizations that are unnecessary for ssr
1226
+ cacheHandlers: false,
1227
+ hoistStatic: false
1228
+ };
1229
+ const ast = compilerDom.baseParse(template, options);
1230
+ // Save raw options for AST. This is needed when performing sub-transforms
1231
+ // on slot vnode branches.
1232
+ rawOptionsMap.set(ast, options);
1233
+ compilerDom.transform(ast, {
1234
+ ...options,
1235
+ hoistStatic: false,
1236
+ nodeTransforms: [
1237
+ ssrTransformIf,
1238
+ ssrTransformFor,
1239
+ compilerDom.trackVForSlotScopes,
1240
+ compilerDom.transformExpression,
1241
+ ssrTransformSlotOutlet,
1242
+ ssrInjectFallthroughAttrs,
1243
+ ssrInjectCssVars,
1244
+ ssrTransformElement,
1245
+ ssrTransformComponent,
1246
+ compilerDom.trackSlotScopes,
1247
+ compilerDom.transformStyle,
1248
+ ...(options.nodeTransforms || []) // user transforms
1249
+ ],
1250
+ directiveTransforms: {
1251
+ // reusing core v-bind
1252
+ bind: compilerDom.transformBind,
1253
+ on: compilerDom.transformOn,
1254
+ // model and show has dedicated SSR handling
1255
+ model: ssrTransformModel,
1256
+ show: ssrTransformShow,
1257
+ // the following are ignored during SSR
1258
+ // on: noopDirectiveTransform,
1259
+ cloak: compilerDom.noopDirectiveTransform,
1260
+ once: compilerDom.noopDirectiveTransform,
1261
+ memo: compilerDom.noopDirectiveTransform,
1262
+ ...(options.directiveTransforms || {}) // user transforms
1263
+ }
1264
+ });
1265
+ // traverse the template AST and convert into SSR codegen AST
1266
+ // by replacing ast.codegenNode.
1267
+ ssrCodegenTransform(ast, options);
1268
+ return compilerDom.generate(ast, options);
1269
1269
  }
1270
1270
 
1271
1271
  exports.compile = compile;