环境代理
沙箱的本质是 ES6 引入的 Proxy 对象,即子应用访问到的 window、document 等都是被代理过的伪装对象,只不过应对具体需求定制了更有利的行为。
下面分别列举了 window 和 document 对象上被定制的属性。
window
| 对象/方法 | 行为 |
|---|---|
| addEventListener | 注册的任何事件在沙箱退出时会被自动从 window 上移除。 |
| removeEventListener | - |
| dispatchEvent | 除非在 escapeWindowEvents 中声明,否则默认派发的事件只作用在沙箱内部,不会被外部接收到。 |
| window | 返回 window 代理对象,只读 |
| self | 返回 window 代理对象,只读 |
| top | 如果当前页面没有父页面,那么返回 window 代理对象,否则返回真实的 top 值,只读 |
| parent | 如果当前页面没有父页面,那么返回 window 代理对象,否则返回真实的 parent 值,只读 |
| gloalThis | 返回 window 代理对象,只读 |
| document | 返回 document 对象,只读 |
| location | 返回真实 location 对象,代理它是因为受到上下文的限制,location 不可以从 Proxy 上获取 |
| localStorage | 如果开启了 sandbox.patches.localStorage,返回一个 Proxy 对象,其读写的 key 均自动增加 appname 前。比如在 foo 下,localStorage.setItem('nano') 实际上写入的是"foo:nano" |
| setTimeout | 如果开启了 sandbox.patches.setTimeout,那么将在沙箱退出时自动 clearTimeout。 |
| setInterval | 如果开启了 sandbox.patches.setInterval,那么将在沙箱退出时自动 clearInterval。 |
| XMLHttpRequest | 如果开启了 sandbox.patches.XMLHttpRequest,那么将在沙箱退出时自动 abort。 |
| MutationObserver | 如果开启了 sandbox.patches.MutationObserver,那么将在沙箱退出时自动 disconnect。 |
| requestAnimationFrame | 如果开启了 sandbox.patches.requestAnimationFrame,那么将在沙箱退出时自动 cancelAnimationFrame。该选项只在支持该函数的浏览器环境下有效。 |
| requestIdleCallback | 如果开启了 sandbox.patches.requestIdleCallback,那么将在沙箱退出时自动 cancelIdleCallback。该选项只在支持该函数的浏览器环境下有效。 |
| fetch | 如果开启了 sandbox.patches.fetch,并且调用fetch时没有传递 signal,那么将自动添加此参数,并在沙箱退出时自动 abort。该选项只在支持AbortController的浏览器环境下有效。 |
| eval | 计划中 |
document
| 对象/方法 | 行为 |
|---|---|
| addEventListener | 注册的任何事件在沙箱退出时会被自动从 document 上移除。 |
| removeEventListener | - |
| dispatchEvent | 除非在 escapeDocumentEvents 中声明,否则默认派发的事件只作用在沙箱内部,不会被外部接收到。 |
| open | 无任何效果,控制台会打印一条警告信息。 |
| close | 无任何效果,控制台会打印一条警告信息。 |
| write | 无任何效果,控制台会打印一条警告信息。 |
| writeln | 无任何效果,控制台会打印一条警告信息。 |
| replaceChildren | 无任何效果,控制台会打印一条警告信息。 |
| getElementById | 只局限在应用自身 <haploid-html> 元素及后代中查询。 |
| getElementsByClassName | 只局限在应用自身 <haploid-html> 元素及后代中查询。 |
| getElementsByTagName | 同上,但是如果参数为 "html"、"body"、"head" 或者 "title",那么将返回对应的 <haploid-*> 元素,例如: document.getElementsByTagName("html") // <haploid-html> document.getElementsByTagName("head") // <haploid-head> document.getElementsByTagName("title") // <haploid-title> document.getElementsByTagName("body") // <haploid-body> |
| querySelector | 同上 |
| querySelectorAll | 同上 |
| getElementsByTagNameNS | 同上 |
| createComment | 创建的节点的下列属性被重新定义:
|
| createDocumentFragment | 同上 |
| createAttribute | 同上 |
| createAttributeNS | 同上 |
| createTextNode | 同上 |
| createTextNode | 同上,但是:
|
| createElementNS | 同上 |
| defaultView | 返回 window 代理对象,只读 |
| documentElement | 返回 <haploid-html> 元素,如果 enableHtmlPretending 被开启,该元素的下列属性会被重新定义:
|
| title | 返回 <haploid-title> 元素的文本内容,可写 |
| head | 返回上述 <haploid-head> 元素,如果 enableHeadPretending 被开启,该元素的下列属性会被重新定义:
|
| body | 返回上述 <haploid-body> 元素,如果 enableBodyPretending 被开启,该元素的下列属性会被重新定义:
|
| all | 只局限在应用自身 <haploid-html> 元素及后代中查询 |
| forms | 同上 |
| embeds | 同上 |
| plugins | 同上 |
| images | 同上 |
| links | 同上 |
| styleSheets | 同上 |
| scripts | 同上,但查询 <haploid-script> 而不是 <script> |
| children | 返回只包含 <haploid-html> 的HTMLCollection |
| childNodes | 返回只包含 <haploid-html> 的 NodeListOf<ChildNode> |
| childElementCount | 返回1 |
| firstElementChild | 返回 <haploid-html> |
| lastElementChild | 返回 <haploid-html> |
| dir | 返回 <haploid-html> 的 dir 属性,可写 |
| hidden | |
| visibilityState | |
| baseURI | 目前返回 entry URL,或者当前浏览器页面 URL。未来将支持 <base> |
| location | 返回真实 location 对象,代理它是因为受到上下文的限制,location 不可以从 Proxy 上获取 |
| cookie | 返回真实 cookie 对象,代理它是因为受到上下文的限制,cookie 不可以从 Proxy 上获取 |
| readyState | 只读,初始为 "loading",在请求子应用CSS和JS之前变为 "interactive",请求并执行完毕后变为 "complete"。如果在 autoDocumentEvents 中声明 readystatechange,那么该属性的变化会在 document 代理对象上触发 readystatechange 事件,这一事件是局域内事件 |
| lastModified | 只读,以标准的 DD/MM/YY HH:ii:ss 格式返回 entry URL 的 Last Modified HTTP Header被解析后的日期字符串。如果没有 entry 或者获取 Header 失败,每次会返回当前时间。 |
注意
上述API可能返回的 NodeListOf、HTMLAllCollection、HTMLCollection、HTMLCollectionOf、StyleSheetList 均为 Haploid.js 实现的模拟结构,因为它们无法用构造函数直接构造。虽然如此,但依然能满足 instanceof 判断条件。
警告
document.all 无法实现与真值相同的布尔表现,即:
typeof document.all; // 得到"object",但应该为 "undefined"
if (document.all) {
} // 得到truly,但应该为 falsy