Skip to content

Commit 690cc10

Browse files
sto3pslyyx990803
authored andcommitted
fix: guard against missing MathMLElement and better type
1 parent 0c942f0 commit 690cc10

File tree

9 files changed

+40
-14
lines changed

9 files changed

+40
-14
lines changed

packages/runtime-core/src/apiCreateApp.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export interface App<HostElement = any> {
4747
mount(
4848
rootContainer: HostElement | string,
4949
isHydrate?: boolean,
50-
namespace?: ElementNamespace
50+
namespace?: boolean | ElementNamespace
5151
): ComponentPublicInstance
5252
unmount(): void
5353
provide<T>(key: InjectionKey<T> | string, value: T): this
@@ -297,7 +297,7 @@ export function createAppAPI<HostElement>(
297297
mount(
298298
rootContainer: HostElement,
299299
isHydrate?: boolean,
300-
namespace?: 'svg' | 'mathml'
300+
namespace?: boolean | ElementNamespace
301301
): any {
302302
if (!isMounted) {
303303
// #5571
@@ -313,10 +313,24 @@ export function createAppAPI<HostElement>(
313313
// this will be set on the root instance on initial mount.
314314
vnode.appContext = context
315315

316+
if (namespace === true) {
317+
namespace = 'svg'
318+
}
319+
320+
if (namespace === false) {
321+
namespace = undefined
322+
}
323+
316324
// HMR root reload
317325
if (__DEV__) {
318326
context.reload = () => {
319-
render(cloneVNode(vnode), rootContainer, namespace)
327+
// casting to ElementNamespace because TS doesn't guarantee type narrowing
328+
// over function boundaries
329+
render(
330+
cloneVNode(vnode),
331+
rootContainer,
332+
namespace as ElementNamespace
333+
)
320334
}
321335
}
322336

packages/runtime-core/src/compat/global.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,11 @@ function installCompatMount(
505505

506506
let namespace: ElementNamespace
507507
if (container instanceof SVGElement) namespace = 'svg'
508-
else if (container instanceof MathMLElement) namespace = 'mathml'
508+
else if (
509+
typeof MathMLElement === 'function' &&
510+
container instanceof MathMLElement
511+
)
512+
namespace = 'mathml'
509513

510514
// HMR root reload
511515
if (__DEV__) {

packages/runtime-core/src/components/Teleport.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const isTargetSVG = (target: RendererElement): boolean =>
3030
typeof SVGElement !== 'undefined' && target instanceof SVGElement
3131

3232
const isTargetMathML = (target: RendererElement): boolean =>
33-
typeof MathMLElement !== 'undefined' && target instanceof MathMLElement
33+
typeof MathMLElement === 'function' && target instanceof MathMLElement
3434

3535
const resolveTarget = <T = RendererElement>(
3636
props: TeleportProps | null,
@@ -113,7 +113,7 @@ export const TeleportImpl = {
113113
if (target) {
114114
insert(targetAnchor, target)
115115
// #2652 we could be teleporting from a non-SVG tree into an SVG tree
116-
if (namespace === true || namespace === 'svg' || isTargetSVG(target)) {
116+
if (namespace === 'svg' || isTargetSVG(target)) {
117117
namespace = 'svg'
118118
}
119119
if (namespace === 'mathml' || isTargetMathML(target)) {
@@ -155,7 +155,7 @@ export const TeleportImpl = {
155155
const currentContainer = wasDisabled ? container : target
156156
const currentAnchor = wasDisabled ? mainAnchor : targetAnchor
157157

158-
if (namespace === true || namespace === 'svg' || isTargetSVG(target)) {
158+
if (namespace === 'svg' || isTargetSVG(target)) {
159159
namespace = 'svg'
160160
}
161161
if (namespace === 'mathml' || isTargetMathML(target)) {

packages/runtime-core/src/renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export interface HydrationRenderer extends Renderer<Element | ShadowRoot> {
8686
/**
8787
* `boolean` is kept for backwards compatibility with the old `isSVG` attribute.
8888
*/
89-
export type ElementNamespace = boolean | 'svg' | 'mathml' | undefined
89+
export type ElementNamespace = 'svg' | 'mathml' | undefined
9090

9191
export type RootRenderFunction<HostElement = RendererElement> = (
9292
vnode: VNode | null,

packages/runtime-dom/src/index.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,11 @@ export const createApp = ((...args) => {
103103
container.innerHTML = ''
104104
let namespace: ElementNamespace
105105
if (container instanceof SVGElement) namespace = 'svg'
106-
else if (container instanceof MathMLElement) namespace = 'mathml'
106+
else if (
107+
typeof MathMLElement === 'function' &&
108+
container instanceof MathMLElement
109+
)
110+
namespace = 'mathml'
107111
const proxy = mount(container, false, namespace)
108112
if (container instanceof Element) {
109113
container.removeAttribute('v-cloak')
@@ -129,7 +133,11 @@ export const createSSRApp = ((...args) => {
129133
if (container) {
130134
let namespace: ElementNamespace
131135
if (container instanceof SVGElement) namespace = 'svg'
132-
else if (container instanceof MathMLElement) namespace = 'mathml'
136+
else if (
137+
typeof MathMLElement === 'function' &&
138+
container instanceof MathMLElement
139+
)
140+
namespace = 'mathml'
133141
return mount(container, true, namespace)
134142
}
135143
}

packages/runtime-dom/src/modules/attrs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function patchAttr(
2020
namespace?: ElementNamespace,
2121
instance?: ComponentInternalInstance | null
2222
) {
23-
if ((namespace === true || namespace === 'svg') && key.startsWith('xlink:')) {
23+
if (namespace === 'svg' && key.startsWith('xlink:')) {
2424
if (value == null) {
2525
el.removeAttributeNS(xlinkNS, key.slice(6, key.length))
2626
} else {

packages/runtime-dom/src/modules/class.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function patchClass(
1919
}
2020
if (value == null) {
2121
el.removeAttribute('class')
22-
} else if (namespace === 'svg' || namespace === true) {
22+
} else if (namespace === 'svg') {
2323
el.setAttribute('class', value)
2424
} else {
2525
el.className = value

packages/runtime-dom/src/nodeOps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {
9393
}
9494

9595
const template = templateContainer.content
96-
if (namespace === true || namespace === 'svg' || namespace === 'mathml') {
96+
if (namespace === 'svg' || namespace === 'mathml') {
9797
// remove outer svg/math wrapper
9898
const wrapper = template.firstChild!
9999
while (wrapper.firstChild) {

packages/runtime-dom/src/patchProp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function shouldSetAsProp(
7171
value: unknown,
7272
namespace?: ElementNamespace
7373
) {
74-
if (namespace === 'svg' || namespace === true) {
74+
if (namespace === 'svg') {
7575
// most keys must be set as attribute on svg elements to work
7676
// ...except innerHTML & textContent
7777
if (key === 'innerHTML' || key === 'textContent') {

0 commit comments

Comments
 (0)