Skip to content

Commit 0aaeef8

Browse files
authored
chore: clean up the repo (#16)
1 parent 2146643 commit 0aaeef8

File tree

7 files changed

+369
-226
lines changed

7 files changed

+369
-226
lines changed

README.md

Lines changed: 18 additions & 226 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# new Global
1+
# Module global
22

3-
Stage: To be presented for advancement to stage 1 at a future TC-39 plenary.
3+
Stage: 1
44

55
Champions:
66

@@ -9,168 +9,17 @@ Champions:
99
- Richard Gibson (RGN), Agoric, @gibson042
1010
- Mark S. Miller (MM), Agoric, @erights
1111

12-
## Synopsis
12+
## Problem statement
13+
14+
A way to evaluate a module and its dependencies in the context of a new global scope within the same Realm
1315

14-
Provide a `globalThis.Global` constructor that produces a new instance of
15-
`globalThis` with a fresh set of evaluators: `eval`, `Function`,
16-
`AsyncFunction`, `GeneratorFunction`, and `AsyncGeneratorFunction` that effect
17-
evaluation with the new `Global` and its associated module map.
18-
The constructor returns the new global with all of the internal slots of
19-
`globalThis` and configurable copies of all the property descriptors from
20-
`globalThis` or just those specified in the array of `keys`.
21-
Dynamic `import` within these new evaluators is bound to the new global.
22-
Dynamic `import` of a `ModuleSource` within these evaluators
23-
instantiates that module in the new global's module map and in the lexical
24-
scope of the new global.
2516

26-
This proposal does not attempt to create a new category of global object, but
27-
creates a mechanism for replicating the existing types such that import and
28-
evaluation behavior can be scoped to different instances.
2917

3018
> This proposal picks up from the previous proposal for
3119
> [Evaluators](https://github.com/tc39/proposal-compartments/blob/7e60fdbce66ef2d97370007afeb807192c653333/3-evaluator.md)
3220
> from the [HardenedJS](https://hardenedjs.org) [`Compartment` proposal][proposal-compartments] and depends upon [proposal-import-hook][],
3321
> [proposal-esm-phase-imports][], and [proposal-source-phase-imports][].
3422
35-
## Interfaces
36-
37-
```ts
38-
interface Global {
39-
constructor({
40-
keys?: string[],
41-
importHook?: ImportHook,
42-
importMetaHook?: ImportMetaHook,
43-
})
44-
45-
Global: typeof Global,
46-
eval: typeof eval,
47-
Function: typeof Function,
48-
// Consequently, internal slots for
49-
// AsyncFunction , GeneratorFunction, AsyncGeneratorFunction
50-
51-
// ... and properties copied from globalThis filtered by keys
52-
}
53-
```
54-
55-
<details>
56-
<summary>proper typescript definition</summary>
57-
58-
```ts
59-
interface Global<K extends keyof typeof globalThis = never> extends Pick<typeof globalThis, K> {
60-
constructor({
61-
keys?: K[],
62-
importHook?: ImportHook,
63-
importMetaHook?: ImportMetaHook,
64-
})
65-
66-
Global: typeof Global,
67-
eval: typeof eval,
68-
Function: typeof Function
69-
}
70-
71-
````
72-
73-
</details>
74-
75-
_Example_
76-
77-
```js
78-
const newGlobal = new globalThis.Global({
79-
keys: ['Buffer'],
80-
importHook,
81-
importMetaHook,
82-
});
83-
84-
newGlobal.process = { env: process.env }
85-
```
86-
87-
The `Global` constructor copies properties for `keys` (or all properties if
88-
`keys` not specified) from the `globalThis` it originates from, except
89-
`configurable` even if they were not.
90-
91-
Produces a _global_ with fresh:
92-
93-
- `Global` - a new `Global` constructor that will use the new _global_ for
94-
purposes of duplicating internal slots, the property descriptors of copied
95-
`keys`, and its `importHook`.
96-
- `Function` and `eval` - evaluators that execute code with the _global_ as the
97-
global scope and `importHook`,`importMetaHook` used for all imports encountered
98-
in the evaluated code
99-
- All other function constructors, which can be accessed through `eval` and
100-
their corresponding, undeniable syntax, like `global.eval('async () =>
101-
{}').constructor`.
102-
103-
The global does not require a fresh `ModuleSource` because
104-
the source is paired with the global by use of dynamic `import` in global evaluation,
105-
as in `new Global().eval('specifier => import(specifier)')(specifier)`.
106-
107-
### Invariants:
108-
109-
110-
111-
- By default the new global would get the same prototype as parent
112-
- The [[Prototype]] **MUST** be settable
113-
114-
```js
115-
const newGlobal = new Global();
116-
Object.setPrototypeOf(newGlobal, Object.prototype);
117-
```
118-
119-
All properties grafted by default
120-
121-
```js
122-
globalThis.x = {};
123-
const newGlobal = new globalThis.Global();
124-
newGlobal.Object === globalThis.Object;
125-
newGlobal.x === globalThis.x;
126-
```
127-
128-
Properties can be selectively grafted
129-
130-
```js
131-
globalThis.x = {};
132-
globalThis.y = {};
133-
const newGlobal = new Global({
134-
keys: ["y"],
135-
});
136-
newGlobal.x === undefined;
137-
newGlobal.y === globalThis.y;
138-
newGlobal.Object === undefined;
139-
```
140-
141-
Own unique evaluators, but shared prototypes
142-
143-
```js
144-
const newGlobal = new Global();
145-
newGlobal.eval !== thisGlobal.eval;
146-
newGlobal.Global !== thisGlobal.Global;
147-
newGlobal.Function !== thisGlobal.Function;
148-
newGlobal.Function.prototype === thisGlobal.Function.prototype;
149-
```
150-
151-
Other unique intrinsic evaluators also share prototypes
152-
153-
```js
154-
const newGlobal = new Global();
155-
newGlobal.eval("Object.getPrototypeOf(async () => {})") ===
156-
Object.getPrototypeOf(async () => {});
157-
newGlobal.eval("Object.getPrototypeOf(function *() {})") ===
158-
Object.getPrototypeOf(function* () {});
159-
newGlobal.eval("Object.getPrototypeOf(async function *() {})") ===
160-
Object.getPrototypeOf(async function* () {});
161-
```
162-
163-
Inherits host import hook and module map
164-
165-
```js
166-
const newGlobal = new Global();
167-
const fs1 = await import("node:fs");
168-
const fs2 = await newGlobal.eval('import("node:fs")');
169-
fs1 === fs2; // if present
170-
```
171-
172-
---
173-
17423
## Motivation
17524

17625
### Domain Specific Languages
@@ -185,7 +34,7 @@ and the hazard is not limited to intrinsics that have anticipated this
18534
problem with work-arounds like `Array.isArray` or thenable `Promise` adoption.
18635

18736
Some of these tools work around this problem by using the platforms existing
188-
facility for creating a new `Global`, albeit an iframe or the Node.js `vm`
37+
facility for creating a new global context, albeit an iframe or the Node.js `vm`
18938
module.
19039
Then, they are obliged to graft the intrinsics of one realm over the other,
19140
which leaks for the cases of syntactically undeniable Realm-specific intrinsics
@@ -194,26 +43,9 @@ implementer to be vigilant to the extent that they graft every intrinsic from
19443
one realm to another.
19544
We have found such arrangements to be fragile and leaky. Also costly in memory efficiency and developer time.
19645

197-
New `Global` provide an alternate solution: evaluate modules or scripts in a
46+
This proposal provides an alternate solution: evaluate modules or scripts in a
19847
separate global scope with shared intrinsics.
19948

200-
```js
201-
const dslGlobal = const new Global();
202-
dslGlobal.describe = () => {}
203-
dslGlobal.before = () => {}
204-
dslGlobal.after = () => {};
205-
206-
const source = await import.source(entrypoint);
207-
await dslGlobal.eval('s => import(s)')(source);
208-
```
209-
210-
In this example, only the entrypoint module for the DSL sees additional
211-
globals.
212-
The `source` adopts the import hook associated with `dslGlobal` by
213-
virtue of using the `dslGlobal`'s dynamic `import`.
214-
Current DSLs cannot execute concurrently or depend on dynamic scope to track
215-
the entrypoint that called each DSL verb.
216-
21749
### Enforcing the principle of least authority
21850

21951
On the web, the same origin policy has become sufficiently effective at
@@ -250,41 +82,18 @@ With `Global` constructor comes the ability to isolate fragments of the applicat
25082
AI generated sources from independently working agents can come with colliding names for global variables to use and may need separate global scopes to collaborate or coexist. Similarly a misguided attempt at an inline polyfill by an AI or a package author could be prevented by freezing the parts of the new global in which the unreliable code subsequently runs.
25183
Using a new global instead of a new Realm avoids the issues like identity discontinuity impeding the composition of software where function calls need to happen across the isolated and non-isolated code.
25284

253-
The isolation use case depends also on the interaction with `importHook` and `ModuleSource` as described in
254-
255-
https://github.com/endojs/proposal-import-hook/?tab=readme-ov-file#new-global
256-
25785

25886
### Incremental or in-context execution
25987

26088
There are tools that currently use much more complex and costly mechanisms (similar to the ones described in [Domain Specific Languages](#domain-specific-languages) among other) to provide the ability to execute fragments of JavaScript code in a very specific context of the tool.
26189

26290
That includes REPLs, inline code execution results in editors (eg. [Quokka.js](https://quokkajs.com/)) and various use cases of IDEs in the browser.
26391

264-
Maintaining the global state between executions of user-provided code snippets would benefit from a `Global` constructor.
92+
Maintaining the global state between executions of user-provided code snippets would benefit from the ability to control scope
26593

26694
## Intersection Semantics
26795

268-
### Shared Structs
269-
270-
We expect that the new global, like old globals, would have both its own module
271-
map and also shared struct prototype registry, such that a module executed
272-
within that global would produce its own shared struct prototypes.
273-
This gives platforms a place to stand to ensure that separate globals do not
274-
share any undeniable mutable state.
275-
276-
### Import Hook
277-
278-
The interaction between importHook and Global is described in the importHook proposal
279-
https://github.com/endojs/proposal-import-hook/?tab=readme-ov-file#new-global
280-
281-
### Get Intrinsic
282-
283-
see https://github.com/tc39/proposal-get-intrinsic
284-
285-
A `new Global` object would need to be the source for `Reflect.getIntrinsic` to get the correct evaluators (including `%AsyncFunction%` etc.) from the internal slots and preserve the limited scope of the _global_ if `keys` were set.
286-
287-
`Reflect` would need to be unique own property of a new _global_
96+
TBD
28897

28998
## Design Questions
29099

@@ -305,47 +114,30 @@ while (pro = Object.getPrototypeOf(pro)) {
305114
[object WindowProperties]
306115
[object EventTarget]
307116
[object Object]
117+
null
118+
```
119+
```
120+
// web extension contentscript
121+
[object Window]
122+
[object WindowProperties]
123+
null
308124
```
309125
```
310126
// Node.js
311127
[object Object]
312128
[object Object]
129+
null
313130
```
314131
```
315132
// Deno
316133
[object Window]
317134
[object EventTarget]
318135
[object Object]
136+
null
319137
```
320138
```
321139
// Hermes
322140
[object Object]
323141
undefined
324142
```
325143

326-
327-
### Backward compatibility and the `constructor` field on a global
328-
329-
`globalThis` already has a constructor in the browser and that constructor is
330-
`Window`, an _Illegal constructor_ as one can inform themselves by attempting
331-
to invoke it.
332-
333-
```js
334-
globalThis.constructor === Window;
335-
const g1 = new Global();
336-
337-
// Which of the following should be true?
338-
339-
g1.globalThis.constructor === Global; // Gets in the way of the web standards potentially
340-
g1.globalThis.constructor === g1.globalThis.Global; // definitely not
341-
g1.globalThis.constructor === g1.globalThis.Window; // maybe?
342-
g1.globalThis.Window === Global; // Would Window no longer be an Illegal constructor?
343-
```
344-
345-
346-
[proposal-source-phase-imports]: https://github.com/tc39/proposal-source-phase-imports
347-
[proposal-esm-phase-imports]: https://github.com/tc39/proposal-esm-phase-imports
348-
[proposal-compartments]: https://github.com/tc39/proposal-compartments
349-
[proposal-import-hook]: https://github.com/endojs/proposal-import-hook
350-
351-
````

0 commit comments

Comments
 (0)