Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I need a concept of "currently running script" #78

Closed
domenic opened this issue Oct 6, 2015 · 13 comments
Closed

I need a concept of "currently running script" #78

domenic opened this issue Oct 6, 2015 · 13 comments

Comments

@domenic
Copy link
Member

domenic commented Oct 6, 2015

This is for HTML/ES integration. HTML has a concept of script which contains a few useful pieces of information. Notably, it contains a "muted errors flag", which is set based on whether the script was retrieved in a cross-origin manner.

When performing NextJob's "implementation defined unhandled exception processing", I need to be able to retrieve the current "HTML script" given the information available to me in the ES context.

I would have thought this would be simple: I'd simply get whatever concept ES has for "script", and add a pointer between them associating "HTML script" and "ES script". Or, I could even try to get rid of "HTML script" entirely, and just store a couple things on the ES script.

But, I can't find any concept of script in ES! :(

The closest thing I can find is the top-level execution context scriptCtx created by ScriptEvaluation.

So far the best I've come up with is:

  • When running script from HTML, via NextJob(ScriptEvaluationJob, ...), smuggle in the HTML script as part of the [[HostDefined]]. Then, say something like "All execution contexts created from this ScriptEvaluationJob must have a state component pointing back to the HTML script". (Apparently execution contexts are allowed to have implementation-dependent state.)
  • When implementation defined unhandled exception processing happens, use "the running execution context" to retrieve the appropriate HTML script.

Does this seem vaguely legit? I don't like "all execution contexts created from".

@anba
Copy link
Contributor

anba commented Oct 6, 2015

I don't like "all execution contexts created from".

I think this part can be done in 8.4.2 NextJob, step 9:

  1. Perform any implementation or host environment defined job initialization using nextPending.

Define that step 9 calls a new abstract operation HostDefinedJobInitialization. In HostDefinedJobInitialization you can now enhance the execution context to store the HTML script info.

HostDefinedJobInitialization(job):

  1. If job.[[HostDefined]] contains HTML script, then
    1. Let callerContext be the running execution context.
    2. Install additional HTML properties in callerContext.

@allenwb
Copy link
Member

allenwb commented Oct 6, 2015

@anba that was the motivation for including step 9 in the design

@domenic
Copy link
Member Author

domenic commented Oct 6, 2015

That seems like the piece I was missing; thank you @anba! My eyes must have just slipped over that line a number of times.

At some point I might submit a PR to refactor out all these "implementation-defined XXX" into abstract ops like your sample of HostDefinedJobInitialization. But I'll wait until I do the whole integration shebang...

Closing since my original question is answered.

@domenic
Copy link
Member Author

domenic commented Dec 9, 2015

@anba OK, I tried this and it didn't work, because it didn't capture what I meant by "all execution contexts created from." In particular it only allows me to correlate the top-level execution contexts created by NextJob. But I am most concerned about the ones created by e.g. declaring functions or calling eval.

Let me try to give an overview of the problem. Given

a.html

<script id="a1">
  frames[0].foo();
</script>

<script id="a2">
  blah();
</script>

<iframe src="b.html"></iframe>

b.html

<script id="b1">
  function foo() {
    // HERE
  }
</script>

<script id="b2">
  blahblah();
</script>

I need some spec language I can insert such that at the "HERE" point, "the currently running script" gives b1.

The execution context stack has foo()'s context on top, then below it a1's top-level context. Your trick allows me to associate a1's top-level context with the a1 script, but I don't see how to associate foo's context with b1.

Any ideas?

@domenic domenic reopened this Dec 9, 2015
@zenparsing
Copy link
Member

Execution contexts have a Function component. Can you somehow associate all functions with their containing "scripts"? Would you need some kind of hook into FunctionAllocate to do that?

@domenic
Copy link
Member Author

domenic commented Dec 9, 2015

Yeah I would need a hook in all the places that push execution contexts onto the stack, of which there are approximately ten.

@zenparsing
Copy link
Member

I was thinking one hook in NextJob and one in FunctionAllocate. Getting the script from an execution context would look like:

  1. If the current execution context has a non-empty Function component:
    1. Get the current script from the Function-to-current-script mapping.
  2. Else, we're evaluating a script or module:
    1. Get the current script from the execution-context-to-script mapping.

You'd set the Function-to-script mapping from within FunctionAllocate, and you'd set the execution-context-to-script mapping from HostDefinedJobInitialization as described above.

I'm not really familiar with how modules and execution contexts interact though. And I could be misunderstanding things as well.

@domenic
Copy link
Member Author

domenic commented Dec 9, 2015

Hmm, I think that might suffice. The eval and generator context manipulation can all be subsumed by the function manipulation, i.e. they can "inherit" their parent function or top-level script. I thought about that for a bit and it seems web-compatible.

and you'd set the execution-context-to-script mapping from HostDefinedJobInitialization as described above.

This isn't quite accurate, it turns out. InitializeHostDefinedRealm only has a single execution context for the entire realm. Within those each ScriptEvaluationJob/ScriptEvaluation and ModuleEvaluationJob/ModuleEvaluation create per-script/module execution contexts. So the right hook is not in NextJob step 9 but in ScriptEvaluation and ModuleEvaluation.

I can probably smuggle this in, although it will be linguistically awkward, since calling EnqueueJob("ScriptJobs", ScriptEvaluationJob, <>) doesn't actually let me customize the [[HostDefined]] part of the PendingJob. Maybe I can add a hostDefined parameter to EnqueueJob.

Hmm, now I am tempted to just not use ScriptEvaluationJob or ModuleEvaluationJob at all, and directly use ScriptEvaluation and ModuleEvaluation... that actually seems a lot easier.


Next problem. When I'm at these hook locations, how do I know what script to associate with?

Consider a modification of the above example that has

<script id="b1">
  function foo() {
    function bar() {
      // HERE
    }

    bar();
  }
</script>

It seems like I need to create the Function-to-script mapping via:

  • If the running execution context has no Function component, this is a top-level function, so use the script from the top-level-execution-context-to-script mapping.
  • Otherwise, use the script from the Function-to-script mapping keyed on the running execution context's Function component.

OK, willing to give this a try.


Does anyone have opinions on whether we should do this in ES, or in HTML? That is, I see two possibilities:

  • Add hooks to ES ModuleEvaluation, ScriptEvaluation, and FunctionAllocate, which HTML uses to associate HTML scripts with the created execution contexts. HTML maintains the Function-to-script mapping and the top-level-execution-context-to-script mapping.
  • ES takes over, and creates or reuses some notion of script or module, so that instead of hooks, it just does the bookkeeping itself, and we add a ScriptOrModule component to all execution contexts. This could be a ModuleRecord for modules. Unsure about scripts; the spec likes to talk about ECMAScript Script but that's kind of strange since it's a grammar production, not an actual thing.

@zenparsing
Copy link
Member

@domenic After thinking about it, it seems yucky and scattershot to add this kind of hook to FunctionAllocate. I think we should explore the ScriptOrModule thing a bit more. I need to look into the module stuff before I have any useful input though.

@domenic
Copy link
Member Author

domenic commented Dec 10, 2015

I tend to agree. I might work on a PR for that, using the ModuleRecord (extended with a [[HostDefined]] field) for modules and a new ScriptRecord which contains { [[Realm]], [[Environment]], [[HostDefined]] }. It seems much nicer to have ES track the concept of modules/scripts here.

I don't think there's much to look in to on the modules side FWIW; it works pretty similarly.

domenic added a commit to domenic/ecma262 that referenced this issue Dec 10, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function.
- Eval execution contexts point to that of their containing function.
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 10, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function.
- Eval execution contexts point to that of their containing function.
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, factored out ParseScript and ScriptEvaluation abstract operations, which now better parallel modules.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 11, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function.
- Eval execution contexts point to that of their containing function.
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 14, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 14, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 14, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 14, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 14, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 15, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
domenic added a commit to domenic/ecma262 that referenced this issue Dec 15, 2015
Fixes tc39#78. Introduces the concept of a Script Record as a counterpart to a Module Record, and adds [[HostDefined]] fields to both of them. Every execution environment now has ScriptOrModule component pointing back to its "creator" script or module:

- Top level script/module execution contexts point to the appropriate script/module.
- Function execution contexts for functions declared at top level point to that of the containing script/module.
- Function execution contexts for functions declared inside other functions point to that of the containing function, skipping built-in functions.
- Eval execution contexts point to that of their containing function (skipping built-in functions, including `eval` itself).
- Job execution contexts (which are largely a spec artifact) point to the script/module that originally enqueued the job.

In the course of doing this, a couple other substantial changes were introduced:

- Factored out ParseScript and ScriptEvaluation abstract operations, so that script parsing now better parallels module parsing.
- Added HostReportErrors for reporting both parsing errors and runtime errors, and wired it in to parsing and NextJob as appropriate.
@allenwb
Copy link
Member

allenwb commented Dec 15, 2015

What you are trying specify here seems very host specific and hence the complexity associated with it should be part of the HTML spec rather than the ES spec. But I think the main hook you need is already there.

Every execution context has a "code evaluation state" component. The intent of that component is that it corresponds to whatever implementation state is needed to actually execute/suspend/resume ES code. In practice it subsumes concepts such as native code cache references, program counters, literal frames, etc. It would also presumably abstract a source map or any other implementation specific state that describes characteristics of the executing code. I don't see why the "HTMLScript" association can't also be treated as part of the host/implementation code evaluation state".

If you look at it that way, then the "implementation dependent unhanded exception handling" just needs to be specified to use the "code evaluation state" of the context that originated the exception to determine the "HTMLScript" and any associated semantics.

There does seem to be a missing hook point that is a more general problem. Currently the point where the exception originated is not captured in a CompletionRecord. So, there is actually no way to get from the job level (implementation-dependent) unhandled exception handler back to the execution context that originated the exception. An likely fix for this is probably to capture a reference to the originating execution context within a throw Completion Record. The [[target]] field could probably be used for that purpose.

@bterlson
Copy link
Member

@allenwb I pulled this in today (forgetting I've yet to ask you to review it closely), but see here: 698819c!

@domenic
Copy link
Member Author

domenic commented Dec 16, 2015

In the end what we have here is used by both Node and browsers, so it's not host specific. But more importantly, it's true that this could be done by using the appropriate slots in execution contexts. The problem is we would need to add hooks in various places in the spec to allow the host to modify those slots (as seen from the many places the diff sets ScriptOrModule). As we concluded upthread it seems better and more natural to have ES track script/module associations, especially since ES already has a module record type, and introducing a script record type (as that commit does) brings script and module execution closer together, and once you have both of those it's a natural step.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants