__TEST__: true,
__VERSION__: require('./package.json').version,
__BROWSER__: false,
- __BUNDLER__: false,
+ __BUNDLER__: true,
__RUNTIME_COMPILE__: true,
__FEATURE_OPTIONS__: true,
__FEATURE_SUSPENSE__: true
--- /dev/null
+// SFC scoped style ID management.
+// These are only used in esm-bundler builds, but since exports cannot be
+// conditional, we can only drop inner implementations in non-bundler builds.
+
+export let currentScopeId: string | null = null
+const scopeIdStack: string[] = []
+
+export function pushScopeId(id: string) {
+ if (__BUNDLER__) {
+ scopeIdStack.push((currentScopeId = id))
+ }
+}
+
+export function popScopeId() {
+ if (__BUNDLER__) {
+ scopeIdStack.pop()
+ currentScopeId = scopeIdStack[scopeIdStack.length - 1] || null
+ }
+}
+
+export function withScopeId(id: string): <T extends Function>(fn: T) => T {
+ if (__BUNDLER__) {
+ return ((fn: Function) => {
+ return function(this: any) {
+ pushScopeId(id)
+ const res = fn.apply(this, arguments)
+ popScopeId()
+ return res
+ }
+ }) as any
+ } else {
+ return undefined as any
+ }
+}
export { toHandlers } from './helpers/toHandlers'
export { renderSlot } from './helpers/renderSlot'
export { createSlots } from './helpers/createSlots'
+export { pushScopeId, popScopeId, withScopeId } from './helpers/scopeId'
export { setBlockTracking, createTextVNode, createCommentVNode } from './vnode'
// Since @vue/shared is inlined into final builds,
// when re-exporting from @vue/shared we need to avoid relying on their original
key: string,
value: any,
oldValue: any,
- isSVG: boolean,
+ isSVG?: boolean,
prevChildren?: VNode<HostNode, HostElement>[],
parentComponent?: ComponentInternalInstance | null,
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
parentNode(node: HostNode): HostElement | null
nextSibling(node: HostNode): HostNode | null
querySelector(selector: string): HostElement | null
+ setScopeId(el: HostNode, id: string): void
}
export type RootRenderFunction<HostNode, HostElement> = (
setElementText: hostSetElementText,
parentNode: hostParentNode,
nextSibling: hostNextSibling,
- querySelector: hostQuerySelector
+ querySelector: hostQuerySelector,
+ setScopeId: hostSetScopeId
} = options
const internals: RendererInternals<HostNode, HostElement> = {
const tag = vnode.type as string
isSVG = isSVG || tag === 'svg'
const el = (vnode.el = hostCreateElement(tag, isSVG))
- const { props, shapeFlag, transition } = vnode
+ const { props, shapeFlag, transition, scopeId } = vnode
+
+ // props
if (props != null) {
for (const key in props) {
if (isReservedProp(key)) continue
invokeDirectiveHook(props.onVnodeBeforeMount, parentComponent, vnode)
}
}
+
+ // scopeId
+ if (__BUNDLER__ && scopeId !== null) {
+ hostSetScopeId(el, scopeId)
+ const treeOwnerId = parentComponent && parentComponent.type.__scopeId
+ // vnode's own scopeId and the current patched component's scopeId is
+ // different - this is a slot content node.
+ if (treeOwnerId != null && treeOwnerId !== scopeId) {
+ hostSetScopeId(el, treeOwnerId + '::slot')
+ }
+ }
+
+ // children
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
hostSetElementText(el, vnode.children as string)
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
import { SuspenseImpl } from './components/Suspense'
import { TransitionHooks } from './components/BaseTransition'
import { warn } from './warning'
+import { currentScopeId } from './helpers/scopeId'
export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
__isFragment: true
props: VNodeProps | null
key: string | number | null
ref: string | Ref | ((ref: object | null) => void) | null
+ scopeId: string | null // SFC only
children: NormalizedChildren<HostNode, HostElement>
component: ComponentInternalInstance | null
suspense: SuspenseBoundary<HostNode, HostElement> | null
props,
key: (props !== null && props.key) || null,
ref: (props !== null && props.ref) || null,
+ scopeId: currentScopeId,
children: null,
component: null,
suspense: null,
: vnode.props,
key: vnode.key,
ref: vnode.ref,
+ scopeId: vnode.scopeId,
children: vnode.children,
target: vnode.target,
shapeFlag: vnode.shapeFlag,
nextSibling: (node: Node): Node | null => node.nextSibling,
querySelector: (selector: string): Element | null =>
- doc.querySelector(selector)
+ doc.querySelector(selector),
+
+ setScopeId(el: Element, id: string) {
+ el.setAttribute(id, '')
+ }
}
throw new Error('querySelector not supported in test renderer.')
}
+function setScopeId(el: TestElement, id: string) {
+ el.props[id] = ''
+}
+
export const nodeOps = {
insert,
remove,
setElementText,
parentNode,
nextSibling,
- querySelector
+ querySelector,
+ setScopeId
}