From 1d6eb9933701ea65f7a9dd670d37a2faa17b8f12 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Fri, 8 Feb 2019 16:47:54 -0500 Subject: [PATCH] Always set [[ScriptOrModule]] to null for event handler functions Closes #4267. Related to previous work in #4181. Tests: https://github.com/web-platform-tests/wpt/pull/15251 --- source | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/source b/source index 19d73cd9541..76bdbdab24f 100644 --- a/source +++ b/source @@ -88539,17 +88539,15 @@ document.querySelector("button").addEventListener("click", bound);
-

active script can be null if the user clicks on the following button, before any - script ever accesses the button's onclick property:

+

active script can be null if the user clicks on the following button:

<button onclick="Promise.resolve('import(`./example.mjs`)').then(eval)">Click me</button>

In this case, the JavaScript function for the event handler will be created by the get the current value of the event handler algorithm as a direct result of user - action, with no script on the stack (i.e., no active script). Thus, when the - promise machinery calls EnqueueJob, there will be no active script to - pass along.

+ handler">get the current value of the event handler algorithm, which creates a function + with null [[ScriptOrModule]] value. Thus, when the promise machinery calls + EnqueueJob, there will be no active script to pass along.

As a consequence, this means that when the import() expression is evaluated, there will still be no active script. Fortunately that is handled by our @@ -88801,15 +88799,17 @@ import "https://example.com/foo/../module2.mjs";

-

referencingScriptOrModule is not usually null. One case where it can be - null is if the user clicks the control in the following example:

+

referencingScriptOrModule is not usually null, but will be so for event handlers + per the get the current value of + the event handler algorithm. For example, given:

<button onclick="import('./foo.mjs')">Click me</button>
-

In this case, at the time the import() expression runs, - GetActiveScriptOrModule will return null, which will be passed to this abstract - operation when HostResolveImportedModule is - called by FinishDynamicImport.

+

If a click event occurs, then at the + time the import() expression runs, GetActiveScriptOrModule will + return null, which will be passed to this abstract operation when HostResolveImportedModule is called by + FinishDynamicImport.

@@ -90983,6 +90983,29 @@ typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEvent
  • Remove settings object's realm execution context from the JavaScript execution context stack.

  • +
  • +

    Set function.[[ScriptOrModule]] to null.

    + +
    +

    This is done because the default behavior, of associating the created function + with the nearest script on the stack, can lead to + path-dependent results. For example, an event handler which is first invoked by user + interaction would end up with null [[ScriptOrModule]] (since then this algorithm would be + first invoked when the active script is null), whereas one that is first invoked + by dispatching an event from script would have its [[ScriptOrModule]] set to that script.

    + +

    Instead, we just always set [[ScriptOrModule]] to null. This is more intuitive anyway; the + idea that the first script which dispatches an event is somehow responsible for the event + handler code is dubious.

    + +

    In practice, this only affects the resolution of relative URLs via import(), + which consult the base URL of the associated + script. Nulling out [[ScriptOrModule]] means that HostResolveImportedModule and + HostImportModuleDynamically will fall back to the current settings + object's API base URL.

    +
    +
  • +
  • Set eventHandler's value to the result of creating a Web IDL EventHandler callback function object whose object