mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-27 20:32:21 +00:00
docs(proposals): add Realm API
This commit is contained in:
parent
3eb580097f
commit
a9217ff93e
@ -865,3 +865,95 @@ getPlayers()
|
||||
::forEach(x => console.log(x));
|
||||
```
|
||||
|
||||
## Realm API
|
||||
|
||||
[Realm API](https://github.com/tc39/proposal-realms) 提供沙箱功能(sandbox),允许隔离代码,防止那些被隔离的代码拿到全局对象。
|
||||
|
||||
以前,经常使用`<iframe>`作为沙箱。
|
||||
|
||||
```javascript
|
||||
const globalOne = window;
|
||||
let iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
const globalTwo = iframe.contentWindow;
|
||||
```
|
||||
|
||||
上面代码中,`<iframe>`的全局对象是独立的(`iframe.contentWindow`)。Realm API 可以取代这个功能。
|
||||
|
||||
```javascript
|
||||
const globalOne = window;
|
||||
const globalTwo = new Realm().global;
|
||||
```
|
||||
|
||||
上面代码中,`Realm API`单独提供了一个全局对象`new Realm().global`。
|
||||
|
||||
Realm API 提供一个`Realm()`构造函数,用来生成一个 Realm 对象。该对象的`global`属性指向一个新的顶层对象,这个顶层对象跟原始的顶层对象类似。
|
||||
|
||||
```javascript
|
||||
const globalOne = window;
|
||||
const globalTwo = new Realm().global;
|
||||
|
||||
globalOne.evaluate('1 + 2') // 3
|
||||
globalTwo.evaluate('1 + 2') // 3
|
||||
```
|
||||
|
||||
上面代码中,Realm 生成的顶层对象的`evaluate()`方法,可以运行代码。
|
||||
|
||||
下面的代码可以证明,Realm 顶层对象与原始对层对象是两个对象。
|
||||
|
||||
```javascript
|
||||
let a1 = globalOne.evaluate('[1,2,3]');
|
||||
let a2 = globalTwo.evaluate('[1,2,3]');
|
||||
a1.prototype === a2.prototype; // false
|
||||
a1 instanceof globalTwo.Array; // false
|
||||
a2 instanceof globalOne.Array; // false
|
||||
```
|
||||
|
||||
上面代码中,Realm 沙箱里面的数组的原型对象,跟原始环境里面的数组是不一样的。
|
||||
|
||||
Realm 沙箱里面只能运行 ECMAScript 语法提供的 API,不能运行宿主环境提供的 API。
|
||||
|
||||
```javascript
|
||||
globalTwo.evaluate('console.log(1)')
|
||||
// throw an error: console is undefined
|
||||
```
|
||||
|
||||
上面代码中,Realm 沙箱里面没有`console`对象,导致报错。因为`console`不是语法标准,是宿主环境提供的。
|
||||
|
||||
如果要解决这个问题,可以使用下面的代码。
|
||||
|
||||
```javascript
|
||||
globalTwo.console = globalOne.console;
|
||||
```
|
||||
|
||||
`Realm()`构造函数可以接受一个参数对象,该参数对象的`intrinsics`属性可以指定 Realm 沙箱继承原始顶层对象的方法。
|
||||
|
||||
```javascript
|
||||
const r1 = new Realm();
|
||||
r1.global === this;
|
||||
r1.global.JSON === JSON; // false
|
||||
|
||||
const r2 = new Realm({ intrinsics: 'inherit' });
|
||||
r2.global === this; // false
|
||||
r2.global.JSON === JSON; // true
|
||||
```
|
||||
|
||||
上面代码中,正常情况下,沙箱的`JSON`方法不同于原始的`JSON`对象。但是,`Realm()`构造函数接受`{ intrinsics: 'inherit' }`作为参数以后,就会继承原始顶层对象的方法。
|
||||
|
||||
用户可以自己定义`Realm`的子类,用来定制自己的沙箱。
|
||||
|
||||
```javascript
|
||||
class FakeWindow extends Realm {
|
||||
init() {
|
||||
super.init();
|
||||
let global = this.global;
|
||||
|
||||
global.document = new FakeDocument(...);
|
||||
global.alert = new Proxy(fakeAlert, { ... });
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面代码中,`FakeWindow`模拟了一个假的顶层对象`window`。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user