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