【重要|官方调研】关于引擎私有变量的访问

检查了下自己使用的私有属性

  1. cc.EventTarget 中的 _callbackTable,因为扩展 EventTarget 需要拿到监听列表

  2. jsb[“onError”],已废弃,未公开接口,用于错误监听

  3. window["__errorHandler"],用于错误监听

  4. cc.EventTarget 中的 clear,用于清理所有事件,功能正常但是不知道为什么不是 public 接口

  5. cc.Asset._uuid,已废弃,用于作为资源索引 key,是否有替代方案?

我这里重申一下引擎这次修改的原因就是想减小包体。包体问题在小游戏平台和 web 平台是敏感的。所以这次的就是关注了这里的需求。而且这次的优化也是针对私有变量的处理,私有变量本来就是不允许外部访问的,是因为语言的限制导致了大家可以随意访问。

至于引擎功能不完善而导致非要访问私有变量,这部分需要根据反馈让引擎看怎么修改合适。而不是通过直接访问私有变量的方式。访问私有变量就得做好准备会被修改的可能。

引擎既要保持兼容性,还得减小包体,提升性能等工作。如果连私有变量和私有函数,以及没导出的代码都要保持兼容的话,那么引擎只能是不断加代码了。因此,后续我们还可能对私有变量和私有函数进行重构。可能不是因为包体问题,可能是逻辑的优化,性能的提升等。

5赞

可不可以通过用户可配置的表,来指定 不被压缩的 私有属性?

赞同,本来私有函数/属性就是不建议公开使用的

这在ios上审核,甚至调用私有函数都可能会下架

既然自己要强行使用用私有函数/属性,就得自己埋单

4赞

_nameToClass 尽管是下划线开头的,但是 export 出去的属性,不会做压缩处理。

我转到这了,可以在这里讨论,主要的是接口已废弃,但是没有新的接口可以代替

export class CallbacksInvoker<EventTypeClass extends EventType = EventType> {
    /**
     * @deprecated since v3.5.0, this is an engine private interface that will be removed in the future.
     */
    public _callbackTable: ICallbackTable = createMap(true);

这个虽然是下划线开头,但之前定义了是 public ,不会做压缩处理。

  1. jsb[‘onError’],不受影响,后续会加入更统一的错误处理接口。
  1. . window["__errorHandler"],用于错误监听

JSB 相关的调用,不受影响

  1. . cc.EventTarget 中的 clear,用于清理所有事件,功能正常但是不知道为什么不是 public 接口

CallbacksInvoker 中是有的,EventTarget 中有 removeAll(keyOrTarget),但是没有 clear,我估计是当时定义 interface IEventified 的人漏了 clear。

  1. cc.Asset._uuid,已废弃,用于作为资源索引 key,是否有替代方案?

有公有接口可以用:

/**
     * @en
     * The UUID of this asset.
     *
     * @zh
     * 资源的 UUID。
     */
    get uuid (): string {
        return this._uuid;
    }

后面引擎内部的私有属性都用#申明吧,别依赖private了。这样就无法滥用了。

好的,我们会评估一下。感谢反馈。

支持,总不能既要又要,本来私有变量就不应该随意hack,hack同时应该要向引擎组提公有需求,为引擎完善出一份力,hack完实现了,又不提issue,让引擎组在新版本支持,那就自己负责就好

1赞

有没有可能,那个属性/函数,不应该设置为私有的

2赞

说到点子上了

1赞

这样把hack的路彻底堵死了,那估计开发者要吵翻天了。 :grinning:

1赞

hack 不能一劳永逸,客观上,它终究会是条死路,就看多久死

应该在 hack 的同时,立即推进它的活路,包括但不限

  1. 联系引擎组同学,提供理由,让它转换为一个公共的
  2. 考虑其他办法
1赞

确实这个意思。比如我想实现排序功能,就需要访问很多私有变量,我一直都不想改引擎代码,但是引擎组啥时候给实现呢?已经冲3.0盼望到现在385了。有实现吗?或者等引擎实现了功能,我们再给游戏做相关功能?

#私有变量最终在 babel 是用 WeakMap 实现的,需要考虑下性能问题,还有包体问题

https://babeljs.io/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=MYGwhgzhAECC0G8BQ1XQMRmgXmgRgG4kBfJJUSGWPRFNAfS10JKA&debug=false&forceAllTransforms=false&modules=false&shippedProposals=false&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Creact%2Cstage-2&prettier=false&targets=&version=7.26.2&externalPlugins=&assumptions={}

所以这个方式估计行不通。
只有支持 ES 新标准的 JS 虚拟机才原生支持 #

我觉得不应该加开关了,应该加一个白名单,如果出现问题,开发者自己把用到的私有变量加上白名单,这样,就能满足所有人的需求,而且不需要定期去加什么getter setter,直接把白名单里面的变量不进行压缩就好了

2赞

+10086

先点赞。

但是:

既然我们以 TypeScript 为主,不用考虑 JavaScript 的兼容性,尊重 private、protected、public 修饰符,能否抽时间看看有没有现成的方案或者自己写个以 private 属性而不是以 $ 结尾的属性为准进行压缩,实在是好丑好 Hack。

还希望再做个功能:给个选项,可以剔除未使用的类成员(可选引擎的还是项目的),这肯定比名称的提升还要大得多。

把前端现代化的工具链全部利用上。