tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit f212adc98da1cccad93acc367a0fe57a870a72be
parent 4b2c560c91239356425452245e6a61604cb0863a
Author: Mathew Hodson <mathew.hodson@gmail.com>
Date:   Thu, 16 Oct 2025 14:44:48 +0000

Bug 1286822 - Remove beforescriptexecute/afterscriptexecute events r=webidl,emilio

Differential Revision: https://phabricator.services.mozilla.com/D264718

Diffstat:
Mdom/base/nsDeprecatedOperationList.h | 2--
Mdom/base/nsDocumentWarningList.h | 2--
Mdom/base/test/test_bug587931.html | 76----------------------------------------------------------------------------
Mdom/events/EventListenerManager.cpp | 28----------------------------
Mdom/events/EventNameList.h | 5-----
Mdom/locales/en-US/chrome/dom/dom.properties | 9---------
Mdom/script/ScriptLoadContext.h | 6------
Mdom/script/ScriptLoader.cpp | 85++++++++++++++++++++++++++-----------------------------------------------------
Mdom/svg/crashtests/1507961-1.html | 2--
Mdom/webidl/Document.webidl | 6------
Mgfx/layers/apz/test/mochitest/helper_wide_crossorigin_iframe_child.html | 2--
Mjs/src/tests/browser.js | 10++--------
Mmodules/libpref/init/StaticPrefList.yaml | 6------
Mtools/@types/generated/lib.gecko.dom.d.ts | 4----
Mtools/@types/generated/lib.gecko.glean.d.ts | 4----
Mwidget/EventMessageList.h | 4----
Mxpcom/ds/StaticAtoms.py | 2--
17 files changed, 30 insertions(+), 223 deletions(-)

diff --git a/dom/base/nsDeprecatedOperationList.h b/dom/base/nsDeprecatedOperationList.h @@ -54,6 +54,4 @@ DEPRECATED_OPERATION(DocumentReleaseCapture) DEPRECATED_OPERATION(OffscreenCanvasToBlob) DEPRECATED_OPERATION(SVGDeselectAll) DEPRECATED_OPERATION(IDBObjectStoreCreateIndexLocale) -DEPRECATED_OPERATION(BeforeScriptExecuteEvent) -DEPRECATED_OPERATION(AfterScriptExecuteEvent) DEPRECATED_OPERATION(FullscreenAttribute) diff --git a/dom/base/nsDocumentWarningList.h b/dom/base/nsDocumentWarningList.h @@ -16,5 +16,3 @@ DOCUMENT_WARNING(SVGRefLoop) DOCUMENT_WARNING(SVGRefChainLengthExceeded) DOCUMENT_WARNING(NotificationsRequireUserGestureDeprecation) DOCUMENT_WARNING(DocumentSetDomainIgnored) -DOCUMENT_WARNING(AfterScriptExecuteEventNotSupported) -DOCUMENT_WARNING(BeforeScriptExecuteEventNotSupported) diff --git a/dom/base/test/test_bug587931.html b/dom/base/test/test_bug587931.html @@ -12,50 +12,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=587931 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=587931">Mozilla Bug 587931</a> <pre id="test"> <script type="application/javascript"> - -const gScriptExecuteEventEnabled = SpecialPowers.getBoolPref("dom.events.script_execute.enabled"); - /** Test for Bug 587931 **/ SimpleTest.waitForExplicitFinish(); -var afterCount = 0; -var lastBeforeExecute = null; -var afterCountForSystemGroup = 0; -// For system group -var afterCountForSystemGroup = 0; -var lastBeforeExecuteForSystemGroup = null; -var expectedCurrentScriptInAfterScriptExecute = null; function verifyScript(n) { var curr = document.currentScript; is(curr, document.getElementById(n), "correct script (" + n + ")"); - is(lastBeforeExecute, gScriptExecuteEventEnabled ? curr : null, "correct beforescript (" + n + ")"); - document.addEventListener("afterscriptexecute", function(event) { - afterCount++; - lastBeforeExecute = null; - is(event.target, curr, "correct afterscript (" + n + ")"); - is(document.currentScript, expectedCurrentScriptInAfterScriptExecute, - "document.currentScript in afterscriptexecute(" + n + ")"); - document.removeEventListener("afterscriptexecute", arguments.callee); - }); - // Test system group - SpecialPowers.wrap(document).addEventListener("afterscriptexecute", function(event) { - afterCountForSystemGroup++; - lastBeforeExecuteForSystemGroup = null; - is(event.target, curr, "correct afterscript (" + n + ") for system group"); - is(document.currentScript, expectedCurrentScriptInAfterScriptExecute, - "document.currentScript in afterscriptexecute(" + n + ") for system group"); - }, { mozSystemGroup: true, once: true }); } -document.onbeforescriptexecute = function(event) { - lastBeforeExecute = event.target; -}; -// Test system group -SpecialPowers.wrap(document).addEventListener("beforescriptexecute", function(event) { - lastBeforeExecuteForSystemGroup = event.target; -}, { mozSystemGroup: true }); window.addEventListener("load", function() { - is(afterCount, gScriptExecuteEventEnabled ? 4 : 0, "correct number of afterscriptexecute"); - is(afterCountForSystemGroup, 4, "correct number of afterscriptexecute for system group"); SimpleTest.finish(); }); </script> @@ -71,52 +35,12 @@ verifyScript("parse-inline"); var s = document.createElement("script"); s.textContent = "verifyScript('dom-inline');"; s.id = "dom-inline"; -expectedCurrentScriptInAfterScriptExecute = document.currentScript; document.body.appendChild(s); -expectedCurrentScriptInAfterScriptExecute = null; s = document.createElement("script"); s.src = "data:text/plain,verifyScript('dom-ext');"; s.id = "dom-ext"; document.body.appendChild(s); </script> - -<!-- Test cancel using beforescriptexecute --> -<script onbeforescriptexecute="return false;" - onafterescriptexecute="window.firedAfterScriptExecuteForCancel = true;"> -ok(!gScriptExecuteEventEnabled, "should have been canceled"); -</script> -<script> -isnot(window.firedAfterScriptExecuteForCancel, true, "onafterscriptexecute executed"); -</script> - -<!-- Test cancel using beforescriptexecute for external --> -<script onbeforescriptexecute="window.extFiredBeforeScriptExecuteForCancel = true; return false;" - onafterescriptexecute="window.extFiredAfterScriptExecuteForCancel = true;" - onload="window.extFiredLoadForCancel = true;" - src="data:text/plain,ok(!window.extFiredBeforeScriptExecuteForCancel, 'should have been canceled');"> -</script> -<script> -isnot(window.extFiredAfterScriptExecuteForCancel, true, "onafterscriptexecute executed"); -is(extFiredLoadForCancel, true, "onload executed"); -</script> - -<!-- Test that all events fire --> -<script onbeforescriptexecute="window.beforeDidExecute = true;" - onafterscriptexecute="window.afterDidExecute = true;" - onload="window.loadDidExecute = true" - onerror="window.errorDidExecute = true" - src="data:text/plain,window.didExecute=true"> -is(window.beforeDidExecute, gScriptExecuteEventEnabled ? true : undefined, 'onbeforescriptexecute executed'); -is(window.afterDidExecute, undefined, 'onafterscriptexecute executed'); -is(window.didExecute, true, 'script executed'); -is(window.loadDidExecute, undefined, 'onload executed'); -is(window.errorDidExecute, undefined, 'onerror executed'); -</script> -<script> -is(window.afterDidExecute, gScriptExecuteEventEnabled ? true : undefined, "onafterscriptexecute executed"); -is(window.loadDidExecute, true, "onload executed"); -is(window.errorDidExecute, undefined, "onerror executed"); -</script> </body> </html> diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp @@ -464,34 +464,6 @@ void EventListenerManager::AddEventListenerInternal( case eFormRadioStateChange: nsContentUtils::SetMayHaveFormRadioStateChangeListeners(); break; - case eAfterScriptExecute: - if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) { - if (Document* doc = window->GetExtantDoc()) { - doc->SetUseCounter(eUseCounter_AfterScriptExecuteEvent); - if (StaticPrefs::dom_events_script_execute_enabled()) { - doc->WarnOnceAbout( - DeprecatedOperations::eAfterScriptExecuteEvent); - } else { - doc->WarnOnceAbout( - Document::eAfterScriptExecuteEventNotSupported); - } - } - } - break; - case eBeforeScriptExecute: - if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) { - if (Document* doc = window->GetExtantDoc()) { - doc->SetUseCounter(eUseCounter_BeforeScriptExecuteEvent); - if (StaticPrefs::dom_events_script_execute_enabled()) { - doc->WarnOnceAbout( - DeprecatedOperations::eBeforeScriptExecuteEvent); - } else { - doc->WarnOnceAbout( - Document::eBeforeScriptExecuteEventNotSupported); - } - } - } - break; default: // XXX Use NS_ASSERTION here to print resolvedEventMessage since // MOZ_ASSERT can take only string literal, not pointer to diff --git a/dom/events/EventNameList.h b/dom/events/EventNameList.h @@ -268,11 +268,6 @@ EVENT(cut, eCut, EventNameType_HTMLXUL | EventNameType_SVGGraphic, eClipboardEventClass) EVENT(paste, ePaste, EventNameType_HTMLXUL | EventNameType_SVGGraphic, eClipboardEventClass) -// Gecko-specific extensions that apply to elements -EVENT(beforescriptexecute, eBeforeScriptExecute, EventNameType_HTMLXUL, - eBasicEventClass) -EVENT(afterscriptexecute, eAfterScriptExecute, EventNameType_HTMLXUL, - eBasicEventClass) FORWARDED_EVENT(blur, eBlur, EventNameType_HTMLXUL, eFocusEventClass) ERROR_EVENT(error, eLoadError, EventNameType_All, eBasicEventClass) diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties @@ -465,15 +465,6 @@ InvalidNamedFormControlUnfocusable=The invalid form control with name=‘%S’ i # LOCALIZATION NOTE: %1$S is the granularity string received as argument by Selection.modify(). SelectionModifyGranualirtyUnsupported=Granularity “%1$S” is not supported yet for Selection.modify() -# LOCALIZATION NOTE: Do not translate "afterscriptexecute". -AfterScriptExecuteEventWarning=Adding a listener for afterscriptexecute events is deprecated and will be removed soon. -# LOCALIZATION NOTE: Do not translate "beforescriptexecute". -BeforeScriptExecuteEventWarning=Adding a listener for beforescriptexecute events is deprecated and will be removed soon. -# LOCALIZATION NOTE: Do not translate "afterscriptexecute". -AfterScriptExecuteEventNotSupportedWarning=Adding a listener for afterscriptexecute events is no longer supported. -# LOCALIZATION NOTE: Do not translate "beforescriptexecute". -BeforeScriptExecuteEventNotSupportedWarning=Adding a listener for beforescriptexecute events is no longer supported. - # LOCALIZATION NOTE: Do not translate "intercept()". %1$S is the overridden option, %2$S is the new value and %3$S is the old value. PreviousInterceptCallOptionOverriddenWarning=The ’%1$S’ option for a previous call to intercept() was overridden by ’%2$S’, and the previous value ’%3$S’ will be ignored. diff --git a/dom/script/ScriptLoadContext.h b/dom/script/ScriptLoadContext.h @@ -209,12 +209,6 @@ class ScriptLoadContext : public JS::loader::LoadContextBase, return mScriptElement; } - // Event target for beforescriptexecute/afterscriptexecute events. - inline nsIScriptElement* GetScriptElementForExecuteEvents() const { - MOZ_ASSERT(mScriptElement); - return mScriptElement; - } - // For ScriptLoader::mCurrentParserInsertedScript. inline nsIScriptElement* GetScriptElementForCurrentParserInsertedScript() const { diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp @@ -2457,15 +2457,6 @@ nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) { } } - nsCOMPtr<nsINode> scriptElem = do_QueryInterface( - aRequest->GetScriptLoadContext()->GetScriptElementForExecuteEvents()); - - nsCOMPtr<Document> doc; - if (!aRequest->GetScriptLoadContext()->mIsInline || - aRequest->IsModuleRequest()) { - doc = scriptElem->OwnerDoc(); - } - nsCOMPtr<nsIScriptElement> oldParserInsertedScript; uint32_t parserCreated = aRequest->GetScriptLoadContext()->GetParserCreated(); if (parserCreated) { @@ -2479,48 +2470,12 @@ nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) { FireScriptAvailable(NS_OK, aRequest); - // The window may have gone away by this point, in which case there's no point - // in trying to run the script. - { // Try to perform a microtask checkpoint nsAutoMicroTask mt; } - nsPIDOMWindowInner* pwin = mDocument->GetInnerWindow(); - bool runScript = !!pwin; - if (runScript) { - nsContentUtils::DispatchTrustedEvent( - scriptElem->OwnerDoc(), scriptElem, u"beforescriptexecute"_ns, - CanBubble::eYes, Cancelable::eYes, &runScript, - StaticPrefs::dom_events_script_execute_enabled() - ? SystemGroupOnly::eNo - : SystemGroupOnly::eYes); - } - - // Inner window could have gone away after firing beforescriptexecute - pwin = mDocument->GetInnerWindow(); - if (!pwin) { - runScript = false; - } - - nsresult rv = NS_OK; - if (runScript) { - if (doc) { - doc->IncrementIgnoreDestructiveWritesCounter(); - } - rv = EvaluateScriptElement(aRequest); - if (doc) { - doc->DecrementIgnoreDestructiveWritesCounter(); - } - - nsContentUtils::DispatchTrustedEvent( - scriptElem->OwnerDoc(), scriptElem, u"afterscriptexecute"_ns, - CanBubble::eYes, Cancelable::eNo, nullptr, - StaticPrefs::dom_events_script_execute_enabled() - ? SystemGroupOnly::eNo - : SystemGroupOnly::eYes); - } + nsresult rv = EvaluateScriptElement(aRequest); FireScriptEvaluated(rv, aRequest); @@ -2902,19 +2857,21 @@ static void ExecuteCompiledScript(JSContext* aCx, ClassicScript* aLoaderScript, } } +// https://html.spec.whatwg.org/#execute-the-script-element nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) { MOZ_ASSERT(aRequest->IsFinished()); + MOZ_ASSERT(mDocument); - // We need a document to evaluate scripts. - if (!mDocument) { - return NS_ERROR_FAILURE; + // The window may have gone away by this point, in which case there's no point + // in trying to run the script. + if (!mDocument->GetInnerWindow()) { + return NS_OK; } + // 2. If el's preparation-time document is not equal to document, then return. Document* ownerDoc = aRequest->GetScriptLoadContext()->GetScriptOwnerDocument(); if (ownerDoc != mDocument) { - // https://html.spec.whatwg.org/#prepare-the-script-element step 16 - // as of 2025-01-15 return NS_ERROR_FAILURE; } @@ -2942,13 +2899,22 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) { globalObject = scriptGlobal; } - // This mechanism is currently only used when the parser returns - // early due to this script loader having a current script. However, - // now that we have this, we could migrate continuing after a - // parser-blocking script to this same mechanism. Not doing it right - // away to reduce risk of introducing bugs. - auto maybeContinueParser = MakeScopeExit([&] { + // 5. If el's from an external file is true, or el's type is "module", then + // increment document's ignore-destructive-writes counter. + const bool ignoreDestructiveWrites = + !aRequest->GetScriptLoadContext()->mIsInline || + aRequest->IsModuleRequest(); + if (ignoreDestructiveWrites) { + ownerDoc->IncrementIgnoreDestructiveWritesCounter(); + } + + auto afterScript = MakeScopeExit([&] { if (mContinueParsingDocumentAfterCurrentScript) { + // This mechanism is currently only used when the parser returns + // early due to this script loader having a current script. However, + // now that we have this, we could migrate continuing after a + // parser-blocking script to this same mechanism. Not doing it right + // away to reduce risk of introducing bugs. mContinueParsingDocumentAfterCurrentScript = false; if (mDocument) { nsCOMPtr<nsIParser> parser = mDocument->CreatorParserOrNull(); @@ -2957,6 +2923,11 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) { } } } + // 7. Decrement the ignore-destructive-writes counter of document, if it was + // incremented in the earlier step. + if (ignoreDestructiveWrites) { + ownerDoc->DecrementIgnoreDestructiveWritesCounter(); + } }); // Update our current script. diff --git a/dom/svg/crashtests/1507961-1.html b/dom/svg/crashtests/1507961-1.html @@ -2255,7 +2255,6 @@ try { var00127.setProperty("float", "-webkit-positioned"); } catch(e) { } try { htmlvar00004.setAttribute("onautocompleteerror", "eventhandler3()"); } catch(e) { } try { svgvar00012.setAttribute("direction", "rtl"); } catch(e) { } try { var00013.scrollLeft = 0.909759935717; } catch(e) { } -try { htmlvar00011.setAttribute("onbeforescriptexecute", "eventhandler2()"); } catch(e) { } try { var00127.setProperty("counter-increment", "c"); } catch(e) { } try { var00084.onwebkitanimationiteration = var00133; } catch(e) { } try { var00057.setAttribute("hanging", "1"); } catch(e) { } @@ -3932,7 +3931,6 @@ try { /* newvar{var00162:DOMRectReadOnly} */ var var00162 = var00163; } catch(e) try { if (!var00162) { var00162 = GetVariable(fuzzervars, 'DOMRectReadOnly'); } else { SetVariable(var00162, 'DOMRectReadOnly'); } } catch(e) { } try { /* newvar{var00161:double} */ var var00161 = var00162.top; } catch(e) { } try { var00089.setAttribute("aria-relevant", "removals"); } catch(e) { } -try { htmlvar00017.setAttribute("onbeforescriptexecute", "eventhandler1()"); } catch(e) { } try { var00132.stopImmediatePropagation(); } catch(e) { } try { /* newvar{var00164:EventHandler} */ var var00164 = htmlvar00023.onmouseenter; } catch(e) { } try { if (!var00164) { var00164 = GetVariable(fuzzervars, 'EventHandler'); } else { SetVariable(var00164, 'EventHandler'); } } catch(e) { } diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl @@ -372,12 +372,6 @@ partial interface Document { // Mozilla extensions of various sorts partial interface Document { - // @deprecated We are going to remove these (bug 1584269). - [Pref="dom.events.script_execute.enabled"] - attribute EventHandler onbeforescriptexecute; - [Pref="dom.events.script_execute.enabled"] - attribute EventHandler onafterscriptexecute; - // Creates a new XUL element regardless of the document's default type. [ChromeOnly, CEReactions, NewObject, Throws] Element createXULElement(DOMString localName, optional (ElementCreationOptions or DOMString) options = {}); diff --git a/gfx/layers/apz/test/mochitest/helper_wide_crossorigin_iframe_child.html b/gfx/layers/apz/test/mochitest/helper_wide_crossorigin_iframe_child.html @@ -62,8 +62,6 @@ html { window.onload = onloaded; window.onDOMContentLoaded = sendDpToParent; document.onreadystatechange = sendDpToParent; - document.onafterscriptexecute = sendDpToParent; - document.onbeforescriptexecute = sendDpToParent; document.onvisibilitychange = sendDpToParent; function onloaded() { numMoreTimesToSend = 10; diff --git a/js/src/tests/browser.js b/js/src/tests/browser.js @@ -545,14 +545,8 @@ let nextScriptIndex = i + 1; if (nextScriptIndex < scripts.length) { var callNextAppend = () => appendScript(nextScriptIndex); - SpecialPowers.wrap(script).addEventListener("afterscriptexecute", callNextAppend, {mozSystemGroup: true, once: true}); - - // Module scripts don't fire the "afterscriptexecute" event when there - // was an error, instead the "error" event is emitted. So listen for - // both events when creating module scripts. - if (spec.module) { - script.addEventListener("error", callNextAppend, {once: true}); - } + script.addEventListener("load", callNextAppend, {once: true}); + script.addEventListener("error", callNextAppend, {once: true}); } scriptElements[i] = script; diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml @@ -3022,12 +3022,6 @@ value: true mirror: always -# Whether to dispatch `beforescriptexecute` and `afterscriptexecute` event. -- name: dom.events.script_execute.enabled - type: bool - value: false - mirror: always - # Whether to expose test interfaces of various sorts - name: dom.expose_test_interfaces type: bool diff --git a/tools/@types/generated/lib.gecko.dom.d.ts b/tools/@types/generated/lib.gecko.dom.d.ts @@ -7778,8 +7778,6 @@ declare var Directory: { }; interface DocumentEventMap extends GlobalEventHandlersEventMap, OnErrorEventHandlerForNodesEventMap, TouchEventHandlersEventMap { - "afterscriptexecute": Event; - "beforescriptexecute": Event; "fullscreenchange": Event; "fullscreenerror": Event; "pointerlockchange": Event; @@ -7851,8 +7849,6 @@ interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GeometryU readonly mozFullScreen: boolean; readonly mozFullScreenEnabled: boolean; readonly mozSyntheticDocument: boolean; - onafterscriptexecute: ((this: Document, ev: Event) => any) | null; - onbeforescriptexecute: ((this: Document, ev: Event) => any) | null; onfullscreenchange: ((this: Document, ev: Event) => any) | null; onfullscreenerror: ((this: Document, ev: Event) => any) | null; onpointerlockchange: ((this: Document, ev: Event) => any) | null; diff --git a/tools/@types/generated/lib.gecko.glean.d.ts b/tools/@types/generated/lib.gecko.glean.d.ts @@ -3105,10 +3105,8 @@ interface GleanImpl { } useCounterDeprecatedOpsDoc: { - afterScriptExecuteEvent: GleanCounter; ambientLightEvent: GleanCounter; appCache: GleanCounter; - beforeScriptExecuteEvent: GleanCounter; components: GleanCounter; createImageBitmapCanvasRenderingContext2D: GleanCounter; deprecatedTestingAttribute: GleanCounter; @@ -3154,10 +3152,8 @@ interface GleanImpl { } useCounterDeprecatedOpsPage: { - afterScriptExecuteEvent: GleanCounter; ambientLightEvent: GleanCounter; appCache: GleanCounter; - beforeScriptExecuteEvent: GleanCounter; components: GleanCounter; createImageBitmapCanvasRenderingContext2D: GleanCounter; deprecatedTestingAttribute: GleanCounter; diff --git a/widget/EventMessageList.h b/widget/EventMessageList.h @@ -395,10 +395,6 @@ NS_EVENT_MESSAGE(eSMILRepeatEvent) NS_EVENT_MESSAGE(eAudioProcess) NS_EVENT_MESSAGE(eAudioComplete) -// script notification events -NS_EVENT_MESSAGE(eBeforeScriptExecute) -NS_EVENT_MESSAGE(eAfterScriptExecute) - NS_EVENT_MESSAGE(eBeforePrint) NS_EVENT_MESSAGE(eAfterPrint) diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py @@ -767,7 +767,6 @@ STATIC_ATOMS = [ Atom("onmozaccesskeynotfound", "onmozaccesskeynotfound"), Atom("onactivate", "onactivate"), Atom("onafterprint", "onafterprint"), - Atom("onafterscriptexecute", "onafterscriptexecute"), Atom("onanimationcancel", "onanimationcancel"), Atom("onanimationend", "onanimationend"), Atom("onanimationiteration", "onanimationiteration"), @@ -781,7 +780,6 @@ STATIC_ATOMS = [ Atom("onbeforematch", "onbeforematch"), Atom("onbeforepaste", "onbeforepaste"), Atom("onbeforeprint", "onbeforeprint"), - Atom("onbeforescriptexecute", "onbeforescriptexecute"), Atom("onbeforeunload", "onbeforeunload"), Atom("onblocked", "onblocked"), Atom("onblur", "onblur"),