icestark icon indicating copy to clipboard operation
icestark copied to clipboard

【icestark-module】加载 Runtime 依赖的时候没有正确识别在沙箱中添加的对象

Open HuColin opened this issue 2 years ago • 5 comments

Bug Report

What is the current behavior?

微模块在加载 runtime.json 的依赖时,会按照顺序依次在沙箱中加载依赖,并且提取出在依赖加载后新增在 window 对象上的属性;然后以提取出的属性注入到新的沙箱中继续加载下一个依赖,提取新增的属性。全部加载完成后,就可以获得配置在 Runtime 中依赖属性 deps。 https://github.com/ice-lab/icestark/blob/a6981bd305f21a6cd6b8ad4897b870710a8d63a2/packages/sandbox/src/index.ts#L97-L114 在沙箱中创建的 sandbox 中对于 window 对象配置的 Proxy,在 set 拦截中,对于新增的属性,方法仅在原 window 对象上不存在该属性的时候会将该属性添加到 propertyAdded 中;而对于原来就存在于 window 对象上的属性,实际上沙箱中 window 对象的该属性已经变成了新的值而不是原有的值,但是这个属性并未标记为新添加的。这也意味着通过 propertyAdded 并不能获取这次解析执行 js 文件向 window 对象(沙箱)上挂载的属性。 进而这种不符合直觉的操作会导致一些问题。

the steps to reproduce

例如:宿主环境使用了 React,但是这个 React 中部分属性存在缺失 React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_cancelCallback,实际上我配置的模块的 runtime 中声明了 React 16.14.0 和 ReactDOM 16.14.0 的资源文件,模块在解析 React 16.14.0的资源文件时,React 对象上确实存在 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_cancelCallback 这个属性,但是因为宿主环境中存在 React 属性,这个通过 runtime 配置的 React 未被提取出来,进而不能作为解析下一个 js 文件的沙箱的注入变量,致使在解析 ReactDOM 16.14.0 的时候,使用的仍然是宿主环境中的缺少属性的 React 对象。然后 ReactDOM 16.14.0 加载过程中需要调用 React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_cancelCallback,因此沙箱中抛出 TypeError: Cannot read properties of undefined (reading 'unstable_cancelCallback') 的错误,导致模块无法被加载。

What is the expected behavior?

对于 window 上存在的,但是在沙箱执行过程中向 window 上写入的属性也视作是新增属性propertyAdded 。同样在清理沙箱的时候也应该是先清理新增属性propertyAdded 然后恢复现场。(L218 ↔ L221) https://github.com/ice-lab/icestark/blob/a6981bd305f21a6cd6b8ad4897b870710a8d63a2/packages/sandbox/src/index.ts#L206-L225

HuColin avatar Jul 17 '22 12:07 HuColin

propertyAdded 主要用于新增 window 变量的记录,在卸载沙箱时可以移除多余的变量 上述复现的逻辑可能引起的原因是目前沙箱的劫持仅到 window.a 如果添加变量为 window.a.b b 属性的新增时无法劫持获取的

ClarkXia avatar Jul 18 '22 02:07 ClarkXia

https://github.com/ice-lab/icestark/blob/a6981bd305f21a6cd6b8ad4897b870710a8d63a2/packages/sandbox/src/index.ts#L99-L103 这里是根据沙箱外的 window 对象中有某个属性,对于没有的属性才会被标记为 propertyAdded ,但是实际上在沙箱中使用的是新的属性target[p] = value

HuColin avatar Jul 18 '22 02:07 HuColin

没错,propertyAdded 仅用于恢复沙箱执行前的场景 实际获取都从 target 获取,所有的 set 最终都反映到 target

ClarkXia avatar Jul 18 '22 03:07 ClarkXia

那对于 window 上属性的修改也应该体现在 propertyAdded 上,就举上面 React 的例子,如果我的宿主环境是 React16.6.0 版本,我的模块的依赖版本是 React16.14.0,在加载 runtime.json 依赖的时候,按照现在的逻辑使用的仍然是宿主环境的 React16.6.0 来加载 依赖中的 ReactDOM16.14.0, 我认为这样是不对的

HuColin avatar Jul 18 '22 12:07 HuColin

提了一个 PR #612,可以看看

HuColin avatar Jul 19 '22 07:07 HuColin