Closed Bug 1584269 Opened 6 years ago Closed 2 months ago

Unimplement onafterscriptexecute and onbeforescriptexecute events (and attributes)

Categories

(Core :: DOM: Core & HTML, task)

task

Tracking

()

RESOLVED FIXED
144 Branch
Tracking Status
firefox144 --- fixed

People

(Reporter: freddy, Assigned: edgar)

References

(Blocks 1 open bug)

Details

(Keywords: dev-doc-complete, site-compat, webcompat:platform-bug)

User Story

platform-scheduled:2025-09-30

Attachments

(1 file)

I suggest we unship the events and attributes.
This is in the document and the script element implementation.

See also https://developer.mozilla.org/en-US/docs/Web/API/Document/onafterscriptexecute

Keywords: site-compat

If they're no longer available to regular web content fine, but aren't these events still quite useful for extensions in general and user scripts in particular that want to intercept script loading?

I've only recently needed to edit a page's script before it is executed in order to fix some bug for me, and all the results I've found on how to achieve that with Greasemonkey et al. pointed to beforescriptexecute as the best solution for Firefox (and it did indeed work out nicely that way).
Also compare https://bugzilla.mozilla.org/show_bug.cgi?id=1286822#c1

Don't Content Scripts give you the guarantee of executing first?

Severity: normal → S3
Severity: normal → S3
See Also: → 1915573
See Also: → 1286822
Blocks: 1915573

If we're worried about this causing compatibility problems we could consider not sending these events on a per-origin basis. That would at least let us unblock the pge.com problem.

I can look at httparchive to see how commonly used these are.

Flags: needinfo?(zcorpan)

589,566 pages out of 12,851,198 (~4.59%) have "beforescriptexecute" or "afterscriptexecute" in httparchive.response_bodies.2024_11_01. It seems very risky to remove.

Pages by rank:
https://docs.google.com/spreadsheets/d/1r7u2UEwZsvH4vlCPCkEnxiy2GIoxM-zHF2CgmR26s_M/edit?usp=sharing

More detailed results with resource urls and extracts:
https://docs.google.com/spreadsheets/d/1i4VNEIZFYTiAcaDYg1aK02mMB5nhgg6kWdCaRBZVcAA/edit?usp=sharing

Flags: needinfo?(zcorpan)

I don't think the existence of beforescriptexecute/afterscriptexecute suggests that removing support will cause webcompat problems. We only care about situations where a site would be doing something like UA sniffing Firefox and using beforescriptexecute/afterscriptexecute and not relying on what ever mechanism they're using in Chrome.

I think we just need to try, see what breaks, and then have interventions that change the behaviour on a per origin basis in one way or the other.

At the same time we should probably do outreach to common users like https://consent.cookiebot.com/uc.js, https://cdn.cookielaw.org/consent/27cca70a-7db3-4852-9ef0-a6660fd0977d/OtAutoBlock.js and https://static.adsafeprotected.com/sca.17.6.4.js to see if we can get them to stop using it.

One could also keep the functionality of UA-sniffing code like "object"==typeof document.onafterscriptexecute alive while removing the event handler code. This wouldn't be a first.

A UseCounter for document property access vs. actual event handler in markup would help shed some light on this.

:jrmuizel, true, but a lot of instances seem to use event listeners for these. We can drop the events and attributes behind a flag and then manually check how the top sites in the httparchive list are affected.

Adding tentative scheduled info to hint that it's on our backlog, and we will try this out.

User Story: (updated)

Assigning this to Edgar, who will firstly add telemetry and ensure we keep the ball rolling here.

Assignee: nobody → echen

FWIW, I don't know that the telemetry will be super helpful in making a decision here. It's going to be very hard to distinguish between uses of beforescriptexecute that are needed vs. ones that are not. If we just want to use the telemetry to track usage over time then that could be useful.

Some things that could help move the needle here:

  1. Updating https://developer.mozilla.org/en-US/docs/Web/API/Document/beforescriptexecute_event etc. to say that the events are deprecated and will be removed.
  2. Adding warnings to the console when they're used.
  3. Turning them off in Nightly

I've also gotten confirmation from OneTrust that they are looking into removing their use of beforescriptexecute

Can I ask again, what's the replacement story for user scripts and the like supposed to be?

beforescriptexecute provides a very handy hook to override a page's scripts via user scripts. (E.g. I've come across a page that breaks the session store's form input data saving by clearing out all input fields on page load, which also clears out any data restored by the session store. With the help of beforescriptexecute, I've been able to write an user script that removes that behaviour on-the-fly while keeping the rest of the page's scripts intact.)

Having to write a full extension utilising web request filtering seems much more heavyweight in comparison.

Flags: needinfo?(jh+bugzilla)

How are you injecting the user script?

Greasemonkey/Violentmonkey et al.

Okay I see, so scanning for any pre-existing <script> elements already present in the DOM, processing them and then adding a mutation observer to catch any <script> elements added afterwards might work, too. I need to try it out, but thanks for the inspiration, this does look like a possible workaround.

Flags: needinfo?(jh+bugzilla)
See Also: 1915573
Depends on: 1949373
Depends on: 1954685
Blocks: 1956063

I've looked a bit into the use of beforescriptexecute by script blockers because they were causing webcompat issues on multiple sites.
All the blockers I've looked at use the techniques described in this article: https://medium.com/snips-ai/how-to-block-third-party-scripts-with-a-few-lines-of-javascript-f0b08b9c4c0.
For scripts that are not added programmatically, they use a MutationObserver that changes the type attribute of any added <script> element that they want to block. The article states that this doesn't block the script in Firefox though and uses a beforescriptexecute handler to block the script. But this information is outdated - the technique does work in current Firefox. So all those script blockers should simply remove their use of beforescriptexecute as changing the type attribute will now have the same effect in Firefox as in Chrome.

So how did this end up causing webcompat issues? The MutationObserver also handles programmatically added <script> elements and erroneously decides it wants to block some of them. According to the article that should not have any effect - changing the type and calling preventDefault() in the beforescriptexecute handler should not block programmatically added <script> elements. But in current Firefox the beforescriptexecute handler does block them.

Depends on: 1964343

Regarding the documentation, once they are removed completely, the compat data for the two events should be updated, see

https://github.com/mdn/browser-compat-data/blob/8395f1e832de3e687fd6b83027c334f6f7b81173/api/Document.json#L348
https://github.com/mdn/browser-compat-data/blob/8395f1e832de3e687fd6b83027c334f6f7b81173/api/Document.json#L718

Maybe, for completeness, the page https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script and the related compat data should also be updated to include the attributes onbeforescriptexecute and onafterscriptexecute.

Sebastian

(In reply to Holger Benl [:hbenl] from comment #19)

For scripts that are not added programmatically, they use a MutationObserver that changes the type attribute of any added <script> element that they want to block. The article states that this doesn't block the script in Firefox though and uses a beforescriptexecute handler to block the script. But this information is outdated - the technique does work in current Firefox. So all those script blockers should simply remove their use of beforescriptexecute as changing the type attribute will now have the same effect in Firefox as in Chrome.

I've found that MutationObserver in Chrome allows for beforescriptexecute-like behaviour, but in Firefox it does not work to prevent script execution.

I've created a minimal example that has different behaviour in Firefox (139) and Chrome (137), at https://github.com/robjwells/ff-beforescriptexecute . The HTML file sources a script that sets an event listener on the button. In Chrome the userscript can prevent the execution of the script, and the addition of the event listener, but in Firefox it cannot.

Further to my previous comment, the behaviour changes if the script to be intercepted has the defer attribute set. I've also simplified the example to remove the need for user interaction.

If the script is marked defer, changing the type has no effect. If it is not marked defer, changing the type prevents the script from executing.

Thanks for reporting this, Rod! I’ve split it into bug 1973704.

Depends on: 1973704
Depends on: 1977808
Blocks: 1977808
No longer depends on: 1977808
See Also: → 1977318
Duplicate of this bug: 1286822
See Also: 1286822
No longer blocks: 1977808
Pushed by echen@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/56bf35ad2666 https://hg.mozilla.org/integration/autoland/rev/bbdb0a95a152 Unship onafterscriptexecute and onbeforescriptexecute events by default; r=hsivonen
Status: NEW → RESOLVED
Closed: 2 months ago
Resolution: --- → FIXED
Target Milestone: --- → 144 Branch
Blocks: 1286822
No longer duplicate of this bug: 1286822
QA Whiteboard: [qa-triage-done-c145/b144]

FF144 MDN docs work can be tracked/viewed in https://github.com/mdn/content/issues/41141

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: