@@ -865,3 +865,95 @@ getPlayers()
865865:: forEach (x  =>  console .log (x));
866866` ` ` 
867867
868+ ## Realm API 
869+ 
870+ [Realm API](https://github.com/tc39/proposal-realms) 提供沙箱功能(sandbox),允许隔离代码,防止那些被隔离的代码拿到全局对象。 
871+ 
872+ 以前,经常使用`  < iframe> ` 作为沙箱。
873+ 
874+ ` ` `  javascript
875+ const  globalOne  =  window ;
876+ let  iframe =  document .createElement (' iframe'  );
877+ document .body .appendChild (iframe);
878+ const  globalTwo  =  iframe .contentWindow ;
879+ ` ` ` 
880+ 
881+ 上面代码中,`  < iframe> ` 的全局对象是独立的(` iframe .contentWindow ` )。Realm API 可以取代这个功能。
882+ 
883+ ` ` `  javascript
884+ const  globalOne  =  window ;
885+ const  globalTwo  =  new  Realm ().global ;
886+ ` ` ` 
887+ 
888+ 上面代码中,`  Realm API ` 单独提供了一个全局对象` new  Realm ().global ` 。
889+ 
890+ Realm API 提供一个`  Realm ()` 构造函数,用来生成一个 Realm 对象。该对象的` global ` 属性指向一个新的顶层对象,这个顶层对象跟原始的顶层对象类似。
891+ 
892+ ` ` `  javascript
893+ const  globalOne  =  window ;
894+ const  globalTwo  =  new  Realm ().global ;
895+ 
896+ globalOne .evaluate (' 1 + 2'  ) //  3
897+ globalTwo .evaluate (' 1 + 2'  ) //  3
898+ ` ` ` 
899+ 
900+ 上面代码中,Realm 生成的顶层对象的`  evaluate ()` 方法,可以运行代码。
901+ 
902+ 下面的代码可以证明,Realm 顶层对象与原始对层对象是两个对象。 
903+ 
904+ ` ` `  javascript
905+ let  a1 =  globalOne .evaluate (' [1,2,3]'  );
906+ let  a2 =  globalTwo .evaluate (' [1,2,3]'  );
907+ a1 .prototype  ===  a2 .prototype ; //  false
908+ a1 instanceof  globalTwo .Array ; //  false
909+ a2 instanceof  globalOne .Array ; //  false
910+ ` ` ` 
911+ 
912+ 上面代码中,Realm 沙箱里面的数组的原型对象,跟原始环境里面的数组是不一样的。 
913+ 
914+ Realm 沙箱里面只能运行 ECMAScript 语法提供的 API,不能运行宿主环境提供的 API。 
915+ 
916+ ` ` `  javascript
917+ globalTwo .evaluate (' console.log(1)'  )
918+ //  throw an error: console is undefined
919+ ` ` ` 
920+ 
921+ 上面代码中,Realm 沙箱里面没有`  console ` 对象,导致报错。因为` console ` 不是语法标准,是宿主环境提供的。
922+ 
923+ 如果要解决这个问题,可以使用下面的代码。 
924+ 
925+ ` ` `  javascript
926+ globalTwo .console  =  globalOne .console ;
927+ ` ` ` 
928+ 
929+ ` Realm ()` 构造函数可以接受一个参数对象,该参数对象的`  intrinsics` 属性可以指定 Realm 沙箱继承原始顶层对象的方法。
930+ 
931+ ` ` `  javascript
932+ const  r1  =  new  Realm ();
933+ r1 .global  ===  this ;
934+ r1 .global .JSON  ===  JSON ; //  false
935+ 
936+ const  r2  =  new  Realm ({ intrinsics:  ' inherit'   });
937+ r2 .global  ===  this ; //  false
938+ r2 .global .JSON  ===  JSON ; //  true
939+ ` ` ` 
940+ 
941+ 上面代码中,正常情况下,沙箱的`  JSON ` 方法不同于原始的` JSON ` 对象。但是,` Realm ()` 构造函数接受`  { intrinsics:  ' inherit'   }` 作为参数以后,就会继承原始顶层对象的方法。
942+ 
943+ 用户可以自己定义`  Realm` 的子类,用来定制自己的沙箱。
944+ 
945+ ` ` `  javascript
946+ class  FakeWindow  extends  Realm  {
947+   init () {
948+     super .init ();
949+     let  global  =  this .global ;
950+ 
951+     global .document  =  new  FakeDocument (... );
952+     global .alert  =  new  Proxy (fakeAlert, { ...  });
953+     //  ...
954+   }
955+ }
956+ ` ` ` 
957+ 
958+ 上面代码中,`  FakeWindow` 模拟了一个假的顶层对象` window ` 。
959+ 
0 commit comments