Repository navigation
Fix rendering of iframes that require dynamic JS (JSXGraph) and are asynchronously rendered via core/template::runTemplateJS() - #1900
Conversation
…ly rendered via core/template::runTemplateJS()
|
Thanks @ngandrass I do appreciate you tracking this down. We will review this. |
|
Updated the branch with current The old run's blocking failures were the PRT "Node 2" visibility check and the Freetext MathJax comparison. Current PHP syntax and diff checks pass. A local browser fixture using Moodle's template renderer and jQuery reproduced corruption with the old encoding and preserved the original arguments in all six patched cases (plain HTML, inline JS and external-script content, each through direct and fragment insertion). This is a transport check, not a full Moodle/JSXGraph integration test. Fresh CI is running; this is not yet an all-green result. |
Hi,
this bug is quite an exotic one so I try to explain it with a lot of context in this PR while I wait for the caffeine to wear off that was required to find this ... 😅 It was found by one of our teachers during Moodle 5 testing but it affects the current Moodle 4.5 (LTS) release alike.
TL;DR: Javascript embedded inside
[[iframe]]blocks fails to load properly if the question is rendered asynchronously viacore/template::runTemplateJS(), e.g., when displaying it inside a modal dialog. This breaks JS logic and thereby also JSXGraph renderings in the question commenting view of the Moodle question bank.How to reproduce
Why the f*ck this breaks ...
Based on the headline you can probably tell that this took me quite some time to figure out ... To put it simple:
stack/cas/castext2/blocks/iframe.block.phpalready does some sanitization of the JS contents.json_encode()leaves<and>fully intact by default, leaving<scriptin there.js_amd_inline()which ultimately ends up incore/template::runTemplateJS()(called by the modalssetBody()method).core/template::runTempalteJS()delegates mounting the content into the DOM to jQuery.<scripttag start and wants to do some optimization by separating plain HTML from script contents.[[javascript]]content fails.This weird behavior is already known to the Moodle core and documented by a respective comment in core/templates::runTemplateJS():
How the fix works
Adding
JSON_HEX_TAGtojson_encode()causes PHP to convert<and>characters to their raw unicode literals (see: https://www.php.net/manual/en/json.constants.php#constant.json-hex-tag). This prevents jQuery from ripping apart the embedded javascript and everything works as expected. Hooray 🎉Validation
I tried the proposed patch on Moodle 4.5 (LTS) and Moodle 5.2. The following examples show how the proposed fix affects different
[[iframe]]scenarios in both direct embedding as well as the asynchronously rendered JS modal of the question commenting view.JSXGraph
Example from: https://docs.stack-assessment.org/en/Specialist_tools/JSXGraph/Basic_plots/
Javascript within iframe
Example from: https://docs.stack-assessment.org/en/Specialist_tools/JSXGraph/Basic_plots/
Plain iframe
Example from: https://docs.stack-assessment.org/en/Authoring/Question_blocks/Iframe_blocks/
Note: This was already working before the fix. It is just to show that normal iframes are unaffected by the changes :)