-
Notifications
You must be signed in to change notification settings - Fork 903
Separate top level scope and globalThis.
#2161
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
base: master
Are you sure you want to change the base?
Separate top level scope and globalThis.
#2161
Conversation
|
Okay, I've almost got this sorted. There remain a small set of failing tests due to nested scopes and associated values, which think I can tackle. This has required an API change in how we create nested scopes from a common sealed parent. I'm going to try and distill that down to a simple API, maybe something like |
2fecd46 to
10c5f88
Compare
|
One concern I have is that it's not great how in so many places you have to do: if (scope instanceof TopLevel) {
scope = ((TopLevel) scope).getGlobalThis();
}I am unsure on how we could improve it, but it's really diffused basically everywhere we have I am not sure why you are doing all the delegation in |
|
@andreabergia I agree that I don't really like the tests for top level that are now scattered through several bits of initialisation code. The original reason to not force the top scope to be a I've prototyped this by doing it in stages
I'm currently on step 2. and have had make small adjustments to four tests, and have another four which seem to need similar fixes. @gbrail how would you feel about this API change? |
|
Okay, I've moved all the initialisation stuff over to requiring a There are still couple of explicit checks for |
|
Well, that went well. 😆 so it turns out that even if we force the creation of all top level scopes to be actual
The serialisation problem is similar in that the relationship between the top level scope and the global this has been fully set up at the point when something is trying to rely on that. I’m setting this back to draft until I can track down those problems. |
|
Had a burst of inspiration this morning and got this down to about 30 failing test cases. I think all the remaining cases are actual bugs where we ended up with The serialisation problem is occurring because of the way I handled associated values on the top level scope. To enable the creation of isolates I put the values on the global object rather than the scope, and relied on being able to reach that object before it has been associated with top level scope, so the lookup breaks. I think the thing to do here is to delegate associated values explicitly when creating isolates. I think two top level scopes created from a sealed shared scope should be guaranteed to share the same type cache. |
Another draft PR on the road to separating scopes and scriptable objects (#2163). I've put the rationale for doing this in a separate issue(#2164)
The global scope in EcmaScript is a a little subtle in that it consists of a declaration environment record and an object environment record for the global object (
globalThis). The global object contains variable declarations, function declarations, generator function declarations, async function declarations, and async generator function declarations. Everything else (constdeclarations,letdeclarations,classdeclarations, etc.) goes on declaration environment and is not added toglobalThis. This change could make that full separation, but currently there is one test inMozillaSuiteTestwhich depends on aconstdeclaration being added to the globalthis. I wonder if we should gate that on a language version.This is working well apart from a couple of edge cases that I think it's worth talking through:
ImporterTopLevelis mostly working, but I don't think I have a great model of how it should work. Currently The behaviour for package lookup is living on the scope half, but I'm wondering ifImporterTopLevelshould really put all the behaviour on a customGlobalThis.globalThis, but maybe like java imports it should live on that half.FunctionObject(which is currently the only way the existingcustomGlobaltest works). The existingModuleScopemodel also doesn't matchrequirein node or common-js.Let me expand on that last point slightly. If I have a file
blah.jscontainingand from node REPL I do
Then we find
thing2 === globalThisandthing2 === thing4.requiresimply introduces a new scope (just like a function does) rather than what we do with a module scope (a new top level scope that happens to have another top level scope as the prototype). What we have doesn't match that, but it also doesn't match the behaviour ofimportwhich should have an entirely separate realm (top level scope).I think I can see two possible ways to resolve this:
globalThis, and the module scope becomes a normal child scope. This would be closest to node as far as I can tell. We might well want to keep theModuleScopeas a special class to mark that we are in a module for relative requires etc.globalThisof whatever custom type provided. To avoid mutating the mainglobalThiswhen executing code in a module we'd need to ensure all modules execute on child scopes of this main module scope (but those need not themselves beModuleScopes, and we'd need to find allinstanceof ModuleScopechecks which currently look at thethisObjand change them to appropriate top scope checks.I don't know if @youngj is still around, still has their use case, and has an opinion on this. I can't tell how well covered this area really is because our Jacoco reports in
rhinoonly cover the tests inrhino, while the coverage report intestsdoesn't seem to be configured to show the core runtime classes.