{"id":346368,"date":"2021-08-09T14:23:44","date_gmt":"2021-08-09T21:23:44","guid":{"rendered":"https:\/\/css-tricks.com\/?p=346368"},"modified":"2021-08-09T14:59:47","modified_gmt":"2021-08-09T21:59:47","slug":"choice-words-about-the-upcoming-deprecation-of-javascript-dialogs","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/choice-words-about-the-upcoming-deprecation-of-javascript-dialogs\/","title":{"rendered":"Choice Words about the Upcoming Deprecation of JavaScript Dialogs"},"content":{"rendered":"\n
It might be the very first thing a lot of people learn in JavaScript:<\/p>\n\n\n\n
alert(\"Hello, World\");<\/code><\/pre>\n\n\n\nOne day at CodePen, we woke up to a ton of customer support tickets about their Pens being broken, which ultimately boiled down to a version of Chrome that shipped where they ripped out alert()<\/code> from functioning in cross-origin iframes. And all other native “JavaScript Dialogs” like confirm()<\/code>, prompt()<\/code> and I-don’t-know-what-else (onbeforeunload<\/code>?, .htpasswd<\/code> protected assets?).<\/p>\n\n\n\n\n\n\n\nCross-origin iframes are essentially the heart of how CodePen<\/a> works. You write code, and we execute it for you in an iframe that doesn’t share the same domain as CodePen itself, as the very first line of security defense. We didn’t hear any heads up or anything, but I’m sure the plans were on display<\/a>. <\/p>\n\n\n\nI tweeted<\/a> out of dismay. I get that there are potential security concerns here. JavaScript dialogs look the same<\/em> whether they are triggered by an iframe or not, so apparently it’s confusing-at-best when they’re triggered by an iframe, particularly a cross-origin iframe where the parent page likely has little control. Well, outside of, ya know, a website like CodePen. Chrome cite performance concerns as well, as the nature of these JavaScript dialogs is that they block the main thread when open, which essentially halts everything. <\/p>\n\n\n\nThere are all sorts of security and UX-annoyance issues that can come from iframes though. That’s why sandboxing is a thing.<\/strong> I can do this:<\/p>\n\n\n\n<iframe sandbox><\/iframe><\/code><\/pre>\n\n\n\nAnd that sucker is locked down. If some form tried to submit something in there: nope<\/em>, won’t work. What if it tries to trigger a download? Nope. Ask for device access? No way. It can’t even load any JavaScript at all<\/em>. That is unless I let it:<\/p>\n\n\n\n<iframe sandbox=\"allow-scripts allow-downloads ...etc\"><\/iframe><\/code><\/pre>\n\n\n\nSo why not an attribute for JavaScript dialogs? Ironically, there already is one: allow-modals<\/code>. I’m not entirely sure why that isn’t good enough, but as I understand it, nuking JavaScript dialogs in cross-origin iframes is just a stepping stone on the ultimate goal: removing them from the web platform entirely.<\/strong><\/p>\n\n\n\nDaaaaaang. Entirely? That’s the word. Imagine the number of programming tutorials that will just be outright broken. <\/p>\n\n\n\n
For now, even the cross-origin removal is delayed until January 2022, but as far as we know this is going to proceed, and then subsequent steps will happen to remove them entirely. This is spearheaded by Chrome<\/a>, but the status reports<\/a> that both Firefox<\/a> and Safari are on board with the change. Plus, this is a specced change<\/a>, so I guess we can waggle our fingers literally everywhere here, if you, like me, feel like this wasn’t particularly well-handled. <\/p>\n\n\n\nWhat we’ve been told so far, the solution is to use postMessage<\/code> if you really absolutely need<\/em> to keep this functionality for cross-origin iframes. That sends the string the user uses in window.alert<\/code> up to the parent page and triggers the alert from there. I’m not the biggest fan here, because:<\/p>\n\n\n\npostMessage<\/code> is not blocking like JavaScript dialogs are.<\/strong> This changes application flow. <\/li>- I have to inject code into users code for this.<\/strong> This is new technical debt and it can harm the expectations of expected user output (e.g. an extra
<script><\/code> in their HTML has weird implications, like changing what :nth-child<\/code> and friends select). <\/li>- I’m generally concerned about passing anything<\/em> user-generated to a parent to execute. I’m sure there are theoretical ways to do it safely, but XSS attack vectors are always surprising in their ingenouity.<\/li><\/ol>\n\n\n\n
Even lower-key suggestions, like window.alert = console.log<\/code>, have essentially the same issues. <\/p>\n\n\n\nAllow me to hand the mic over to others for their opinions.<\/p>\n\n\n\n
Couldn’t the alert be contained to the iframe instead of showing up in the parent window?<\/p>Jaden Baptista<\/em>, Twitter<\/a><\/cite><\/blockquote>\n\n\n\nYes, please! Doesn’t that solve a big part of this? While making the UX of these dialogs more useful? Put the dang dialogs inside<\/em> the <iframe><\/code>. <\/p>\n\n\n\n“Don’t break the web.” to “Don’t break 90% of the web.” and now “Don’t break the web whose content we agree with.”<\/p>Matthew Phillips<\/em>, Twitter<\/a><\/cite><\/blockquote>\n\n\n\nI respect the desire to get rid of inelegant parts [of the HTML spec] that can be seen as historical mistakes and that cause implementation complexity, but I can\u2019t shake the feeling that the existing use cases are treated with very little respect or curiosity.<\/p>Dan Abramov<\/em>, Twitter<\/a><\/cite><\/blockquote>\n\n\n\nIt’s weird to me this is part of the HTML spec, not the JavaScript spec. Right?!<\/p>\n\n\n\n
I always thought there was a sort of “prime directive” not to break the web? I’ve literally seen web-based games that used alert<\/code> as a “pause”, leveraging the blocking nature as a feature. Like: <button onclick=\"alert('paused')\">Pause<\/button><\/code>[.] Funny, but true.<\/p>Ben Lesh<\/em>, Twitter<\/a><\/cite><\/blockquote>\n\n\n\nA metric was cited that only 0.006% of all page views contain a cross-origin iframe that uses these functions, yet:<\/p>\n\n\n\n
Seems like a misleading metric for something like confirm()<\/code>. E.g. if account deletion flow is using confirm()<\/code> and breaks because of a change to it, this doesn\u2019t mean account deletion flow wasn\u2019t important. It just means people don\u2019t hit it on every session.<\/p>Dan Abramov<\/em>, Twitter<\/a><\/cite><\/blockquote>\n\n\n\nThat’s what’s extra concerning to me: alert()<\/code> is one thing, but confirm()<\/code> literally returns true<\/code> or false<\/code>, meaning it is a logical control structure in a program. Removing that breaks websites, no question. Chris Ferdinandi showed me this little obscure website that uses it:<\/p>\n\n\n\n