环境代理
沙箱的本质是 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