@vue/server-renderer 3.2.45 → 3.2.47

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.
@@ -2,10 +2,23 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var vue = require('vue');
5
+ var Vue = require('vue');
6
6
  var shared = require('@vue/shared');
7
7
  var compilerSsr = require('@vue/compiler-ssr');
8
8
 
9
+ function _interopNamespaceDefault(e) {
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ for (var k in e) {
13
+ n[k] = e[k];
14
+ }
15
+ }
16
+ n.default = e;
17
+ return Object.freeze(n);
18
+ }
19
+
20
+ var Vue__namespace = /*#__PURE__*/_interopNamespaceDefault(Vue);
21
+
9
22
  // leading comma for empty string ""
10
23
  const shouldIgnoreProp = shared.makeMap(`,key,ref,innerHTML,textContent,ref_key,ref_for`);
11
24
  function ssrRenderAttrs(props, tag) {
@@ -77,44 +90,73 @@ function ssrRenderStyle(raw) {
77
90
  return shared.escapeHtml(shared.stringifyStyle(styles));
78
91
  }
79
92
 
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
- const message = `[@vue/server-renderer] Template compilation error: ${err.message}`;
106
- const codeFrame = err.loc &&
107
- shared.generateCodeFrame(template, err.loc.start.offset, err.loc.end.offset);
108
- vue.warn(codeFrame ? `${message}\n${codeFrame}` : message);
93
+ function ssrRenderComponent(comp, props = null, children = null, parentComponent = null, slotScopeId) {
94
+ return renderComponentVNode(Vue.createVNode(comp, props, children), parentComponent, slotScopeId);
95
+ }
96
+
97
+ function ssrRenderSlot(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId) {
98
+ // template-compiled slots are always rendered as fragments
99
+ push(`<!--[-->`);
100
+ ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId);
101
+ push(`<!--]-->`);
102
+ }
103
+ function ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId, transition) {
104
+ const slotFn = slots[slotName];
105
+ if (slotFn) {
106
+ const slotBuffer = [];
107
+ const bufferedPush = (item) => {
108
+ slotBuffer.push(item);
109
+ };
110
+ const ret = slotFn(slotProps, bufferedPush, parentComponent, slotScopeId ? ' ' + slotScopeId : '');
111
+ if (shared.isArray(ret)) {
112
+ // normal slot
113
+ renderVNodeChildren(push, ret, parentComponent, slotScopeId);
109
114
  }
110
- };
111
- const { code } = compilerSsr.compile(template, finalCompilerOptions);
112
- return (compileCache[cacheKey] = Function('require', code)(require));
115
+ else {
116
+ // ssr slot.
117
+ // check if the slot renders all comments, in which case use the fallback
118
+ let isEmptySlot = true;
119
+ if (transition) {
120
+ isEmptySlot = false;
121
+ }
122
+ else {
123
+ for (let i = 0; i < slotBuffer.length; i++) {
124
+ if (!isComment(slotBuffer[i])) {
125
+ isEmptySlot = false;
126
+ break;
127
+ }
128
+ }
129
+ }
130
+ if (isEmptySlot) {
131
+ if (fallbackRenderFn) {
132
+ fallbackRenderFn();
133
+ }
134
+ }
135
+ else {
136
+ for (let i = 0; i < slotBuffer.length; i++) {
137
+ push(slotBuffer[i]);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ else if (fallbackRenderFn) {
143
+ fallbackRenderFn();
144
+ }
145
+ }
146
+ const commentTestRE = /^<!--.*-->$/s;
147
+ const commentRE = /<!--[^]*?-->/gm;
148
+ function isComment(item) {
149
+ if (typeof item !== 'string' || !commentTestRE.test(item))
150
+ return false;
151
+ // if item is '<!---->' or '<!--[-->' or '<!--]-->', return true directly
152
+ if (item.length <= 8)
153
+ return true;
154
+ return !item.replace(commentRE, '').trim();
113
155
  }
114
156
 
115
157
  function ssrRenderTeleport(parentPush, contentRenderFn, target, disabled, parentComponent) {
116
158
  parentPush('<!--teleport start-->');
117
- const context = parentComponent.appContext.provides[vue.ssrContextKey];
159
+ const context = parentComponent.appContext.provides[Vue.ssrContextKey];
118
160
  const teleportBuffers = context.__teleportBuffers || (context.__teleportBuffers = {});
119
161
  const targetBuffer = teleportBuffers[target] || (teleportBuffers[target] = []);
120
162
  // record current index of the target buffer to handle nested teleports
@@ -135,890 +177,906 @@ function ssrRenderTeleport(parentPush, contentRenderFn, target, disabled, parent
135
177
  parentPush('<!--teleport end-->');
136
178
  }
137
179
 
138
- const { createComponentInstance, setCurrentRenderingInstance, setupComponent, renderComponentRoot, normalizeVNode } = vue.ssrUtils;
139
- // Each component has a buffer array.
140
- // A buffer array can contain one of the following:
141
- // - plain string
142
- // - A resolved buffer (recursive arrays of strings that can be unrolled
143
- // synchronously)
144
- // - An async buffer (a Promise that resolves to a resolved buffer)
145
- function createBuffer() {
146
- let appendable = false;
147
- const buffer = [];
148
- return {
149
- getBuffer() {
150
- // Return static buffer and await on items during unroll stage
151
- return buffer;
152
- },
153
- push(item) {
154
- const isStringItem = shared.isString(item);
155
- if (appendable && isStringItem) {
156
- buffer[buffer.length - 1] += item;
157
- }
158
- else {
159
- buffer.push(item);
160
- }
161
- appendable = isStringItem;
162
- if (shared.isPromise(item) || (shared.isArray(item) && item.hasAsync)) {
163
- // promise, or child buffer with async, mark as async.
164
- // this allows skipping unnecessary await ticks during unroll stage
165
- buffer.hasAsync = true;
166
- }
167
- }
168
- };
180
+ function ssrInterpolate(value) {
181
+ return shared.escapeHtml(shared.toDisplayString(value));
169
182
  }
170
- function renderComponentVNode(vnode, parentComponent = null, slotScopeId) {
171
- const instance = createComponentInstance(vnode, parentComponent, null);
172
- const res = setupComponent(instance, true /* isSSR */);
173
- const hasAsyncSetup = shared.isPromise(res);
174
- const prefetches = instance.sp; /* LifecycleHooks.SERVER_PREFETCH */
175
- if (hasAsyncSetup || prefetches) {
176
- let p = hasAsyncSetup
177
- ? res
178
- : Promise.resolve();
179
- if (prefetches) {
180
- p = p
181
- .then(() => Promise.all(prefetches.map(prefetch => prefetch.call(instance.proxy))))
182
- // Note: error display is already done by the wrapped lifecycle hook function.
183
- .catch(() => { });
184
- }
185
- return p.then(() => renderComponentSubTree(instance, slotScopeId));
183
+
184
+ let shouldTrack = true;
185
+ const trackStack = [];
186
+ function pauseTracking() {
187
+ trackStack.push(shouldTrack);
188
+ shouldTrack = false;
189
+ }
190
+ function resetTracking() {
191
+ const last = trackStack.pop();
192
+ shouldTrack = last === undefined ? true : last;
193
+ }
194
+
195
+ function toRaw(observed) {
196
+ const raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */];
197
+ return raw ? toRaw(raw) : observed;
198
+ }
199
+
200
+ function isRef(r) {
201
+ return !!(r && r.__v_isRef === true);
202
+ }
203
+
204
+ const stack = [];
205
+ function pushWarningContext(vnode) {
206
+ stack.push(vnode);
207
+ }
208
+ function popWarningContext() {
209
+ stack.pop();
210
+ }
211
+ function warn(msg, ...args) {
212
+ // avoid props formatting or warn handler tracking deps that might be mutated
213
+ // during patch, leading to infinite recursion.
214
+ pauseTracking();
215
+ const instance = stack.length ? stack[stack.length - 1].component : null;
216
+ const appWarnHandler = instance && instance.appContext.config.warnHandler;
217
+ const trace = getComponentTrace();
218
+ if (appWarnHandler) {
219
+ callWithErrorHandling(appWarnHandler, instance, 11 /* ErrorCodes.APP_WARN_HANDLER */, [
220
+ msg + args.join(''),
221
+ instance && instance.proxy,
222
+ trace
223
+ .map(({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`)
224
+ .join('\n'),
225
+ trace
226
+ ]);
186
227
  }
187
228
  else {
188
- return renderComponentSubTree(instance, slotScopeId);
229
+ const warnArgs = [`[Vue warn]: ${msg}`, ...args];
230
+ /* istanbul ignore if */
231
+ if (trace.length &&
232
+ // avoid spamming console during tests
233
+ !false) {
234
+ warnArgs.push(`\n`, ...formatTrace(trace));
235
+ }
236
+ console.warn(...warnArgs);
189
237
  }
238
+ resetTracking();
190
239
  }
191
- function renderComponentSubTree(instance, slotScopeId) {
192
- const comp = instance.type;
193
- const { getBuffer, push } = createBuffer();
194
- if (shared.isFunction(comp)) {
195
- let root = renderComponentRoot(instance);
196
- // #5817 scope ID attrs not falling through if functional component doesn't
197
- // have props
198
- if (!comp.props) {
199
- for (const key in instance.attrs) {
200
- if (key.startsWith(`data-v-`)) {
201
- (root.props || (root.props = {}))[key] = ``;
202
- }
203
- }
204
- }
205
- renderVNode(push, (instance.subTree = root), instance, slotScopeId);
240
+ function getComponentTrace() {
241
+ let currentVNode = stack[stack.length - 1];
242
+ if (!currentVNode) {
243
+ return [];
206
244
  }
207
- else {
208
- if ((!instance.render || instance.render === shared.NOOP) &&
209
- !instance.ssrRender &&
210
- !comp.ssrRender &&
211
- shared.isString(comp.template)) {
212
- comp.ssrRender = ssrCompile(comp.template, instance);
245
+ // we can't just use the stack because it will be incomplete during updates
246
+ // that did not start from the root. Re-construct the parent chain using
247
+ // instance parent pointers.
248
+ const normalizedStack = [];
249
+ while (currentVNode) {
250
+ const last = normalizedStack[0];
251
+ if (last && last.vnode === currentVNode) {
252
+ last.recurseCount++;
213
253
  }
214
- // perf: enable caching of computed getters during render
215
- // since there cannot be state mutations during render.
216
- for (const e of instance.scope.effects) {
217
- if (e.computed)
218
- e.computed._cacheable = true;
219
- }
220
- const ssrRender = instance.ssrRender || comp.ssrRender;
221
- if (ssrRender) {
222
- // optimized
223
- // resolve fallthrough attrs
224
- let attrs = instance.inheritAttrs !== false ? instance.attrs : undefined;
225
- let hasCloned = false;
226
- let cur = instance;
227
- while (true) {
228
- const scopeId = cur.vnode.scopeId;
229
- if (scopeId) {
230
- if (!hasCloned) {
231
- attrs = { ...attrs };
232
- hasCloned = true;
233
- }
234
- attrs[scopeId] = '';
235
- }
236
- const parent = cur.parent;
237
- if (parent && parent.subTree && parent.subTree === cur.vnode) {
238
- // parent is a non-SSR compiled component and is rendering this
239
- // component as root. inherit its scopeId if present.
240
- cur = parent;
241
- }
242
- else {
243
- break;
244
- }
245
- }
246
- if (slotScopeId) {
247
- if (!hasCloned)
248
- attrs = { ...attrs };
249
- attrs[slotScopeId.trim()] = '';
250
- }
251
- // set current rendering instance for asset resolution
252
- const prev = setCurrentRenderingInstance(instance);
253
- try {
254
- ssrRender(instance.proxy, push, instance, attrs,
255
- // compiler-optimized bindings
256
- instance.props, instance.setupState, instance.data, instance.ctx);
257
- }
258
- finally {
259
- setCurrentRenderingInstance(prev);
260
- }
261
- }
262
- else if (instance.render && instance.render !== shared.NOOP) {
263
- renderVNode(push, (instance.subTree = renderComponentRoot(instance)), instance, slotScopeId);
264
- }
265
- else {
266
- const componentName = comp.name || comp.__file || `<Anonymous>`;
267
- vue.warn(`Component ${componentName} is missing template or render function.`);
268
- push(`<!---->`);
254
+ else {
255
+ normalizedStack.push({
256
+ vnode: currentVNode,
257
+ recurseCount: 0
258
+ });
269
259
  }
260
+ const parentInstance = currentVNode.component && currentVNode.component.parent;
261
+ currentVNode = parentInstance && parentInstance.vnode;
270
262
  }
271
- return getBuffer();
263
+ return normalizedStack;
272
264
  }
273
- function renderVNode(push, vnode, parentComponent, slotScopeId) {
274
- const { type, shapeFlag, children } = vnode;
275
- switch (type) {
276
- case vue.Text:
277
- push(shared.escapeHtml(children));
278
- break;
279
- case vue.Comment:
280
- push(children ? `<!--${shared.escapeHtmlComment(children)}-->` : `<!---->`);
281
- break;
282
- case vue.Static:
283
- push(children);
284
- break;
285
- case vue.Fragment:
286
- if (vnode.slotScopeIds) {
287
- slotScopeId =
288
- (slotScopeId ? slotScopeId + ' ' : '') + vnode.slotScopeIds.join(' ');
289
- }
290
- push(`<!--[-->`); // open
291
- renderVNodeChildren(push, children, parentComponent, slotScopeId);
292
- push(`<!--]-->`); // close
293
- break;
294
- default:
295
- if (shapeFlag & 1 /* ShapeFlags.ELEMENT */) {
296
- renderElementVNode(push, vnode, parentComponent, slotScopeId);
297
- }
298
- else if (shapeFlag & 6 /* ShapeFlags.COMPONENT */) {
299
- push(renderComponentVNode(vnode, parentComponent, slotScopeId));
300
- }
301
- else if (shapeFlag & 64 /* ShapeFlags.TELEPORT */) {
302
- renderTeleportVNode(push, vnode, parentComponent, slotScopeId);
303
- }
304
- else if (shapeFlag & 128 /* ShapeFlags.SUSPENSE */) {
305
- renderVNode(push, vnode.ssContent, parentComponent, slotScopeId);
306
- }
307
- else {
308
- vue.warn('[@vue/server-renderer] Invalid VNode type:', type, `(${typeof type})`);
309
- }
310
- }
265
+ /* istanbul ignore next */
266
+ function formatTrace(trace) {
267
+ const logs = [];
268
+ trace.forEach((entry, i) => {
269
+ logs.push(...(i === 0 ? [] : [`\n`]), ...formatTraceEntry(entry));
270
+ });
271
+ return logs;
311
272
  }
312
- function renderVNodeChildren(push, children, parentComponent, slotScopeId) {
313
- for (let i = 0; i < children.length; i++) {
314
- renderVNode(push, normalizeVNode(children[i]), parentComponent, slotScopeId);
273
+ function formatTraceEntry({ vnode, recurseCount }) {
274
+ const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``;
275
+ const isRoot = vnode.component ? vnode.component.parent == null : false;
276
+ const open = ` at <${formatComponentName(vnode.component, vnode.type, isRoot)}`;
277
+ const close = `>` + postfix;
278
+ return vnode.props
279
+ ? [open, ...formatProps(vnode.props), close]
280
+ : [open + close];
281
+ }
282
+ /* istanbul ignore next */
283
+ function formatProps(props) {
284
+ const res = [];
285
+ const keys = Object.keys(props);
286
+ keys.slice(0, 3).forEach(key => {
287
+ res.push(...formatProp(key, props[key]));
288
+ });
289
+ if (keys.length > 3) {
290
+ res.push(` ...`);
315
291
  }
292
+ return res;
316
293
  }
317
- function renderElementVNode(push, vnode, parentComponent, slotScopeId) {
318
- const tag = vnode.type;
319
- let { props, children, shapeFlag, scopeId, dirs } = vnode;
320
- let openTag = `<${tag}`;
321
- if (dirs) {
322
- props = applySSRDirectives(vnode, props, dirs);
294
+ /* istanbul ignore next */
295
+ function formatProp(key, value, raw) {
296
+ if (shared.isString(value)) {
297
+ value = JSON.stringify(value);
298
+ return raw ? value : [`${key}=${value}`];
323
299
  }
324
- if (props) {
325
- openTag += ssrRenderAttrs(props, tag);
300
+ else if (typeof value === 'number' ||
301
+ typeof value === 'boolean' ||
302
+ value == null) {
303
+ return raw ? value : [`${key}=${value}`];
326
304
  }
327
- if (scopeId) {
328
- openTag += ` ${scopeId}`;
305
+ else if (isRef(value)) {
306
+ value = formatProp(key, toRaw(value.value), true);
307
+ return raw ? value : [`${key}=Ref<`, value, `>`];
329
308
  }
330
- // inherit parent chain scope id if this is the root node
331
- let curParent = parentComponent;
332
- let curVnode = vnode;
333
- while (curParent && curVnode === curParent.subTree) {
334
- curVnode = curParent.vnode;
335
- if (curVnode.scopeId) {
336
- openTag += ` ${curVnode.scopeId}`;
337
- }
338
- curParent = curParent.parent;
309
+ else if (shared.isFunction(value)) {
310
+ return [`${key}=fn${value.name ? `<${value.name}>` : ``}`];
339
311
  }
340
- if (slotScopeId) {
341
- openTag += ` ${slotScopeId}`;
312
+ else {
313
+ value = toRaw(value);
314
+ return raw ? value : [`${key}=`, value];
342
315
  }
343
- push(openTag + `>`);
344
- if (!shared.isVoidTag(tag)) {
345
- let hasChildrenOverride = false;
346
- if (props) {
347
- if (props.innerHTML) {
348
- hasChildrenOverride = true;
349
- push(props.innerHTML);
350
- }
351
- else if (props.textContent) {
352
- hasChildrenOverride = true;
353
- push(shared.escapeHtml(props.textContent));
354
- }
355
- else if (tag === 'textarea' && props.value) {
356
- hasChildrenOverride = true;
357
- push(shared.escapeHtml(props.value));
316
+ }
317
+
318
+ const ErrorTypeStrings = {
319
+ ["sp" /* LifecycleHooks.SERVER_PREFETCH */]: 'serverPrefetch hook',
320
+ ["bc" /* LifecycleHooks.BEFORE_CREATE */]: 'beforeCreate hook',
321
+ ["c" /* LifecycleHooks.CREATED */]: 'created hook',
322
+ ["bm" /* LifecycleHooks.BEFORE_MOUNT */]: 'beforeMount hook',
323
+ ["m" /* LifecycleHooks.MOUNTED */]: 'mounted hook',
324
+ ["bu" /* LifecycleHooks.BEFORE_UPDATE */]: 'beforeUpdate hook',
325
+ ["u" /* LifecycleHooks.UPDATED */]: 'updated',
326
+ ["bum" /* LifecycleHooks.BEFORE_UNMOUNT */]: 'beforeUnmount hook',
327
+ ["um" /* LifecycleHooks.UNMOUNTED */]: 'unmounted hook',
328
+ ["a" /* LifecycleHooks.ACTIVATED */]: 'activated hook',
329
+ ["da" /* LifecycleHooks.DEACTIVATED */]: 'deactivated hook',
330
+ ["ec" /* LifecycleHooks.ERROR_CAPTURED */]: 'errorCaptured hook',
331
+ ["rtc" /* LifecycleHooks.RENDER_TRACKED */]: 'renderTracked hook',
332
+ ["rtg" /* LifecycleHooks.RENDER_TRIGGERED */]: 'renderTriggered hook',
333
+ [0 /* ErrorCodes.SETUP_FUNCTION */]: 'setup function',
334
+ [1 /* ErrorCodes.RENDER_FUNCTION */]: 'render function',
335
+ [2 /* ErrorCodes.WATCH_GETTER */]: 'watcher getter',
336
+ [3 /* ErrorCodes.WATCH_CALLBACK */]: 'watcher callback',
337
+ [4 /* ErrorCodes.WATCH_CLEANUP */]: 'watcher cleanup function',
338
+ [5 /* ErrorCodes.NATIVE_EVENT_HANDLER */]: 'native event handler',
339
+ [6 /* ErrorCodes.COMPONENT_EVENT_HANDLER */]: 'component event handler',
340
+ [7 /* ErrorCodes.VNODE_HOOK */]: 'vnode hook',
341
+ [8 /* ErrorCodes.DIRECTIVE_HOOK */]: 'directive hook',
342
+ [9 /* ErrorCodes.TRANSITION_HOOK */]: 'transition hook',
343
+ [10 /* ErrorCodes.APP_ERROR_HANDLER */]: 'app errorHandler',
344
+ [11 /* ErrorCodes.APP_WARN_HANDLER */]: 'app warnHandler',
345
+ [12 /* ErrorCodes.FUNCTION_REF */]: 'ref function',
346
+ [13 /* ErrorCodes.ASYNC_COMPONENT_LOADER */]: 'async component loader',
347
+ [14 /* ErrorCodes.SCHEDULER */]: 'scheduler flush. This is likely a Vue internals bug. ' +
348
+ 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core'
349
+ };
350
+ function callWithErrorHandling(fn, instance, type, args) {
351
+ let res;
352
+ try {
353
+ res = args ? fn(...args) : fn();
354
+ }
355
+ catch (err) {
356
+ handleError(err, instance, type);
357
+ }
358
+ return res;
359
+ }
360
+ function handleError(err, instance, type, throwInDev = true) {
361
+ const contextVNode = instance ? instance.vnode : null;
362
+ if (instance) {
363
+ let cur = instance.parent;
364
+ // the exposed instance is the render proxy to keep it consistent with 2.x
365
+ const exposedInstance = instance.proxy;
366
+ // in production the hook receives only the error code
367
+ const errorInfo = ErrorTypeStrings[type] ;
368
+ while (cur) {
369
+ const errorCapturedHooks = cur.ec;
370
+ if (errorCapturedHooks) {
371
+ for (let i = 0; i < errorCapturedHooks.length; i++) {
372
+ if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) {
373
+ return;
374
+ }
375
+ }
358
376
  }
377
+ cur = cur.parent;
359
378
  }
360
- if (!hasChildrenOverride) {
361
- if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
362
- push(shared.escapeHtml(children));
363
- }
364
- else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
365
- renderVNodeChildren(push, children, parentComponent, slotScopeId);
366
- }
379
+ // app-level handling
380
+ const appErrorHandler = instance.appContext.config.errorHandler;
381
+ if (appErrorHandler) {
382
+ callWithErrorHandling(appErrorHandler, null, 10 /* ErrorCodes.APP_ERROR_HANDLER */, [err, exposedInstance, errorInfo]);
383
+ return;
367
384
  }
368
- push(`</${tag}>`);
369
385
  }
386
+ logError(err, type, contextVNode, throwInDev);
370
387
  }
371
- function applySSRDirectives(vnode, rawProps, dirs) {
372
- const toMerge = [];
373
- for (let i = 0; i < dirs.length; i++) {
374
- const binding = dirs[i];
375
- const { dir: { getSSRProps } } = binding;
376
- if (getSSRProps) {
377
- const props = getSSRProps(binding, vnode);
378
- if (props)
379
- toMerge.push(props);
388
+ function logError(err, type, contextVNode, throwInDev = true) {
389
+ {
390
+ const info = ErrorTypeStrings[type];
391
+ if (contextVNode) {
392
+ pushWarningContext(contextVNode);
380
393
  }
381
- }
382
- return vue.mergeProps(rawProps || {}, ...toMerge);
383
- }
384
- function renderTeleportVNode(push, vnode, parentComponent, slotScopeId) {
385
- const target = vnode.props && vnode.props.to;
386
- const disabled = vnode.props && vnode.props.disabled;
387
- if (!target) {
388
- if (!disabled) {
389
- vue.warn(`[@vue/server-renderer] Teleport is missing target prop.`);
394
+ warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`);
395
+ if (contextVNode) {
396
+ popWarningContext();
397
+ }
398
+ // crash in dev by default so it's more noticeable
399
+ if (throwInDev) {
400
+ throw err;
401
+ }
402
+ else {
403
+ console.error(err);
390
404
  }
391
- return [];
392
- }
393
- if (!shared.isString(target)) {
394
- vue.warn(`[@vue/server-renderer] Teleport target must be a query selector string.`);
395
- return [];
396
405
  }
397
- ssrRenderTeleport(push, push => {
398
- renderVNodeChildren(push, vnode.children, parentComponent, slotScopeId);
399
- }, target, disabled || disabled === '', parentComponent);
400
406
  }
401
407
 
402
- const { isVNode } = vue.ssrUtils;
403
- async function unrollBuffer(buffer) {
404
- if (buffer.hasAsync) {
405
- let ret = '';
406
- for (let i = 0; i < buffer.length; i++) {
407
- let item = buffer[i];
408
- if (shared.isPromise(item)) {
409
- item = await item;
410
- }
411
- if (shared.isString(item)) {
412
- ret += item;
413
- }
414
- else {
415
- ret += await unrollBuffer(item);
416
- }
408
+ const classifyRE = /(?:^|[-_])(\w)/g;
409
+ const classify = (str) => str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '');
410
+ function getComponentName(Component, includeInferred = true) {
411
+ return shared.isFunction(Component)
412
+ ? Component.displayName || Component.name
413
+ : Component.name || (includeInferred && Component.__name);
414
+ }
415
+ /* istanbul ignore next */
416
+ function formatComponentName(instance, Component, isRoot = false) {
417
+ let name = getComponentName(Component);
418
+ if (!name && Component.__file) {
419
+ const match = Component.__file.match(/([^/\\]+)\.\w+$/);
420
+ if (match) {
421
+ name = match[1];
417
422
  }
418
- return ret;
419
423
  }
420
- else {
421
- // sync buffer can be more efficiently unrolled without unnecessary await
422
- // ticks
423
- return unrollBufferSync(buffer);
424
+ if (!name && instance && instance.parent) {
425
+ // try to infer the name based on reverse resolution
426
+ const inferFromRegistry = (registry) => {
427
+ for (const key in registry) {
428
+ if (registry[key] === Component) {
429
+ return key;
430
+ }
431
+ }
432
+ };
433
+ name =
434
+ inferFromRegistry(instance.components ||
435
+ instance.parent.type.components) || inferFromRegistry(instance.appContext.components);
424
436
  }
437
+ return name ? classify(name) : isRoot ? `App` : `Anonymous`;
425
438
  }
426
- function unrollBufferSync(buffer) {
427
- let ret = '';
428
- for (let i = 0; i < buffer.length; i++) {
429
- let item = buffer[i];
430
- if (shared.isString(item)) {
431
- ret += item;
432
- }
433
- else {
434
- // since this is a sync buffer, child buffers are never promises
435
- ret += unrollBufferSync(item);
439
+
440
+ function ssrRenderList(source, renderItem) {
441
+ if (shared.isArray(source) || shared.isString(source)) {
442
+ for (let i = 0, l = source.length; i < l; i++) {
443
+ renderItem(source[i], i);
436
444
  }
437
445
  }
438
- return ret;
439
- }
440
- async function renderToString(input, context = {}) {
441
- if (isVNode(input)) {
442
- // raw vnode, wrap with app (for context)
443
- return renderToString(vue.createApp({ render: () => input }), context);
444
- }
445
- // rendering an app
446
- const vnode = vue.createVNode(input._component, input._props);
447
- vnode.appContext = input._context;
448
- // provide the ssr context to the tree
449
- input.provide(vue.ssrContextKey, context);
450
- const buffer = await renderComponentVNode(vnode);
451
- const result = await unrollBuffer(buffer);
452
- await resolveTeleports(context);
453
- if (context.__watcherHandles) {
454
- for (const unwatch of context.__watcherHandles) {
455
- unwatch();
446
+ else if (typeof source === 'number') {
447
+ if (!Number.isInteger(source)) {
448
+ warn(`The v-for range expect an integer value but got ${source}.`);
449
+ return;
456
450
  }
457
- }
458
- return result;
459
- }
460
- async function resolveTeleports(context) {
461
- if (context.__teleportBuffers) {
462
- context.teleports = context.teleports || {};
463
- for (const key in context.__teleportBuffers) {
464
- // note: it's OK to await sequentially here because the Promises were
465
- // created eagerly in parallel.
466
- context.teleports[key] = await unrollBuffer(await Promise.all([context.__teleportBuffers[key]]));
451
+ for (let i = 0; i < source; i++) {
452
+ renderItem(i + 1, i);
467
453
  }
468
454
  }
469
- }
470
-
471
- const { isVNode: isVNode$1 } = vue.ssrUtils;
472
- async function unrollBuffer$1(buffer, stream) {
473
- if (buffer.hasAsync) {
474
- for (let i = 0; i < buffer.length; i++) {
475
- let item = buffer[i];
476
- if (shared.isPromise(item)) {
477
- item = await item;
478
- }
479
- if (shared.isString(item)) {
480
- stream.push(item);
455
+ else if (shared.isObject(source)) {
456
+ if (source[Symbol.iterator]) {
457
+ const arr = Array.from(source);
458
+ for (let i = 0, l = arr.length; i < l; i++) {
459
+ renderItem(arr[i], i);
481
460
  }
482
- else {
483
- await unrollBuffer$1(item, stream);
461
+ }
462
+ else {
463
+ const keys = Object.keys(source);
464
+ for (let i = 0, l = keys.length; i < l; i++) {
465
+ const key = keys[i];
466
+ renderItem(source[key], key, i);
484
467
  }
485
468
  }
486
469
  }
470
+ }
471
+
472
+ async function ssrRenderSuspense(push, { default: renderContent }) {
473
+ if (renderContent) {
474
+ renderContent();
475
+ }
487
476
  else {
488
- // sync buffer can be more efficiently unrolled without unnecessary await
489
- // ticks
490
- unrollBufferSync$1(buffer, stream);
477
+ push(`<!---->`);
491
478
  }
492
479
  }
493
- function unrollBufferSync$1(buffer, stream) {
494
- for (let i = 0; i < buffer.length; i++) {
495
- let item = buffer[i];
496
- if (shared.isString(item)) {
497
- stream.push(item);
498
- }
499
- else {
500
- // since this is a sync buffer, child buffers are never promises
501
- unrollBufferSync$1(item, stream);
502
- }
480
+
481
+ function ssrGetDirectiveProps(instance, dir, value, arg, modifiers = {}) {
482
+ if (typeof dir !== 'function' && dir.getSSRProps) {
483
+ return (dir.getSSRProps({
484
+ dir,
485
+ instance,
486
+ value,
487
+ oldValue: undefined,
488
+ arg,
489
+ modifiers
490
+ }, null) || {});
503
491
  }
492
+ return {};
504
493
  }
505
- function renderToSimpleStream(input, context, stream) {
506
- if (isVNode$1(input)) {
507
- // raw vnode, wrap with app (for context)
508
- return renderToSimpleStream(vue.createApp({ render: () => input }), context, stream);
494
+
495
+ const ssrLooseEqual = shared.looseEqual;
496
+ function ssrLooseContain(arr, value) {
497
+ return shared.looseIndexOf(arr, value) > -1;
498
+ }
499
+ // for <input :type="type" v-model="model" value="value">
500
+ function ssrRenderDynamicModel(type, model, value) {
501
+ switch (type) {
502
+ case 'radio':
503
+ return shared.looseEqual(model, value) ? ' checked' : '';
504
+ case 'checkbox':
505
+ return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
506
+ ? ' checked'
507
+ : '';
508
+ default:
509
+ // text types
510
+ return ssrRenderAttr('value', model);
509
511
  }
510
- // rendering an app
511
- const vnode = vue.createVNode(input._component, input._props);
512
- vnode.appContext = input._context;
513
- // provide the ssr context to the tree
514
- input.provide(vue.ssrContextKey, context);
515
- Promise.resolve(renderComponentVNode(vnode))
516
- .then(buffer => unrollBuffer$1(buffer, stream))
517
- .then(() => resolveTeleports(context))
518
- .then(() => {
519
- if (context.__watcherHandles) {
520
- for (const unwatch of context.__watcherHandles) {
521
- unwatch();
522
- }
523
- }
524
- })
525
- .then(() => stream.push(null))
526
- .catch(error => {
527
- stream.destroy(error);
528
- });
529
- return stream;
530
512
  }
531
- /**
532
- * @deprecated
533
- */
534
- function renderToStream(input, context = {}) {
535
- console.warn(`[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`);
536
- return renderToNodeStream(input, context);
513
+ // for <input v-bind="obj" v-model="model">
514
+ function ssrGetDynamicModelProps(existingProps = {}, model) {
515
+ const { type, value } = existingProps;
516
+ switch (type) {
517
+ case 'radio':
518
+ return shared.looseEqual(model, value) ? { checked: true } : null;
519
+ case 'checkbox':
520
+ return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
521
+ ? { checked: true }
522
+ : null;
523
+ default:
524
+ // text types
525
+ return { value: model };
526
+ }
537
527
  }
538
- function renderToNodeStream(input, context = {}) {
539
- const stream = new (require('stream').Readable)({ read() { } })
540
- ;
541
- if (!stream) {
542
- throw new Error(`ESM build of renderToStream() does not support renderToNodeStream(). ` +
543
- `Use pipeToNodeWritable() with an existing Node.js Writable stream ` +
544
- `instance instead.`);
528
+
529
+ // internal runtime helpers
530
+
531
+ var helpers = /*#__PURE__*/Object.freeze({
532
+ __proto__: null,
533
+ ssrGetDirectiveProps: ssrGetDirectiveProps,
534
+ ssrGetDynamicModelProps: ssrGetDynamicModelProps,
535
+ ssrIncludeBooleanAttr: shared.includeBooleanAttr,
536
+ ssrInterpolate: ssrInterpolate,
537
+ ssrLooseContain: ssrLooseContain,
538
+ ssrLooseEqual: ssrLooseEqual,
539
+ ssrRenderAttr: ssrRenderAttr,
540
+ ssrRenderAttrs: ssrRenderAttrs,
541
+ ssrRenderClass: ssrRenderClass,
542
+ ssrRenderComponent: ssrRenderComponent,
543
+ ssrRenderDynamicAttr: ssrRenderDynamicAttr,
544
+ ssrRenderDynamicModel: ssrRenderDynamicModel,
545
+ ssrRenderList: ssrRenderList,
546
+ ssrRenderSlot: ssrRenderSlot,
547
+ ssrRenderSlotInner: ssrRenderSlotInner,
548
+ ssrRenderStyle: ssrRenderStyle,
549
+ ssrRenderSuspense: ssrRenderSuspense,
550
+ ssrRenderTeleport: ssrRenderTeleport,
551
+ ssrRenderVNode: renderVNode
552
+ });
553
+
554
+ const compileCache = Object.create(null);
555
+ function ssrCompile(template, instance) {
556
+ // TODO: This is copied from runtime-core/src/component.ts and should probably be refactored
557
+ const Component = instance.type;
558
+ const { isCustomElement, compilerOptions } = instance.appContext.config;
559
+ const { delimiters, compilerOptions: componentCompilerOptions } = Component;
560
+ const finalCompilerOptions = shared.extend(shared.extend({
561
+ isCustomElement,
562
+ delimiters
563
+ }, compilerOptions), componentCompilerOptions);
564
+ finalCompilerOptions.isCustomElement =
565
+ finalCompilerOptions.isCustomElement || shared.NO;
566
+ finalCompilerOptions.isNativeTag = finalCompilerOptions.isNativeTag || shared.NO;
567
+ const cacheKey = JSON.stringify({
568
+ template,
569
+ compilerOptions: finalCompilerOptions
570
+ }, (key, value) => {
571
+ return shared.isFunction(value) ? value.toString() : value;
572
+ });
573
+ const cached = compileCache[cacheKey];
574
+ if (cached) {
575
+ return cached;
545
576
  }
546
- return renderToSimpleStream(input, context, stream);
577
+ finalCompilerOptions.onError = (err) => {
578
+ {
579
+ const message = `[@vue/server-renderer] Template compilation error: ${err.message}`;
580
+ const codeFrame = err.loc &&
581
+ shared.generateCodeFrame(template, err.loc.start.offset, err.loc.end.offset);
582
+ Vue.warn(codeFrame ? `${message}\n${codeFrame}` : message);
583
+ }
584
+ };
585
+ const { code } = compilerSsr.compile(template, finalCompilerOptions);
586
+ const requireMap = {
587
+ vue: Vue__namespace,
588
+ 'vue/server-renderer': helpers
589
+ };
590
+ const fakeRequire = (id) => requireMap[id];
591
+ return (compileCache[cacheKey] = Function('require', code)(fakeRequire));
547
592
  }
548
- function pipeToNodeWritable(input, context = {}, writable) {
549
- renderToSimpleStream(input, context, {
550
- push(content) {
551
- if (content != null) {
552
- writable.write(content);
593
+
594
+ const { createComponentInstance, setCurrentRenderingInstance, setupComponent, renderComponentRoot, normalizeVNode } = Vue.ssrUtils;
595
+ // Each component has a buffer array.
596
+ // A buffer array can contain one of the following:
597
+ // - plain string
598
+ // - A resolved buffer (recursive arrays of strings that can be unrolled
599
+ // synchronously)
600
+ // - An async buffer (a Promise that resolves to a resolved buffer)
601
+ function createBuffer() {
602
+ let appendable = false;
603
+ const buffer = [];
604
+ return {
605
+ getBuffer() {
606
+ // Return static buffer and await on items during unroll stage
607
+ return buffer;
608
+ },
609
+ push(item) {
610
+ const isStringItem = shared.isString(item);
611
+ if (appendable && isStringItem) {
612
+ buffer[buffer.length - 1] += item;
553
613
  }
554
614
  else {
555
- writable.end();
615
+ buffer.push(item);
616
+ }
617
+ appendable = isStringItem;
618
+ if (shared.isPromise(item) || (shared.isArray(item) && item.hasAsync)) {
619
+ // promise, or child buffer with async, mark as async.
620
+ // this allows skipping unnecessary await ticks during unroll stage
621
+ buffer.hasAsync = true;
556
622
  }
557
- },
558
- destroy(err) {
559
- writable.destroy(err);
560
623
  }
561
- });
624
+ };
562
625
  }
563
- function renderToWebStream(input, context = {}) {
564
- if (typeof ReadableStream !== 'function') {
565
- throw new Error(`ReadableStream constructor is not available in the global scope. ` +
566
- `If the target environment does support web streams, consider using ` +
567
- `pipeToWebWritable() with an existing WritableStream instance instead.`);
626
+ function renderComponentVNode(vnode, parentComponent = null, slotScopeId) {
627
+ const instance = createComponentInstance(vnode, parentComponent, null);
628
+ const res = setupComponent(instance, true /* isSSR */);
629
+ const hasAsyncSetup = shared.isPromise(res);
630
+ const prefetches = instance.sp; /* LifecycleHooks.SERVER_PREFETCH */
631
+ if (hasAsyncSetup || prefetches) {
632
+ let p = hasAsyncSetup
633
+ ? res
634
+ : Promise.resolve();
635
+ if (prefetches) {
636
+ p = p
637
+ .then(() => Promise.all(prefetches.map(prefetch => prefetch.call(instance.proxy))))
638
+ // Note: error display is already done by the wrapped lifecycle hook function.
639
+ .catch(() => { });
640
+ }
641
+ return p.then(() => renderComponentSubTree(instance, slotScopeId));
568
642
  }
569
- const encoder = new TextEncoder();
570
- let cancelled = false;
571
- return new ReadableStream({
572
- start(controller) {
573
- renderToSimpleStream(input, context, {
574
- push(content) {
575
- if (cancelled)
576
- return;
577
- if (content != null) {
578
- controller.enqueue(encoder.encode(content));
579
- }
580
- else {
581
- controller.close();
582
- }
583
- },
584
- destroy(err) {
585
- controller.error(err);
643
+ else {
644
+ return renderComponentSubTree(instance, slotScopeId);
645
+ }
646
+ }
647
+ function renderComponentSubTree(instance, slotScopeId) {
648
+ const comp = instance.type;
649
+ const { getBuffer, push } = createBuffer();
650
+ if (shared.isFunction(comp)) {
651
+ let root = renderComponentRoot(instance);
652
+ // #5817 scope ID attrs not falling through if functional component doesn't
653
+ // have props
654
+ if (!comp.props) {
655
+ for (const key in instance.attrs) {
656
+ if (key.startsWith(`data-v-`)) {
657
+ (root.props || (root.props = {}))[key] = ``;
586
658
  }
587
- });
588
- },
589
- cancel() {
590
- cancelled = true;
659
+ }
591
660
  }
592
- });
593
- }
594
- function pipeToWebWritable(input, context = {}, writable) {
595
- const writer = writable.getWriter();
596
- const encoder = new TextEncoder();
597
- // #4287 CloudFlare workers do not implement `ready` property
598
- let hasReady = false;
599
- try {
600
- hasReady = shared.isPromise(writer.ready);
661
+ renderVNode(push, (instance.subTree = root), instance, slotScopeId);
601
662
  }
602
- catch (e) { }
603
- renderToSimpleStream(input, context, {
604
- async push(content) {
605
- if (hasReady) {
606
- await writer.ready;
607
- }
608
- if (content != null) {
609
- return writer.write(encoder.encode(content));
610
- }
611
- else {
612
- return writer.close();
613
- }
614
- },
615
- destroy(err) {
616
- // TODO better error handling?
617
- console.log(err);
618
- writer.close();
663
+ else {
664
+ if ((!instance.render || instance.render === shared.NOOP) &&
665
+ !instance.ssrRender &&
666
+ !comp.ssrRender &&
667
+ shared.isString(comp.template)) {
668
+ comp.ssrRender = ssrCompile(comp.template, instance);
619
669
  }
620
- });
621
- }
622
-
623
- function ssrRenderComponent(comp, props = null, children = null, parentComponent = null, slotScopeId) {
624
- return renderComponentVNode(vue.createVNode(comp, props, children), parentComponent, slotScopeId);
625
- }
626
-
627
- function ssrRenderSlot(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId) {
628
- // template-compiled slots are always rendered as fragments
629
- push(`<!--[-->`);
630
- ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId);
631
- push(`<!--]-->`);
632
- }
633
- function ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId, transition) {
634
- const slotFn = slots[slotName];
635
- if (slotFn) {
636
- const slotBuffer = [];
637
- const bufferedPush = (item) => {
638
- slotBuffer.push(item);
639
- };
640
- const ret = slotFn(slotProps, bufferedPush, parentComponent, slotScopeId ? ' ' + slotScopeId : '');
641
- if (shared.isArray(ret)) {
642
- // normal slot
643
- renderVNodeChildren(push, ret, parentComponent, slotScopeId);
670
+ // perf: enable caching of computed getters during render
671
+ // since there cannot be state mutations during render.
672
+ for (const e of instance.scope.effects) {
673
+ if (e.computed)
674
+ e.computed._cacheable = true;
644
675
  }
645
- else {
646
- // ssr slot.
647
- // check if the slot renders all comments, in which case use the fallback
648
- let isEmptySlot = true;
649
- if (transition) {
650
- isEmptySlot = false;
651
- }
652
- else {
653
- for (let i = 0; i < slotBuffer.length; i++) {
654
- if (!isComment(slotBuffer[i])) {
655
- isEmptySlot = false;
656
- break;
676
+ const ssrRender = instance.ssrRender || comp.ssrRender;
677
+ if (ssrRender) {
678
+ // optimized
679
+ // resolve fallthrough attrs
680
+ let attrs = instance.inheritAttrs !== false ? instance.attrs : undefined;
681
+ let hasCloned = false;
682
+ let cur = instance;
683
+ while (true) {
684
+ const scopeId = cur.vnode.scopeId;
685
+ if (scopeId) {
686
+ if (!hasCloned) {
687
+ attrs = { ...attrs };
688
+ hasCloned = true;
657
689
  }
690
+ attrs[scopeId] = '';
658
691
  }
659
- }
660
- if (isEmptySlot) {
661
- if (fallbackRenderFn) {
662
- fallbackRenderFn();
692
+ const parent = cur.parent;
693
+ if (parent && parent.subTree && parent.subTree === cur.vnode) {
694
+ // parent is a non-SSR compiled component and is rendering this
695
+ // component as root. inherit its scopeId if present.
696
+ cur = parent;
663
697
  }
664
- }
665
- else {
666
- for (let i = 0; i < slotBuffer.length; i++) {
667
- push(slotBuffer[i]);
698
+ else {
699
+ break;
668
700
  }
669
701
  }
702
+ if (slotScopeId) {
703
+ if (!hasCloned)
704
+ attrs = { ...attrs };
705
+ attrs[slotScopeId.trim()] = '';
706
+ }
707
+ // set current rendering instance for asset resolution
708
+ const prev = setCurrentRenderingInstance(instance);
709
+ try {
710
+ ssrRender(instance.proxy, push, instance, attrs,
711
+ // compiler-optimized bindings
712
+ instance.props, instance.setupState, instance.data, instance.ctx);
713
+ }
714
+ finally {
715
+ setCurrentRenderingInstance(prev);
716
+ }
717
+ }
718
+ else if (instance.render && instance.render !== shared.NOOP) {
719
+ renderVNode(push, (instance.subTree = renderComponentRoot(instance)), instance, slotScopeId);
670
720
  }
671
- }
672
- else if (fallbackRenderFn) {
673
- fallbackRenderFn();
674
- }
675
- }
676
- const commentTestRE = /^<!--.*-->$/s;
677
- const commentRE = /<!--[^]*?-->/gm;
678
- function isComment(item) {
679
- if (typeof item !== 'string' || !commentTestRE.test(item))
680
- return false;
681
- // if item is '<!---->' or '<!--[-->' or '<!--]-->', return true directly
682
- if (item.length <= 8)
683
- return true;
684
- return !item.replace(commentRE, '').trim();
685
- }
686
-
687
- function ssrInterpolate(value) {
688
- return shared.escapeHtml(shared.toDisplayString(value));
689
- }
690
-
691
- function toRaw(observed) {
692
- const raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */];
693
- return raw ? toRaw(raw) : observed;
694
- }
695
-
696
- function isRef(r) {
697
- return !!(r && r.__v_isRef === true);
698
- }
699
-
700
- const stack = [];
701
- function pushWarningContext(vnode) {
702
- stack.push(vnode);
703
- }
704
- function popWarningContext() {
705
- stack.pop();
706
- }
707
- function warn(msg, ...args) {
708
- const instance = stack.length ? stack[stack.length - 1].component : null;
709
- const appWarnHandler = instance && instance.appContext.config.warnHandler;
710
- const trace = getComponentTrace();
711
- if (appWarnHandler) {
712
- callWithErrorHandling(appWarnHandler, instance, 11 /* ErrorCodes.APP_WARN_HANDLER */, [
713
- msg + args.join(''),
714
- instance && instance.proxy,
715
- trace
716
- .map(({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`)
717
- .join('\n'),
718
- trace
719
- ]);
720
- }
721
- else {
722
- const warnArgs = [`[Vue warn]: ${msg}`, ...args];
723
- /* istanbul ignore if */
724
- if (trace.length &&
725
- // avoid spamming console during tests
726
- !false) {
727
- warnArgs.push(`\n`, ...formatTrace(trace));
728
- }
729
- console.warn(...warnArgs);
730
- }
731
- }
732
- function getComponentTrace() {
733
- let currentVNode = stack[stack.length - 1];
734
- if (!currentVNode) {
735
- return [];
736
- }
737
- // we can't just use the stack because it will be incomplete during updates
738
- // that did not start from the root. Re-construct the parent chain using
739
- // instance parent pointers.
740
- const normalizedStack = [];
741
- while (currentVNode) {
742
- const last = normalizedStack[0];
743
- if (last && last.vnode === currentVNode) {
744
- last.recurseCount++;
745
- }
746
721
  else {
747
- normalizedStack.push({
748
- vnode: currentVNode,
749
- recurseCount: 0
750
- });
722
+ const componentName = comp.name || comp.__file || `<Anonymous>`;
723
+ Vue.warn(`Component ${componentName} is missing template or render function.`);
724
+ push(`<!---->`);
751
725
  }
752
- const parentInstance = currentVNode.component && currentVNode.component.parent;
753
- currentVNode = parentInstance && parentInstance.vnode;
754
726
  }
755
- return normalizedStack;
756
- }
757
- /* istanbul ignore next */
758
- function formatTrace(trace) {
759
- const logs = [];
760
- trace.forEach((entry, i) => {
761
- logs.push(...(i === 0 ? [] : [`\n`]), ...formatTraceEntry(entry));
762
- });
763
- return logs;
764
- }
765
- function formatTraceEntry({ vnode, recurseCount }) {
766
- const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``;
767
- const isRoot = vnode.component ? vnode.component.parent == null : false;
768
- const open = ` at <${formatComponentName(vnode.component, vnode.type, isRoot)}`;
769
- const close = `>` + postfix;
770
- return vnode.props
771
- ? [open, ...formatProps(vnode.props), close]
772
- : [open + close];
727
+ return getBuffer();
773
728
  }
774
- /* istanbul ignore next */
775
- function formatProps(props) {
776
- const res = [];
777
- const keys = Object.keys(props);
778
- keys.slice(0, 3).forEach(key => {
779
- res.push(...formatProp(key, props[key]));
780
- });
781
- if (keys.length > 3) {
782
- res.push(` ...`);
729
+ function renderVNode(push, vnode, parentComponent, slotScopeId) {
730
+ const { type, shapeFlag, children } = vnode;
731
+ switch (type) {
732
+ case Vue.Text:
733
+ push(shared.escapeHtml(children));
734
+ break;
735
+ case Vue.Comment:
736
+ push(children ? `<!--${shared.escapeHtmlComment(children)}-->` : `<!---->`);
737
+ break;
738
+ case Vue.Static:
739
+ push(children);
740
+ break;
741
+ case Vue.Fragment:
742
+ if (vnode.slotScopeIds) {
743
+ slotScopeId =
744
+ (slotScopeId ? slotScopeId + ' ' : '') + vnode.slotScopeIds.join(' ');
745
+ }
746
+ push(`<!--[-->`); // open
747
+ renderVNodeChildren(push, children, parentComponent, slotScopeId);
748
+ push(`<!--]-->`); // close
749
+ break;
750
+ default:
751
+ if (shapeFlag & 1 /* ShapeFlags.ELEMENT */) {
752
+ renderElementVNode(push, vnode, parentComponent, slotScopeId);
753
+ }
754
+ else if (shapeFlag & 6 /* ShapeFlags.COMPONENT */) {
755
+ push(renderComponentVNode(vnode, parentComponent, slotScopeId));
756
+ }
757
+ else if (shapeFlag & 64 /* ShapeFlags.TELEPORT */) {
758
+ renderTeleportVNode(push, vnode, parentComponent, slotScopeId);
759
+ }
760
+ else if (shapeFlag & 128 /* ShapeFlags.SUSPENSE */) {
761
+ renderVNode(push, vnode.ssContent, parentComponent, slotScopeId);
762
+ }
763
+ else {
764
+ Vue.warn('[@vue/server-renderer] Invalid VNode type:', type, `(${typeof type})`);
765
+ }
783
766
  }
784
- return res;
785
767
  }
786
- /* istanbul ignore next */
787
- function formatProp(key, value, raw) {
788
- if (shared.isString(value)) {
789
- value = JSON.stringify(value);
790
- return raw ? value : [`${key}=${value}`];
791
- }
792
- else if (typeof value === 'number' ||
793
- typeof value === 'boolean' ||
794
- value == null) {
795
- return raw ? value : [`${key}=${value}`];
768
+ function renderVNodeChildren(push, children, parentComponent, slotScopeId) {
769
+ for (let i = 0; i < children.length; i++) {
770
+ renderVNode(push, normalizeVNode(children[i]), parentComponent, slotScopeId);
796
771
  }
797
- else if (isRef(value)) {
798
- value = formatProp(key, toRaw(value.value), true);
799
- return raw ? value : [`${key}=Ref<`, value, `>`];
772
+ }
773
+ function renderElementVNode(push, vnode, parentComponent, slotScopeId) {
774
+ const tag = vnode.type;
775
+ let { props, children, shapeFlag, scopeId, dirs } = vnode;
776
+ let openTag = `<${tag}`;
777
+ if (dirs) {
778
+ props = applySSRDirectives(vnode, props, dirs);
800
779
  }
801
- else if (shared.isFunction(value)) {
802
- return [`${key}=fn${value.name ? `<${value.name}>` : ``}`];
780
+ if (props) {
781
+ openTag += ssrRenderAttrs(props, tag);
803
782
  }
804
- else {
805
- value = toRaw(value);
806
- return raw ? value : [`${key}=`, value];
783
+ if (scopeId) {
784
+ openTag += ` ${scopeId}`;
807
785
  }
808
- }
809
-
810
- const ErrorTypeStrings = {
811
- ["sp" /* LifecycleHooks.SERVER_PREFETCH */]: 'serverPrefetch hook',
812
- ["bc" /* LifecycleHooks.BEFORE_CREATE */]: 'beforeCreate hook',
813
- ["c" /* LifecycleHooks.CREATED */]: 'created hook',
814
- ["bm" /* LifecycleHooks.BEFORE_MOUNT */]: 'beforeMount hook',
815
- ["m" /* LifecycleHooks.MOUNTED */]: 'mounted hook',
816
- ["bu" /* LifecycleHooks.BEFORE_UPDATE */]: 'beforeUpdate hook',
817
- ["u" /* LifecycleHooks.UPDATED */]: 'updated',
818
- ["bum" /* LifecycleHooks.BEFORE_UNMOUNT */]: 'beforeUnmount hook',
819
- ["um" /* LifecycleHooks.UNMOUNTED */]: 'unmounted hook',
820
- ["a" /* LifecycleHooks.ACTIVATED */]: 'activated hook',
821
- ["da" /* LifecycleHooks.DEACTIVATED */]: 'deactivated hook',
822
- ["ec" /* LifecycleHooks.ERROR_CAPTURED */]: 'errorCaptured hook',
823
- ["rtc" /* LifecycleHooks.RENDER_TRACKED */]: 'renderTracked hook',
824
- ["rtg" /* LifecycleHooks.RENDER_TRIGGERED */]: 'renderTriggered hook',
825
- [0 /* ErrorCodes.SETUP_FUNCTION */]: 'setup function',
826
- [1 /* ErrorCodes.RENDER_FUNCTION */]: 'render function',
827
- [2 /* ErrorCodes.WATCH_GETTER */]: 'watcher getter',
828
- [3 /* ErrorCodes.WATCH_CALLBACK */]: 'watcher callback',
829
- [4 /* ErrorCodes.WATCH_CLEANUP */]: 'watcher cleanup function',
830
- [5 /* ErrorCodes.NATIVE_EVENT_HANDLER */]: 'native event handler',
831
- [6 /* ErrorCodes.COMPONENT_EVENT_HANDLER */]: 'component event handler',
832
- [7 /* ErrorCodes.VNODE_HOOK */]: 'vnode hook',
833
- [8 /* ErrorCodes.DIRECTIVE_HOOK */]: 'directive hook',
834
- [9 /* ErrorCodes.TRANSITION_HOOK */]: 'transition hook',
835
- [10 /* ErrorCodes.APP_ERROR_HANDLER */]: 'app errorHandler',
836
- [11 /* ErrorCodes.APP_WARN_HANDLER */]: 'app warnHandler',
837
- [12 /* ErrorCodes.FUNCTION_REF */]: 'ref function',
838
- [13 /* ErrorCodes.ASYNC_COMPONENT_LOADER */]: 'async component loader',
839
- [14 /* ErrorCodes.SCHEDULER */]: 'scheduler flush. This is likely a Vue internals bug. ' +
840
- 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core'
841
- };
842
- function callWithErrorHandling(fn, instance, type, args) {
843
- let res;
844
- try {
845
- res = args ? fn(...args) : fn();
786
+ // inherit parent chain scope id if this is the root node
787
+ let curParent = parentComponent;
788
+ let curVnode = vnode;
789
+ while (curParent && curVnode === curParent.subTree) {
790
+ curVnode = curParent.vnode;
791
+ if (curVnode.scopeId) {
792
+ openTag += ` ${curVnode.scopeId}`;
793
+ }
794
+ curParent = curParent.parent;
846
795
  }
847
- catch (err) {
848
- handleError(err, instance, type);
796
+ if (slotScopeId) {
797
+ openTag += ` ${slotScopeId}`;
849
798
  }
850
- return res;
851
- }
852
- function handleError(err, instance, type, throwInDev = true) {
853
- const contextVNode = instance ? instance.vnode : null;
854
- if (instance) {
855
- let cur = instance.parent;
856
- // the exposed instance is the render proxy to keep it consistent with 2.x
857
- const exposedInstance = instance.proxy;
858
- // in production the hook receives only the error code
859
- const errorInfo = ErrorTypeStrings[type] ;
860
- while (cur) {
861
- const errorCapturedHooks = cur.ec;
862
- if (errorCapturedHooks) {
863
- for (let i = 0; i < errorCapturedHooks.length; i++) {
864
- if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) {
865
- return;
866
- }
867
- }
799
+ push(openTag + `>`);
800
+ if (!shared.isVoidTag(tag)) {
801
+ let hasChildrenOverride = false;
802
+ if (props) {
803
+ if (props.innerHTML) {
804
+ hasChildrenOverride = true;
805
+ push(props.innerHTML);
806
+ }
807
+ else if (props.textContent) {
808
+ hasChildrenOverride = true;
809
+ push(shared.escapeHtml(props.textContent));
810
+ }
811
+ else if (tag === 'textarea' && props.value) {
812
+ hasChildrenOverride = true;
813
+ push(shared.escapeHtml(props.value));
868
814
  }
869
- cur = cur.parent;
870
815
  }
871
- // app-level handling
872
- const appErrorHandler = instance.appContext.config.errorHandler;
873
- if (appErrorHandler) {
874
- callWithErrorHandling(appErrorHandler, null, 10 /* ErrorCodes.APP_ERROR_HANDLER */, [err, exposedInstance, errorInfo]);
875
- return;
816
+ if (!hasChildrenOverride) {
817
+ if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
818
+ push(shared.escapeHtml(children));
819
+ }
820
+ else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
821
+ renderVNodeChildren(push, children, parentComponent, slotScopeId);
822
+ }
876
823
  }
824
+ push(`</${tag}>`);
877
825
  }
878
- logError(err, type, contextVNode, throwInDev);
879
826
  }
880
- function logError(err, type, contextVNode, throwInDev = true) {
881
- {
882
- const info = ErrorTypeStrings[type];
883
- if (contextVNode) {
884
- pushWarningContext(contextVNode);
827
+ function applySSRDirectives(vnode, rawProps, dirs) {
828
+ const toMerge = [];
829
+ for (let i = 0; i < dirs.length; i++) {
830
+ const binding = dirs[i];
831
+ const { dir: { getSSRProps } } = binding;
832
+ if (getSSRProps) {
833
+ const props = getSSRProps(binding, vnode);
834
+ if (props)
835
+ toMerge.push(props);
885
836
  }
886
- warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`);
887
- if (contextVNode) {
888
- popWarningContext();
837
+ }
838
+ return Vue.mergeProps(rawProps || {}, ...toMerge);
839
+ }
840
+ function renderTeleportVNode(push, vnode, parentComponent, slotScopeId) {
841
+ const target = vnode.props && vnode.props.to;
842
+ const disabled = vnode.props && vnode.props.disabled;
843
+ if (!target) {
844
+ if (!disabled) {
845
+ Vue.warn(`[@vue/server-renderer] Teleport is missing target prop.`);
889
846
  }
890
- // crash in dev by default so it's more noticeable
891
- if (throwInDev) {
892
- throw err;
847
+ return [];
848
+ }
849
+ if (!shared.isString(target)) {
850
+ Vue.warn(`[@vue/server-renderer] Teleport target must be a query selector string.`);
851
+ return [];
852
+ }
853
+ ssrRenderTeleport(push, push => {
854
+ renderVNodeChildren(push, vnode.children, parentComponent, slotScopeId);
855
+ }, target, disabled || disabled === '', parentComponent);
856
+ }
857
+
858
+ const { isVNode: isVNode$1 } = Vue.ssrUtils;
859
+ async function unrollBuffer$1(buffer) {
860
+ if (buffer.hasAsync) {
861
+ let ret = '';
862
+ for (let i = 0; i < buffer.length; i++) {
863
+ let item = buffer[i];
864
+ if (shared.isPromise(item)) {
865
+ item = await item;
866
+ }
867
+ if (shared.isString(item)) {
868
+ ret += item;
869
+ }
870
+ else {
871
+ ret += await unrollBuffer$1(item);
872
+ }
873
+ }
874
+ return ret;
875
+ }
876
+ else {
877
+ // sync buffer can be more efficiently unrolled without unnecessary await
878
+ // ticks
879
+ return unrollBufferSync$1(buffer);
880
+ }
881
+ }
882
+ function unrollBufferSync$1(buffer) {
883
+ let ret = '';
884
+ for (let i = 0; i < buffer.length; i++) {
885
+ let item = buffer[i];
886
+ if (shared.isString(item)) {
887
+ ret += item;
893
888
  }
894
889
  else {
895
- console.error(err);
890
+ // since this is a sync buffer, child buffers are never promises
891
+ ret += unrollBufferSync$1(item);
896
892
  }
897
893
  }
894
+ return ret;
898
895
  }
899
-
900
- const classifyRE = /(?:^|[-_])(\w)/g;
901
- const classify = (str) => str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '');
902
- function getComponentName(Component, includeInferred = true) {
903
- return shared.isFunction(Component)
904
- ? Component.displayName || Component.name
905
- : Component.name || (includeInferred && Component.__name);
906
- }
907
- /* istanbul ignore next */
908
- function formatComponentName(instance, Component, isRoot = false) {
909
- let name = getComponentName(Component);
910
- if (!name && Component.__file) {
911
- const match = Component.__file.match(/([^/\\]+)\.\w+$/);
912
- if (match) {
913
- name = match[1];
896
+ async function renderToString(input, context = {}) {
897
+ if (isVNode$1(input)) {
898
+ // raw vnode, wrap with app (for context)
899
+ return renderToString(Vue.createApp({ render: () => input }), context);
900
+ }
901
+ // rendering an app
902
+ const vnode = Vue.createVNode(input._component, input._props);
903
+ vnode.appContext = input._context;
904
+ // provide the ssr context to the tree
905
+ input.provide(Vue.ssrContextKey, context);
906
+ const buffer = await renderComponentVNode(vnode);
907
+ const result = await unrollBuffer$1(buffer);
908
+ await resolveTeleports(context);
909
+ if (context.__watcherHandles) {
910
+ for (const unwatch of context.__watcherHandles) {
911
+ unwatch();
914
912
  }
915
913
  }
916
- if (!name && instance && instance.parent) {
917
- // try to infer the name based on reverse resolution
918
- const inferFromRegistry = (registry) => {
919
- for (const key in registry) {
920
- if (registry[key] === Component) {
921
- return key;
922
- }
923
- }
924
- };
925
- name =
926
- inferFromRegistry(instance.components ||
927
- instance.parent.type.components) || inferFromRegistry(instance.appContext.components);
914
+ return result;
915
+ }
916
+ async function resolveTeleports(context) {
917
+ if (context.__teleportBuffers) {
918
+ context.teleports = context.teleports || {};
919
+ for (const key in context.__teleportBuffers) {
920
+ // note: it's OK to await sequentially here because the Promises were
921
+ // created eagerly in parallel.
922
+ context.teleports[key] = await unrollBuffer$1(await Promise.all([context.__teleportBuffers[key]]));
923
+ }
928
924
  }
929
- return name ? classify(name) : isRoot ? `App` : `Anonymous`;
930
925
  }
931
926
 
932
- function ssrRenderList(source, renderItem) {
933
- if (shared.isArray(source) || shared.isString(source)) {
934
- for (let i = 0, l = source.length; i < l; i++) {
935
- renderItem(source[i], i);
927
+ const { isVNode } = Vue.ssrUtils;
928
+ async function unrollBuffer(buffer, stream) {
929
+ if (buffer.hasAsync) {
930
+ for (let i = 0; i < buffer.length; i++) {
931
+ let item = buffer[i];
932
+ if (shared.isPromise(item)) {
933
+ item = await item;
934
+ }
935
+ if (shared.isString(item)) {
936
+ stream.push(item);
937
+ }
938
+ else {
939
+ await unrollBuffer(item, stream);
940
+ }
936
941
  }
937
942
  }
938
- else if (typeof source === 'number') {
939
- if (!Number.isInteger(source)) {
940
- warn(`The v-for range expect an integer value but got ${source}.`);
941
- return;
942
- }
943
- for (let i = 0; i < source; i++) {
944
- renderItem(i + 1, i);
945
- }
943
+ else {
944
+ // sync buffer can be more efficiently unrolled without unnecessary await
945
+ // ticks
946
+ unrollBufferSync(buffer, stream);
946
947
  }
947
- else if (shared.isObject(source)) {
948
- if (source[Symbol.iterator]) {
949
- const arr = Array.from(source);
950
- for (let i = 0, l = arr.length; i < l; i++) {
951
- renderItem(arr[i], i);
952
- }
948
+ }
949
+ function unrollBufferSync(buffer, stream) {
950
+ for (let i = 0; i < buffer.length; i++) {
951
+ let item = buffer[i];
952
+ if (shared.isString(item)) {
953
+ stream.push(item);
953
954
  }
954
955
  else {
955
- const keys = Object.keys(source);
956
- for (let i = 0, l = keys.length; i < l; i++) {
957
- const key = keys[i];
958
- renderItem(source[key], key, i);
959
- }
956
+ // since this is a sync buffer, child buffers are never promises
957
+ unrollBufferSync(item, stream);
960
958
  }
961
959
  }
962
960
  }
963
-
964
- async function ssrRenderSuspense(push, { default: renderContent }) {
965
- if (renderContent) {
966
- renderContent();
967
- }
968
- else {
969
- push(`<!---->`);
961
+ function renderToSimpleStream(input, context, stream) {
962
+ if (isVNode(input)) {
963
+ // raw vnode, wrap with app (for context)
964
+ return renderToSimpleStream(Vue.createApp({ render: () => input }), context, stream);
970
965
  }
966
+ // rendering an app
967
+ const vnode = Vue.createVNode(input._component, input._props);
968
+ vnode.appContext = input._context;
969
+ // provide the ssr context to the tree
970
+ input.provide(Vue.ssrContextKey, context);
971
+ Promise.resolve(renderComponentVNode(vnode))
972
+ .then(buffer => unrollBuffer(buffer, stream))
973
+ .then(() => resolveTeleports(context))
974
+ .then(() => {
975
+ if (context.__watcherHandles) {
976
+ for (const unwatch of context.__watcherHandles) {
977
+ unwatch();
978
+ }
979
+ }
980
+ })
981
+ .then(() => stream.push(null))
982
+ .catch(error => {
983
+ stream.destroy(error);
984
+ });
985
+ return stream;
971
986
  }
972
-
973
- function ssrGetDirectiveProps(instance, dir, value, arg, modifiers = {}) {
974
- if (typeof dir !== 'function' && dir.getSSRProps) {
975
- return (dir.getSSRProps({
976
- dir,
977
- instance,
978
- value,
979
- oldValue: undefined,
980
- arg,
981
- modifiers
982
- }, null) || {});
987
+ /**
988
+ * @deprecated
989
+ */
990
+ function renderToStream(input, context = {}) {
991
+ console.warn(`[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`);
992
+ return renderToNodeStream(input, context);
993
+ }
994
+ function renderToNodeStream(input, context = {}) {
995
+ const stream = new (require('stream').Readable)({ read() { } })
996
+ ;
997
+ if (!stream) {
998
+ throw new Error(`ESM build of renderToStream() does not support renderToNodeStream(). ` +
999
+ `Use pipeToNodeWritable() with an existing Node.js Writable stream ` +
1000
+ `instance instead.`);
983
1001
  }
984
- return {};
1002
+ return renderToSimpleStream(input, context, stream);
985
1003
  }
986
-
987
- const ssrLooseEqual = shared.looseEqual;
988
- function ssrLooseContain(arr, value) {
989
- return shared.looseIndexOf(arr, value) > -1;
1004
+ function pipeToNodeWritable(input, context = {}, writable) {
1005
+ renderToSimpleStream(input, context, {
1006
+ push(content) {
1007
+ if (content != null) {
1008
+ writable.write(content);
1009
+ }
1010
+ else {
1011
+ writable.end();
1012
+ }
1013
+ },
1014
+ destroy(err) {
1015
+ writable.destroy(err);
1016
+ }
1017
+ });
990
1018
  }
991
- // for <input :type="type" v-model="model" value="value">
992
- function ssrRenderDynamicModel(type, model, value) {
993
- switch (type) {
994
- case 'radio':
995
- return shared.looseEqual(model, value) ? ' checked' : '';
996
- case 'checkbox':
997
- return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
998
- ? ' checked'
999
- : '';
1000
- default:
1001
- // text types
1002
- return ssrRenderAttr('value', model);
1019
+ function renderToWebStream(input, context = {}) {
1020
+ if (typeof ReadableStream !== 'function') {
1021
+ throw new Error(`ReadableStream constructor is not available in the global scope. ` +
1022
+ `If the target environment does support web streams, consider using ` +
1023
+ `pipeToWebWritable() with an existing WritableStream instance instead.`);
1003
1024
  }
1025
+ const encoder = new TextEncoder();
1026
+ let cancelled = false;
1027
+ return new ReadableStream({
1028
+ start(controller) {
1029
+ renderToSimpleStream(input, context, {
1030
+ push(content) {
1031
+ if (cancelled)
1032
+ return;
1033
+ if (content != null) {
1034
+ controller.enqueue(encoder.encode(content));
1035
+ }
1036
+ else {
1037
+ controller.close();
1038
+ }
1039
+ },
1040
+ destroy(err) {
1041
+ controller.error(err);
1042
+ }
1043
+ });
1044
+ },
1045
+ cancel() {
1046
+ cancelled = true;
1047
+ }
1048
+ });
1004
1049
  }
1005
- // for <input v-bind="obj" v-model="model">
1006
- function ssrGetDynamicModelProps(existingProps = {}, model) {
1007
- const { type, value } = existingProps;
1008
- switch (type) {
1009
- case 'radio':
1010
- return shared.looseEqual(model, value) ? { checked: true } : null;
1011
- case 'checkbox':
1012
- return (shared.isArray(model) ? ssrLooseContain(model, value) : model)
1013
- ? { checked: true }
1014
- : null;
1015
- default:
1016
- // text types
1017
- return { value: model };
1050
+ function pipeToWebWritable(input, context = {}, writable) {
1051
+ const writer = writable.getWriter();
1052
+ const encoder = new TextEncoder();
1053
+ // #4287 CloudFlare workers do not implement `ready` property
1054
+ let hasReady = false;
1055
+ try {
1056
+ hasReady = shared.isPromise(writer.ready);
1018
1057
  }
1058
+ catch (e) { }
1059
+ renderToSimpleStream(input, context, {
1060
+ async push(content) {
1061
+ if (hasReady) {
1062
+ await writer.ready;
1063
+ }
1064
+ if (content != null) {
1065
+ return writer.write(encoder.encode(content));
1066
+ }
1067
+ else {
1068
+ return writer.close();
1069
+ }
1070
+ },
1071
+ destroy(err) {
1072
+ // TODO better error handling?
1073
+ console.log(err);
1074
+ writer.close();
1075
+ }
1076
+ });
1019
1077
  }
1020
1078
 
1021
- vue.initDirectivesForSSR();
1079
+ Vue.initDirectivesForSSR();
1022
1080
 
1023
1081
  exports.ssrIncludeBooleanAttr = shared.includeBooleanAttr;
1024
1082
  exports.pipeToNodeWritable = pipeToNodeWritable;