In early 2021, the Web Hypertext Application Technology Working Group (WHATWG) changed the HTML specification to deprecate support for the alert(), confirm(), and prompt() APIs when used in a third-party context. In this article we’re going to share with you some solutions we’ve implemented and will be implementing in the future as alternatives to these features. We’ll also be talking a little bit about the background of this change and share how Salesforce has been working with browser vendors to mitigate the impact of this change on our customers. As we walk you through what you can do as a developer, we’ll share some best practices and advice on how to prepare for this major shift in browser features.

Cross-domain prompt deprecation so far

The release of Chromium 92 was the first to introduce this change, resulting in numerous cases raised by our customers. Later in the summer, it was also introduced in Safari 15 and iOS 15. The Salesforce UI platform team reached out to Apple and the Chromium project to revert this change due to the impact on Salesforce customers, among others. In a testament to the important relationship between Salesforce and browser vendors, they agreed to temporarily roll back the change.

While we requested a delay to the eventual implementation, Salesforce greatly appreciates the security and stability that this important standard brings to browsers. For this reason, we’ve worked to understand the potentially impacted areas to Salesforce technology and customers. While we’re addressing any code that Salesforce controls, we also understand that many of you have implemented custom UIs in Visualforce, Aura, and LWC with these APIs. Consequently, you may likewise find broken features when the APIs are once again removed. To prepare for their eventual removal, we have created a set of solutions for you to make the necessary fixes.

The first solution that we have to offer is an open source project that you can adapt to fix your Visualforce pages and Canvas apps. We’re making this solution available today.

In the future, we will also be releasing a set of new Lightning base components to address fixing this in any LWC or Aura components. The current product roadmap is for these to be available in some public capacity in the Summer ’22 release.

Who is impacted by this change?

Determining precisely those customers impacted is complicated. Not every invocation of alert(), confirm(), and prompt() APIs are impacted. In fact, they will only stop working when they are being executed on a different origin than the top-level instance of window — primarily in the context of an iFrame.

Because you can’t simply look at your codebase and know which usage of one of these APIs fits this criteria, we recommend that you migrate ALL of your utilization of alert(), confirm(), or prompt() to one of the solutions below. This is especially true if you’ve created a UI library. Handing over functionality that only works some of the time will not inspire confidence in your work. Even if you’ve taken great care to document clearly how and when to use specific features, you’re bound to incur additional (and unnecessary) support time helping those developers who missed your warnings.

And let’s face it, using only one implementation of dialogs will provide a more consistent dialog experience for your users.

For the good of the web

For years, developers building modern web apps have looked sideways at the blocking behavior of alert, confirm, and prompt. JavaScript’s single-thread model means that the best-case design principle for web apps is one of cooperative access to that thread. Tasks should only use the thread while needed and release control early and often to allow other work to proceed.

In the discussion of the adoption of this new standard, there are even suggestions that one day support for these APIs could be removed entirely. Only time will tell if that actually happens, but for now, you can get ahead of the curve by getting rid of them now. Let’s see a few examples of how to accomplish this.

Visualforce/Canvas open source solution

We created a sample dialog to replace window.alert() and window.prompt() in Visualforce pages. The sample dialog web resources are available in our sample project on Github. You’ll have to deploy them to your org as a static resource. The following Visualforce code shows how to implement the sample dialog; it assumes that you’ve deployed the files as a zipped static resource called dialog_samples.

Before:

<apex:page>
    <apex:form id="theForm">
        <apex:commandButton id="save" action="{!save}" value="Save"
              onclick="if (!confirm('are you sure?')) { return false; }" />
    </apex:form>
</apex:page>          

After:

<apex:page>
    <script type="text/javascript" src="{!URLFOR($Resource.dialog_samples, 'dialog.js')}" />
    <link rel="stylesheet" href="{!URLFOR($Resource.dialog_samples, 'dialog.css')}" />
    
    <apex:form id="theForm">
        <apex:commandButton id="save" action="{!save}" value="Save"
              onclick="event.preventDefault(); Dialog.confirm('Are you sure?', {ok: 'OK', cancel: 'Cancel'},(ret) => { if (ret) submitData(this); })" />
    </apex:form>
    
     <script>
        function submitData(theButton) {
             //In order to perform the action of the apex:commandButton
              //must add a hidden input before submitting the form.
              var hiddenInput = document.createElement('input');
             hiddenInput.setAttribute('name', theButton.id);            
             hiddenInput.setAttribute('value', theButton.value);
              hiddenInput.setAttribute('type', 'hidden');
              theButton.form.appendChild(hiddenInput);

             theButton.form.submit();                  
        }
    </script>
</apex:page>    

Here is another sample of using the above dialog on a simple HTML page:

Before:

<form id="theForm" action="checkAnswer" method="post">     
     <input type="hidden" id="num1Value" name="num1Value" value=""/>
     <input type="hidden" id="num2Value" name="num2Value" value=""/>
     <input type="text" name="answerValue" id="answerValue"/>
     <input type="submit" value="Submit" onclick="return window.confirm('Is this your final answer?');"/>              
</form>

After:

<form id="theForm" action="checkAnswer" method="post">     
     <input type="hidden" id="num1Value" name="num1Value" value=""/>
     <input type="hidden" id="num2Value" name="num2Value" value=""/>
     <input type="text" name="answerValue" id="answerValue"/>
     <input type="submit" value="Submit" onclick="Dialog.confirm('Is this your final answer?', {ok: 'OK', cancel: 'Cancel'}, (ret) => { if(ret) this.form.submit(); });return false;"/>
</form>

Canvas API apps

While the above examples should get you across the line with basic dialogs in your Visualforce page, if you have a Canvas API-based UI, you clearly won’t have access to static resources stored on the Salesforce CDN. Your hosted web app may already have implemented a solution, but if not, you could bundle up the static resource files in your web app and implement a similar flow there.

New Lightning base components

For Aura and LWC components, we are planning to release three new base components called LightningAlert, LightningConfirm, and LightningPrompt. As the names suggest, these can replace your current alert(), confirm(), and prompt() APIs. While Salesforce is flexible enough that you can use any alternative UI flow you want, we hope that these will ease the transition for our developers. As mentioned above, while you only need to replace your cross-origin implementations, we do recommend that you convert all instances of alert(), confirm(), and prompt() to LightningAlert, LightningConfirm, and LightningPrompt respectively. Here’s what the change might look like:

Before:

// alert
const confirmMessage = 'this is the alert message';
const result = window.confirm(confirmMessage);

// confirm
const alertMessage = 'this is the confirm message';
const result = window.alert(alertMessage);

// prompt
const promptMessage = 'this is the prompt message';
const result = window.prompt(promptMessage);

After:

// alert
LightningAlert.open({
    message: 'this is the alert message',
    //label defaults to "Alert"
    variant: 'headerless',
}).then((result) => {
    console.log('alert result', result);
});


// confirm
LightningConfirm.open({
    message: 'this is the confirm message',
    label: 'Please Confirm',
    theme: 'warning',
}).then((result) => {
    console.log('confirm result', result);
});


// prompt
LightningPrompt.open({
    message: 'this is the prompt message',
    defaultValue: 'test',
    label: 'Please Respond',
    // use default theme
}).then((result) => {
    console.log('prompt result', result);
});

Salesforce mobile app on iOS and Android

The Salesforce mobile app on iOS and Android will be able to invoke and display the new alert, prompt, and confirm dialogs. However, there is an important behavior difference that could affect your workflows.

The previous dialogs on mobile are blocking dialogs, which required a user to interact with the prompt or dismiss it to continue using any other part of the app. These are operating system-level dialogs and look and feel different between iOS and Android.

The new dialogs do not block the app; instead, they only block the page in which they are presented. It is possible for the user to navigate to a different section of the Salesforce mobile app while an alert, prompt, or confirm dialog is presented. These new dialogs are shown on an iOS device in these examples, but they are identical in style and presentation on Android devices.

Changes in user experience are always best if communicated clearly to the user base. If you’ve used the system-based dialogs previously, you’ll want to make sure to communicate this key change in app behavior to your users before rolling it out!

Timeline for browsers to re-introduce the breaking change

We are grateful that browser vendors have temporarily delayed the introduction of these important API changes. We’re also working with them to manage expectations of when these Visualforce and Lightning solutions will be available. But ultimately, Salesforce cannot control the roadmaps of the browser vendor development teams.

For this reason, we highly recommend that you prioritize these changes and implement them as quickly as possible after they become available in the Winter ‘23 release.

When we become aware of the release versions of Chrome, Edge, Safari, and Firefox, we’ll update you through the Salesforce Developers blog and social channels, and we’ll inform the Salesforce Developer Support team.

To provide feedback on these solutions, please reach out through your normal support channels.

About the authors

Maeve Tuntivate is a Senior Product Manager at Salesforce leading the Lightning Base Components team. Outside of work, you can find her running or playing board games with friends and family.

Hung Van Lam is a senior software engineer at Salesforce where he works on maintain and enhance Visualforce. In his spare time he enjoys traveling and spending time with his wife and two children.

Greg Whitworth is the Director of LWC, LWR & the Standards & Web Platform teams. You can follow him on Twitter and LinkedIn.

Ronald Ledwich is the Senior Director of Product Management for the Salesforce Mobile App for iOS and Android.

Stay up to date with the latest news from the Salesforce Developers Blog

Subscribe