`;
exports[`scopeId compiler support should wrap default slot 1`] = `
-"import { createVNode as _createVNode, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
+"import { createVNode as _createVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
const _withId = _withScopeId(\\"test\\")
export const render = _withId(function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_component_Child, null, {
default: _withId(() => [
_createVNode(\\"div\\")
- ]),
+ ], _ctx),
_: 1
}))
})"
`;
exports[`scopeId compiler support should wrap dynamic slots 1`] = `
-"import { createVNode as _createVNode, resolveComponent as _resolveComponent, renderList as _renderList, createSlots as _createSlots, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
+"import { createVNode as _createVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, renderList as _renderList, createSlots as _createSlots, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
const _withId = _withScopeId(\\"test\\")
export const render = _withId(function render(_ctx, _cache) {
name: \\"foo\\",
fn: _withId(() => [
_createVNode(\\"div\\")
- ])
+ ], _ctx)
}
: undefined,
_renderList(_ctx.list, (i) => {
name: i,
fn: _withId(() => [
_createVNode(\\"div\\")
- ])
+ ], _ctx)
}
})
]), 1024 /* DYNAMIC_SLOTS */))
`;
exports[`scopeId compiler support should wrap named slots 1`] = `
-"import { toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, createVNode as _createVNode, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
+"import { toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, createVNode as _createVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock, withScopeId as _withScopeId } from \\"vue\\"
const _withId = _withScopeId(\\"test\\")
export const render = _withId(function render(_ctx, _cache) {
return (_openBlock(), _createBlock(_component_Child, null, {
foo: _withId(({ msg }) => [
_createTextVNode(_toDisplayString(msg), 1 /* TEXT */)
- ]),
+ ], _ctx),
bar: _withId(() => [
_createVNode(\\"div\\")
- ]),
+ ], _ctx),
_: 1
}))
})"
return function render(_ctx, _cache) {
with (_ctx) {
- const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- default: ({ foo }) => [
+ default: _withCtx(({ foo }) => [
_createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)
- ],
+ ], _ctx),
_: 1
}))
}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`compiler: transform component slots dynamically named slots 1`] = `
-"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- [_ctx.one]: ({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)],
- [_ctx.two]: ({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)],
+ [_ctx.one]: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)], _ctx),
+ [_ctx.two]: _withCtx(({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)], _ctx),
_: 1
}, 1024 /* DYNAMIC_SLOTS */))
}"
`;
exports[`compiler: transform component slots implicit default slot 1`] = `
-"const { createVNode: _createVNode, resolveComponent: _resolveComponent, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { createVNode: _createVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- default: () => [
+ default: _withCtx(() => [
_createVNode(\\"div\\")
- ],
+ ], _ctx),
_: 1
}))
}"
`;
exports[`compiler: transform component slots named slot with v-for w/ prefixIdentifiers: true 1`] = `
-"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, renderList: _renderList, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, renderList: _renderList, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent(\\"Comp\\")
_renderList(_ctx.list, (name) => {
return {
name: name,
- fn: () => [_toDisplayString(name)]
+ fn: _withCtx(() => [_toDisplayString(name)], _ctx)
}
})
]), 1024 /* DYNAMIC_SLOTS */))
`;
exports[`compiler: transform component slots named slot with v-if + prefixIdentifiers: true 1`] = `
-"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent(\\"Comp\\")
(_ctx.ok)
? {
name: \\"one\\",
- fn: (props) => [_toDisplayString(props)]
+ fn: _withCtx((props) => [_toDisplayString(props)], _ctx)
}
: undefined
]), 1024 /* DYNAMIC_SLOTS */))
return function render(_ctx, _cache) {
with (_ctx) {
- const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
ok
? {
name: \\"one\\",
- fn: () => [\\"foo\\"]
+ fn: _withCtx(() => [\\"foo\\"], _ctx)
}
: orNot
? {
name: \\"two\\",
- fn: (props) => [\\"bar\\"]
+ fn: _withCtx((props) => [\\"bar\\"], _ctx)
}
: {
name: \\"one\\",
- fn: () => [\\"baz\\"]
+ fn: _withCtx(() => [\\"baz\\"], _ctx)
}
]), 1024 /* DYNAMIC_SLOTS */))
}
return function render(_ctx, _cache) {
with (_ctx) {
- const { resolveComponent: _resolveComponent, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
ok
? {
name: \\"one\\",
- fn: () => [\\"hello\\"]
+ fn: _withCtx(() => [\\"hello\\"], _ctx)
}
: undefined
]), 1024 /* DYNAMIC_SLOTS */))
`;
exports[`compiler: transform component slots named slots 1`] = `
-"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- one: ({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)],
- two: ({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)],
+ one: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)], _ctx),
+ two: _withCtx(({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)], _ctx),
_: 1
}))
}"
return function render(_ctx, _cache) {
with (_ctx) {
- const { createVNode: _createVNode, resolveComponent: _resolveComponent, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+ const { createVNode: _createVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- one: () => [\\"foo\\"],
- default: () => [
+ one: _withCtx(() => [\\"foo\\"], _ctx),
+ default: _withCtx(() => [
\\"bar\\",
_createVNode(\\"span\\")
- ],
+ ], _ctx),
_: 1
}))
}
`;
exports[`compiler: transform component slots nested slots scoping 1`] = `
-"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Inner = _resolveComponent(\\"Inner\\")
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- default: ({ foo }) => [
+ default: _withCtx(({ foo }) => [
_createVNode(_component_Inner, null, {
- default: ({ bar }) => [_toDisplayString(foo), _toDisplayString(bar), _toDisplayString(_ctx.baz)],
+ default: _withCtx(({ bar }) => [_toDisplayString(foo), _toDisplayString(bar), _toDisplayString(_ctx.baz)], _ctx),
_: 1
}, 1024 /* DYNAMIC_SLOTS */),
\\" \\",
_toDisplayString(foo),
_toDisplayString(_ctx.bar),
_toDisplayString(_ctx.baz)
- ],
+ ], _ctx),
_: 1
}))
}"
`;
exports[`compiler: transform component slots on-component default slot 1`] = `
-"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
+"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
return function render(_ctx, _cache) {
const _component_Comp = _resolveComponent(\\"Comp\\")
return (_openBlock(), _createBlock(_component_Comp, null, {
- default: ({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)],
+ default: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)], _ctx),
_: 1
}))
}"
if (genScopeId) {
push(`_withId(`)
+ } else if (isSlot) {
+ push(`_withCtx(`)
}
push(`(`, node)
if (isArray(params)) {
deindent()
push(`}`)
}
- if (genScopeId) {
- push(`)`)
+ if (genScopeId || isSlot) {
+ push(`, _ctx)`)
}
}
export const PUSH_SCOPE_ID = Symbol(__DEV__ ? `pushScopeId` : ``)
export const POP_SCOPE_ID = Symbol(__DEV__ ? `popScopeId` : ``)
export const WITH_SCOPE_ID = Symbol(__DEV__ ? `withScopeId` : ``)
+export const WITH_CTX = Symbol(__DEV__ ? `withCtx` : ``)
// Name mapping for runtime helpers that need to be imported from 'vue' in
// generated code. Make sure these are correctly exported in the runtime!
[SET_BLOCK_TRACKING]: `setBlockTracking`,
[PUSH_SCOPE_ID]: `pushScopeId`,
[POP_SCOPE_ID]: `popScopeId`,
- [WITH_SCOPE_ID]: `withScopeId`
+ [WITH_SCOPE_ID]: `withScopeId`,
+ [WITH_CTX]: `withCtx`
}
export function registerRuntimeHelpers(helpers: any) {
import { TransformContext, NodeTransform } from '../transform'
import { createCompilerError, ErrorCodes } from '../errors'
import { findDir, isTemplateNode, assert, isVSlot, hasScopeRef } from '../utils'
-import { CREATE_SLOTS, RENDER_LIST } from '../runtimeHelpers'
+import { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers'
import { parseForExpression, createForLoopParams } from './vFor'
const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
slots: SlotsExpression
hasDynamicSlots: boolean
} {
+ context.helper(WITH_CTX)
+
const { children, loc } = node
const slotsProperties: Property[] = []
const dynamicSlots: (ConditionalExpression | CallExpression)[] = []
describe('ssr: components', () => {
test('basic', () => {
expect(compile(`<foo id="a" :prop="b" />`).code).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
test('dynamic component', () => {
expect(compile(`<component is="foo" prop="b" />`).code)
.toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
expect(compile(`<component :is="foo" prop="b" />`).code)
.toMatchInlineSnapshot(`
- "const { resolveDynamicComponent: _resolveDynamicComponent } = require(\\"vue\\")
+ "const { resolveDynamicComponent: _resolveDynamicComponent, withCtx: _withCtx } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
describe('slots', () => {
test('implicit default slot', () => {
expect(compile(`<foo>hello<div/></foo>`).code).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, createVNode: _createVNode, createTextVNode: _createTextVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, createTextVNode: _createTextVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_foo = _resolveComponent(\\"foo\\")
_push(_ssrRenderComponent(_component_foo, null, {
- default: (_, _push, _parent, _scopeId) => {
+ default: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`hello<div\${_scopeId}></div>\`)
} else {
_createVNode(\\"div\\")
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
test('explicit default slot', () => {
expect(compile(`<foo v-slot="{ msg }">{{ msg + outer }}</foo>`).code)
.toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_foo = _resolveComponent(\\"foo\\")
_push(_ssrRenderComponent(_component_foo, null, {
- default: ({ msg }, _push, _parent, _scopeId) => {
+ default: _withCtx(({ msg }, _push, _parent, _scopeId) => {
if (_push) {
_push(\`\${_ssrInterpolate(msg + _ctx.outer)}\`)
} else {
_createTextVNode(_toDisplayString(msg + _ctx.outer), 1 /* TEXT */)
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
<template v-slot:named>bar</template>
</foo>`).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_foo = _resolveComponent(\\"foo\\")
_push(_ssrRenderComponent(_component_foo, null, {
- default: (_, _push, _parent, _scopeId) => {
+ default: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`foo\`)
} else {
_createTextVNode(\\"foo\\")
]
}
- },
- named: (_, _push, _parent, _scopeId) => {
+ }, _ctx),
+ named: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`bar\`)
} else {
_createTextVNode(\\"bar\\")
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
<template v-slot:named v-if="ok">foo</template>
</foo>`).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, createTextVNode: _createTextVNode, createSlots: _createSlots } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode, createSlots: _createSlots } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
(_ctx.ok)
? {
name: \\"named\\",
- fn: (_, _push, _parent, _scopeId) => {
+ fn: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`foo\`)
} else {
_createTextVNode(\\"foo\\")
]
}
- }
+ }, _ctx)
}
: undefined
]), _parent))
<template v-for="key in names" v-slot:[key]="{ msg }">{{ msg + key + bar }}</template>
</foo>`).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, renderList: _renderList, createSlots: _createSlots } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, renderList: _renderList, createSlots: _createSlots } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
_renderList(_ctx.names, (key) => {
return {
name: key,
- fn: ({ msg }, _push, _parent, _scopeId) => {
+ fn: _withCtx(({ msg }, _push, _parent, _scopeId) => {
if (_push) {
_push(\`\${_ssrInterpolate(msg + key + _ctx.bar)}\`)
} else {
_createTextVNode(_toDisplayString(msg + _ctx.key + _ctx.bar), 1 /* TEXT */)
]
}
- }
+ }, _ctx)
}
})
]), _parent))
</template>
</foo>`).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode, createCommentVNode: _createCommentVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode, createCommentVNode: _createCommentVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderList: _ssrRenderList } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_foo = _resolveComponent(\\"foo\\")
_push(_ssrRenderComponent(_component_foo, null, {
- foo: ({ list }, _push, _parent, _scopeId) => {
+ foo: _withCtx(({ list }, _push, _parent, _scopeId) => {
if (_push) {
if (_ctx.ok) {
_push(\`<div\${_scopeId}><!--[-->\`)
: _createCommentVNode(\\"v-if\\", true)
]
}
- },
- bar: ({ ok }, _push, _parent, _scopeId) => {
+ }, _ctx),
+ bar: _withCtx(({ ok }, _push, _parent, _scopeId) => {
if (_push) {
if (ok) {
_push(\`<div\${_scopeId}><!--[-->\`)
: _createCommentVNode(\\"v-if\\", true)
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
expect(compile(`<keep-alive><foo/></keep-alive>`).code)
.toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
scopeId
}).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, createTextVNode: _createTextVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_foo = _resolveComponent(\\"foo\\")
_push(_ssrRenderComponent(_component_foo, null, {
- default: (_, _push, _parent, _scopeId) => {
+ default: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`foo\`)
} else {
_createTextVNode(\\"foo\\")
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
scopeId
}).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, createVNode: _createVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_foo = _resolveComponent(\\"foo\\")
_push(_ssrRenderComponent(_component_foo, null, {
- default: (_, _push, _parent, _scopeId) => {
+ default: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`<span data-v-xxxxxxx\${_scopeId}>hello</span>\`)
} else {
_createVNode(\\"span\\", null, \\"hello\\")
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
scopeId
}).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent, createVNode: _createVNode } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
const _component_bar = _resolveComponent(\\"bar\\")
_push(_ssrRenderComponent(_component_foo, null, {
- default: (_, _push, _parent, _scopeId) => {
+ default: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`<span data-v-xxxxxxx\${_scopeId}>hello</span>\`)
_push(_ssrRenderComponent(_component_bar, null, {
- default: (_, _push, _parent, _scopeId) => {
+ default: _withCtx((_, _push, _parent, _scopeId) => {
if (_push) {
_push(\`<span data-v-xxxxxxx\${_scopeId}></span>\`)
} else {
_createVNode(\\"span\\")
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
} else {
return [
_createVNode(\\"span\\", null, \\"hello\\"),
_createVNode(_component_bar, null, {
- default: () => [
+ default: _withCtx(() => [
_createVNode(\\"span\\")
- ],
+ ], _ctx),
_: 1
})
]
}
- },
+ }, _ctx),
_: 1
}, _parent))
}"
describe('ssr compile: suspense', () => {
test('implicit default', () => {
expect(compile(`<suspense><foo/></suspense>`).code).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
</template>
</suspense>`).code
).toMatchInlineSnapshot(`
- "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
+ "const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\\"vue\\")
const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\\"@vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent) {
// resolveComponent, resolveDirective) during render
export let currentRenderingInstance: ComponentInternalInstance | null = null
-// exposed for server-renderer only
export function setCurrentRenderingInstance(
instance: ComponentInternalInstance | null
) {
// These are only used in esm-bundler builds, but since exports cannot be
// conditional, we can only drop inner implementations in non-bundler builds.
+import { ComponentInternalInstance } from '../component'
+import { withCtx } from './withRenderContext'
+
export let currentScopeId: string | null = null
const scopeIdStack: string[] = []
export function withScopeId(id: string): <T extends Function>(fn: T) => T {
if (__BUNDLER__) {
- return ((fn: Function) => {
- return function(this: any) {
+ return ((fn: Function, ctx?: ComponentInternalInstance) => {
+ function renderWithId(this: any) {
pushScopeId(id)
const res = fn.apply(this, arguments)
popScopeId()
return res
}
+ return ctx ? withCtx(renderWithId, ctx) : renderWithId
}) as any
} else {
return undefined as any
--- /dev/null
+import { Slot } from '../componentSlots'
+import { ComponentInternalInstance } from '../component'
+import {
+ setCurrentRenderingInstance,
+ currentRenderingInstance
+} from '../componentRenderUtils'
+
+export function withCtx(fn: Slot, ctx: ComponentInternalInstance) {
+ return function renderFnWithContext() {
+ const owner = currentRenderingInstance
+ setCurrentRenderingInstance(ctx)
+ const res = fn.apply(null, arguments)
+ setCurrentRenderingInstance(owner)
+ return res
+ }
+}
// For compiler generated code
// should sync with '@vue/compiler-core/src/runtimeConstants.ts'
+export { withCtx } from './helpers/withRenderContext'
export { withDirectives } from './directives'
export {
resolveComponent,