-
Creator 版本: 3.8.7
-
目标平台: web 和原生(安卓、IOS)
-
重现方式:
Cocos Creator 3.8.7 release 构建 minify 错误
严重性:高。仅 release 包复现,无报错、无日志,条件静默反转。
环境:Cocos Creator 3.8.7 / Windows / android(windows 发布包同样复现)/ debug:false / mangleProperties:false / polyfills.targets: "chrome 80" / 脚本加密开启。
现象
export function repro(p: { findOnMoving?: boolean }, o: { findOnMoving?: boolean } | null | undefined, g: { moving: boolean }): boolean {
const f = p.findOnMoving ?? o?.findOnMoving ?? false;
if (!f && g.moving) {
return false;
}
return true;
}
release 产物(script-backup/assets/main/index.js,变量已 mangle):
function i(n){const{p:o,o:i,g:t}=n;return!((o.findOnMoving??(null==i?void 0:i.findOnMoving)??1)&&t.moving)}
期望:return !(!(... ?? false) && t.moving)
两处错误:?? false 变成 ?? 1;!f && moving 变成 !(f && moving),内层 ! 丢失(od -c 已确认字节为 ??1,非 ??!1)。
影响
正确:moving && !findOnMoving 才拒绝。产物:moving && findOnMoving 才拒绝。
findOnMoving |
moving |
正确 | 产物 |
|---|---|---|---|
未设置 / false
|
true | 拒绝 | 通过 |
true |
true | 通过 | 拒绝 |
触发条件
同一工程同一构建内放 4 个变体:
| 变体 | 写法 | 产物 | 结果 |
|---|---|---|---|
| A |
?? 链 + if (!f && moving)
|
!(...(??1) && moving) |
错误 |
| B |
coalesce() 封装 + Boolean(f)
|
!1 !== Boolean(f) \|\| !moving |
正确 |
| C |
coalesce() 封装 + f === false
|
!1 !== coalesce(...) \|\| !moving |
正确 |
| D | 显式 if/else 赋值 |
let e=!1; e=null!=...? : ...; return !(moving && !e) |
正确 |
结论:需同时满足 ①?? 链(≥2 层)含可选链 ?.;②结果参与 !x && y;③release 压缩。单层 ??(无 ?.)编译为 ??!1,正常。
最小复现
- Cocos 3.8.7 空工程,
assets/scripts/repro.ts放上面的函数,场景组件调用一次(防裁掉); - 构建 android,
debug=false;
样例代码
/**
* 目标代码:把执行结果打印到 Label 上
*/
export function repro(p: any, o: any, g: any): boolean {
const f = p.findOnMoving ?? o?.findOnMoving ?? false;
if (!f && g.moving) return false;
return true;
}
// 参数按需修改
const configA = { findOnMoving: undefined };
const configB = { findOnMoving: true };
const configC = { moving: true };
const result = repro(configA, configB, configC);
// web 平台
// result = true
// release包,如安卓
// result = false
表现:移动中的单位被判为不可索敌,或本应拒绝的目标被放行,无任何日志。
已排除
- debug 构建输出正确;
- 构建后的第三方加固与输入逐字节一致(
cmp相同),未参与改写; - 稳定落在 Cocos 构建的脚本压缩(terser)阶段。
规避写法(均已验证产物正确)
// 方案 1:显式判断
let f = false;
if (p.findOnMoving != null) f = p.findOnMoving;
else if (o?.findOnMoving != null) f = o.findOnMoving;
if (f === false && g.moving) return false;
期望修复
-
!(A) && B?? false这类写法能正确编译; - 建议提供关闭
compress.conditionals/evaluate细分规则的构建开关,或升级 terser。
附件
- 最小工程:
dev_wzt_test/NewProject(assets/scripts/CoalescingEquivalenceTest.ts) - 明文产物:
build/android/script-backup/assets/main/index.js - 加密产物:
build/android/data/assets/main/index.jsc(构建时 xxtea key 解密后与明文一致)
NewProject_feedback_20261106.zip (857.6 KB)
