环境代理

沙箱的本质是 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创建的节点的下列属性被重新定义:
  1. ownerDocument:指向 document 代理对象,只读
  2. baseURI:指向 ownerDocument 的 baseURI,只读
createDocumentFragment同上
createAttribute同上
createAttributeNS同上
createTextNode同上
createTextNode同上,但是:
  • 如果参数为 "script",则会创建一个 <haploid-script> 元素而不是 <script> 元素,并在一旦被插入到 <haploid-head> 中,就会自动下载并在沙箱中执行
  • 如果参数为 "link",则会创建一个 <haploid-link> 元素而不是 <link> 元素,并在一旦被插入到 <haploid-head> 中,就会自动下载并在 <style> 中生效;如果开启了 CSS 隔离,也会自动被转换
createElementNS同上
defaultView返回 window 代理对象,只读
documentElement返回 <haploid-html> 元素,如果 enableHtmlPretending 被开启,该元素的下列属性会被重新定义:
  • tagNamenodeName 均为 "HTML"
  • parentNode 为 document 代理对象
  • parentElement 为 null
  • version 为空字符串""
  • constructorHTMLHtmlElement
  • 原型链可上溯到 HTMLHtmlElement.prototype
title返回 <haploid-title> 元素的文本内容,可写
head返回上述 <haploid-head> 元素,如果 enableHeadPretending 被开启,该元素的下列属性会被重新定义:
  • tagNamenodeName 均为 "HEAD"
  • constructorHTMLHeadElement
  • 原型链可上溯到 HTMLHeadElement.prototype
body返回上述 <haploid-body> 元素,如果 enableBodyPretending 被开启,该元素的下列属性会被重新定义:
  • tagNamenodeName 均为 "BODY"
  • constructorHTMLBodyElement
  • 原型链可上溯到 HTMLBodyElement.prototype
all只局限在应用自身 <haploid-html> 元素及后代中查询
forms同上
embeds同上
plugins同上
images同上
links同上
styleSheets同上
scripts同上,但查询 <haploid-script> 而不是 <script>
children返回只包含 <haploid-html> 的HTMLCollection
childNodes返回只包含 <haploid-html> 的 NodeListOf&lt;ChildNode&gt;
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可能返回的 NodeListOfHTMLAllCollectionHTMLCollectionHTMLCollectionOfStyleSheetList 均为 Haploid.js 实现的模拟结构,因为它们无法用构造函数直接构造。虽然如此,但依然能满足 instanceof 判断条件。

警告

document.all 无法实现与真值相同的布尔表现,即:

typeof document.all; // 得到"object",但应该为 "undefined"
if (document.all) {
} // 得到truly,但应该为 falsy