A short while ago, Chrome broke the web by disabling alert()
, confirm()
and prompt()
dialogs from cross-origin iframes. The justification was that "the current UX is confusing, and has previously led to spoofs where sites pretend the message comes from Chrome or a different website"; removing the feature was deemed preferable to fixing the UX.
But legitimate uses were affected too. Users of CodePen, the widely-used code-sharing site co-founded by Chris Coyier, suddenly discovered that they were unable to use these functions in their projects, since CodePen runs your code inside a cross-origin iframe to guard against XSS attacks. Reports from other sites followed, and in the ensuing chaos the change was rolled back until 2022.
Hidden in the replies to Coyier's tweet was a surprising statement from Domenic Denicola, an engineer on the Chrome team:
It's best that such teaching sites be prepared for the eventual end state where these are removed from the web platform entirely.
Wait, what?
Reading the intent to remove thread confirms that this is indeed Chrome's stance: blocking dialogs (including onbeforeunload
) were a mistake, and their future removal is a fait accompli.
After I tweeted about the situation last week, my notifications tab became a Boschian hellscape, so I'm hesitant to write this post. But there are several aspects to this story that are too important for us not to talk about. It's not just a story about unloved APIs, it's a story about power, standards design, and who owns the platform — and it makes me afraid for the future of the web.
Onramps
Facebook's Dan Abramov pointed out that the changes nuked many programming tutorials. Google's Emily Stark suggested they should use the <dialog>
element instead. For the moment, we'll gloss over the fact that <dialog>
is sufficiently flawed that Denicola floated removing it from the spec — or that MDN's suggested fallback for browsers that don't support it is none other than alert
— and instead consider what this would look like in real life.
Often, when I'm teaching people web development, they begin learning JavaScript by building a simple number guessing game along these lines:
function game() {
let number = Math.ceil(Math.random() * 100);
let guess = prompt(`Guess a number between 1 and 100`);
guess = Number(guess);
while (guess !== number) {
if (guess < number) {
guess = prompt(`Too low! Guess again`);
} else {
guess = prompt(`Too high! Guess again`);
}
guess = Number(guess);
}
alert(`That's right! The number was ${number}`);
}
game();
It's pretty straightforward-looking stuff, but in the space of a few lines of code the students are exposed to many unfamiliar concepts:
- Data types (strings vs numbers, and converting between them)
- Functions, both built-in and the ones you write yourself
- Loops and if-else statements
- Operators
It's a popular lesson, and even foreshadows future discussions of algorithms (the smartest students soon intuit that they can 'win' by conducting a binary search), but it's hard — easily an hour's worth of material. Imagine now that before they could complete it they were required to learn about the DOM, event handling, and asynchronous programming. Educators gravitated towards blocking dialog APIs for a reason.
Failing to understand why these APIs are so valuable in an educational context is inevitable if you don't consider teachers part of your constituency when designing standards. It's cliché (and only partly accurate) to say that the web used to have better onramps for developers, but there's truth behind the nostalgic grumbling: the web platform's learnability has long been essential to its success. We damage it at our peril.
Hidden signals
The 'primary signal' Chrome uses to determine whether something can safely be removed from the web platform is the number of page views impacted. A feature appearing on 0.001% of page views is considered 'small but non-trivial' usage. (Cross-origin alert
is at around 0.006%, significantly above this threshold; with same-origin the figure is 50x higher still.)
It's easy to overindex on the things you can quantify, especially if you're Google. But not all things that count as uses of some feature show up in the data, when the data is predominantly public-facing production websites. Teaching is one such case. There are others.
For example, I've had several experiences in which a well-placed alert
was the only way to test hypotheses during debugging. In an ideal world we'd all have well-stocked device labs and be able to remotely inspect our code wherever it's running, no matter how imminent the deadline. Reality isn't always so accommodating.
Even when my code is working as intended — it happens sometimes — I'm likely to reach for alert
before adding complex error handling, if I'm building something for myself or my coworkers and I expect errors to be rare occurrences.
And security researchers frequently use alert
to demonstrate vulnerabilities. (Yes, in future they could use something less concise and less visible like console.log
, but in the meantime years' worth of literature would instantly fall out of date if alert
vanished.)
All of these are legitimate uses, but none will affect the metric that determines whether they're important enough to be supported by Chrome. Even when we do focus solely on production websites, usage doesn't necessarily correlate with importance, as noted by Dan Abramov.
Breakage
According to Emily Stark, a security expert on the Chrome team, breakage is something that happens often on the web.
But if that's true, it's very largely because of Chrome. For a long time, 'don't break the web' was considered something of a prime directive in standards work. Recall #smooshgate: a proposal to add a flatten
method to Array.prototype
turned out to be a breaking change because an ancient version of MooTools, still in use by a handful of sites, added its own incompatible flatten
. Disappointingly, some developers argued that breaking the web was acceptable, but TC39 took its backwards compatibility responsibilities seriously and ended up renaming flatten
to flat
instead. Google's Mathias Bynens wrote:
As it turns out, “don’t break the Web” is the number one design principle for HTML, CSS, JavaScript, and any other standard that’s widely used on the Web.
This time around, the approach was rather more cavalier.
Reasonable people can disagree about the balance of priorities when considering breaking changes, but it's good to be clear-eyed about what 'breakage' means. One of the many anecdotes I heard in the wake of the cross-origin alert changes stood out:
I was attempting to delete my recurring payments account from my local waste management's super old-school site. I was bit by the cross-domain confirm() in Chrome 92. I switched to Firefox to complete.
What if Firefox was no longer an option, either because a cash-strapped Mozilla had stopped developing it, or because they had implemented the now standardized spec changes? We're not talking about the Space Jam website rendering incorrectly, we're talking about people being unable to use essential services on the web. A frequent implication in the discussion last week was that website owners could simply re-engineer their apps to not use blocking dialogs, regardless of the cost of doing so. But many sites are no longer maintained, and they're no less valuable because of it.
We can't normalise the attitude that collateral damage is the price of progress, even if we accept the premise — which I don't — that removing APIs like alert
represents progress. For all its flaws, the web is generally agreed to be a stable platform, where investments made today will stand the test of time. A world in which websites are treated as inherently transient objects, where APIs we commonly rely on today could be cast aside as unwanted baggage by tomorrow's spec wranglers, is a world in which the web has already lost.
What if alert is... good, actually?
We're often reminded to use the web's built-in form elements instead of recreating checkboxes and buttons with a <div>
salad. Not only are they more accessible than what you'd likely build yourself, the visual consistency makes your app easier for users to navigate even if you consider the default appearance 'ugly'.
Yet when it comes to dialogs, the ugly default is treated as a bug rather than a feature. Why? As Heydon Pickering puts it:
Using alert(), prompt(), and confirm() in an MVP is the closest most devs will get to providing accessible dialogs. Chrome removing them just cuts out that step. Devs can go straight onto building their own underperforming, inaccessible dialogs
In the bad old days, the behaviour of alert
was somewhat obnoxious — it would focus the tab in question, and prevent you from navigating away. Thanks to years of hard work, that's no longer the case, to the extent that I'd argue alert
is in many cases better than whatever you'd have cobbled together yourself.
There are security issues with cross-origin iframes. I remain unconvinced that removal is a better solution than improving the design in a way that makes their provenance clearer.
Who owns the web?
A common response to last week's kerfuffle was 'use Firefox'. But that's not a solution. Even though the change was proposed by Chromium (the intent to remove preceded any discussion with other browser vendors), Firefox ultimately supported it. That's all it takes for something to become a 'standard' — support from two vendors, and stated opposition from none.
Put differently: when it comes to web standards, browsers call the shots exclusively.
Whenever I've questioned the wisdom of this or that proposal, I've been told I should simply get involved in the standards discussions — they're right there on GitHub! But openness means nothing without the power to effect change, and browsers have all the power. This should strike us as odd — the W3C's priority of constituencies explicitly states that the needs of users and authors (i.e. developers) should be treated as higher priority than those of implementors (i.e. browser vendors), yet the higher priority constituencies are at the mercy of the lower priority ones. (Chrome developers argue that they are acting in the interests of users in this case, but this thread from Mike Sherov makes a convincing case that this is a fig leaf for the real motivation, which is technical debt.)
Meanwhile, we don't seem to be learning from the past. If alert
is fair game for removal, then so is every API we add to the platform if the web's future stewards deem it harmful. Given that, you'd think we'd expand the platform's surface area with extreme caution; instead, we're adding APIs at breakneck speed, to the almost-guaranteed detriment of its future stability.
Given Chrome's near-monopoly control of the browser market, I'm genuinely concerned about what this all means for the future of the web. An ad company shouldn't have this much influence over something that belongs to all of us. I don't know how to fix the standards process so that it's more representative of the diversity of the web's stakeholders, but I'm increasingly convinced that we need to figure it out.
Top comments (51)
I agree with some of this and I disagree with some of this. I think the Chromium team's handling of this situation was not good, but I don't think most developers are criticizing this fairly.
For instance, in the thread you linked, Mike Sherov said this:
Did we ever stop to consider why the one of the people who wrote the HTML spec would want to see alert gone? Did we ever consider that maybe, just maybe, the core maintainers aren't completely incapable developers? Do we really think that when these devs were confronted with the fact that cross-origin alerts are used by scammers / phishers a lot, that their first instinct was to remove it entirely? Do we really think that the Chromium developers just want to break the web for the sake of tech debt? I don't think that's giving them enough credit.
Do we really think that browser vendors haven't tried things like styling the dialogs differently? The Safari team did quite a lot of work re-styling their alerts and dialogs to be within the context of the webpage, yet phishing and scams that utilize this still run rampant on iOS. Repeated alerts are used to lock up the browser and make it unusable, forcing non-technical users to call a scam telephone number because they think their device was hacked.
Pop-up windows are a good example of where engineers have tried this approach before, and it worked. Pop-up windows used to be much, much worse than they are right now. A big reason why things got better is because browser vendors put in the work to allow the valid use cases of them, but block the invalid uses of them. After working year after year to do this and to eliminate the new versions of the popup scripts, annoying popup windows have gotten much less frequent. The web didn't break because it was possible to solve this issue.
Do we really think that the Chromium team didn't try to take the same approach with this one? Do we really think that browser vendors haven't explored alternatives to these problems? That doesn't make sense to me.
Instead, I think that it's more likely that this has been a point of contention for a lot of browser developers for a long time; major browser vendors are aligned about wanting to move the web away from alert() and co. What seems more likely to me is that most browser vendors have tried for years to implement better designs, explored multiple alternatives to how
alert()
behaves today, and ultimately decided that removal was better. I don't know if it's valid for us, as people on the outside not working on this full-time and knee-deep in browser code and user research and standards and the like, to think that our opinions hold the same weight.This is a slippery slope argument. We've removed plenty of features and APIs before that have had breaking changes, and none of them have led to this free-for-all removal of features that you're suggesting.
Nowhere do I suggest that the developers involved are 'incapable'. You're willing to give them the benefit of the doubt, which is fine, but to my knowledge the rationale for wanting to remove these features has never been discussed in a public forum; all we really see are occasional tweets from Chrome engineers that hint at conversations that happened out of public view. If this post prompts such a discussion, I will consider it to have been a public service. Until then, healthy skepticism is the appropriate stance.
This post seems to assume (just from how I read it):
alert()
is being used for today is a valid use of the feature.You're assuming that
alert()
is a good feature for the rest of the web. Ultimately, browser vendors have access to a lot more data and a lot more user research than we do, and they seem to have concluded that that's not the case, that it's not a good feature.What is good for developers is not necessarily what is good for all users on the web. We accept that this is the case with accessibility: developers often have to write more code and rethink their UIs, but that makes the UIs a better experience for everyone. It's not appropriate to apply that approach with accessibility and to not apply that approach everywhere else. If
alert()
is not a good user experience (which seems to be the case), then you using it for debugging is a hack; it's not being used for its intended use. Ifdebugger;
or other statements aren't sufficient for what you're debugging, then we should absolutely discuss how to improve them, but we shouldn't program based on hacks.Programming tutorials break all the time, not just JS tutorials. Library versions go out of date. Unapproved JavaScript syntax (like decorators) breaks. Behavior of certain features changes and causes breaks. Best practices change, which could be seen as breakage. Breakage on the web has happened many times before: with Flash, with different CSS properties, with old JS behavior, etc. We are not special. If that breakage was okay (which I don't know your position on), then we can't say that this breakage is not okay.
You're missing the point.
You're taking browser vendors' statements about what is best for users — and that they are making decisions in users' interests rather than their own — on faith. Even if browsers' and users' interests do coincide, and even if their data (which they admitted last week was woefully inadequate) could be trusted, there is nothing forcing that alignment. It's naïve to believe otherwise.
Whether
alert
is good-for-developers-but-bad-for-users is a valid question, but that's not the only consideration here. Are broken websites good for users?You seem to be talking about JS syntax that hasn't yet made it to stage 4 and vendor-prefixed CSS. Sorry, but that's a nonsensical comparison.
No, based on their track record, which is extremely good. Browser vendors have a reliable track record of implementing changes that are good for the average user and that improve user experience. No group of developers puts more effort into researching how users interact with browser and understanding how they think. It's just logical to assume that they aren't making these decisions for bad reasons and that they are much more likely than us to understand what users want.
The browser market literally enforces this????? If Chrome implements a change that decreases user experience enough, users switch browsers. That's just how the browser market works lol. Browser vendors are highly incentivized not to add features that impact users' experience in a negative way.
Again, you're assuming that the developers who made the decision don't know what they're doing. The data they had indicated that the vast majority of websites that users visit don't rely on this feature. The sites that broke were programming tutorials which, as we've already established, we expect to break at some point. And again, if a large number of websites break, users switch browsers. The entire reason why people use Chrome is because websites just work in it, whereas in other browsers, they don't.
Developers are not the majority of users on the internet; we're an incredibly small portion of the users on the web. It's objectively false to say that this impacted the majority of users in a negative way.
I'm not. I'd recommend reading through this awesome document from the Blink team that describes how they don't take breaking changes lightly, and gives tons of examples of breaking changes that have been made before.
Here's a link to the initial proposal to remove cross-origin alert, prompt, and confirm, along with the data about how it would affect site breakage.
This would affect:
Have you read through this document? Has anyone at Google read through this document?
I have.
First, and foremost, "gives tons of examples of breaking changes that have been made before." is not an excuse to have more and more breaking changes. Moreover, there are great examples that show exactly why breaking changes have to be handled with care.
So let's look into that document, shall we?
According to your own breakdown:
This would affect:
0.006% of page loads using alert()
0.003% of page loads using confirm()
So. "Small but not trivial" and significantly heavier than "even 0.0001%"
Immediately after that we have:
So, no. 0.001% doesn't mean you can just remove it.
Let's skip ahead to an example directly relevant to this issue:
Look. The exact same issue as with alert.
Do you know what one of the suggestions for that was? "To announce these changes at least 6 months beforehand, and to provide developers with a clear upgrade path, alternatives, workarounds and polyfills".
Where's all that?
Oh, look. Some of it is right there in the document:
Have they done any of that? Of course not.
And here's the best quote of all:
Instead, we've seen high-visibility Chrome people be consistently dismissive, condescending, ignorant and so on.
Oh. And don't forget: they are removing this functionality, and there's literally nothing in the pipeline to replace it.
As a developer there is never a reason to use these antiquated (nonsensical and legacy) application flow functions. As developers we can easily implement the required functionality ourselves, ensuring our own application flow.
Let's put this into things/perspective users and developers can/should understand. (Noting; It actually currently only entails cross-origin iframe usage and a possible future complete removal from the spec).
As a user I do not want 3rd party scripts possibly pretending they are the site I am visiting; i.e. alert/confirm with clicks to some nefarious site => cross-origin-removal (what it is all about)
As a user I do not want a site/app possibly pretending they are the browser/os; i.e. alert/confirm with clicks to some nefarious site => complete-removal (what it will become)
As a developer I do not want to rely on "a" browser for my application flow. => complete-removal (what it will become)
I wholeheartedly agree with @samwight comments. The argument against his comments are mostly making elephants from ants (or is that ... from ...).
As developers we should not accept that "old" is better, above "safer" is better. We live in a world wherein we know that the web is abused. As true developers we should all be behind this proposed change (spec from day1/not break the web arguments are superfluous as the current real world usage is mostly only nefarious cross origin scripts).
Are there really any real world examples of the usage? No; only tutorials. Tutorials are what they are; mostly always need to change to be applicable; given the weather. This is the weather.
p.s.
A lot of people are stating nuclear silos confirm etc. The only real world apps which use these functions are already probably running on isolated browsers that are fixed (i.e. app built for IE 5.5). These apps are not nuclear silo apps; those run with VBasic ;-) Apart from tutorials there are no real world examples that merit the usage of these methods.
p.p.s. I wrote this fast on a mobile so I apologize for typ0s etc
The article clearly stated the reasons. You decided to dismiss them out of hand
That's the thing though: you can't easily implement this functionality. Saying that you can easily implement this functionality betrays the fact that you know very little of what goes into implementing into a proper accessible dialog.
On top of that the "replacement" that browsers have (
<dialog>
) is so bad that Chrome devs themselves argued for its removal. But you'd know that if you read the article.So instead of solving these issues browser implementors decided to remove a feature without providing a proper replacement.
And you know this how? From numbers that Chrome provided from public usage data that they themselves admitted was incomplete and incorrect?
The article that you didn't read provides real world usage examples.
But its also telling how you dismiss tutorial sites out of hand because in your mind they are entirely unimportant. What else is unimportant to you?
Market forces cease to be meaningful as you approach monopoly conditions. Regardless, users have no meaningful choice when browsers act in concert. If browsers' and users' interests truly were aligned, the W3C wouldn't regard them as separate constituencies in its famous conflict resolution clause.
Even if you accept the premise that page loads is a suitable metric (read the article; I don't), even Chrome have acknowledged that the data is inadequate.
And to respond to your dismissive point about 'programming tutorials', the article already provided an example of someone being unable to cancel a recurring payment because of this change. I heard plenty of examples of equivalent severity. If top-level dialogs were removed, the breakage would be orders of magnitude worse.
@samwightt You speak on behalf of the 'average user' quite often in your replies here, but you maybe shouldn't, since you make assertions like 'and again, if a large number of websites break, users switch browsers.' I'd love to see evidence to back this up, because, anecdotally, this is absolutely not true. Do you actually think the 'average user' is aware different browsers use different rendering engines?
That said, catering to the 'average user', or the majority of browser users is also just an insane idea.
Also: I'm honestly a little surprised at how much credit you give the Chrome team in general. As Rich mentioned elsewhere, Chrome is a product developed by an advertising company, and acting like they are the benevolent steward and saviours of the web is a little far-fetched.
Ultimately, this situation reflects very poorly on the Chrome team for several reasons:
1) The complete lack of meaningful communication
2) Largely ignoring the feedback provided by the few developers who were aware of this in advance (or more likely, saw websites break), and merely delaying the change.
3) Failure to consider other solutions to a completely valid problem.* Phishing/scamming efforts online are absolutely a problem, but why is this the fix?
*: you may argue that, internally, they have weighed alternative solutions, but without public communication and discourse, we don't know that.
Also to be clear, this has been discussed as early as March 2020. I agree that they could've done a much better job discussing this and that they absolutely should have removed this once
<detail />
was stabilized.Yes, I completely believe the same browser team that refuses to make view-source: use the original code the page received instead of doing a separate GET (whose contents could be completely different) is indeed indifferent to real-world use cases or getting public feedback first.
Unfortunately, I think the war is already lost. Web standards, just like Firefox, are both kept around by google so that they can pretend they don't control the web.
I am not at all certain they can be unseated, implementing a new browser or even just maintaining a fork of an existing one is a herculean task beyond the capability of all but the largest organisations.
I think if more stuff like this happens we are going to see a proliferation of home grown solutions for lots of controls for no reason, div class=button on everything even more than now.
Using public web usage tracking as your "primary signal" to determine feature usage is an utter #FAIL. The private web applications that Google doesn't see is where most of the use of "less desired" web features are used, and where they are most depended on.
By all means discourage the use of confirm() and friends, however attempting to remove them when
<dialog/>
isn't available yet (9 years and counting bugs.webkit.org/show_bug.cgi?id=84635) is just bonkers.What also isn't clear is what is the behavior when these are removed. e.g. what values do
foo
andbar
get?depending on the mood browser will either stop the execution completely with 'x is not a function' or silently assign null, pretty neat, don't you think?
ugh... yeah I think at a minimum... if for some reason this removal actually goes through, the replacement behavior needs to be standardized.
It will still mess things up, but at least if consistent we can focus on applicable solutions. e.g.
Seems like they should be able to add a Content Security Policy setting to allow sites to opt in or out of it. I haven't thought it all the way through, but I feel like CSP addresses this sort of thing already, like what are valid JS sources, can JS call
eval
, can it run inline JS, where can it load iframe sources from, etc. Feels like this wouldalert
fit right in.Yes, or why not make it an option in Chrome or whatever browser so that the user can enable or disable it.
Default would be "off" for max security, the user then sees a little warning icon when visiting a site that uses bespoke disabled feature - the user can then choose to enable it (once, or permanently) for that site, or all sites, so that the site's feature becomes usable when that's of vital important to the user.
Long story short - make it an option that the user can control!
One thing that doesn't get much of a mention with the removal of these three modals in cross-origin iframes is the accessibility impact. With accessibility being given such a low focus in web development courses and tutorials, I think it's a fairly safe assumption that a lot of new developers don't think too much about accessibility concerns.
I wrote about this impact a couple of days ago also. In short, current modals:
Given that
alert()
is a single line call that does all of these things and the alternative is dozens of lines of code (and that's without being able to halt script execution which is effectively impossible with and code not under your full control), I think it's another safe assumption that things will be missed. The end result is a less accessible web because Chrome tried to tackle the wrong problem.As their main stated reason was abuse leading to security concerns, then they should have attempted to tackle that. What they've done is the equivalent to bricking over all doors and windows of a house to prevent break-ins. Sure, it does as they intend, but the owner can no longer access their house except via the chimney.
We should all be concerned about Google's
nearmonopoly of the web. It's terrifying.That aside, I think what we need is a new kind of practice. A "reprecation-fill", if you will, where we create "polyfills" that reinstate what Google has deemed unworthy.
A small library that checks for the existence of
alert()
and friends, and if they aren't there, it attempts to recreate it with<dialog>
. (Of course, that means<dialog>
has to be polyfilled, too).And then we take the "reprecation-fills" and try to put them in some sort of Chrome Extension and/or modernizr toolkit so that we can smooth the transition just a tad.
And then, of course, we burn it all down because we've reached the point in front-end development where we're now qualifying our hellscapes.
When I hear the argument "alert from iframe is not distinguishable from main page and can be used maliciously" First thing that comes to my mind is to make them distinguishable, not remove them entirely.
I pray for one thing and one thing only.
When you call alert, if it's been removed, the page needs to fucking crash. It is not safe to assume that you can just pretend the function call does not exist.
alert("Are you sure you want to delete your account? This is irreversible")
Browser has no safe choice but to crash tab completely, throw an error, or return early.
const confirmed = confirm("Dear Federal Agent, are you sure you want to launch the missiles?")
Could the browser just return false for every confirm call?
How about:
const input = prompt("Enter STOP to prevent launching the nukes")
if (input === "STOP") return
Ah, Google's AI can decide what the input should be!
I really don't think they've explored things enough. The fact that we are all caught off guard is proof they are not working hard enough. I hate to say it, but it seems like they just don't give a shit. Seriously, there's so many little things that the team could be doing but are not.
Nicely put. Couldn't have said it better. When I read the tweets regarding breaking changes, I lost my mind.
Well put. It's disappointing that they use their dominant market position to convince everyone that "to make an omelette, you have to break a few eggs", and that anything less would be to oppose innovation, or a suggestion (even if tweeted in a personal capacity) that it makes you unprepared, or inferior as a developer. Every now and then I forget that it's a browser made by an ads company, but events like these remind me.