From bc8f91d181964e350caea87d960e2897f19b5fe4 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 6 Feb 2020 12:07:25 -0500 Subject: [PATCH] refactor(ssr): prefix ssr helpers --- packages/compiler-core/src/ast.ts | 2 +- packages/compiler-core/src/index.ts | 7 +- .../compiler-core/src/transforms/vSlot.ts | 55 ++++----- packages/compiler-ssr/src/runtimeHelpers.ts | 52 ++++---- ...rpolate.spec.ts => ssrInterpolate.spec.ts} | 12 +- ...erAttrs.spec.ts => ssrRenderAttrs.spec.ts} | 60 ++++----- ...nderList.spec.ts => ssrRenderList.spec.ts} | 0 ...ring.spec.ts => ssrRenderToString.spec.ts} | 6 +- .../__tests__/ssrVModelHelpers.spec.ts | 115 ++++++++++++++++++ .../{interpolate.ts => ssrInterpolate.ts} | 2 +- .../{renderAttrs.ts => ssrRenderAttrs.ts} | 16 +-- .../{renderList.ts => ssrRenderList.ts} | 2 +- .../{renderSlot.ts => ssrRenderSlot.ts} | 2 +- .../{vModelHelpers.ts => ssrVModelHelpers.ts} | 25 ++-- packages/server-renderer/src/index.ts | 30 ++--- .../server-renderer/src/renderToString.ts | 6 +- 16 files changed, 256 insertions(+), 136 deletions(-) rename packages/server-renderer/__tests__/{interpolate.spec.ts => ssrInterpolate.spec.ts} (58%) rename packages/server-renderer/__tests__/{renderAttrs.spec.ts => ssrRenderAttrs.spec.ts} (70%) rename packages/server-renderer/__tests__/{renderList.spec.ts => ssrRenderList.spec.ts} (100%) rename packages/server-renderer/__tests__/{renderToString.spec.ts => ssrRenderToString.spec.ts} (98%) create mode 100644 packages/server-renderer/__tests__/ssrVModelHelpers.spec.ts rename packages/server-renderer/src/helpers/{interpolate.ts => ssrInterpolate.ts} (64%) rename packages/server-renderer/src/helpers/{renderAttrs.ts => ssrRenderAttrs.ts} (84%) rename packages/server-renderer/src/helpers/{renderList.ts => ssrRenderList.ts} (96%) rename packages/server-renderer/src/helpers/{renderSlot.ts => ssrRenderSlot.ts} (96%) rename packages/server-renderer/src/helpers/{vModelHelpers.ts => ssrVModelHelpers.ts} (50%) diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index dca1989a..2123fe82 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -292,7 +292,7 @@ export interface ArrayExpression extends Node { export interface FunctionExpression extends Node { type: NodeTypes.JS_FUNCTION_EXPRESSION - params: ExpressionNode | ExpressionNode[] | undefined + params: ExpressionNode | string | (ExpressionNode | string)[] | undefined returns?: TemplateChildNode | TemplateChildNode[] | JSChildNode body?: BlockStatement newline: boolean diff --git a/packages/compiler-core/src/index.ts b/packages/compiler-core/src/index.ts index 8e0152f5..56c908fe 100644 --- a/packages/compiler-core/src/index.ts +++ b/packages/compiler-core/src/index.ts @@ -41,7 +41,12 @@ export { transformExpression, processExpression } from './transforms/transformExpression' -export { trackVForSlotScopes, trackSlotScopes } from './transforms/vSlot' +export { + buildSlots, + SlotFnBuilder, + trackVForSlotScopes, + trackSlotScopes +} from './transforms/vSlot' export { resolveComponentType, buildProps } from './transforms/transformElement' export { processSlotOutlet } from './transforms/transformSlotOutlet' diff --git a/packages/compiler-core/src/transforms/vSlot.ts b/packages/compiler-core/src/transforms/vSlot.ts index 75481150..053db5b8 100644 --- a/packages/compiler-core/src/transforms/vSlot.ts +++ b/packages/compiler-core/src/transforms/vSlot.ts @@ -93,11 +93,27 @@ export const trackVForSlotScopes: NodeTransform = (node, context) => { } } +export type SlotFnBuilder = ( + slotProps: ExpressionNode | undefined, + slotChildren: TemplateChildNode[], + loc: SourceLocation +) => FunctionExpression + +const buildClientSlotFn: SlotFnBuilder = (props, children, loc) => + createFunctionExpression( + props, + children, + false /* newline */, + true /* isSlot */, + children.length ? children[0].loc : loc + ) + // Instead of being a DirectiveTransform, v-slot processing is called during // transformElement to build the slots object for a component. export function buildSlots( node: ElementNode, - context: TransformContext + context: TransformContext, + buildSlotFn: SlotFnBuilder = buildClientSlotFn ): { slots: ObjectExpression | CallExpression hasDynamicSlots: boolean @@ -106,6 +122,11 @@ export function buildSlots( const slotsProperties: Property[] = [] const dynamicSlots: (ConditionalExpression | CallExpression)[] = [] + const buildDefaultSlotProperty = ( + props: ExpressionNode | undefined, + children: TemplateChildNode[] + ) => createObjectProperty(`default`, buildSlotFn(props, children, loc)) + // If the slot is inside a v-for or another v-slot, force it to be dynamic // since it likely uses a scope variable. let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0 @@ -125,7 +146,7 @@ export function buildSlots( createCompilerError(ErrorCodes.X_V_SLOT_NAMED_SLOT_ON_COMPONENT, loc) ) } - slotsProperties.push(buildDefaultSlot(exp, children, loc)) + slotsProperties.push(buildDefaultSlotProperty(exp, children)) } // 2. Iterate through children and check for template slots @@ -174,14 +195,7 @@ export function buildSlots( hasDynamicSlots = true } - const slotFunction = createFunctionExpression( - slotProps, - slotChildren, - false /* newline */, - true /* isSlot */, - slotChildren.length ? slotChildren[0].loc : slotLoc - ) - + const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc) // check if this slot is conditional (v-if/v-for) let vIf: DirectiveNode | undefined let vElse: DirectiveNode | undefined @@ -280,7 +294,7 @@ export function buildSlots( if (!onComponentDefaultSlot) { if (!hasTemplateSlots) { // implicit default slot (on component) - slotsProperties.push(buildDefaultSlot(undefined, children, loc)) + slotsProperties.push(buildDefaultSlotProperty(undefined, children)) } else if (implicitDefaultChildren.length) { // implicit default slot (mixed with named slots) if (hasNamedDefaultSlot) { @@ -292,7 +306,7 @@ export function buildSlots( ) } else { slotsProperties.push( - buildDefaultSlot(undefined, implicitDefaultChildren, loc) + buildDefaultSlotProperty(undefined, implicitDefaultChildren) ) } } @@ -317,23 +331,6 @@ export function buildSlots( } } -function buildDefaultSlot( - slotProps: ExpressionNode | undefined, - children: TemplateChildNode[], - loc: SourceLocation -): Property { - return createObjectProperty( - `default`, - createFunctionExpression( - slotProps, - children, - false /* newline */, - true /* isSlot */, - children.length ? children[0].loc : loc - ) - ) -} - function buildDynamicSlot( name: ExpressionNode, fn: FunctionExpression diff --git a/packages/compiler-ssr/src/runtimeHelpers.ts b/packages/compiler-ssr/src/runtimeHelpers.ts index 84358609..00865ca6 100644 --- a/packages/compiler-ssr/src/runtimeHelpers.ts +++ b/packages/compiler-ssr/src/runtimeHelpers.ts @@ -1,33 +1,33 @@ import { registerRuntimeHelpers } from '@vue/compiler-dom' -export const SSR_INTERPOLATE = Symbol(`interpolate`) -export const SSR_RENDER_COMPONENT = Symbol(`renderComponent`) -export const SSR_RENDER_SLOT = Symbol(`renderSlot`) -export const SSR_RENDER_CLASS = Symbol(`renderClass`) -export const SSR_RENDER_STYLE = Symbol(`renderStyle`) -export const SSR_RENDER_ATTRS = Symbol(`renderAttrs`) -export const SSR_RENDER_ATTR = Symbol(`renderAttr`) -export const SSR_RENDER_DYNAMIC_ATTR = Symbol(`renderDynamicAttr`) -export const SSR_RENDER_LIST = Symbol(`renderList`) -export const SSR_LOOSE_EQUAL = Symbol(`looseEqual`) -export const SSR_LOOSE_CONTAIN = Symbol(`looseContain`) -export const SSR_RENDER_DYNAMIC_MODEL = Symbol(`renderDynamicModel`) -export const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`getDynamicModelProps`) +export const SSR_INTERPOLATE = Symbol(`ssrInterpolate`) +export const SSR_RENDER_COMPONENT = Symbol(`ssrRenderComponent`) +export const SSR_RENDER_SLOT = Symbol(`ssrRenderSlot`) +export const SSR_RENDER_CLASS = Symbol(`ssrRenderClass`) +export const SSR_RENDER_STYLE = Symbol(`ssrRenderStyle`) +export const SSR_RENDER_ATTRS = Symbol(`ssrRenderAttrs`) +export const SSR_RENDER_ATTR = Symbol(`ssrRenderAttr`) +export const SSR_RENDER_DYNAMIC_ATTR = Symbol(`ssrRenderDynamicAttr`) +export const SSR_RENDER_LIST = Symbol(`ssrRenderList`) +export const SSR_LOOSE_EQUAL = Symbol(`ssrLooseEqual`) +export const SSR_LOOSE_CONTAIN = Symbol(`ssrLooseContain`) +export const SSR_RENDER_DYNAMIC_MODEL = Symbol(`ssrRenderDynamicModel`) +export const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`ssrGetDynamicModelProps`) export const ssrHelpers = { - [SSR_INTERPOLATE]: `_interpolate`, - [SSR_RENDER_COMPONENT]: `_renderComponent`, - [SSR_RENDER_SLOT]: `_renderSlot`, - [SSR_RENDER_CLASS]: `_renderClass`, - [SSR_RENDER_STYLE]: `_renderStyle`, - [SSR_RENDER_ATTRS]: `_renderAttrs`, - [SSR_RENDER_ATTR]: `_renderAttr`, - [SSR_RENDER_DYNAMIC_ATTR]: `_renderDynamicAttr`, - [SSR_RENDER_LIST]: `_renderList`, - [SSR_LOOSE_EQUAL]: `_looseEqual`, - [SSR_LOOSE_CONTAIN]: `_looseContain`, - [SSR_RENDER_DYNAMIC_MODEL]: `_renderDynamicModel`, - [SSR_GET_DYNAMIC_MODEL_PROPS]: `_getDynamicModelProps` + [SSR_INTERPOLATE]: `_ssrInterpolate`, + [SSR_RENDER_COMPONENT]: `_ssrRenderComponent`, + [SSR_RENDER_SLOT]: `_ssrRenderSlot`, + [SSR_RENDER_CLASS]: `_ssrRenderClass`, + [SSR_RENDER_STYLE]: `_ssrRenderStyle`, + [SSR_RENDER_ATTRS]: `_ssrRenderAttrs`, + [SSR_RENDER_ATTR]: `_ssrRenderAttr`, + [SSR_RENDER_DYNAMIC_ATTR]: `_ssrRenderDynamicAttr`, + [SSR_RENDER_LIST]: `_ssrRenderList`, + [SSR_LOOSE_EQUAL]: `_ssrLooseEqual`, + [SSR_LOOSE_CONTAIN]: `_ssrLooseContain`, + [SSR_RENDER_DYNAMIC_MODEL]: `_ssrRenderDynamicModel`, + [SSR_GET_DYNAMIC_MODEL_PROPS]: `_ssrGetDynamicModelProps` } // Note: these are helpers imported from @vue/server-renderer diff --git a/packages/server-renderer/__tests__/interpolate.spec.ts b/packages/server-renderer/__tests__/ssrInterpolate.spec.ts similarity index 58% rename from packages/server-renderer/__tests__/interpolate.spec.ts rename to packages/server-renderer/__tests__/ssrInterpolate.spec.ts index c3a5ae41..fc9a4a3b 100644 --- a/packages/server-renderer/__tests__/interpolate.spec.ts +++ b/packages/server-renderer/__tests__/ssrInterpolate.spec.ts @@ -1,16 +1,16 @@ -import { interpolate } from '../src/helpers/interpolate' +import { ssrInterpolate } from '../src/helpers/ssrInterpolate' import { escapeHtml } from '@vue/shared' test('ssr: interpolate', () => { - expect(interpolate(0)).toBe(`0`) - expect(interpolate(`foo`)).toBe(`foo`) - expect(interpolate(`
`)).toBe(`<div>`) + expect(ssrInterpolate(0)).toBe(`0`) + expect(ssrInterpolate(`foo`)).toBe(`foo`) + expect(ssrInterpolate(`
`)).toBe(`<div>`) // should escape interpolated values - expect(interpolate([1, 2, 3])).toBe( + expect(ssrInterpolate([1, 2, 3])).toBe( escapeHtml(JSON.stringify([1, 2, 3], null, 2)) ) expect( - interpolate({ + ssrInterpolate({ foo: 1, bar: `
` }) diff --git a/packages/server-renderer/__tests__/renderAttrs.spec.ts b/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts similarity index 70% rename from packages/server-renderer/__tests__/renderAttrs.spec.ts rename to packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts index 69d966b6..87521a49 100644 --- a/packages/server-renderer/__tests__/renderAttrs.spec.ts +++ b/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts @@ -1,15 +1,15 @@ import { - renderAttrs, - renderClass, - renderStyle, - renderAttr -} from '../src/helpers/renderAttrs' + ssrRenderAttrs, + ssrRenderClass, + ssrRenderStyle, + ssrRenderAttr +} from '../src/helpers/ssrRenderAttrs' import { escapeHtml } from '@vue/shared' describe('ssr: renderAttrs', () => { test('ignore reserved props', () => { expect( - renderAttrs({ + ssrRenderAttrs({ key: 1, ref: () => {}, onClick: () => {} @@ -19,7 +19,7 @@ describe('ssr: renderAttrs', () => { test('normal attrs', () => { expect( - renderAttrs({ + ssrRenderAttrs({ id: 'foo', title: 'bar' }) @@ -28,7 +28,7 @@ describe('ssr: renderAttrs', () => { test('escape attrs', () => { expect( - renderAttrs({ + ssrRenderAttrs({ id: '"> { test('boolean attrs', () => { expect( - renderAttrs({ + ssrRenderAttrs({ checked: true, multiple: false }) @@ -45,7 +45,7 @@ describe('ssr: renderAttrs', () => { test('ignore falsy values', () => { expect( - renderAttrs({ + ssrRenderAttrs({ foo: false, title: null, baz: undefined @@ -55,7 +55,7 @@ describe('ssr: renderAttrs', () => { test('ingore non-renderable values', () => { expect( - renderAttrs({ + ssrRenderAttrs({ foo: {}, bar: [], baz: () => {} @@ -65,7 +65,7 @@ describe('ssr: renderAttrs', () => { test('props to attrs', () => { expect( - renderAttrs({ + ssrRenderAttrs({ readOnly: true, // simple lower case conversion htmlFor: 'foobar' // special cases }) @@ -74,7 +74,7 @@ describe('ssr: renderAttrs', () => { test('preserve name on custom element', () => { expect( - renderAttrs( + ssrRenderAttrs( { fooBar: 'ok' }, @@ -86,16 +86,16 @@ describe('ssr: renderAttrs', () => { describe('ssr: renderAttr', () => { test('basic', () => { - expect(renderAttr('foo', 'bar')).toBe(` foo="bar"`) + expect(ssrRenderAttr('foo', 'bar')).toBe(` foo="bar"`) }) test('null and undefined', () => { - expect(renderAttr('foo', null)).toBe(``) - expect(renderAttr('foo', undefined)).toBe(``) + expect(ssrRenderAttr('foo', null)).toBe(``) + expect(ssrRenderAttr('foo', undefined)).toBe(``) }) test('escape', () => { - expect(renderAttr('foo', '