Skip to content

Commit e191b13

Browse files
authored
removing the section about censoring stack frames (#384)
1 parent f028a3c commit e191b13

File tree

1 file changed

+5
-116
lines changed

1 file changed

+5
-116
lines changed

errors.md

+5-116
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Errors Propagation in ShadowRealm
22

3-
This document describes the various mechanism that different browsers must implement when exposing message and stack information via Error objects. The objective is to provide guidance for implementers.
3+
This document describes the various mechanism that different browsers must implement when exposing information via Error objects. The objective is to provide guidance for implementers.
44

55
## Errors Crossing Callable Boundary
66

7-
Errors thrown across the ShadowRealm's callable boundary in either direction are replaced by a fresh `TypeError` as described by the spec. Additionally, the new `TypeError` instance can be augmented with a `message` and `stack` properties to help developers.
7+
Errors thrown across the ShadowRealm's callable boundary in either direction are replaced by a fresh `TypeError` as described by the spec. Additionally, the new `TypeError` instance can be augmented with a `message` properties to help developers.
88

99
### New Error.message
1010

@@ -22,13 +22,11 @@ New `error.message` after crossing a boundary:
2222
TypeError: wrapped function threw, error was TypeError: null has no properties
2323
```
2424

25-
This error allows developers to clearly understand that the error was thrown from another Realm. If the error crosses multiple nested ShadowRealms, the second time the error is created when crossing another boundary, the message should still be formed from scratch rather than providing nesting of the message. The same applies to re-entrancing as well since the error re-entring the ShadowRealm where it was originated, will come as a brand new TypeError object, with no connection to the original Error object.
25+
This error allows developers to clearly understand that the error was thrown from another Realm. If the error crosses multiple nested ShadowRealms, the second time the error is copied when crossing another boundary, the message should still be formed from scratch rather than providing nesting of the message. The same applies to re-entrancing as well since the error re-entering the ShadowRealm where it was originated, will come as a brand new TypeError object, with no visible reference to the original Error object.
2626

27-
Accessing the `name` and `message` of the original Error object must not be observed by the user-land code. The following logic may be used:
27+
Accessing the `name` and `message` of the original Error object must not be observed by user-land code. The following logic may be used:
2828

29-
If _originalError_ has an `[[ErrorData]]` internal slot, then use the data values of `name` and `message` of the data properties. In case of accesor properties, use the cached values stored during the creation of the original error by the host.
30-
31-
_Note: It is possible to only cache the `name` and `message` if the error could cross a boundary (based on the stack frames)._
29+
If _originalError_ has an `[[ErrorData]]` internal slot, then use the data values of `name` and `message` of the data properties. In case of accessor properties, use the cached values stored during the creation of the original error by the host.
3230

3331
If _originalError_ does not have an `[[ErrorData]]` internal slot, then produce a generic message. E.g.:
3432

@@ -45,112 +43,3 @@ wrapped function threw, error was uncaught exception: Object
4543
```
4644

4745
_Note: FF implementation follows the logic described above._
48-
49-
### error.stack
50-
51-
A good error message is sometimes not enough. We encourage engines to enable their engine-specific stack introspection mechanisms for errors in ShadowRealms. In this case, the Error's stack is subject to censorship constraints.
52-
53-
Some of the use-cases for ShadowRealm, e.g., the virtualization, require a mechanism to control the error's stack, so those accessing it should not observe that the program is running inside a ShadowRealm. Early versions of the spec were simply nulling out the stack when an error crosses the callable boundary, but that was not sufficient, in fact, it was faulty for two main reasons:
54-
55-
1. It was impossible for developers to figure out where the error occurred, including errors from the module graph linkage phase.
56-
2. Errors originated from within a ShadowRealm, and observed inside the same ShadowRealm, were still leaking all the information.
57-
58-
This document describes how to solve both of these problems by applying a censoring process for all errors.
59-
60-
#### Censoring Error objects accessible within ShadowRealms
61-
62-
The first step is to make sure that when an error of any kind is observed (by reference) inside a ShadowRealm instance, the host is censoring all stack frames that are not associated to the ShadowRealm instance itself. This allows the following example to work properly:
63-
64-
```js
65-
try { null.foo } catch (e) {
66-
console.log(e.stack);
67-
throw e;
68-
}
69-
```
70-
71-
In the example above, `e` never crossed a callable boundary, but regardless, it should not contain a stack frame associated to another realm. Assuming that this error is observed (accessed) in two different places, a try/catch from above when running inside the ShadowRealm instances, and another try/catch in the incubator realm, which happens to be the main page (top level window), we should see two different error's stack for the two different errors:
72-
73-
1. ShadowRealm's `error.stack`:
74-
```
75-
foo@http://127.0.0.1:8081/y.js:2:5
76-
bar@http://127.0.0.1:8081/y.js:6:12
77-
captureStack@http://127.0.0.1:8081/x.js:9:9
78-
```
79-
80-
_Note: Only the 3 stack frames must be exposed on this error because they correspond to code evaluated inside the ShadowRealm associated to the error instance._
81-
82-
2. Main page's `Error.stack`:
83-
```
84-
foo@http://127.0.0.1:8081/y.js:2:5
85-
bar@http://127.0.0.1:8081/y.js:6:12
86-
captureStack@http://127.0.0.1:8081/x.js:9:9
87-
runInSandbox@http://127.0.0.1:8081/demo.html:6:17
88-
@http://127.0.0.1:8081/demo.html:8:1
89-
```
90-
91-
_Note: All 5 stack frames should be exposed on this error regardless of their location and associated Realms, this is analogous to what happen with same domain iframes today._
92-
93-
In the example above, we have 2 modules, `x.js` and `y.js`:
94-
95-
```js
96-
import { foo, bar } from './y.js';
97-
98-
export function letItThrow() {
99-
return foo();
100-
}
101-
102-
export function captureStack() {
103-
try {
104-
bar();
105-
} catch (e) {
106-
return e.stack;
107-
}
108-
return '';
109-
}
110-
```
111-
112-
```js
113-
export function foo() {
114-
return null.x;
115-
}
116-
117-
export function bar() {
118-
return foo();
119-
}
120-
```
121-
122-
The incubator realm running (demo.html) can do the following:
123-
124-
```js
125-
const s = new ShadowRealm();
126-
const letItThrow = await s.importValue('./x.js', 'letItThrow');
127-
const captureStack = await s.importValue('./x.js', 'captureStack');
128-
function runInSandbox() {
129-
letItThrow();
130-
// or captureStack();
131-
}
132-
runInSandbox();
133-
```
134-
135-
#### When not to censor Errors?
136-
137-
Since ShadowRealm provides integrity guarantees, errors instances belonging to a ShadowRealm are only accessible inside the ShadowRealm (thanks to the callable boundary), this censoring process only affect errors inside a ShadowRealm, developers, and dev-tools observing errors at the top level (main window), should still be able to observe the full stack information. This covers tools to collect metrics about errors, and any other mechanism running on the main program.
138-
139-
### Example
140-
141-
Now, let's assume that we have 3 programs:
142-
143-
- Main Program (running on top level)
144-
- Program A (running inside a ShadowRealm created by the Main Program)
145-
- Program B (running inside a ShadowRealm created by Program A)
146-
147-
The same mechanism must be applied if the error was generated by a child ShadowRealm B (Program B), which was created by Program A. Let's explore the different scenarios:
148-
149-
1. A try/catch in Program B catches the error, it will qualify to be censored, only revealing stack frames associated to the ShadowRealm where Program B runs, and none from Program A or the Main Program.
150-
1. A try/catch in Program A catches the error, it will qualify to be censored, only revealing stack frames associated to the ShadowRealm where Program A runs, and none from Program B or the Main Program.
151-
152-
Hosts can:
153-
154-
a) identify, at the time of creation of the original Error instance, if that error might cross the callable boundary, and store the original stack information, along with the `name` and `meessage`.
155-
b) generate a censored stack information depending on the realm observing the error.
156-
c) generate the stack information lazily by producing the stack when it is accessed the first time per realm.

0 commit comments

Comments
 (0)