lacunacoil.com - Buttons are not working
Categories
(Web Compatibility :: Site Reports, defect, P2)
Tracking
(Webcompat Priority:P3, Webcompat Score:1, firefox148 affected, firefox149 affected)
People
(Reporter: rbucata, Assigned: twisniewski)
References
()
Details
(4 keywords, Whiteboard: [webcompat-source:web-bugs])
User Story
platform:windows,mac,linux,android impact:site-broken configuration:general affects:all branch:release diagnosis-team:dom user-impact-score:0
Attachments
(2 files)
Environment:
Operating system: Android 16 and Windows 10
Firefox version: Firefox Mobile 147.0
Steps to reproduce:
- Navigate to: https://lacunacoil.com/
- Click on any buttons and observe
Expected Behavior:
Buttons are working
Actual Behavior:
No buttons or links work on site
Notes:
- Reproduces regardless of the status of ETP
- Reproduces in firefox-nightly, and firefox-release
- Does not reproduce in chrome
Created from https://github.com/webcompat/web-bugs/issues/209108
| Reporter | ||
Updated•1 month ago
|
| Reporter | ||
Comment 1•1 month ago
|
||
Updated•1 month ago
|
Updated•24 days ago
|
Comment 2•23 days ago
|
||
There's a global click handler that calls preventDefault(). But there's also a click handler in each anchor element. Firefox somehow pass through the dom hierarchy and only calls the global listener...
Comment 3•23 days ago
|
||
Somehow all jQuery-added listeners are being ignored? Breakpoints don't run either from devtools.
Comment 4•22 days ago
|
||
Huge thanks for Nicolas Chevobbe and Julian Descottes from devtools for helping the investigation.
They noticed that wp-rocket is involved - https://docs.wp-rocket.me/article/1349-delay-javascript-execution, and that overrides on* event handler attributes and addEventListener methods. Per the doc it converts the page to load the scripts asynchronously and run things later.
All scripts that are present in the HTML of the page, will be delayed. Any scripts which are inserted after the page loads, or fetched indirectly from another script, cannot be delayed.
The page has a relevant inline script block:
( () => {
class RocketLazyLoadScripts {
constructor() {
this.v = "2.0.3",
this.userEvents = ["keydown", "keyup", "mousedown", "mouseup", "mousemove", "mouseover", "mouseenter", "mouseout", "mouseleave", "touchmove", "touchstart", "touchend", "touchcancel", "wheel", "click", "dblclick", "input", "visibilitychange"],
this.attributeEvents = ["onblur", "onclick", "oncontextmenu", "ondblclick", "onfocus", "onmousedown", "onmouseenter", "onmouseleave", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmousewheel", "onscroll", "onsubmit"]
}
async t() {
this.i(),
this.o(),
/iP(ad|hone)/.test(navigator.userAgent) && this.h(),
this.u(),
this.l(this),
this.m(),
this.k(this),
this.p(this),
this._(),
await Promise.all([this.R(), this.L()]),
this.lastBreath = Date.now(),
this.S(this),
this.P(),
this.D(),
this.O(),
this.M(),
await this.C(this.delayedScripts.normal),
await this.C(this.delayedScripts.defer),
await this.C(this.delayedScripts.async),
this.F("domReady"),
await this.T(),
await this.j(),
await this.I(),
this.F("windowLoad"),
await this.A(),
window.dispatchEvent(new Event("rocket-allScriptsLoaded")),
this.everythingLoaded = !0,
this.lastTouchEnd && await new Promise((t => setTimeout(t, 500 - Date.now() + this.lastTouchEnd))),
this.H(),
this.F("all"),
this.U(),
this.W()
}
Chrome hits this.everythingLoaded = !0, which is checked in the overridden event listener stuffs. Somehow not on Firefox.
Comment 5•22 days ago
|
||
(And it seems devtools is confused and thinks listeners are added via jQuery when they are actually not)
Comment 6•22 days ago
|
||
Looks like we are stuck here:
await this.C(this.delayedScripts.normal),
await this.C(this.delayedScripts.defer),
await this.C(this.delayedScripts.async),
The await expression for normal never resolves.
Comment 7•22 days ago
|
||
Wait, Chrome Mask makes it work.
Comment 8•22 days ago
|
||
There's a documented behavior difference for wp-rocket:
In Chrome and Safari, inline scripts will have a
src="data:text/javascript;base64,...attribute, used to speed up the processing of the script after it was delayed.
And there's this block in the inline script (inserted by wp-rocket)
if (
navigator.userAgent.includes('Firefox/') ||
'' === navigator.vendor ||
this.CSPIssue
) i = document.createElement('script'),
[
...t.attributes
].forEach(
(
t => {
let e = t.nodeName;
'type' !== e &&
(
'data-rocket-type' === e &&
(e = 'type'),
'data-rocket-src' === e &&
(e = 'src'),
i.setAttribute(e, t.nodeValue)
)
}
)
),
Comment 9•22 days ago
|
||
async $(t) {
if (
(await this.G(),
!0 !== t.noModule || !("noModule" in HTMLScriptElement.prototype))
)
return new Promise((e) => {
let i;
function o() {
((i || t).setAttribute("data-rocket-status", "executed"), e());
}
try {
if (
navigator.userAgent.includes("Firefox/") ||
"" === navigator.vendor ||
this.CSPIssue
)
((i = document.createElement("script")),
[...t.attributes].forEach((t) => {
let e = t.nodeName;
"type" !== e &&
("data-rocket-type" === e && (e = "type"),
"data-rocket-src" === e && (e = "src"),
i.setAttribute(e, t.nodeValue));
}),
t.text && (i.text = t.text),
t.nonce && (i.nonce = t.nonce),
i.hasAttribute("src")
? (i.addEventListener("load", o, {
isRocket: !0,
}),
i.addEventListener(
"error",
() => {
(i.setAttribute("data-rocket-status", "failed-network"),
e());
},
{
isRocket: !0,
},
),
setTimeout(() => {
i.isConnected || e();
}, 1))
: ((i.text = t.text), o()),
(i.isWPRocket = !0),
t.parentNode.replaceChild(i, t));
else {
const i = t.getAttribute("data-rocket-type"),
s = t.getAttribute("data-rocket-src");
(i
? ((t.type = i), t.removeAttribute("data-rocket-type"))
: t.removeAttribute("type"),
t.addEventListener("load", o, {
isRocket: !0,
}),
t.addEventListener(
"error",
(i) => {
this.CSPIssue && i.target.src.startsWith("data:")
? (console.log("WPRocket: CSP fallback activated"),
t.removeAttribute("src"),
this.$(t).then(e))
: (t.setAttribute("data-rocket-status", "failed-network"),
e());
},
{
isRocket: !0,
},
),
s
? ((t.fetchPriority = "high"),
t.removeAttribute("data-rocket-src"),
(t.src = s))
: (t.src =
"data:text/javascript;base64," +
window.btoa(unescape(encodeURIComponent(t.text)))));
}
} catch (i) {
(t.setAttribute("data-rocket-status", "failed-transform"), e());
}
});
t.setAttribute("data-rocket-status", "skipped");
}
This whole function goes very different route when it detects Firefox.
The core breakage comes from this part:
[...t.attributes].forEach((t) => {
let e = t.nodeName;
"type" !== e &&
("data-rocket-type" === e && (e = "type"),
"data-rocket-src" === e && (e = "src"),
i.setAttribute(e, t.nodeValue));
}),
It tries to copy <script type="rocketlazyloadscript" data-rocket-src="https://www.google.com/recaptcha/api.js?render=explicit&ver=3.35.1" id="elementor-recaptcha_v3-api-js"></script> into a new script element with data-rocket- prefix removed. But somehow it doesn't work:
i2 = document.createElement("script")
i2.src = "https://www.google.com/recaptcha/api.js?render=explicit&ver=3.35.1"
i2.src // ... 'https://lacunacoil.com/'. What?
I'm not sure what's happening in the src setter?
Comment 10•22 days ago
|
||
document[_0x3bf812(436) + _0x3bf812(272) + _0x3bf812(503) + 't'] = function (..._0x3d2064) {
var _0x1d86f9 = _0x3bf812;
let _0xff708a = _0x3d2064[ - 67 * - 39 + - 271 * 25 + 4162][_0x1d86f9(208) + _0x1d86f9(630) + _0x1d86f9(844)]();
if (_0xff708a !== _0x1d86f9(1660) + 'pt') return _0x2254af[_0x1d86f9(400)](document) (..._0x3d2064);
const _0x821b6e = _0x2254af[_0x1d86f9(400)](document) (..._0x3d2064);
try {
Object[_0x1d86f9(939) + _0x1d86f9(174) + _0x1d86f9(1749) + _0x1d86f9(1061)](
_0x821b6e,
{
'src': {
..._0x415b3a[_0x1d86f9(442)],
'set'(_0x1c8ff7) {
var _0xc878fe = _0x1d86f9;
if (typeof _0x1c8ff7 !== _0xc878fe(177) + _0xc878fe(1212) + 'd') {
var _0x2962ce = _0x1c8ff7[_0xc878fe(1650) + _0xc878fe(304)]();
var _0x25d570 = ![];
var {
api_key: _0x16d2a9,
found_item: _0x16dc28
}
Oh... god.
Comment 11•22 days ago
•
|
||
So that cryptic script ends up making script.src setter, through a dark magic, to set type=text/plain. A plain text script element is not going to fire any load/error events, thus breaking wp-rocket's expectation.
The recommended intervention is to ignore all the details and override the user agent string to not include Firefox, to make wp-rocket not enter Firefox specific branch.
Comment 12•22 days ago
|
||
And probably contact wp-rocket to stop Firefox specific behavior?
| Assignee | ||
Updated•22 days ago
|
| Assignee | ||
Comment 13•22 days ago
|
||
Updated•22 days ago
|
Comment 14•8 days ago
|
||
Comment 15•7 days ago
|
||
| bugherder | ||
| Assignee | ||
Updated•7 days ago
|
Updated•7 days ago
|
Description
•