From 0757db3e56513ab75b370e518857158f893519ad Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Tue, 3 Feb 2026 20:29:31 -0600 Subject: [PATCH] Fix a possible infinite loop in the MathView initializion code. When a MathView element is initialized the `mvInitialized` data attribute is set on the element, and if that attribute is found for the element in the mutation observer code, then the it does not try to reinitialize MathView for the element. However, the code only checks the primary node in the mutations list, and does not also check for this data attribute on any element contained therein. As a result, those elements can be initialized more than once. Now that the problem grader for webwork2 is in a collapse, the element for instructor comments is not initialy visible in the page and is revealed later by the problem grader javascript. This causes the MathView initializer to trigger repeatedly and crashes the page. To test this set the "Assist with student entry process" to "MathView" for a course. Then open a problem when acting as a student. Make sure that a student has answered so that the comment box is available. With the develop branches for both webwork2 and pg, that will crash the page. With the develop branch of webwork2 and this pull request to pg that won't happen. --- htdocs/js/MathView/mathview.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/htdocs/js/MathView/mathview.js b/htdocs/js/MathView/mathview.js index 92e3acb10a..1162363876 100644 --- a/htdocs/js/MathView/mathview.js +++ b/htdocs/js/MathView/mathview.js @@ -410,7 +410,12 @@ if (node.dataset.mvInitialized === 'true') continue; if (node.classList.contains('codeshard')) new MathViewer(node); - else node.querySelectorAll('.codeshard').forEach((input) => new MathViewer(input)); + else { + for (const input of node.querySelectorAll('.codeshard')) { + if (input.dataset.mvInitialized === 'true') continue; + new MathViewer(input); + } + } if (node.classList.contains('latexentryfield')) new MathViewer(node, { renderingMode: 'LATEX', @@ -418,14 +423,14 @@ includeDelimiters: true }); else - node.querySelectorAll('.latexentryfield').forEach( - (input) => - new MathViewer(input, { - renderingMode: 'LATEX', - decoratedTextBoxAsInput: false, - includeDelimiters: true - }) - ); + for (const input of node.querySelectorAll('.latexentryfield')) { + if (input.dataset.mvInitialized === 'true') continue; + new MathViewer(input, { + renderingMode: 'LATEX', + decoratedTextBoxAsInput: false, + includeDelimiters: true + }); + } } } }