@vue/server-renderer 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.
@@ -6,756 +6,756 @@ var vue = require('vue');
6
6
  var shared = require('@vue/shared');
7
7
  var compilerSsr = require('@vue/compiler-ssr');
8
8
 
9
- // leading comma for empty string ""
10
- const shouldIgnoreProp = shared.makeMap(`,key,ref,innerHTML,textContent,ref_key,ref_for`);
11
- function ssrRenderAttrs(props, tag) {
12
- let ret = '';
13
- for (const key in props) {
14
- if (shouldIgnoreProp(key) ||
15
- shared.isOn(key) ||
16
- (tag === 'textarea' && key === 'value')) {
17
- continue;
18
- }
19
- const value = props[key];
20
- if (key === 'class') {
21
- ret += ` class="${ssrRenderClass(value)}"`;
22
- }
23
- else if (key === 'style') {
24
- ret += ` style="${ssrRenderStyle(value)}"`;
25
- }
26
- else {
27
- ret += ssrRenderDynamicAttr(key, value, tag);
28
- }
29
- }
30
- return ret;
31
- }
32
- // render an attr with dynamic (unknown) key.
33
- function ssrRenderDynamicAttr(key, value, tag) {
34
- if (!isRenderableValue(value)) {
35
- return ``;
36
- }
37
- const attrKey = tag && (tag.indexOf('-') > 0 || shared.isSVGTag(tag))
38
- ? key // preserve raw name on custom elements and svg
39
- : shared.propsToAttrMap[key] || key.toLowerCase();
40
- if (shared.isBooleanAttr(attrKey)) {
41
- return shared.includeBooleanAttr(value) ? ` ${attrKey}` : ``;
42
- }
43
- else if (shared.isSSRSafeAttrName(attrKey)) {
44
- return value === '' ? ` ${attrKey}` : ` ${attrKey}="${shared.escapeHtml(value)}"`;
45
- }
46
- else {
47
- console.warn(`[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`);
48
- return ``;
49
- }
50
- }
51
- // Render a v-bind attr with static key. The key is pre-processed at compile
52
- // time and we only need to check and escape value.
53
- function ssrRenderAttr(key, value) {
54
- if (!isRenderableValue(value)) {
55
- return ``;
56
- }
57
- return ` ${key}="${shared.escapeHtml(value)}"`;
58
- }
59
- function isRenderableValue(value) {
60
- if (value == null) {
61
- return false;
62
- }
63
- const type = typeof value;
64
- return type === 'string' || type === 'number' || type === 'boolean';
65
- }
66
- function ssrRenderClass(raw) {
67
- return shared.escapeHtml(shared.normalizeClass(raw));
68
- }
69
- function ssrRenderStyle(raw) {
70
- if (!raw) {
71
- return '';
72
- }
73
- if (shared.isString(raw)) {
74
- return shared.escapeHtml(raw);
75
- }
76
- const styles = shared.normalizeStyle(raw);
77
- return shared.escapeHtml(shared.stringifyStyle(styles));
9
+ // leading comma for empty string ""
10
+ const shouldIgnoreProp = shared.makeMap(`,key,ref,innerHTML,textContent,ref_key,ref_for`);
11
+ function ssrRenderAttrs(props, tag) {
12
+ let ret = '';
13
+ for (const key in props) {
14
+ if (shouldIgnoreProp(key) ||
15
+ shared.isOn(key) ||
16
+ (tag === 'textarea' && key === 'value')) {
17
+ continue;
18
+ }
19
+ const value = props[key];
20
+ if (key === 'class') {
21
+ ret += ` class="${ssrRenderClass(value)}"`;
22
+ }
23
+ else if (key === 'style') {
24
+ ret += ` style="${ssrRenderStyle(value)}"`;
25
+ }
26
+ else {
27
+ ret += ssrRenderDynamicAttr(key, value, tag);
28
+ }
29
+ }
30
+ return ret;
31
+ }
32
+ // render an attr with dynamic (unknown) key.
33
+ function ssrRenderDynamicAttr(key, value, tag) {
34
+ if (!isRenderableValue(value)) {
35
+ return ``;
36
+ }
37
+ const attrKey = tag && (tag.indexOf('-') > 0 || shared.isSVGTag(tag))
38
+ ? key // preserve raw name on custom elements and svg
39
+ : shared.propsToAttrMap[key] || key.toLowerCase();
40
+ if (shared.isBooleanAttr(attrKey)) {
41
+ return shared.includeBooleanAttr(value) ? ` ${attrKey}` : ``;
42
+ }
43
+ else if (shared.isSSRSafeAttrName(attrKey)) {
44
+ return value === '' ? ` ${attrKey}` : ` ${attrKey}="${shared.escapeHtml(value)}"`;
45
+ }
46
+ else {
47
+ console.warn(`[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`);
48
+ return ``;
49
+ }
50
+ }
51
+ // Render a v-bind attr with static key. The key is pre-processed at compile
52
+ // time and we only need to check and escape value.
53
+ function ssrRenderAttr(key, value) {
54
+ if (!isRenderableValue(value)) {
55
+ return ``;
56
+ }
57
+ return ` ${key}="${shared.escapeHtml(value)}"`;
58
+ }
59
+ function isRenderableValue(value) {
60
+ if (value == null) {
61
+ return false;
62
+ }
63
+ const type = typeof value;
64
+ return type === 'string' || type === 'number' || type === 'boolean';
65
+ }
66
+ function ssrRenderClass(raw) {
67
+ return shared.escapeHtml(shared.normalizeClass(raw));
68
+ }
69
+ function ssrRenderStyle(raw) {
70
+ if (!raw) {
71
+ return '';
72
+ }
73
+ if (shared.isString(raw)) {
74
+ return shared.escapeHtml(raw);
75
+ }
76
+ const styles = shared.normalizeStyle(raw);
77
+ return shared.escapeHtml(shared.stringifyStyle(styles));
78
78
  }
79
79
 
80
- const compileCache = Object.create(null);
81
- function ssrCompile(template, instance) {
82
- // TODO: This is copied from runtime-core/src/component.ts and should probably be refactored
83
- const Component = instance.type;
84
- const { isCustomElement, compilerOptions } = instance.appContext.config;
85
- const { delimiters, compilerOptions: componentCompilerOptions } = Component;
86
- const finalCompilerOptions = shared.extend(shared.extend({
87
- isCustomElement,
88
- delimiters
89
- }, compilerOptions), componentCompilerOptions);
90
- finalCompilerOptions.isCustomElement =
91
- finalCompilerOptions.isCustomElement || shared.NO;
92
- finalCompilerOptions.isNativeTag = finalCompilerOptions.isNativeTag || shared.NO;
93
- const cacheKey = JSON.stringify({
94
- template,
95
- compilerOptions: finalCompilerOptions
96
- }, (key, value) => {
97
- return shared.isFunction(value) ? value.toString() : value;
98
- });
99
- const cached = compileCache[cacheKey];
100
- if (cached) {
101
- return cached;
102
- }
103
- finalCompilerOptions.onError = (err) => {
104
- {
105
- throw err;
106
- }
107
- };
108
- const { code } = compilerSsr.compile(template, finalCompilerOptions);
109
- return (compileCache[cacheKey] = Function('require', code)(require));
80
+ const compileCache = Object.create(null);
81
+ function ssrCompile(template, instance) {
82
+ // TODO: This is copied from runtime-core/src/component.ts and should probably be refactored
83
+ const Component = instance.type;
84
+ const { isCustomElement, compilerOptions } = instance.appContext.config;
85
+ const { delimiters, compilerOptions: componentCompilerOptions } = Component;
86
+ const finalCompilerOptions = shared.extend(shared.extend({
87
+ isCustomElement,
88
+ delimiters
89
+ }, compilerOptions), componentCompilerOptions);
90
+ finalCompilerOptions.isCustomElement =
91
+ finalCompilerOptions.isCustomElement || shared.NO;
92
+ finalCompilerOptions.isNativeTag = finalCompilerOptions.isNativeTag || shared.NO;
93
+ const cacheKey = JSON.stringify({
94
+ template,
95
+ compilerOptions: finalCompilerOptions
96
+ }, (key, value) => {
97
+ return shared.isFunction(value) ? value.toString() : value;
98
+ });
99
+ const cached = compileCache[cacheKey];
100
+ if (cached) {
101
+ return cached;
102
+ }
103
+ finalCompilerOptions.onError = (err) => {
104
+ {
105
+ throw err;
106
+ }
107
+ };
108
+ const { code } = compilerSsr.compile(template, finalCompilerOptions);
109
+ return (compileCache[cacheKey] = Function('require', code)(require));
110
110
  }
111
111
 
112
- function ssrRenderTeleport(parentPush, contentRenderFn, target, disabled, parentComponent) {
113
- parentPush('<!--teleport start-->');
114
- const context = parentComponent.appContext.provides[vue.ssrContextKey];
115
- const teleportBuffers = context.__teleportBuffers || (context.__teleportBuffers = {});
116
- const targetBuffer = teleportBuffers[target] || (teleportBuffers[target] = []);
117
- // record current index of the target buffer to handle nested teleports
118
- // since the parent needs to be rendered before the child
119
- const bufferIndex = targetBuffer.length;
120
- let teleportContent;
121
- if (disabled) {
122
- contentRenderFn(parentPush);
123
- teleportContent = `<!--teleport anchor-->`;
124
- }
125
- else {
126
- const { getBuffer, push } = createBuffer();
127
- contentRenderFn(push);
128
- push(`<!--teleport anchor-->`);
129
- teleportContent = getBuffer();
130
- }
131
- targetBuffer.splice(bufferIndex, 0, teleportContent);
132
- parentPush('<!--teleport end-->');
112
+ function ssrRenderTeleport(parentPush, contentRenderFn, target, disabled, parentComponent) {
113
+ parentPush('<!--teleport start-->');
114
+ const context = parentComponent.appContext.provides[vue.ssrContextKey];
115
+ const teleportBuffers = context.__teleportBuffers || (context.__teleportBuffers = {});
116
+ const targetBuffer = teleportBuffers[target] || (teleportBuffers[target] = []);
117
+ // record current index of the target buffer to handle nested teleports
118
+ // since the parent needs to be rendered before the child
119
+ const bufferIndex = targetBuffer.length;
120
+ let teleportContent;
121
+ if (disabled) {
122
+ contentRenderFn(parentPush);
123
+ teleportContent = `<!--teleport anchor-->`;
124
+ }
125
+ else {
126
+ const { getBuffer, push } = createBuffer();
127
+ contentRenderFn(push);
128
+ push(`<!--teleport anchor-->`);
129
+ teleportContent = getBuffer();
130
+ }
131
+ targetBuffer.splice(bufferIndex, 0, teleportContent);
132
+ parentPush('<!--teleport end-->');
133
133
  }
134
134
 
135
- const { createComponentInstance, setCurrentRenderingInstance, setupComponent, renderComponentRoot, normalizeVNode } = vue.ssrUtils;
136
- // Each component has a buffer array.
137
- // A buffer array can contain one of the following:
138
- // - plain string
139
- // - A resolved buffer (recursive arrays of strings that can be unrolled
140
- // synchronously)
141
- // - An async buffer (a Promise that resolves to a resolved buffer)
142
- function createBuffer() {
143
- let appendable = false;
144
- const buffer = [];
145
- return {
146
- getBuffer() {
147
- // Return static buffer and await on items during unroll stage
148
- return buffer;
149
- },
150
- push(item) {
151
- const isStringItem = shared.isString(item);
152
- if (appendable && isStringItem) {
153
- buffer[buffer.length - 1] += item;
154
- }
155
- else {
156
- buffer.push(item);
157
- }
158
- appendable = isStringItem;
159
- if (shared.isPromise(item) || (shared.isArray(item) && item.hasAsync)) {
160
- // promise, or child buffer with async, mark as async.
161
- // this allows skipping unnecessary await ticks during unroll stage
162
- buffer.hasAsync = true;
163
- }
164
- }
165
- };
166
- }
167
- function renderComponentVNode(vnode, parentComponent = null, slotScopeId) {
168
- const instance = createComponentInstance(vnode, parentComponent, null);
169
- const res = setupComponent(instance, true /* isSSR */);
170
- const hasAsyncSetup = shared.isPromise(res);
171
- const prefetches = instance.sp; /* LifecycleHooks.SERVER_PREFETCH */
172
- if (hasAsyncSetup || prefetches) {
173
- let p = hasAsyncSetup
174
- ? res
175
- : Promise.resolve();
176
- if (prefetches) {
177
- p = p
178
- .then(() => Promise.all(prefetches.map(prefetch => prefetch.call(instance.proxy))))
179
- // Note: error display is already done by the wrapped lifecycle hook function.
180
- .catch(() => { });
181
- }
182
- return p.then(() => renderComponentSubTree(instance, slotScopeId));
183
- }
184
- else {
185
- return renderComponentSubTree(instance, slotScopeId);
186
- }
187
- }
188
- function renderComponentSubTree(instance, slotScopeId) {
189
- const comp = instance.type;
190
- const { getBuffer, push } = createBuffer();
191
- if (shared.isFunction(comp)) {
192
- let root = renderComponentRoot(instance);
193
- // #5817 scope ID attrs not falling through if functional component doesn't
194
- // have props
195
- if (!comp.props) {
196
- for (const key in instance.attrs) {
197
- if (key.startsWith(`data-v-`)) {
198
- (root.props || (root.props = {}))[key] = ``;
199
- }
200
- }
201
- }
202
- renderVNode(push, (instance.subTree = root), instance, slotScopeId);
203
- }
204
- else {
205
- if ((!instance.render || instance.render === shared.NOOP) &&
206
- !instance.ssrRender &&
207
- !comp.ssrRender &&
208
- shared.isString(comp.template)) {
209
- comp.ssrRender = ssrCompile(comp.template, instance);
210
- }
211
- // perf: enable caching of computed getters during render
212
- // since there cannot be state mutations during render.
213
- for (const e of instance.scope.effects) {
214
- if (e.computed)
215
- e.computed._cacheable = true;
216
- }
217
- const ssrRender = instance.ssrRender || comp.ssrRender;
218
- if (ssrRender) {
219
- // optimized
220
- // resolve fallthrough attrs
221
- let attrs = instance.inheritAttrs !== false ? instance.attrs : undefined;
222
- let hasCloned = false;
223
- let cur = instance;
224
- while (true) {
225
- const scopeId = cur.vnode.scopeId;
226
- if (scopeId) {
227
- if (!hasCloned) {
228
- attrs = { ...attrs };
229
- hasCloned = true;
230
- }
231
- attrs[scopeId] = '';
232
- }
233
- const parent = cur.parent;
234
- if (parent && parent.subTree && parent.subTree === cur.vnode) {
235
- // parent is a non-SSR compiled component and is rendering this
236
- // component as root. inherit its scopeId if present.
237
- cur = parent;
238
- }
239
- else {
240
- break;
241
- }
242
- }
243
- if (slotScopeId) {
244
- if (!hasCloned)
245
- attrs = { ...attrs };
246
- attrs[slotScopeId.trim()] = '';
247
- }
248
- // set current rendering instance for asset resolution
249
- const prev = setCurrentRenderingInstance(instance);
250
- try {
251
- ssrRender(instance.proxy, push, instance, attrs,
252
- // compiler-optimized bindings
253
- instance.props, instance.setupState, instance.data, instance.ctx);
254
- }
255
- finally {
256
- setCurrentRenderingInstance(prev);
257
- }
258
- }
259
- else if (instance.render && instance.render !== shared.NOOP) {
260
- renderVNode(push, (instance.subTree = renderComponentRoot(instance)), instance, slotScopeId);
261
- }
262
- else {
263
- const componentName = comp.name || comp.__file || `<Anonymous>`;
264
- vue.warn(`Component ${componentName} is missing template or render function.`);
265
- push(`<!---->`);
266
- }
267
- }
268
- return getBuffer();
269
- }
270
- function renderVNode(push, vnode, parentComponent, slotScopeId) {
271
- const { type, shapeFlag, children } = vnode;
272
- switch (type) {
273
- case vue.Text:
274
- push(shared.escapeHtml(children));
275
- break;
276
- case vue.Comment:
277
- push(children ? `<!--${shared.escapeHtmlComment(children)}-->` : `<!---->`);
278
- break;
279
- case vue.Static:
280
- push(children);
281
- break;
282
- case vue.Fragment:
283
- if (vnode.slotScopeIds) {
284
- slotScopeId =
285
- (slotScopeId ? slotScopeId + ' ' : '') + vnode.slotScopeIds.join(' ');
286
- }
287
- push(`<!--[-->`); // open
288
- renderVNodeChildren(push, children, parentComponent, slotScopeId);
289
- push(`<!--]-->`); // close
290
- break;
291
- default:
292
- if (shapeFlag & 1 /* ShapeFlags.ELEMENT */) {
293
- renderElementVNode(push, vnode, parentComponent, slotScopeId);
294
- }
295
- else if (shapeFlag & 6 /* ShapeFlags.COMPONENT */) {
296
- push(renderComponentVNode(vnode, parentComponent, slotScopeId));
297
- }
298
- else if (shapeFlag & 64 /* ShapeFlags.TELEPORT */) {
299
- renderTeleportVNode(push, vnode, parentComponent, slotScopeId);
300
- }
301
- else if (shapeFlag & 128 /* ShapeFlags.SUSPENSE */) {
302
- renderVNode(push, vnode.ssContent, parentComponent, slotScopeId);
303
- }
304
- else {
305
- vue.warn('[@vue/server-renderer] Invalid VNode type:', type, `(${typeof type})`);
306
- }
307
- }
308
- }
309
- function renderVNodeChildren(push, children, parentComponent, slotScopeId) {
310
- for (let i = 0; i < children.length; i++) {
311
- renderVNode(push, normalizeVNode(children[i]), parentComponent, slotScopeId);
312
- }
313
- }
314
- function renderElementVNode(push, vnode, parentComponent, slotScopeId) {
315
- const tag = vnode.type;
316
- let { props, children, shapeFlag, scopeId, dirs } = vnode;
317
- let openTag = `<${tag}`;
318
- if (dirs) {
319
- props = applySSRDirectives(vnode, props, dirs);
320
- }
321
- if (props) {
322
- openTag += ssrRenderAttrs(props, tag);
323
- }
324
- if (scopeId) {
325
- openTag += ` ${scopeId}`;
326
- }
327
- // inherit parent chain scope id if this is the root node
328
- let curParent = parentComponent;
329
- let curVnode = vnode;
330
- while (curParent && curVnode === curParent.subTree) {
331
- curVnode = curParent.vnode;
332
- if (curVnode.scopeId) {
333
- openTag += ` ${curVnode.scopeId}`;
334
- }
335
- curParent = curParent.parent;
336
- }
337
- if (slotScopeId) {
338
- openTag += ` ${slotScopeId}`;
339
- }
340
- push(openTag + `>`);
341
- if (!shared.isVoidTag(tag)) {
342
- let hasChildrenOverride = false;
343
- if (props) {
344
- if (props.innerHTML) {
345
- hasChildrenOverride = true;
346
- push(props.innerHTML);
347
- }
348
- else if (props.textContent) {
349
- hasChildrenOverride = true;
350
- push(shared.escapeHtml(props.textContent));
351
- }
352
- else if (tag === 'textarea' && props.value) {
353
- hasChildrenOverride = true;
354
- push(shared.escapeHtml(props.value));
355
- }
356
- }
357
- if (!hasChildrenOverride) {
358
- if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
359
- push(shared.escapeHtml(children));
360
- }
361
- else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
362
- renderVNodeChildren(push, children, parentComponent, slotScopeId);
363
- }
364
- }
365
- push(`</${tag}>`);
366
- }
367
- }
368
- function applySSRDirectives(vnode, rawProps, dirs) {
369
- const toMerge = [];
370
- for (let i = 0; i < dirs.length; i++) {
371
- const binding = dirs[i];
372
- const { dir: { getSSRProps } } = binding;
373
- if (getSSRProps) {
374
- const props = getSSRProps(binding, vnode);
375
- if (props)
376
- toMerge.push(props);
377
- }
378
- }
379
- return vue.mergeProps(rawProps || {}, ...toMerge);
380
- }
381
- function renderTeleportVNode(push, vnode, parentComponent, slotScopeId) {
382
- const target = vnode.props && vnode.props.to;
383
- const disabled = vnode.props && vnode.props.disabled;
384
- if (!target) {
385
- if (!disabled) {
386
- vue.warn(`[@vue/server-renderer] Teleport is missing target prop.`);
387
- }
388
- return [];
389
- }
390
- if (!shared.isString(target)) {
391
- vue.warn(`[@vue/server-renderer] Teleport target must be a query selector string.`);
392
- return [];
393
- }
394
- ssrRenderTeleport(push, push => {
395
- renderVNodeChildren(push, vnode.children, parentComponent, slotScopeId);
396
- }, target, disabled || disabled === '', parentComponent);
135
+ const { createComponentInstance, setCurrentRenderingInstance, setupComponent, renderComponentRoot, normalizeVNode } = vue.ssrUtils;
136
+ // Each component has a buffer array.
137
+ // A buffer array can contain one of the following:
138
+ // - plain string
139
+ // - A resolved buffer (recursive arrays of strings that can be unrolled
140
+ // synchronously)
141
+ // - An async buffer (a Promise that resolves to a resolved buffer)
142
+ function createBuffer() {
143
+ let appendable = false;
144
+ const buffer = [];
145
+ return {
146
+ getBuffer() {
147
+ // Return static buffer and await on items during unroll stage
148
+ return buffer;
149
+ },
150
+ push(item) {
151
+ const isStringItem = shared.isString(item);
152
+ if (appendable && isStringItem) {
153
+ buffer[buffer.length - 1] += item;
154
+ }
155
+ else {
156
+ buffer.push(item);
157
+ }
158
+ appendable = isStringItem;
159
+ if (shared.isPromise(item) || (shared.isArray(item) && item.hasAsync)) {
160
+ // promise, or child buffer with async, mark as async.
161
+ // this allows skipping unnecessary await ticks during unroll stage
162
+ buffer.hasAsync = true;
163
+ }
164
+ }
165
+ };
166
+ }
167
+ function renderComponentVNode(vnode, parentComponent = null, slotScopeId) {
168
+ const instance = createComponentInstance(vnode, parentComponent, null);
169
+ const res = setupComponent(instance, true /* isSSR */);
170
+ const hasAsyncSetup = shared.isPromise(res);
171
+ const prefetches = instance.sp; /* LifecycleHooks.SERVER_PREFETCH */
172
+ if (hasAsyncSetup || prefetches) {
173
+ let p = hasAsyncSetup
174
+ ? res
175
+ : Promise.resolve();
176
+ if (prefetches) {
177
+ p = p
178
+ .then(() => Promise.all(prefetches.map(prefetch => prefetch.call(instance.proxy))))
179
+ // Note: error display is already done by the wrapped lifecycle hook function.
180
+ .catch(() => { });
181
+ }
182
+ return p.then(() => renderComponentSubTree(instance, slotScopeId));
183
+ }
184
+ else {
185
+ return renderComponentSubTree(instance, slotScopeId);
186
+ }
187
+ }
188
+ function renderComponentSubTree(instance, slotScopeId) {
189
+ const comp = instance.type;
190
+ const { getBuffer, push } = createBuffer();
191
+ if (shared.isFunction(comp)) {
192
+ let root = renderComponentRoot(instance);
193
+ // #5817 scope ID attrs not falling through if functional component doesn't
194
+ // have props
195
+ if (!comp.props) {
196
+ for (const key in instance.attrs) {
197
+ if (key.startsWith(`data-v-`)) {
198
+ (root.props || (root.props = {}))[key] = ``;
199
+ }
200
+ }
201
+ }
202
+ renderVNode(push, (instance.subTree = root), instance, slotScopeId);
203
+ }
204
+ else {
205
+ if ((!instance.render || instance.render === shared.NOOP) &&
206
+ !instance.ssrRender &&
207
+ !comp.ssrRender &&
208
+ shared.isString(comp.template)) {
209
+ comp.ssrRender = ssrCompile(comp.template, instance);
210
+ }
211
+ // perf: enable caching of computed getters during render
212
+ // since there cannot be state mutations during render.
213
+ for (const e of instance.scope.effects) {
214
+ if (e.computed)
215
+ e.computed._cacheable = true;
216
+ }
217
+ const ssrRender = instance.ssrRender || comp.ssrRender;
218
+ if (ssrRender) {
219
+ // optimized
220
+ // resolve fallthrough attrs
221
+ let attrs = instance.inheritAttrs !== false ? instance.attrs : undefined;
222
+ let hasCloned = false;
223
+ let cur = instance;
224
+ while (true) {
225
+ const scopeId = cur.vnode.scopeId;
226
+ if (scopeId) {
227
+ if (!hasCloned) {
228
+ attrs = { ...attrs };
229
+ hasCloned = true;
230
+ }
231
+ attrs[scopeId] = '';
232
+ }
233
+ const parent = cur.parent;
234
+ if (parent && parent.subTree && parent.subTree === cur.vnode) {
235
+ // parent is a non-SSR compiled component and is rendering this
236
+ // component as root. inherit its scopeId if present.
237
+ cur = parent;
238
+ }
239
+ else {
240
+ break;
241
+ }
242
+ }
243
+ if (slotScopeId) {
244
+ if (!hasCloned)
245
+ attrs = { ...attrs };
246
+ attrs[slotScopeId.trim()] = '';
247
+ }
248
+ // set current rendering instance for asset resolution
249
+ const prev = setCurrentRenderingInstance(instance);
250
+ try {
251
+ ssrRender(instance.proxy, push, instance, attrs,
252
+ // compiler-optimized bindings
253
+ instance.props, instance.setupState, instance.data, instance.ctx);
254
+ }
255
+ finally {
256
+ setCurrentRenderingInstance(prev);
257
+ }
258
+ }
259
+ else if (instance.render && instance.render !== shared.NOOP) {
260
+ renderVNode(push, (instance.subTree = renderComponentRoot(instance)), instance, slotScopeId);
261
+ }
262
+ else {
263
+ const componentName = comp.name || comp.__file || `<Anonymous>`;
264
+ vue.warn(`Component ${componentName} is missing template or render function.`);
265
+ push(`<!---->`);
266
+ }
267
+ }
268
+ return getBuffer();
269
+ }
270
+ function renderVNode(push, vnode, parentComponent, slotScopeId) {
271
+ const { type, shapeFlag, children } = vnode;
272
+ switch (type) {
273
+ case vue.Text:
274
+ push(shared.escapeHtml(children));
275
+ break;
276
+ case vue.Comment:
277
+ push(children ? `<!--${shared.escapeHtmlComment(children)}-->` : `<!---->`);
278
+ break;
279
+ case vue.Static:
280
+ push(children);
281
+ break;
282
+ case vue.Fragment:
283
+ if (vnode.slotScopeIds) {
284
+ slotScopeId =
285
+ (slotScopeId ? slotScopeId + ' ' : '') + vnode.slotScopeIds.join(' ');
286
+ }
287
+ push(`<!--[-->`); // open
288
+ renderVNodeChildren(push, children, parentComponent, slotScopeId);
289
+ push(`<!--]-->`); // close
290
+ break;
291
+ default:
292
+ if (shapeFlag & 1 /* ShapeFlags.ELEMENT */) {
293
+ renderElementVNode(push, vnode, parentComponent, slotScopeId);
294
+ }
295
+ else if (shapeFlag & 6 /* ShapeFlags.COMPONENT */) {
296
+ push(renderComponentVNode(vnode, parentComponent, slotScopeId));
297
+ }
298
+ else if (shapeFlag & 64 /* ShapeFlags.TELEPORT */) {
299
+ renderTeleportVNode(push, vnode, parentComponent, slotScopeId);
300
+ }
301
+ else if (shapeFlag & 128 /* ShapeFlags.SUSPENSE */) {
302
+ renderVNode(push, vnode.ssContent, parentComponent, slotScopeId);
303
+ }
304
+ else {
305
+ vue.warn('[@vue/server-renderer] Invalid VNode type:', type, `(${typeof type})`);
306
+ }
307
+ }
308
+ }
309
+ function renderVNodeChildren(push, children, parentComponent, slotScopeId) {
310
+ for (let i = 0; i < children.length; i++) {
311
+ renderVNode(push, normalizeVNode(children[i]), parentComponent, slotScopeId);
312
+ }
313
+ }
314
+ function renderElementVNode(push, vnode, parentComponent, slotScopeId) {
315
+ const tag = vnode.type;
316
+ let { props, children, shapeFlag, scopeId, dirs } = vnode;
317
+ let openTag = `<${tag}`;
318
+ if (dirs) {
319
+ props = applySSRDirectives(vnode, props, dirs);
320
+ }
321
+ if (props) {
322
+ openTag += ssrRenderAttrs(props, tag);
323
+ }
324
+ if (scopeId) {
325
+ openTag += ` ${scopeId}`;
326
+ }
327
+ // inherit parent chain scope id if this is the root node
328
+ let curParent = parentComponent;
329
+ let curVnode = vnode;
330
+ while (curParent && curVnode === curParent.subTree) {
331
+ curVnode = curParent.vnode;
332
+ if (curVnode.scopeId) {
333
+ openTag += ` ${curVnode.scopeId}`;
334
+ }
335
+ curParent = curParent.parent;
336
+ }
337
+ if (slotScopeId) {
338
+ openTag += ` ${slotScopeId}`;
339
+ }
340
+ push(openTag + `>`);
341
+ if (!shared.isVoidTag(tag)) {
342
+ let hasChildrenOverride = false;
343
+ if (props) {
344
+ if (props.innerHTML) {
345
+ hasChildrenOverride = true;
346
+ push(props.innerHTML);
347
+ }
348
+ else if (props.textContent) {
349
+ hasChildrenOverride = true;
350
+ push(shared.escapeHtml(props.textContent));
351
+ }
352
+ else if (tag === 'textarea' && props.value) {
353
+ hasChildrenOverride = true;
354
+ push(shared.escapeHtml(props.value));
355
+ }
356
+ }
357
+ if (!hasChildrenOverride) {
358
+ if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
359
+ push(shared.escapeHtml(children));
360
+ }
361
+ else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
362
+ renderVNodeChildren(push, children, parentComponent, slotScopeId);
363
+ }
364
+ }
365
+ push(`</${tag}>`);
366
+ }
367
+ }
368
+ function applySSRDirectives(vnode, rawProps, dirs) {
369
+ const toMerge = [];
370
+ for (let i = 0; i < dirs.length; i++) {
371
+ const binding = dirs[i];
372
+ const { dir: { getSSRProps } } = binding;
373
+ if (getSSRProps) {
374
+ const props = getSSRProps(binding, vnode);
375
+ if (props)
376
+ toMerge.push(props);
377
+ }
378
+ }
379
+ return vue.mergeProps(rawProps || {}, ...toMerge);
380
+ }
381
+ function renderTeleportVNode(push, vnode, parentComponent, slotScopeId) {
382
+ const target = vnode.props && vnode.props.to;
383
+ const disabled = vnode.props && vnode.props.disabled;
384
+ if (!target) {
385
+ if (!disabled) {
386
+ vue.warn(`[@vue/server-renderer] Teleport is missing target prop.`);
387
+ }
388
+ return [];
389
+ }
390
+ if (!shared.isString(target)) {
391
+ vue.warn(`[@vue/server-renderer] Teleport target must be a query selector string.`);
392
+ return [];
393
+ }
394
+ ssrRenderTeleport(push, push => {
395
+ renderVNodeChildren(push, vnode.children, parentComponent, slotScopeId);
396
+ }, target, disabled || disabled === '', parentComponent);
397
397
  }
398
398
 
399
- const { isVNode } = vue.ssrUtils;
400
- async function unrollBuffer(buffer) {
401
- if (buffer.hasAsync) {
402
- let ret = '';
403
- for (let i = 0; i < buffer.length; i++) {
404
- let item = buffer[i];
405
- if (shared.isPromise(item)) {
406
- item = await item;
407
- }
408
- if (shared.isString(item)) {
409
- ret += item;
410
- }
411
- else {
412
- ret += await unrollBuffer(item);
413
- }
414
- }
415
- return ret;
416
- }
417
- else {
418
- // sync buffer can be more efficiently unrolled without unnecessary await
419
- // ticks
420
- return unrollBufferSync(buffer);
421
- }
422
- }
423
- function unrollBufferSync(buffer) {
424
- let ret = '';
425
- for (let i = 0; i < buffer.length; i++) {
426
- let item = buffer[i];
427
- if (shared.isString(item)) {
428
- ret += item;
429
- }
430
- else {
431
- // since this is a sync buffer, child buffers are never promises
432
- ret += unrollBufferSync(item);
433
- }
434
- }
435
- return ret;
436
- }
437
- async function renderToString(input, context = {}) {
438
- if (isVNode(input)) {
439
- // raw vnode, wrap with app (for context)
440
- return renderToString(vue.createApp({ render: () => input }), context);
441
- }
442
- // rendering an app
443
- const vnode = vue.createVNode(input._component, input._props);
444
- vnode.appContext = input._context;
445
- // provide the ssr context to the tree
446
- input.provide(vue.ssrContextKey, context);
447
- const buffer = await renderComponentVNode(vnode);
448
- const result = await unrollBuffer(buffer);
449
- await resolveTeleports(context);
450
- return result;
451
- }
452
- async function resolveTeleports(context) {
453
- if (context.__teleportBuffers) {
454
- context.teleports = context.teleports || {};
455
- for (const key in context.__teleportBuffers) {
456
- // note: it's OK to await sequentially here because the Promises were
457
- // created eagerly in parallel.
458
- context.teleports[key] = await unrollBuffer(await Promise.all([context.__teleportBuffers[key]]));
459
- }
460
- }
399
+ const { isVNode } = vue.ssrUtils;
400
+ async function unrollBuffer(buffer) {
401
+ if (buffer.hasAsync) {
402
+ let ret = '';
403
+ for (let i = 0; i < buffer.length; i++) {
404
+ let item = buffer[i];
405
+ if (shared.isPromise(item)) {
406
+ item = await item;
407
+ }
408
+ if (shared.isString(item)) {
409
+ ret += item;
410
+ }
411
+ else {
412
+ ret += await unrollBuffer(item);
413
+ }
414
+ }
415
+ return ret;
416
+ }
417
+ else {
418
+ // sync buffer can be more efficiently unrolled without unnecessary await
419
+ // ticks
420
+ return unrollBufferSync(buffer);
421
+ }
422
+ }
423
+ function unrollBufferSync(buffer) {
424
+ let ret = '';
425
+ for (let i = 0; i < buffer.length; i++) {
426
+ let item = buffer[i];
427
+ if (shared.isString(item)) {
428
+ ret += item;
429
+ }
430
+ else {
431
+ // since this is a sync buffer, child buffers are never promises
432
+ ret += unrollBufferSync(item);
433
+ }
434
+ }
435
+ return ret;
436
+ }
437
+ async function renderToString(input, context = {}) {
438
+ if (isVNode(input)) {
439
+ // raw vnode, wrap with app (for context)
440
+ return renderToString(vue.createApp({ render: () => input }), context);
441
+ }
442
+ // rendering an app
443
+ const vnode = vue.createVNode(input._component, input._props);
444
+ vnode.appContext = input._context;
445
+ // provide the ssr context to the tree
446
+ input.provide(vue.ssrContextKey, context);
447
+ const buffer = await renderComponentVNode(vnode);
448
+ const result = await unrollBuffer(buffer);
449
+ await resolveTeleports(context);
450
+ return result;
451
+ }
452
+ async function resolveTeleports(context) {
453
+ if (context.__teleportBuffers) {
454
+ context.teleports = context.teleports || {};
455
+ for (const key in context.__teleportBuffers) {
456
+ // note: it's OK to await sequentially here because the Promises were
457
+ // created eagerly in parallel.
458
+ context.teleports[key] = await unrollBuffer(await Promise.all([context.__teleportBuffers[key]]));
459
+ }
460
+ }
461
461
  }
462
462
 
463
- const { isVNode: isVNode$1 } = vue.ssrUtils;
464
- async function unrollBuffer$1(buffer, stream) {
465
- if (buffer.hasAsync) {
466
- for (let i = 0; i < buffer.length; i++) {
467
- let item = buffer[i];
468
- if (shared.isPromise(item)) {
469
- item = await item;
470
- }
471
- if (shared.isString(item)) {
472
- stream.push(item);
473
- }
474
- else {
475
- await unrollBuffer$1(item, stream);
476
- }
477
- }
478
- }
479
- else {
480
- // sync buffer can be more efficiently unrolled without unnecessary await
481
- // ticks
482
- unrollBufferSync$1(buffer, stream);
483
- }
484
- }
485
- function unrollBufferSync$1(buffer, stream) {
486
- for (let i = 0; i < buffer.length; i++) {
487
- let item = buffer[i];
488
- if (shared.isString(item)) {
489
- stream.push(item);
490
- }
491
- else {
492
- // since this is a sync buffer, child buffers are never promises
493
- unrollBufferSync$1(item, stream);
494
- }
495
- }
496
- }
497
- function renderToSimpleStream(input, context, stream) {
498
- if (isVNode$1(input)) {
499
- // raw vnode, wrap with app (for context)
500
- return renderToSimpleStream(vue.createApp({ render: () => input }), context, stream);
501
- }
502
- // rendering an app
503
- const vnode = vue.createVNode(input._component, input._props);
504
- vnode.appContext = input._context;
505
- // provide the ssr context to the tree
506
- input.provide(vue.ssrContextKey, context);
507
- Promise.resolve(renderComponentVNode(vnode))
508
- .then(buffer => unrollBuffer$1(buffer, stream))
509
- .then(() => resolveTeleports(context))
510
- .then(() => stream.push(null))
511
- .catch(error => {
512
- stream.destroy(error);
513
- });
514
- return stream;
515
- }
516
- /**
517
- * @deprecated
518
- */
519
- function renderToStream(input, context = {}) {
520
- console.warn(`[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`);
521
- return renderToNodeStream(input, context);
522
- }
523
- function renderToNodeStream(input, context = {}) {
524
- const stream = new (require('stream').Readable)({ read() { } })
525
- ;
526
- if (!stream) {
527
- throw new Error(`ESM build of renderToStream() does not support renderToNodeStream(). ` +
528
- `Use pipeToNodeWritable() with an existing Node.js Writable stream ` +
529
- `instance instead.`);
530
- }
531
- return renderToSimpleStream(input, context, stream);
532
- }
533
- function pipeToNodeWritable(input, context = {}, writable) {
534
- renderToSimpleStream(input, context, {
535
- push(content) {
536
- if (content != null) {
537
- writable.write(content);
538
- }
539
- else {
540
- writable.end();
541
- }
542
- },
543
- destroy(err) {
544
- writable.destroy(err);
545
- }
546
- });
547
- }
548
- function renderToWebStream(input, context = {}) {
549
- if (typeof ReadableStream !== 'function') {
550
- throw new Error(`ReadableStream constructor is not available in the global scope. ` +
551
- `If the target environment does support web streams, consider using ` +
552
- `pipeToWebWritable() with an existing WritableStream instance instead.`);
553
- }
554
- const encoder = new TextEncoder();
555
- let cancelled = false;
556
- return new ReadableStream({
557
- start(controller) {
558
- renderToSimpleStream(input, context, {
559
- push(content) {
560
- if (cancelled)
561
- return;
562
- if (content != null) {
563
- controller.enqueue(encoder.encode(content));
564
- }
565
- else {
566
- controller.close();
567
- }
568
- },
569
- destroy(err) {
570
- controller.error(err);
571
- }
572
- });
573
- },
574
- cancel() {
575
- cancelled = true;
576
- }
577
- });
578
- }
579
- function pipeToWebWritable(input, context = {}, writable) {
580
- const writer = writable.getWriter();
581
- const encoder = new TextEncoder();
582
- // #4287 CloudFlare workers do not implement `ready` property
583
- let hasReady = false;
584
- try {
585
- hasReady = shared.isPromise(writer.ready);
586
- }
587
- catch (e) { }
588
- renderToSimpleStream(input, context, {
589
- async push(content) {
590
- if (hasReady) {
591
- await writer.ready;
592
- }
593
- if (content != null) {
594
- return writer.write(encoder.encode(content));
595
- }
596
- else {
597
- return writer.close();
598
- }
599
- },
600
- destroy(err) {
601
- // TODO better error handling?
602
- console.log(err);
603
- writer.close();
604
- }
605
- });
463
+ const { isVNode: isVNode$1 } = vue.ssrUtils;
464
+ async function unrollBuffer$1(buffer, stream) {
465
+ if (buffer.hasAsync) {
466
+ for (let i = 0; i < buffer.length; i++) {
467
+ let item = buffer[i];
468
+ if (shared.isPromise(item)) {
469
+ item = await item;
470
+ }
471
+ if (shared.isString(item)) {
472
+ stream.push(item);
473
+ }
474
+ else {
475
+ await unrollBuffer$1(item, stream);
476
+ }
477
+ }
478
+ }
479
+ else {
480
+ // sync buffer can be more efficiently unrolled without unnecessary await
481
+ // ticks
482
+ unrollBufferSync$1(buffer, stream);
483
+ }
484
+ }
485
+ function unrollBufferSync$1(buffer, stream) {
486
+ for (let i = 0; i < buffer.length; i++) {
487
+ let item = buffer[i];
488
+ if (shared.isString(item)) {
489
+ stream.push(item);
490
+ }
491
+ else {
492
+ // since this is a sync buffer, child buffers are never promises
493
+ unrollBufferSync$1(item, stream);
494
+ }
495
+ }
496
+ }
497
+ function renderToSimpleStream(input, context, stream) {
498
+ if (isVNode$1(input)) {
499
+ // raw vnode, wrap with app (for context)
500
+ return renderToSimpleStream(vue.createApp({ render: () => input }), context, stream);
501
+ }
502
+ // rendering an app
503
+ const vnode = vue.createVNode(input._component, input._props);
504
+ vnode.appContext = input._context;
505
+ // provide the ssr context to the tree
506
+ input.provide(vue.ssrContextKey, context);
507
+ Promise.resolve(renderComponentVNode(vnode))
508
+ .then(buffer => unrollBuffer$1(buffer, stream))
509
+ .then(() => resolveTeleports(context))
510
+ .then(() => stream.push(null))
511
+ .catch(error => {
512
+ stream.destroy(error);
513
+ });
514
+ return stream;
515
+ }
516
+ /**
517
+ * @deprecated
518
+ */
519
+ function renderToStream(input, context = {}) {
520
+ console.warn(`[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`);
521
+ return renderToNodeStream(input, context);
522
+ }
523
+ function renderToNodeStream(input, context = {}) {
524
+ const stream = new (require('stream').Readable)({ read() { } })
525
+ ;
526
+ if (!stream) {
527
+ throw new Error(`ESM build of renderToStream() does not support renderToNodeStream(). ` +
528
+ `Use pipeToNodeWritable() with an existing Node.js Writable stream ` +
529
+ `instance instead.`);
530
+ }
531
+ return renderToSimpleStream(input, context, stream);
532
+ }
533
+ function pipeToNodeWritable(input, context = {}, writable) {
534
+ renderToSimpleStream(input, context, {
535
+ push(content) {
536
+ if (content != null) {
537
+ writable.write(content);
538
+ }
539
+ else {
540
+ writable.end();
541
+ }
542
+ },
543
+ destroy(err) {
544
+ writable.destroy(err);
545
+ }
546
+ });
547
+ }
548
+ function renderToWebStream(input, context = {}) {
549
+ if (typeof ReadableStream !== 'function') {
550
+ throw new Error(`ReadableStream constructor is not available in the global scope. ` +
551
+ `If the target environment does support web streams, consider using ` +
552
+ `pipeToWebWritable() with an existing WritableStream instance instead.`);
553
+ }
554
+ const encoder = new TextEncoder();
555
+ let cancelled = false;
556
+ return new ReadableStream({
557
+ start(controller) {
558
+ renderToSimpleStream(input, context, {
559
+ push(content) {
560
+ if (cancelled)
561
+ return;
562
+ if (content != null) {
563
+ controller.enqueue(encoder.encode(content));
564
+ }
565
+ else {
566
+ controller.close();
567
+ }
568
+ },
569
+ destroy(err) {
570
+ controller.error(err);
571
+ }
572
+ });
573
+ },
574
+ cancel() {
575
+ cancelled = true;
576
+ }
577
+ });
578
+ }
579
+ function pipeToWebWritable(input, context = {}, writable) {
580
+ const writer = writable.getWriter();
581
+ const encoder = new TextEncoder();
582
+ // #4287 CloudFlare workers do not implement `ready` property
583
+ let hasReady = false;
584
+ try {
585
+ hasReady = shared.isPromise(writer.ready);
586
+ }
587
+ catch (e) { }
588
+ renderToSimpleStream(input, context, {
589
+ async push(content) {
590
+ if (hasReady) {
591
+ await writer.ready;
592
+ }
593
+ if (content != null) {
594
+ return writer.write(encoder.encode(content));
595
+ }
596
+ else {
597
+ return writer.close();
598
+ }
599
+ },
600
+ destroy(err) {
601
+ // TODO better error handling?
602
+ console.log(err);
603
+ writer.close();
604
+ }
605
+ });
606
606
  }
607
607
 
608
- function ssrRenderComponent(comp, props = null, children = null, parentComponent = null, slotScopeId) {
609
- return renderComponentVNode(vue.createVNode(comp, props, children), parentComponent, slotScopeId);
608
+ function ssrRenderComponent(comp, props = null, children = null, parentComponent = null, slotScopeId) {
609
+ return renderComponentVNode(vue.createVNode(comp, props, children), parentComponent, slotScopeId);
610
610
  }
611
611
 
612
- function ssrRenderSlot(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId) {
613
- // template-compiled slots are always rendered as fragments
614
- push(`<!--[-->`);
615
- ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId);
616
- push(`<!--]-->`);
617
- }
618
- function ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId, transition) {
619
- const slotFn = slots[slotName];
620
- if (slotFn) {
621
- const slotBuffer = [];
622
- const bufferedPush = (item) => {
623
- slotBuffer.push(item);
624
- };
625
- const ret = slotFn(slotProps, bufferedPush, parentComponent, slotScopeId ? ' ' + slotScopeId : '');
626
- if (shared.isArray(ret)) {
627
- // normal slot
628
- renderVNodeChildren(push, ret, parentComponent, slotScopeId);
629
- }
630
- else {
631
- // ssr slot.
632
- // check if the slot renders all comments, in which case use the fallback
633
- let isEmptySlot = true;
634
- if (transition) {
635
- isEmptySlot = false;
636
- }
637
- else {
638
- for (let i = 0; i < slotBuffer.length; i++) {
639
- if (!isComment(slotBuffer[i])) {
640
- isEmptySlot = false;
641
- break;
642
- }
643
- }
644
- }
645
- if (isEmptySlot) {
646
- if (fallbackRenderFn) {
647
- fallbackRenderFn();
648
- }
649
- }
650
- else {
651
- for (let i = 0; i < slotBuffer.length; i++) {
652
- push(slotBuffer[i]);
653
- }
654
- }
655
- }
656
- }
657
- else if (fallbackRenderFn) {
658
- fallbackRenderFn();
659
- }
660
- }
661
- const commentTestRE = /^<!--.*-->$/s;
662
- const commentRE = /<!--[^]*?-->/gm;
663
- function isComment(item) {
664
- if (typeof item !== 'string' || !commentTestRE.test(item))
665
- return false;
666
- // if item is '<!---->' or '<!--[-->' or '<!--]-->', return true directly
667
- if (item.length <= 8)
668
- return true;
669
- return !item.replace(commentRE, '').trim();
612
+ function ssrRenderSlot(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId) {
613
+ // template-compiled slots are always rendered as fragments
614
+ push(`<!--[-->`);
615
+ ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId);
616
+ push(`<!--]-->`);
617
+ }
618
+ function ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId, transition) {
619
+ const slotFn = slots[slotName];
620
+ if (slotFn) {
621
+ const slotBuffer = [];
622
+ const bufferedPush = (item) => {
623
+ slotBuffer.push(item);
624
+ };
625
+ const ret = slotFn(slotProps, bufferedPush, parentComponent, slotScopeId ? ' ' + slotScopeId : '');
626
+ if (shared.isArray(ret)) {
627
+ // normal slot
628
+ renderVNodeChildren(push, ret, parentComponent, slotScopeId);
629
+ }
630
+ else {
631
+ // ssr slot.
632
+ // check if the slot renders all comments, in which case use the fallback
633
+ let isEmptySlot = true;
634
+ if (transition) {
635
+ isEmptySlot = false;
636
+ }
637
+ else {
638
+ for (let i = 0; i < slotBuffer.length; i++) {
639
+ if (!isComment(slotBuffer[i])) {
640
+ isEmptySlot = false;
641
+ break;
642
+ }
643
+ }
644
+ }
645
+ if (isEmptySlot) {
646
+ if (fallbackRenderFn) {
647
+ fallbackRenderFn();
648
+ }
649
+ }
650
+ else {
651
+ for (let i = 0; i < slotBuffer.length; i++) {
652
+ push(slotBuffer[i]);
653
+ }
654
+ }
655
+ }
656
+ }
657
+ else if (fallbackRenderFn) {
658
+ fallbackRenderFn();
659
+ }
660
+ }
661
+ const commentTestRE = /^<!--.*-->$/s;
662
+ const commentRE = /<!--[^]*?-->/gm;
663
+ function isComment(item) {
664
+ if (typeof item !== 'string' || !commentTestRE.test(item))
665
+ return false;
666
+ // if item is '<!---->' or '<!--[-->' or '<!--]-->', return true directly
667
+ if (item.length <= 8)
668
+ return true;
669
+ return !item.replace(commentRE, '').trim();
670
670
  }
671
671
 
672
- function ssrInterpolate(value) {
673
- return shared.escapeHtml(shared.toDisplayString(value));
672
+ function ssrInterpolate(value) {
673
+ return shared.escapeHtml(shared.toDisplayString(value));
674
674
  }
675
675
 
676
- function ssrRenderList(source, renderItem) {
677
- if (shared.isArray(source) || shared.isString(source)) {
678
- for (let i = 0, l = source.length; i < l; i++) {
679
- renderItem(source[i], i);
680
- }
681
- }
682
- else if (typeof source === 'number') {
683
- for (let i = 0; i < source; i++) {
684
- renderItem(i + 1, i);
685
- }
686
- }
687
- else if (shared.isObject(source)) {
688
- if (source[Symbol.iterator]) {
689
- const arr = Array.from(source);
690
- for (let i = 0, l = arr.length; i < l; i++) {
691
- renderItem(arr[i], i);
692
- }
693
- }
694
- else {
695
- const keys = Object.keys(source);
696
- for (let i = 0, l = keys.length; i < l; i++) {
697
- const key = keys[i];
698
- renderItem(source[key], key, i);
699
- }
700
- }
701
- }
676
+ function ssrRenderList(source, renderItem) {
677
+ if (shared.isArray(source) || shared.isString(source)) {
678
+ for (let i = 0, l = source.length; i < l; i++) {
679
+ renderItem(source[i], i);
680
+ }
681
+ }
682
+ else if (typeof source === 'number') {
683
+ for (let i = 0; i < source; i++) {
684
+ renderItem(i + 1, i);
685
+ }
686
+ }
687
+ else if (shared.isObject(source)) {
688
+ if (source[Symbol.iterator]) {
689
+ const arr = Array.from(source);
690
+ for (let i = 0, l = arr.length; i < l; i++) {
691
+ renderItem(arr[i], i);
692
+ }
693
+ }
694
+ else {
695
+ const keys = Object.keys(source);
696
+ for (let i = 0, l = keys.length; i < l; i++) {
697
+ const key = keys[i];
698
+ renderItem(source[key], key, i);
699
+ }
700
+ }
701
+ }
702
702
  }
703
703
 
704
- async function ssrRenderSuspense(push, { default: renderContent }) {
705
- if (renderContent) {
706
- renderContent();
707
- }
708
- else {
709
- push(`<!---->`);
710
- }
704
+ async function ssrRenderSuspense(push, { default: renderContent }) {
705
+ if (renderContent) {
706
+ renderContent();
707
+ }
708
+ else {
709
+ push(`<!---->`);
710
+ }
711
711
  }
712
712
 
713
- function ssrGetDirectiveProps(instance, dir, value, arg, modifiers = {}) {
714
- if (typeof dir !== 'function' && dir.getSSRProps) {
715
- return (dir.getSSRProps({
716
- dir,
717
- instance,
718
- value,
719
- oldValue: undefined,
720
- arg,
721
- modifiers
722
- }, null) || {});
723
- }
724
- return {};
713
+ function ssrGetDirectiveProps(instance, dir, value, arg, modifiers = {}) {
714
+ if (typeof dir !== 'function' && dir.getSSRProps) {
715
+ return (dir.getSSRProps({
716
+ dir,
717
+ instance,
718
+ value,
719
+ oldValue: undefined,
720
+ arg,
721
+ modifiers
722
+ }, null) || {});
723
+ }
724
+ return {};
725
725
  }
726
726
 
727
- const ssrLooseEqual = shared.looseEqual;
728
- function ssrLooseContain(arr, value) {
729
- return shared.looseIndexOf(arr, value) > -1;
730
- }
731
- // for <input :type="type" v-model="model" value="value">
732
- function ssrRenderDynamicModel(type, model, value) {
733
- switch (type) {
734
- case 'radio':
735
- return shared.looseEqual(model, value) ? ' checked' : '';
736
- case 'checkbox':
737
- return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
738
- ? ' checked'
739
- : '';
740
- default:
741
- // text types
742
- return ssrRenderAttr('value', model);
743
- }
744
- }
745
- // for <input v-bind="obj" v-model="model">
746
- function ssrGetDynamicModelProps(existingProps = {}, model) {
747
- const { type, value } = existingProps;
748
- switch (type) {
749
- case 'radio':
750
- return shared.looseEqual(model, value) ? { checked: true } : null;
751
- case 'checkbox':
752
- return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
753
- ? { checked: true }
754
- : null;
755
- default:
756
- // text types
757
- return { value: model };
758
- }
727
+ const ssrLooseEqual = shared.looseEqual;
728
+ function ssrLooseContain(arr, value) {
729
+ return shared.looseIndexOf(arr, value) > -1;
730
+ }
731
+ // for <input :type="type" v-model="model" value="value">
732
+ function ssrRenderDynamicModel(type, model, value) {
733
+ switch (type) {
734
+ case 'radio':
735
+ return shared.looseEqual(model, value) ? ' checked' : '';
736
+ case 'checkbox':
737
+ return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
738
+ ? ' checked'
739
+ : '';
740
+ default:
741
+ // text types
742
+ return ssrRenderAttr('value', model);
743
+ }
744
+ }
745
+ // for <input v-bind="obj" v-model="model">
746
+ function ssrGetDynamicModelProps(existingProps = {}, model) {
747
+ const { type, value } = existingProps;
748
+ switch (type) {
749
+ case 'radio':
750
+ return shared.looseEqual(model, value) ? { checked: true } : null;
751
+ case 'checkbox':
752
+ return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
753
+ ? { checked: true }
754
+ : null;
755
+ default:
756
+ // text types
757
+ return { value: model };
758
+ }
759
759
  }
760
760
 
761
761
  vue.initDirectivesForSSR();