commit c8a9b2340a5e4a066a18ee11d9773bd47c46d087
parent 66b973dc4f5b7d61b9b6147a350c45286b85c9c2
Author: Denis Palmeiro <dpalmeiro@mozilla.com>
Date: Thu, 13 Nov 2025 04:16:39 +0000
Bug 1995614: Add a test to exercise single digit attribute strings across various element types. r=hsivonen
Differential Revision: https://phabricator.services.mozilla.com/D271245
Diffstat:
2 files changed, 684 insertions(+), 0 deletions(-)
diff --git a/dom/html/test/mochitest.toml b/dom/html/test/mochitest.toml
@@ -800,6 +800,8 @@ skip-if = ["os == 'android'"]
["test_bug1785739.html"]
+["test_bug1995614_atomized_attributes.html"]
+
["test_change_crossorigin.html"]
skip-if = [
"http3",
diff --git a/dom/html/test/test_bug1995614_atomized_attributes.html b/dom/html/test/test_bug1995614_atomized_attributes.html
@@ -0,0 +1,682 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1995614 - Single digit attribute atomization</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1995614">Mozilla Bug 1995614</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function testBasicHTMLElements(container) {
+ let passed = 0;
+
+ // Test 1: HTMLLinkElement with all possible single digit attributes
+ try {
+ container.innerHTML = '<link href="1" rel="2" type="3" media="4" hreflang="5" as="6" crossorigin="7" ' +
+ 'referrerpolicy="8" integrity="9" sizes="0" fetchpriority="1" blocking="2" class="3" id="4" ' +
+ 'title="5" lang="6" dir="7" nonce="8">';
+ ok(true, "HTMLLinkElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLLinkElement crashed: " + e);
+ }
+
+ // Test 2: HTMLSourceElement with all possible single digit attributes
+ try {
+ container.innerHTML = '<picture>' +
+ '<source srcset="2" media="3" src="4" type="5" sizes="6" width="7" height="8" class="9" id="0" ' +
+ 'title="1" lang="2" dir="3">' +
+ '<img src="5"></picture>';
+ ok(true, "HTMLSourceElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLSourceElement crashed: " + e);
+ }
+
+ // Test 3: HTMLInputElement with extensive single digit attributes
+ try {
+ container.innerHTML = '<input type="image" src="6" alt="7" width="8" height="9" ' +
+ 'name="0" value="1" placeholder="2" autocomplete="3" ' +
+ 'maxlength="4" minlength="5" size="6" pattern="7" ' +
+ 'min="8" max="9" step="0" list="1" ' +
+ 'dirname="2" form="3" formaction="4" formmethod="5" formtarget="6" formenctype="7" ' +
+ 'accept="8" multiple="9" readonly="0" disabled="1" required="2" ' +
+ 'inputmode="3" enterkeyhint="4" autocorrect="5" autocapitalize="6" spellcheck="7" ' +
+ 'class="8" id="9" title="0" lang="1" dir="2" tabindex="3" accesskey="4">';
+ ok(true, "HTMLInputElement with extensive single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLInputElement crashed: " + e);
+ }
+
+ // Test 4: HTMLScriptElement with all possible single digit attributes
+ try {
+ container.innerHTML = '<script src="7" type="8" async="9" defer="0" crossorigin="1" ' +
+ 'integrity="2" referrerpolicy="3" nonce="4" nomodule="5" fetchpriority="6" blocking="7" ' +
+ 'class="8" id="9"></' + 'script>';
+ ok(true, "HTMLScriptElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLScriptElement crashed: " + e);
+ }
+
+ // Test 5: HTMLButtonElement with all possible single digit attributes
+ try {
+ container.innerHTML = '<button command="8" commandfor="9" type="0" name="1" value="2" ' +
+ 'form="3" formaction="4" formmethod="5" formtarget="6" formenctype="7" formnovalidate="8" ' +
+ 'popovertarget="9" popovertargetaction="0" disabled="1" autofocus="2" ' +
+ 'class="3" id="4" title="5" tabindex="6" accesskey="7">Test</button>';
+ ok(true, "HTMLButtonElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLButtonElement crashed: " + e);
+ }
+
+ // Test 6: HTMLMediaElement (audio/video) with all possible single digit attributes
+ try {
+ container.innerHTML = '<audio src="1" preload="2" controls="3" autoplay="4" loop="5" muted="6" ' +
+ 'crossorigin="7" volume="8" class="9" id="0"></audio>' +
+ '<video src="1" poster="2" width="3" height="4" preload="5" controls="6" autoplay="7" ' +
+ 'loop="8" muted="9" crossorigin="0" playsinline="1" disablepictureinpicture="2" ' +
+ 'class="3" id="4" title="5"></video>';
+ ok(true, "HTMLMediaElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLMediaElement crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testSpecificAttributes(container) {
+ let passed = 0;
+
+ // Test 7: Elements with nonce attribute
+ try {
+ container.innerHTML = '<div nonce="9">Test</div><script nonce="1"></' + 'script>';
+ ok(true, "Elements with single digit nonce don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Nonce attribute crashed: " + e);
+ }
+
+ // Test 8: class attribute (specifically atomized)
+ try {
+ container.innerHTML = '<div class="1">A</div><span class="2">B</span>';
+ ok(true, "Elements with single digit class don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Class attribute crashed: " + e);
+ }
+
+ // Test 9: type attribute (specifically atomized)
+ try {
+ container.innerHTML = '<input type="3"><button type="4">Test</button>';
+ ok(true, "Elements with single digit type don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Type attribute crashed: " + e);
+ }
+
+ // Test 10: Dynamic attribute setting
+ try {
+ let link = document.createElement("link");
+ link.setAttribute("href", "5");
+ container.appendChild(link);
+ ok(true, "Dynamic setAttribute with single digit doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Dynamic setAttribute crashed: " + e);
+ }
+
+ // Test 11: Event handlers
+ try {
+ let div = document.createElement("div");
+ div.setAttribute("onclick", "console.log('test')");
+ container.appendChild(div);
+ ok(true, "Event handler attribute doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Event handler crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testFormElements(container) {
+ let passed = 0;
+
+ // Test 12: HTMLFontElement with all possible single digit attributes
+ try {
+ container.innerHTML = '<font face="6" size="7" color="8" class="9" id="0" ' +
+ 'title="1" lang="2" dir="3">Test</font>';
+ ok(true, "HTMLFontElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLFontElement crashed: " + e);
+ }
+
+ // Test 12a: HTMLFrameSetElement with all possible single digit attributes
+ try {
+ container.innerHTML = '<frameset rows="1" cols="2" border="3" bordercolor="4" ' +
+ 'frameborder="5" framespacing="6" class="7" id="8">' +
+ '<frame src="9" name="0" scrolling="1" noresize="2" marginwidth="3" marginheight="4" ' +
+ 'frameborder="5" bordercolor="6" longdesc="7">' +
+ '</frameset>';
+ ok(true, "HTMLFrameSetElement with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "HTMLFrameSetElement crashed: " + e);
+ }
+
+ // Test 12b: Textarea with all possible single digit attributes
+ try {
+ container.innerHTML = '<textarea name="8" rows="9" cols="0" wrap="1" maxlength="2" minlength="3" ' +
+ 'placeholder="4" form="5" dirname="6" readonly="7" disabled="8" required="9" ' +
+ 'autocomplete="0" inputmode="1" spellcheck="2" autocorrect="3" autocapitalize="4" ' +
+ 'class="5" id="6" tabindex="7">Text</textarea>';
+ ok(true, "Textarea with all single digit attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Textarea crashed: " + e);
+ }
+
+ // Test 12c: Select and option with all possible attributes
+ try {
+ container.innerHTML = '<select name="8" size="9" form="0" autocomplete="1" multiple="2" ' +
+ 'disabled="3" required="4" autofocus="5" class="6" id="7">' +
+ '<option value="8" selected="9" disabled="0" label="1" class="2">A</option>' +
+ '<option value="3" class="4">B</option>' +
+ '<optgroup label="5" disabled="6" class="7">' +
+ '<option value="8">C</option>' +
+ '</optgroup>' +
+ '</select>';
+ ok(true, "Select/option with all single digit attributes don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Select/option crashed: " + e);
+ }
+
+ // Test 12d: Form elements (label, fieldset, output, progress, meter)
+ try {
+ container.innerHTML = '<form action="9" method="0" name="1" target="2" autocomplete="3" ' +
+ 'enctype="4" accept-charset="5" novalidate="6" class="7" id="8">' +
+ '<label for="9" form="0" class="1">Label</label>' +
+ '<fieldset name="2" form="3" disabled="4" class="5"><legend>6</legend></fieldset>' +
+ '<output name="7" for="8" form="9" class="0">Output</output>' +
+ '<progress value="1" max="2" class="3">4</progress>' +
+ '<meter value="5" min="6" max="7" low="8" high="9" optimum="0" class="1">2</meter>' +
+ '</form>';
+ ok(true, "Form/label/fieldset/output/progress/meter with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Form elements crashed: " + e);
+ }
+
+ // Test 12e: Details and dialog
+ try {
+ container.innerHTML = '<details name="3" open="4" class="5"><summary class="6">7</summary>8</details>' +
+ '<dialog open="9" class="0">1</dialog>';
+ ok(true, "Details/dialog with single digit attributes don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Details/dialog crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testARIAAndDataAttributes(container) {
+ let passed = 0;
+
+ // Test 13: ARIA attributes with single digits
+ try {
+ container.innerHTML = `
+ <div role="1" aria-label="2" aria-describedby="3" aria-labelledby="4" aria-controls="5">A</div>
+ <div aria-hidden="6" aria-live="7" aria-atomic="8" aria-busy="9" aria-disabled="0">B</div>
+ <div aria-checked="1" aria-pressed="2" aria-selected="3" aria-expanded="4" aria-level="5">C</div>
+ <div aria-valuemin="6" aria-valuemax="7" aria-valuenow="8" aria-valuetext="9">D</div>
+ <div aria-colcount="0" aria-colindex="1" aria-colspan="2" aria-rowcount="3" aria-rowindex="4" aria-rowspan="5">E</div>
+ <div aria-posinset="6" aria-setsize="7" aria-owns="8" aria-activedescendant="9">F</div>
+ `;
+ ok(true, "ARIA attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "ARIA attributes crashed: " + e);
+ }
+
+ // Test 14: data-* attributes with single digits
+ try {
+ container.innerHTML = `
+ <div data-id="1" data-value="2" data-index="3" data-count="4" data-level="5">A</div>
+ <div data-priority="6" data-size="7" data-width="8" data-height="9">B</div>
+ <div data-0="0" data-1="1" data-2="2" data-3="3">C</div>
+ `;
+ ok(true, "data-* attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "data-* attributes crashed: " + e);
+ }
+
+ // Test 15: Global attributes with single digits
+ try {
+ container.innerHTML = `
+ <div id="4" title="5" lang="6" dir="7" tabindex="8" accesskey="9">A</div>
+ <div contenteditable="0" spellcheck="1" translate="2" hidden="3" draggable="4">B</div>
+ <div enterkeyhint="5" inputmode="6" autocapitalize="7" autocorrect="8">C</div>
+ `;
+ ok(true, "Global attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Global attributes crashed: " + e);
+ }
+
+ // Test 16: Microdata attributes with single digits
+ try {
+ container.innerHTML = `
+ <div itemscope itemtype="1" itemprop="2" itemid="3" itemref="4">A</div>
+ <div itemprop="5">B</div>
+ `;
+ ok(true, "Microdata attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Microdata attributes crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testResourceAndLayoutAttributes(container) {
+ let passed = 0;
+
+ // Test 17: Form-related attributes with single digits
+ try {
+ container.innerHTML = `
+ <input name="1" value="2" placeholder="3" pattern="4" maxlength="5" minlength="6">
+ <input min="7" max="8" step="9" size="0">
+ <textarea rows="1" cols="2" maxlength="3" minlength="4">5</textarea>
+ <select name="6" size="7"><option value="8">9</option></select>
+ `;
+ ok(true, "Form attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Form attributes crashed: " + e);
+ }
+
+ // Test 18: Resource loading attributes with single digits
+ try {
+ container.innerHTML = '<img loading="1" decoding="2" fetchpriority="3" crossorigin="4" referrerpolicy="5" src="6">' +
+ '<iframe loading="7" src="8"></iframe>' +
+ '<link rel="preload" as="9" href="0" fetchpriority="1">' +
+ '<script blocking="2" src="3"></' + 'script>';
+ ok(true, "Resource loading attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Resource loading attributes crashed: " + e);
+ }
+
+ // Test 19: Table attributes with single digits
+ try {
+ container.innerHTML = `
+ <table border="1" cellpadding="2" cellspacing="3">
+ <tr>
+ <td colspan="4" rowspan="5" width="6" height="7" align="8" valign="9">A</td>
+ </tr>
+ </table>
+ `;
+ ok(true, "Table attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Table attributes crashed: " + e);
+ }
+
+ // Test 20: List attributes with single digits
+ try {
+ container.innerHTML = `
+ <ol type="0" start="1" reversed="2">
+ <li value="3">A</li>
+ <li value="4">B</li>
+ </ol>
+ `;
+ ok(true, "List attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "List attributes crashed: " + e);
+ }
+
+ // Test 21: Link attributes with single digits
+ try {
+ container.innerHTML = `
+ <a href="5" target="6" rel="7" hreflang="8" type="9" download="0" ping="1" referrerpolicy="2">Link</a>
+ <area href="3" alt="4" coords="5" shape="6">
+ `;
+ ok(true, "Link attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Link attributes crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testMediaElements(container) {
+ let passed = 0;
+
+ // Test 22: Media attributes with single digits
+ try {
+ container.innerHTML = '<video width="7" height="8" poster="9" preload="0" controls="1" autoplay="2" loop="3" muted="4">' +
+ '<source src="5" type="6" media="7">' +
+ '<track kind="8" src="9" srclang="0" label="1" default="2">' +
+ '</video>' +
+ '<audio src="3" preload="4" controls="5" autoplay="6" loop="7" muted="8" crossorigin="9"></audio>';
+ ok(true, "Media attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Media attributes crashed: " + e);
+ }
+
+ // Test 22a: Picture element with srcset and sizes
+ try {
+ container.innerHTML = '<picture>' +
+ '<source srcset="1" media="2" type="3" sizes="4" width="5" height="6">' +
+ '<source srcset="7" media="8">' +
+ '<img src="9" srcset="0" sizes="1" alt="2" width="3" height="4">' +
+ '</picture>';
+ ok(true, "Picture/source with srcset/sizes single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Picture element crashed: " + e);
+ }
+
+ // Test 22b: Iframe with various attributes
+ try {
+ container.innerHTML = '<iframe src="5" srcdoc="6" name="7" width="8" height="9" sandbox="0" allow="1" loading="2" referrerpolicy="3"></iframe>';
+ ok(true, "Iframe attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Iframe attributes crashed: " + e);
+ }
+
+ // Test 22c: Embed and object elements
+ try {
+ container.innerHTML = '<embed src="4" type="5" width="6" height="7">' +
+ '<object data="8" type="9" name="0" width="1" height="2" form="3">' +
+ '<param name="4" value="5">' +
+ '</object>';
+ ok(true, "Embed/object attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Embed/object crashed: " + e);
+ }
+
+ // Test 22d: Canvas element
+ try {
+ container.innerHTML = '<canvas width="6" height="7" class="8">9</canvas>';
+ ok(true, "Canvas attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Canvas crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testModernHTMLFeatures(container) {
+ let passed = 0;
+
+ // Test 23: Popover and command attributes with single digits
+ try {
+ container.innerHTML = `
+ <div popover="3" id="p1">Popover</div>
+ <button popovertarget="4" popovertargetaction="5">Toggle</button>
+ <button commandfor="6" command="7">Command</button>
+ `;
+ ok(true, "Popover and command attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Popover/command attributes crashed: " + e);
+ }
+
+ // Test 24: Shadow DOM attributes with single digits
+ try {
+ container.innerHTML = `
+ <div slot="8" part="9">Slotted</div>
+ <template shadowrootmode="0">Shadow</template>
+ `;
+ ok(true, "Shadow DOM attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Shadow DOM attributes crashed: " + e);
+ }
+
+ // Test 25: Deprecated element attributes with single digits
+ try {
+ container.innerHTML = '<marquee behavior="1" direction="2" scrollamount="3" scrolldelay="4" loop="5">Text</marquee>' +
+ '<frameset rows="6" cols="7" border="8"></frameset>';
+ ok(true, "Deprecated element attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Deprecated element attributes crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testSVGElements(container) {
+ let passed = 0;
+
+ // Test 26: SVGAnimationElement with single digit attributes
+ try {
+ container.innerHTML = '<svg><animate href="#t" attributeName="x" from="1" to="2" dur="3s"/></svg>';
+ ok(true, "SVGAnimationElement with single digit href/from/to doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "SVGAnimationElement crashed: " + e);
+ }
+
+ // Test 27: animateMotion with path attribute
+ try {
+ container.innerHTML = '<svg><animateMotion path="M 1 2 L 3 4" dur="5s"/></svg>';
+ ok(true, "animateMotion with path containing digits doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "animateMotion crashed: " + e);
+ }
+
+ // Test 28: animateMotion with values/by attributes
+ try {
+ container.innerHTML = '<svg><animateMotion values="1;2;3" dur="4s"/><animateMotion by="5" dur="6s"/></svg>';
+ ok(true, "animateMotion with values/by containing digits doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "animateMotion values/by crashed: " + e);
+ }
+
+ // Test 29: SVG elements with nonce and event handlers
+ try {
+ container.innerHTML = '<svg><rect nonce="7" onclick="console.log(\'8\')" class="9" width="10" height="10"/></svg>';
+ ok(true, "SVG elements with single digit nonce/onclick/class don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "SVG nonce/onclick/class crashed: " + e);
+ }
+
+ // Test 30: SVG with various single digit attributes
+ try {
+ container.innerHTML = `
+ <svg width="1" height="2" viewBox="3">
+ <rect x="4" y="5" width="6" height="7" fill="8" stroke="9" opacity="0"/>
+ <circle cx="1" cy="2" r="3" class="4"/>
+ <text x="5" y="6" font-size="7">Text</text>
+ <use href="#8" x="9" y="0"/>
+ </svg>
+ `;
+ ok(true, "SVG geometry attributes with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "SVG geometry attributes crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testMathMLElements(container) {
+ let passed = 0;
+
+ // Test 31: MathML elements with width attribute
+ try {
+ container.innerHTML = '<math><mspace width="1" height="2"/></math>';
+ ok(true, "MathML mspace with single digit width/height doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "MathML width/height crashed: " + e);
+ }
+
+ // Test 32: MathML scriptlevel attribute (commonly uses single digits)
+ try {
+ container.innerHTML = `
+ <math>
+ <mstyle scriptlevel="0"><mi>a</mi></mstyle>
+ <mstyle scriptlevel="1"><mi>b</mi></mstyle>
+ <mstyle scriptlevel="2"><mi>c</mi></mstyle>
+ <mstyle scriptlevel="+1"><mi>d</mi></mstyle>
+ <mstyle scriptlevel="-1"><mi>e</mi></mstyle>
+ </math>
+ `;
+ ok(true, "MathML scriptlevel with single digits doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "MathML scriptlevel crashed: " + e);
+ }
+
+ // Test 33: MathML mathsize and mathvariant
+ try {
+ container.innerHTML = `
+ <math>
+ <mstyle mathsize="3"><mi mathvariant="4">x</mi></mstyle>
+ <mi mathvariant="5">y</mi>
+ </math>
+ `;
+ ok(true, "MathML mathsize/mathvariant with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "MathML mathsize/mathvariant crashed: " + e);
+ }
+
+ // Test 34: MathML dir, displaystyle, href
+ try {
+ container.innerHTML = '<math dir="6"><mstyle displaystyle="7"><mtext href="8">Link</mtext></mstyle></math>';
+ ok(true, "MathML dir/displaystyle/href with single digits don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "MathML dir/displaystyle/href crashed: " + e);
+ }
+
+ // Test 35: MathML event handlers, nonce, class
+ try {
+ container.innerHTML = '<math><mi onclick="console.log(\'9\')" nonce="0" class="1">x</mi></math>';
+ ok(true, "MathML elements with onclick/nonce/class don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "MathML onclick/nonce/class crashed: " + e);
+ }
+
+ return passed;
+}
+
+function testDigitCoverage(container) {
+ let passed = 0;
+
+ // Test 36: All single digits 0-9 with class attribute
+ try {
+ container.innerHTML = `
+ <div class="0">0</div>
+ <div class="1">1</div>
+ <div class="2">2</div>
+ <div class="3">3</div>
+ <div class="4">4</div>
+ <div class="5">5</div>
+ <div class="6">6</div>
+ <div class="7">7</div>
+ <div class="8">8</div>
+ <div class="9">9</div>
+ `;
+ ok(true, "All single digits 0-9 as class values don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Digits 0-9 crashed: " + e);
+ }
+
+ // Test 37: All single digits 0-9 with type attribute
+ try {
+ container.innerHTML = '<input type="0">' +
+ '<input type="1">' +
+ '<input type="2">' +
+ '<input type="3">' +
+ '<button type="4">A</button>' +
+ '<button type="5">B</button>' +
+ '<link type="6" href="test">' +
+ '<script type="7"></' + 'script>' +
+ '<style type="8"></style>';
+ ok(true, "All single digits with type attribute don't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Type attribute digits crashed: " + e);
+ }
+
+ // Test 38: Re-parsing via innerHTML (original crash scenario)
+ try {
+ let tempDiv = document.createElement("div");
+ tempDiv.innerHTML = `
+ <link href="1">
+ <source srcset="2">
+ <input type="image" src="3">
+ <svg><animate href="#x" from="4" to="5"/></svg>
+ <math><mstyle scriptlevel="6" mathsize="7"><mi>x</mi></mstyle></math>
+ `;
+ container.appendChild(tempDiv);
+ // eslint-disable-next-line no-self-assign
+ container.innerHTML = container.innerHTML;
+ ok(true, "Re-parsing innerHTML with atomized attributes doesn't crash");
+ passed++;
+ } catch (e) {
+ ok(false, "Re-parsing innerHTML crashed: " + e);
+ }
+
+ return passed;
+}
+
+function runTests() {
+ let container = document.getElementById("content");
+ let testsPassed = 0;
+
+ testsPassed += testBasicHTMLElements(container);
+ testsPassed += testSpecificAttributes(container);
+ testsPassed += testFormElements(container);
+ testsPassed += testARIAAndDataAttributes(container);
+ testsPassed += testResourceAndLayoutAttributes(container);
+ testsPassed += testMediaElements(container);
+ testsPassed += testModernHTMLFeatures(container);
+ testsPassed += testSVGElements(container);
+ testsPassed += testMathMLElements(container);
+ testsPassed += testDigitCoverage(container);
+
+ is(testsPassed, 47, "All 47 atomization tests passed");
+ SimpleTest.finish();
+}
+
+addLoadEvent(runTests);
+
+</script>
+</pre>
+</body>
+</html>