mip2 icon indicating copy to clipboard operation
mip2 copied to clipboard

MIP.sandbox.document.querySelector('body').ownerDocument.defaultView 指向 window

Open clark-t opened this issue 6 years ago • 4 comments

要解决什么问题 MIP.sandbox.document.querySelector('body').ownerDocument.defaultView 指向 window

描述一下你理想中的解决方案 MIP.sandbox.document.querySelector('body').ownerDocument.defaultView 指向 MIP.sandbox

描述你的备选方案

补充信息

clark-t avatar Jul 25 '18 05:07 clark-t

问题的原因在于 Node.prototype.ownerDocument ,实例化后的对象调用ownerDocument 会返回当前 document 对象,而 document 的原型链上的属性 defaultView 指向 document 所关联的 window,因此需要对这个属性进行屏蔽操作:

Object.defineProperty(Node.prototype, 'ownerDocument', {
  get: function () {
    return MIP.sandbox.document
  }
})

这样,这些操作结果均返回 undefined

MIP.sandbox.document.defaultView // undefined
document.querySelector('.markdown-body').ownerDocument.defaultView // undefined
document.body.ownerDocument.defaultView // undefined

如果存在需要 document.defaultView 的情况,可申请 document.defaultView 的白名单,这样,MIP.sandbox.document.defaultView 将返回 MIP.sandbox:

Object.defineProperty(MIP.sandbox.document, 'defaultView', {
  get: function () {
    return MIP.sandbox
  }
})

已知兼容性问题有: 华为荣耀6出错

clark-t avatar Jul 25 '18 06:07 clark-t

但这个做法存在一个问题,就是修改 Node.prototype 的影响面是全局性的,并不能将其仅作用在组件代码中,这样是否会导致某些第三方库出错呢? 或者是否有一些别的方法去处理这个 ownerDocument?

clark-t avatar Jul 25 '18 06:07 clark-t

想到一个解决方案,就是对需要进行沙盒诸如的代码中,所有的 MemberExpression 做处理。 举例如下:

// a.b
wrapper(a, 'b')

// a['a' + 1]
wrapper(a, 'b' + c)

// a[1].b.c
wrapper(wrapper(wrapper(a, 1), 'b'), 'c')

// def wrapper
function wrapper (obj, prop) {
  let val = obj[prop]
  if (val === window) {
    return MIP.sandbox
  }
  if (val === document) {
    return MIP.sandbox.document
  }
  return val
}

这样一来就能够解决 document.querySelector('body').ownerDocument.defaultView 指向 window 的问题,以及类似的通过别的属性访问操作,访问到 window 或者 document 的情况。而且这种做法也不会导致之前讨论中提到的会影响到全局。

当然,这样子处理存在的问题就是,会降低属性访问的执行效率,就看值不值得了。

clark-t avatar Oct 08 '18 09:10 clark-t

性能问题是否可以考虑只在开发环境下校验

huanghuiquan avatar Dec 28 '18 10:12 huanghuiquan