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
* [Why not separate processes?](#Whynotseparateprocesses)
33
+
34
+
<!-- vscode-markdown-toc-config
35
+
numbering=false
36
+
autoSave=true
37
+
/vscode-markdown-toc-config -->
38
+
<!-- /vscode-markdown-toc -->
39
+
40
+
## <aname='Introduction'></a>Introduction
4
41
5
42
Realms are a distinct global environment, with its own global object containing its own intrinsics and built-ins (standard objects that are not bound to global variables, like the initial value of Object.prototype).
6
43
@@ -10,7 +47,7 @@ The Realms API does not create - or rely on - a new executing thread. New realms
10
47
11
48
Any code executed within this realm may introduce changes to global variables or built-ins, but limited to the realm global Record.
@@ -37,8 +66,9 @@ It's quite common for an applications to contain programs from multiple sources,
37
66
Various examples where Realms can be used to avoid this:
38
67
39
68
* Web-based IDEs or any kind of 3rd party code execution uses same origin evaluation.
40
-
* Test frameworks (in-browser tests, but also in node using `vm`).
41
-
* testing/mocking (e.g., jsdom)
69
+
* DOM Virtualization (e.g.: AMP)
70
+
* Test frameworks and reporters(in-browser tests, but also in node using `vm`).
71
+
* testing/mocking (e.g.: jsdom)
42
72
* Most plugin mechanism for the web (e.g., spreadsheet functions).
43
73
* Sandboxing (e.g.: Oasis Project)
44
74
* Server side rendering (to avoid collision and data leakage)
@@ -47,42 +77,158 @@ Various examples where Realms can be used to avoid this:
47
77
48
78
Note: the majority of the examples above will require synchronous operations to be supported, which makes it almost impossible to use Workers & co., or any other isolation mechanism in browsers and nodejs today.
49
79
50
-
## Overview
80
+
## <aname='Clarifications'></a>Clarifications
81
+
82
+
### <aname='Terminology'></a>Terminology
83
+
84
+
In the Web Platform, both `Realm` and `Global Object` are usually associated to Window, Worker, and Worklets semantics. They are also associated to their detachable nature.
85
+
86
+
This proposal is limited to the semantics specified by ECMA-262 with no extra requirements from the web counterparts.
87
+
88
+
### <aname='TheRealmsGlobalObject'></a>The Realm's Global Object
89
+
90
+
- The Realm's [Global Object](https://tc39.es/ecma262/#sec-ordinary-object) is an [Ordinary Object](https://tc39.es/ecma262/#sec-ordinary-object).
91
+
- A Realm Object (and its global object) are not detachable
92
+
- A Realm Object has a lifeline to its incubator Realm
93
+
94
+

95
+
96
+
### <aname='Evaluation'></a>Evaluation
97
+
98
+
The Realm API does not introduce a new way to evaluate code, it reuses the existing evaluation mechanisms:
99
+
100
+
- If you disable CSP `unsafe-eval`, you cannot evaluate code synchronously.
101
+
- If you disable CSP `default-src`, you cannot use `Realm.prototype.import()`.
102
+
103
+
### <aname='Modulegraph'></a>Module graph
104
+
105
+
Every Realm object has its own module graph.
106
+
107
+
```js
108
+
constrealm=newRealm();
109
+
110
+
// imports code that executes within its own environment.
Code generation should not be subject to pollution (global, prototype, etc.). E.g.: Lodash's `_.template()` uses `Function(...)` to create a compiled template function, instead it could use a Realm to avoid leaking global variables. The same Realm could be reused multiple times.
195
+
196
+
```js
197
+
var compiled =_.template(
198
+
'<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>'
In principle, the Realm proposal does not provide the controls for the module graphs. Every new Realm initializes its own module graph, while any invocation to `Realm.prototype.import()` method, or by using `import()` when evaluating code inside the realm, will populate this module graph. This is analogous to same-domain iframes, and VM in nodejs.
88
234
@@ -100,25 +246,23 @@ There are some precedents on how to solve the identity discontinuity issues by u
100
246
101
247
There is one important thing to keep in mind when it comes to sharing module graphs. The ESM linkage is not asynchronous. This dictates that in order to share modules between realms, those realms should share the same process, otherwise the bindings between those modules cannot work according to the language. This is another reason to support our claim that Realms should be running within the same process.
102
248
103
-
## Use Cases
249
+
## <aname='GeneralGoalsandValuesforRealms'></a>General Goals and Values for Realms
104
250
105
-
### Integrity
251
+
### <aname='Integrity'></a>Integrity
106
252
107
253
We believe that realms can be a good complement to integrity mechanisms by providing ways to evaluate code who access different object graphs (different global objects) while maintaining the integrity of the outer realm. A concrete example of this is the Google's AMP current mechanism:
108
254
109
255
* Google News App creates multiples sub-apps that can be presented to the user.
110
256
* Each sub-app runs in a cross-domain iframe (communicating with the main app via post-message).
111
257
* Each vendor (one per app) can attempt to enhance their sub-app that display their content by executing their code in a realm that provide access to a well defined set of APIs to preserve the integrity of the sub-app.
112
258
113
-
_TODO: cc @jridgewell to see if this is accurate._
114
-
115
259
There are many examples like this for the web: Google Sheets, Figma's plugins, or Salesforce's Locker Service for Web Components.
116
260
117
-
#### Security vs Integrity
261
+
#### <aname='SecurityvsIntegrity'></a>Security vs Integrity
118
262
119
263
There are also other more exotic cases in which measuring of time ("security") is not a concern, especially in IOT where many devices might not have process boundaries at all. Or examples where security is not a concern, e.g.: test runners like jest (from facebook) that relies on nodejs, JSDOM and VM contexts to execute individual tests while sharing a segment of the object graph to achieve the desired performance budget. No doubts that this type of tools are extremely popular these days, e.g.: JSDOM has 10M installs per week according to NPM's registry.
The usage of different realms allow customized access to the global environment. To start, The global object could be immediately frozen.
124
268
@@ -147,7 +291,7 @@ realm.import('./file.js');
147
291
iframe.contentWindow.eval("import('./file.js')");
148
292
```
149
293
150
-
#### DOM mocking
294
+
#### <aname='DOMmocking'></a>DOM mocking
151
295
152
296
The Realms API allows a much smarter approach for DOM mocking, where the globalThis can be setup in userland. This also takes advantage of the Realm constructor being subclassable:
153
297
@@ -166,50 +310,21 @@ class FakeWindow extends Realm {
166
310
167
311
This code allows a customized set of properties to each new Realm and avoid issues on handling immutable accessors/properties from the Window proxy. e.g.: `window.top`, `window.location`, etc..
168
312
169
-
## Testing
170
-
171
-
The Realms API is very useful for testing purposes. It can provide a limited context that can observe code reliance:
172
-
173
-
```js
174
-
importTesterfrom'myTestFramework';
175
-
176
-
classTestRealmextendsRealm {
177
-
constructor(...args) {
178
-
super(...args);
179
-
constglobalThis=this.globalThis;
180
-
181
-
// Loads the globalThis with the Tester API
182
-
Object.assign(globalThis, newTester());
183
-
184
-
Object.freeze(globalThis);
185
-
}
186
-
187
-
asyncexec(testFile) {
188
-
// Assuming testFile matches a valid loader specifier
189
-
returnawaitthis.import(testFile);
190
-
}
191
-
}
192
-
193
-
constmyTests=newTestRealm();
194
-
195
-
myTests.exec('./hanoi-tower-spec.js');
196
-
```
197
-
198
-
## Alternatives
313
+
## <aname='Alternatives'></a> Alternatives
199
314
200
-
### Status Quo
315
+
### <aname='StatusQuo'></a>Status Quo
201
316
202
317
Using VM module in nodejs, and same-domain iframes in browsers. Although, VM modules in node is a very good approximation to this proposal, iframes are problematic.
203
318
204
-
### Iframes
319
+
### <aname='Iframes'></a>Iframes
205
320
206
321
Developers can technically already create a new Realm by creating new same-domain iframe, but there are few impediments to use this as a reliable mechanism:
207
322
208
323
* the global object of the iframe is a window proxy, which implements a bizarre behavior, including its unforgeable proto chain.
209
324
* there are multiple ~~unforgeable~~ unvirtualizable objects due to the DOM semantics, this makes it almost impossible to eliminate certain capabilities while downgrading the window to a brand new global without DOM.
210
325
* global `top` reference is ~~unforgeable~~ not virtualizable and leaks a reference to another global object. The only way to null out this behavior is to detach the iframe, which imposes other problems, the more relevant is dynamic `import()` calls, __which cannot work in detached realms__.
211
326
212
-
### Why not separate processes?
327
+
### <aname='Whynotseparateprocesses'></a>Why not separate processes?
213
328
214
329
This is another alternative, creating a Realm that runs in a separate process, while allowing users to define and create their own protocol of communication between these processes. This alternative was discarded for two main reasons:
0 commit comments