diff --git a/src/constants.js b/src/constants.js
index 7a823a3efd..1ad82b208e 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -31,3 +31,5 @@ export const NULL = null;
export const UNDEFINED = undefined;
export const EMPTY_OBJ = /** @type {any} */ ({});
export const EMPTY_ARR = [];
+
+export const MATHML_TOKEN_ELEMENTS = /(mi|mn|mo|ms$|mte|msp)/;
diff --git a/src/diff/index.js b/src/diff/index.js
index 73c4a01ebb..427d3cf314 100644
--- a/src/diff/index.js
+++ b/src/diff/index.js
@@ -12,7 +12,8 @@ import {
RESET_MODE,
SVG_NAMESPACE,
UNDEFINED,
- XHTML_NAMESPACE
+ XHTML_NAMESPACE,
+ MATHML_TOKEN_ELEMENTS
} from '../constants';
import { BaseComponent, getDomSibling } from '../component';
import { Fragment } from '../create-element';
@@ -608,6 +609,13 @@ function diffElementNodes(
} else {
if (oldHtml) dom.innerHTML = '';
+ if (
+ nodeType == 'foreignObject' ||
+ (namespace == MATH_NAMESPACE && MATHML_TOKEN_ELEMENTS.test(nodeType))
+ ) {
+ namespace = XHTML_NAMESPACE;
+ }
+
diffChildren(
// @ts-expect-error
nodeType == 'template' ? dom.content : dom,
@@ -615,7 +623,7 @@ function diffElementNodes(
newVNode,
oldVNode,
globalContext,
- nodeType == 'foreignObject' ? XHTML_NAMESPACE : namespace,
+ namespace,
excessDomChildren,
commitQueue,
excessDomChildren
diff --git a/test/browser/mathml.test.jsx b/test/browser/mathml.test.jsx
index 79439f4016..0f5f43023e 100644
--- a/test/browser/mathml.test.jsx
+++ b/test/browser/mathml.test.jsx
@@ -2,6 +2,9 @@ import { createElement, Component, render } from 'preact';
import { setupRerender } from 'preact/test-utils';
import { setupScratch, teardown } from '../_util/helpers';
+const XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
+const MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
+
describe('mathml', () => {
let scratch;
@@ -18,7 +21,7 @@ describe('mathml', () => {
let namespace = scratch.querySelector('math').namespaceURI;
- expect(namespace).to.equal('http://www.w3.org/1998/Math/MathML');
+ expect(namespace).to.equal(MATH_NAMESPACE);
});
it('should render children with the correct namespace URI', () => {
@@ -31,12 +34,12 @@ describe('mathml', () => {
let namespace = scratch.querySelector('mrow').namespaceURI;
- expect(namespace).to.equal('http://www.w3.org/1998/Math/MathML');
+ expect(namespace).to.equal(MATH_NAMESPACE);
});
it('should inherit correct namespace URI from parent', () => {
const math = document.createElementNS(
- 'http://www.w3.org/1998/Math/MathML',
+ MATH_NAMESPACE,
'math'
);
scratch.appendChild(math);
@@ -44,14 +47,14 @@ describe('mathml', () => {
render(