From 8fe80e743cad96ae6abfe97838efc2e26c6787f4 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 24 Mar 2023 21:27:36 +0800 Subject: [PATCH] MDL-77740 editor_tiny: Set the Editor window from the iFrame element This is a workaround for an upstream bug which I have not been able to reproduce outside of Moodle whereby the editor.contentWindow does not match the editor.iframeElement.contentWindow when it should. This issue only seems to affect Firefox, and it may even be a bug in Firefox. It can only be reproduced when using a fresh browser which has never had a TinyMCE window open. --- lib/editor/tiny/amd/build/editor.min.js | Bin 7353 -> 7481 bytes lib/editor/tiny/amd/build/editor.min.js.map | Bin 20547 -> 21358 bytes lib/editor/tiny/amd/build/utils.min.js | Bin 5012 -> 4873 bytes lib/editor/tiny/amd/build/utils.min.js.map | Bin 14953 -> 14856 bytes lib/editor/tiny/amd/src/editor.js | 29 ++++++++++++++------ lib/editor/tiny/amd/src/utils.js | 3 +- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/editor/tiny/amd/build/editor.min.js b/lib/editor/tiny/amd/build/editor.min.js index 633a127d1c5c994eec15d8433d2608bd075eb48a..ec662ee42097a4a10158c85d8192c591637fdd20 100644 GIT binary patch delta 241 zcmdmKxzlQco}gDiQL1NNW{HxHMp|iJa!F=>o`z<1Nk(R|UUGh3Norn6cxGNoez`4J zC^M}nF*nsUCp8x+fvTWZbF-r02ljgFlFYnHUuRdn^wbg!O}(_toRZWc4UN>4%#!>f zTRTMv10)MI2B;{r*f~EhFEzO&HANGsCBMiuF*yUFry8oKC^a{~ELB6ZR#Vd&=(yq% ih1817VxWELt`O6K%*iT}?mWnbPhKdwV{?&|I}-p@epr+M delta 106 zcmdmKwbOEgp5W$I!N=^3I+L$TMw*o*7Nw__xaQ>QCFkT9rxurJC?(~mR4Qp|R%fPZ pq*i1Wmt^LpyQXB8YlwYZ_`Gb@v698>TD2M<6 diff --git a/lib/editor/tiny/amd/build/editor.min.js.map b/lib/editor/tiny/amd/build/editor.min.js.map index f52ed8c8056b2d427c1df0afba715a916a5bc024..0696a47ae25659fed293f34029a890086b7eda53 100644 GIT binary patch delta 2027 zcmaJ=L2nyH6jo3X6eK93(5SRx+E8MvBRfr+#wkjrnc1=B+K%nmmPv&aHtVr>6KB@h zUE6UgWbqs34{!pGNI7xl#sv<*i6a-J3ULA?F1(qwlQ@d-VZA%=z3;v6d*6Kb#oQlX z&VBRK!j(!O^6KY>#c|UQ_K_X)MWJ#Ym9nwSe8+NZ-=4R(ZG>!YNvE%7}?Shs4MIiAnP!Y+^p^Jt*!Fb zPGggQT;Z(FEhK_K>m#SLPvjh*mlX7@yU|D-M9;Y|2NPtXjQyLw)l(BlMYmIURQsOaRk4`$$Wr=M_g@2*Y)z#u~bwz&_YDM!rv~WlXbFE1IP?*1V$gxdIoPnUgsLRyfg@w7k zdawBF+^YJgh{lh&?y>}01M}KC*BUaJz0W6o(i(u+kfznIXq*m>EXZaN4`Wf8(HllH z!5Rkn@?CZuAI}D1H!y2;iDFGSL*H^WFkiDmOA~GIp8Bd(n+w&yrJMKCOeZ%iv+^#5 z#9WUS49$*(eEZTONWNgO`W*hotY>9o_7Gyvw4;eICmxl$in**~ zz=X^K54N>w5KHDc%<7%-0WF%kIHPWwEN2Y~yv#|VOQn(6qgk_@KArBLV1C{Jg5>u& zC~agGV(bpF~wekb?XZgk(%lh8t+wGW|dZ&{5556^OO8@`> delta 1316 zcmZ`&%W@Jy6fM++x^ZKfDj#KDhNRL)2q8qn!rMJP1Az&d5KLiZLneebLtro=F7O|E zf9D8#5!#W2(Naqd0m%#Zhhi+6#KU*-lg3-hYuFCQBV)3lf@hi=eJgWF!du3d#K5gDt zUpJSPynatj#qX-e_@nn~+*Q5cEftR6nYvVbgkWv2w>bD5w{HxhW+I^8S__ZHJ!jeM zXe4}+?Y7s(|51^;ux187t?$>=Rr{If36_V5xwpjx;Khm{_EIbdkWaG=K*pw%CKt>F zDDjrTvH;mUy}4|egNTWadSg%ZduEke)Fbfldcw~I&U@GD4 z4|`c4qVjiCm#kt*<)0-ESTSQV+x#CwMZ>ZJK!G7f-JGoYt4JMeKj>e|*uW0nAMPBtE+!peFIf zzKLf=TKoxDS2A+}Pc3A=_0K5=1&dla3F53_um%D~IOs@-x%A@%hABE@PY-ZvG8@2VCzAF_>$pvnq^i87 ziLG!`OVZ_IlgLSv6d_rahqP3QmvPcrG%sNt%V0MbGGUIJ(kH$uSqQxX=$X+gZO{_8?Sb1N@huZkzRUgiEB=3ZfahMhNfO-v2%W2UTShlYKlEX-YTy&CuegG Hp9U)cU9}X; delta 196 zcmeBFo1(s98*hDeSz?hwd}>N&Nq&(^Nn%lYYKd!3u60prNoi4@LSAW3j-o9@R!t4U zv(>;*4ppHC*RQFjR+gWcqF|tCYm1>;O${Mr4z*A(IVZn3wYWq>DJegtQc2SuVyBe` Zgw{&|$`$2TYG~?!9HCje`5~_cD**0YM~?si diff --git a/lib/editor/tiny/amd/build/utils.min.js.map b/lib/editor/tiny/amd/build/utils.min.js.map index 8739dc5bec533ddccc08f21574adcef7c45522df..2523ae174d4fed590434003a552625073298fa4b 100644 GIT binary patch delta 376 zcmYk1%}N4M7>0Lc%P`P360^zROYKh`A>uvX8OFgx1`%_Y*c9scM^i@7s!fY%b7&V` zgWv_U=nA@wmfb;T#-dh-bDsA+-}`+A55bI6>zNBLuzYXe4TJPnrhCbw;n3>@-kF*i zYxAen$!hX1VUY1JF;C>~m$qG0_XMa0)CQ8;K%1!r#}{L%AIlE)8J&qB2Dq-i@-ML| zlMA>z>bda#cR4L?Cia;o0+z{44WM-$8c>_6*J5&|z*N^-*;Q}Fjr1>)WCM1HP`9Zs zz~{cydWIgz&Oj}jrONGsm$l6*=&lu@vdht7hgBNK(a*7Ps0lO=7D#HT-4l7H9K)+d u3-r{Zc^Dgo6X5#l!_3C7M7Xp^4&ZRq_eRA_M~R;hhqR-qm6c;Q?!Ey5Z*k55 delta 458 zcmYjMPfG$(5T{GnF+A8wL;@8DSFv>05SceC+h!srB0(gkTbQo9?ke#2Kx9j$24sV$G{dvE6@IJj4idSkmZ{S=RUVUoTa>J?R8m^a4U09<4ady5KTtV7F+Q&mdsH_KRQGZ#Fnc<7YV^49L^aC4V8&MmYyQ{wPv61 zmEZn`uW~9T6U-Ub6(XU<)1?|X<#|=!*^&r4s83aspUa8#52S*IsQD0fG(Qqu+I|Z0 zF(K)5{w!BEiu^;4mP-T;#D?Yv?j8qRo9WO)>?vzV6*k&6%M#=Xjb@N}#!~e^qL+kVHN@6lh&iJxbnv0}`Bx@c;k- diff --git a/lib/editor/tiny/amd/src/editor.js b/lib/editor/tiny/amd/src/editor.js index 6a68ec727d6..7c07215fe1f 100644 --- a/lib/editor/tiny/amd/src/editor.js +++ b/lib/editor/tiny/amd/src/editor.js @@ -267,6 +267,14 @@ const getStandardConfig = (target, tinyMCE, options, plugins) => { setup: (editor) => { Options.register(editor, options); + editor.on('PreInit', function() { + // Work around a bug in TinyMCE with Firefox. + // When an editor is removed, and replaced with an identically attributed editor (same ID), + // and the Firefox window is freshly opened (e.g. Behat, Private browsing), the wrong contentWindow + // is assigned to the editor instance leading to an NS_ERROR_UNEXPECTED error in Firefox. + // This is a workaround for that issue. + this.contentWindow = this.iframeElement.contentWindow; + }); editor.on('init', function() { // Hide justify alignment sub-menu. removeSubmenuItem(editor, 'align', 'tiny:justify'); @@ -390,18 +398,21 @@ export const setupForTarget = async(target, options = {}) => { // we need to manually destroy the editor. // We could theoretically do this with a Mutation Observer, but in some cases the Node may be moved, // or added back elsewhere in the DOM. + + // First remove any detached editors. + tinyMCE.get().filter((editor) => !editor.getElement().isConnected).forEach((editor) => { + editor.remove(); + }); + + // Now check for any existing editor which shares the same ID. const existingEditor = tinyMCE.EditorManager.get(target.id); if (existingEditor) { - if (existingEditor.targetElm.closest('body')) { - if (existingEditor.targetElm === target) { - pendingPromise.resolve(); - return Promise.resolve(existingEditor); - } else { - pendingPromise.resolve(); - throw new Error('TinyMCE instance already exists for different target with same ID'); - } + if (existingEditor.getElement() === target) { + pendingPromise.resolve(); + return Promise.resolve(existingEditor); } else { - existingEditor.destroy(); + pendingPromise.resolve(); + throw new Error('TinyMCE instance already exists for different target with same ID'); } } diff --git a/lib/editor/tiny/amd/src/utils.js b/lib/editor/tiny/amd/src/utils.js index c053504bd67..0113a92c1ad 100644 --- a/lib/editor/tiny/amd/src/utils.js +++ b/lib/editor/tiny/amd/src/utils.js @@ -238,8 +238,7 @@ export const ensureEditorIsValid = (editor) => { // we need to manually destroy the editor. // We could theoretically do this with a Mutation Observer, but in some cases the Node may be moved, // or added back elsewhere in the DOM. - if (!editor?.targetElm?.closest('body')) { - editor.destroy(); + if (!editor.getElement().isConnected) { return null; } -- 2.43.0