You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Provide a `Global` constructor that produces a new instance of globalThis with `Global`, `eval`, `Function` constructor, and `ModuleSource` (or equivalent) constructor such that execution contexts
14
-
generated from the evaluators refer back to this global, and with
15
-
virtualized host behavior for dynamic import in script
16
-
contexts based on the `importHook` and `importMeta` provided.
17
-
Based on the `keys` option (that defaults to all) further fields are copied from the `globalThis` in which the `Global` constructor lives.
18
-
19
-
All options are optional.
20
-
13
+
Provide a `globalThis.Global` constructor that produces a new instance of
14
+
`globalThis` with a fresh set of evaluators: `eval`, `Function`,
15
+
`AsyncFunction`, `GeneratorFunction`, and `AsyncGeneratorFunction` that effect
16
+
evaluation with the new `Global` and its associated module map.
17
+
The constructor returns the new global with all of the internal slots of
18
+
`globalThis` and configurable copies of all the property descriptors from
19
+
`globalThis` or just those specified in the array of `keys`.
20
+
Dynamic `import` within these new evaluators is bound to the new global.
21
+
Dynamic `import` of a `ModuleSource` within these evaluators
22
+
instantiates that module in the new global's module map and in the lexical
23
+
scope of the new global.
24
+
25
+
> This proposal picks up from the previous proposal for
> from the [HardenedJS](https://hardenedjs.org)[`Compartment`
29
+
> proposal][proposal-compartment].
21
30
22
31
## Interfaces
32
+
23
33
```ts
24
34
interfaceGlobal {
25
35
constructor({
@@ -31,7 +41,6 @@ interface Global {
31
41
Global:typeofGlobal,
32
42
Function:typeofFunction,
33
43
eval:typeofeval,
34
-
ModuleSource:typeofModuleSource,
35
44
36
45
// and ...globalThis[...keys]
37
46
}
@@ -45,48 +54,138 @@ new globalThis.Global({
45
54
});
46
55
```
47
56
48
-
The `Global` constructor copies values for `keys` (or all entries if `keys` not specified) from the globalThis it originates from.
57
+
The `Global` constructor copies values for `keys` (or all entries if `keys` not
58
+
specified) from the globalThis it originates from.
49
59
50
60
Produces a _global_ with fresh:
51
-
-`Global` - the same Global constructor but copying values from the new _global_
52
-
-`Function` and `eval` - evaluators that execute code with the _global_ as the global scope and `importHook`,`importMeta` used for all imports encountered in the evaluated code
53
-
-`ModuleSource` - (tentatively, but we need some way to execute modules with that _global_) TBD
61
+
-`Global` - a new `Global` constructor that will use the new _global_ for
62
+
purposes of duplicating internal slots, the property descriptors of copied
63
+
`keys`, and its `importHook`.
64
+
-`Function` and `eval` - evaluators that execute code with the _global_ as the
65
+
global scope and `importHook`,`importMeta` used for all imports encountered
66
+
in the evaluated code
67
+
- All other function constructors, which can be accessed through `eval` and
68
+
their corresponding, undeniable syntax, like `global.eval('async () =>
69
+
{}').constructor`.
70
+
71
+
The global does not require a fresh `ModuleSource` because
72
+
the source is paired with the global by use of dynamic `import` in global evaluation,
73
+
as in `new Global().eval('specifier => import(specifier)')(specifier)`.
Tools like Mocha, Jest, and Jasmine install the verbs and nouns of their
95
+
domain-specific-language in global scope.
74
96
75
-
- what about non-enumerable keys?
76
-
- what about symbol keys?
77
-
- what copying semantics is used?
78
-
- would getters be invoked or copied?
97
+
Isolating these changes currently requires creation of a new realm,
98
+
and creating new realms comes with the hazard of identity discontinuity.
99
+
For example, `array instanceof Array` is not as reliable as `Array.isArray`,
100
+
and the hazard is not limited to intrinsics that have anticipated this
101
+
problem with work-arounds like `Array.isArray` or thenable `Promise` adoption.
79
102
80
-
structuredClone() is not part of ECMAScript, sadly
103
+
Some of these tools work around this problem by using the platforms existing
104
+
facility for creating a new `Global`, albeit an iframe or the Node.js `vm`
105
+
module.
106
+
Then, they are obliged to graft the intrinsics of one realm over the other,
107
+
which leaks for the cases of syntactically undeniable Realm-specific intrinsics
108
+
like the `AsyncFunction` constructor and prototype, and requires the
109
+
implementer to be vigilant to the extent that they graft every intrinsic from
110
+
one realm to another.
111
+
We have found such arrangements to be fragile and leaky.
81
112
82
-
### prototype chain in the browser
113
+
New `Global` provide an alternate solution: evaluate modules or scripts in a
114
+
separate global scope with shared intrinsics.
83
115
84
-
`globalThis` in the browser has a non-trivial prototype chain for some Window API functionality and events
116
+
```js
117
+
constdslGlobal=constnewGlobal({
118
+
globalThis: {
119
+
__proto__:globalThis,
120
+
describe,
121
+
before,
122
+
after,
123
+
}
124
+
});
125
+
dslGlobal.describe= () => {}
126
+
dslGlobal.before= () => {}
127
+
dslGlobal.after= () => {};
85
128
129
+
constsource=awaitimport.source(entrypoint);
130
+
awaitdslGlobal.eval('s => import(s)')(source);
131
+
```
132
+
133
+
In this example, only the entrypoint module for the DSL sees additional
134
+
globals.
135
+
The `source` adopts the import hook associatd with `dslGlobal` by
136
+
virtue of using the `dslGlobal`'s dynamic `import`.
137
+
Current DSLs cannot execute concurrently or depend on dynamic scope to track
138
+
the entrypoint that called each DSL verb.
139
+
140
+
### Enforcing the principle of least authority
141
+
142
+
On the web, the same origin policy has become sufficiently effective at
143
+
preventing cross-site scripting attacks that attackers have been forced to
144
+
attack from within the same origin.
145
+
Conveniently for attackers, the richness of the JavaScript library ecosystem
146
+
has produced ample vectors to enter the same origin.
147
+
The vast bulk of a modern web application is its supply chain, including code
148
+
that will be eventually incorporated into the scripts that will run in the same
149
+
origin, but also the tools that generate those scripts, and the tools that
150
+
prepare the developer environment.
151
+
152
+
The same-origin-policy protects the rapidly deteriorating fiction that
153
+
web browsers mediate an interaction between just two parties: the service and
154
+
the user.
155
+
For modern applications, particularly platforms that mediate interactions among
156
+
many parties or simply have a deep supply chain, web application developers
157
+
need a mechanism to isolate third-party dependencies and minimize their access
158
+
to powerful objects like high resolution timers or network, compute, or storage
159
+
capability bearing interfaces.
160
+
161
+
Some hosts, including a community of embedded systems represented at [ECMA
162
+
TC53][tc53], do not have an origin on which to build a same-origin-policy, and
163
+
have elected to build their security model on isolated evaluators, through the
164
+
high-level Compartment interface.
165
+
166
+
## Intersection Semantics
167
+
168
+
### Shared Structs
169
+
170
+
We expect that the new global, like old globals, would have both its own module
171
+
map and also shared struct prototype registry, such that a module executed
172
+
within that global would produce its own shared struct prototypes.
173
+
This gives platforms a place to stand to ensure that separate globals do not
174
+
share any undeniable mutable state.
175
+
176
+
## Design Questions
177
+
178
+
### prototype chain in the browser
179
+
180
+
`globalThis` in the browser has a non-trivial prototype chain for some Window
181
+
API functionality and events.
86
182
87
183
### Backward compatibility and the `constructor` field on a global
88
184
89
-
`globalThis` already has a constructor in the browser and that constructor is `Window`, an _Illegal constructor_ as one can inform themselves by attempting to invoke it
185
+
`globalThis` already has a constructor in the browser and that constructor is
186
+
`Window`, an _Illegal constructor_ as one can inform themselves by attempting
0 commit comments