收藏
回答

启用插件时,Object.setPrototypeOf 被设为了错误的函数

问题模块 框架类型 问题类型 终端类型 微信版本 基础库版本
框架 小程序 Bug 工具 7.0.0 2.4.3

- 当前 Bug 的表现


1. 未使用插件时不会触发这个异常。

2. 使用插件时,全局的 `Object.setPrototypeOf` 会被覆写,并且覆写的方法没有按 ecma-262 的定义返回第一个传参的值

3. 在实际应用中,如果使用了 babel 提前编译代码,会有大量依赖于 `Object.setPrototypeOf` 的方法无法按预期执行,例如使用了继承语法的代码会由于 https://github.com/babel/babel/blob/0859535b/packages/babel-helpers/src/helpers.js#L517-L546 中读取的 `Object.setPrototypeOf` 的返回值变成 `undefined` 而抛出异常。

4. 该异常的根源可以排查到是在小程序的 `appservice/__dev__/WAService.js` 中,经 VSCode - Format Document 反混淆后位于 4908-4913 行(不同的反混淆工具得出的具体的行数也不同),截图可参考:https://media.discordapp.net/attachments/410768182102589454/527489845140914178/unknown.png


// WAService.js 4908-4913L


Object.defineProperty(o.Object, "setPrototypeOf", {

  value: function (e, t) {
    e.__proto__ = t
  },
  configurable: !0
})


2018.12.27 补充:使用微信开发者工具的 Devtools 反混淆后位于 6040-6045L



- 预期表现


`Object.setPrototypeOf(o, p)` 应返回 `o`。


具体可查阅:

- https://www.ecma-international.org/ecma-262/6.0/#sec-object.setprototypeof

- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf#Notes

- https://github.com/babel/babel/blob/0859535b/packages/babel-helpers/src/helpers.js#L444-L452


Object.setPrototypeOf ( O, proto )

When the setPrototypeOf function is called with arguments O and proto, the following steps are taken:


1. Let O be RequireObjectCoercible(O).

2. ReturnIfAbrupt(O).

3. If Type(proto) is neither Object nor Null, throw a TypeError exception.

4. If Type(O) is not Object, return O.

5. Let status be O.[[SetPrototypeOf]](proto).

6. ReturnIfAbrupt(status).

7. If status is false, throw a TypeError exception.

8. Return O.


例如改为:

function _setPrototypeOf(o, p) {
  o.__proto__ = p;
  return o;
}



- 复现路径


请使用下面的小程序代码片段复现



- 提供一个最简复现 Demo


小程序代码片段:

https://developers.weixin.qq.com/s/VWjLSXmb724n


当 app.json 中去除了 plugins 时,测试用例通过;当 app.json 中包含 plugins 时,测试用例不通过。



- 2018.12.27 第一次更新

有人处理吗?


这个问题的影响面很大,使用 babel 自行预编译代码的用户可能随时都会踩到这个雷。我是 tinajsmina-webpack 的作者(社区里的用户大部分都会在项目中使用 babel),昨天从一位用户反馈的情况排查到这个问题,相关的讨论可以在这里查阅:


https://discordapp.com/channels/410768182102589451/410768182102589454



- 2018.12.27 第二次更新

我更新了测试用例的代码片段:https://developers.weixin.qq.com/s/zLmvOYmU7w4x


通过在 WAService.js:formatted - 6042 Line  打断点(可搜索 Object, 快速找到这个位置),然后点击模拟器界面中的「测试」按钮,可以确认问题代码确实就出在这一函数。



最后一次编辑于  2018-12-28
回答关注问题邀请回答
收藏

1 个回答