Why enforce Readonly on certain commonly used node properties?

Hello,

I really appreciate the work going on the creator, thanks a lot for the effort put into this engine. I can only imagine how powerful the engine is going to be once WASM becomes a staple in the web standards.

So I’ll get to the point
I’m using Cocos Creator v3.2.0

I just need to know on what basis certain commonly used properties were made readonly, even though they have setter methods. For example node.position or node.worldPosition.

I’m attaching a snippet taken from the declaration files and from the Node section specifically.

PS: I’m aware that I can modify the declaration to suit my needs. I need clarification on why these properties were made Readonly.

Thank you

@slackmoehrle @jare @zzf_Cocos

It’s been a while since I touched cocos creator. Please help me understand why this was done?
Is it to encourage use of vectors?

Alrighty. I got you.

ive’ seen similar stuff on Sprite Component, the color property is readonly for crying out loud :frowning: fortunately setting it still works as expected but ya its’ strange that some of these properties are set as readonly.

Yea, it works in my case as well. Just that I don’t like adding a bunch of ts-ignore statements.
My question is whether these were made Readonly intentionally or not.

The documentation states we can assign it directly. And I understand that it’s a challenge to keep the documentation up-to date on each release.

Hence I had to make this post to get some clarity.

1 Like

First of all, a real readonly property will only have a getter or will have its declaration like this

public readonly pos;

Here is the reason, the readonly syntax is for protecting internal data without having performance issues.

Take a look at the getter of position

public get position (): Readonly<Vec3> {
    return this._lpos;
}

We are exposing the private property _lpos without copy it, that means if user directly modify the vec3 retrieved from this API, then Node won’t know anything is updated. So the readonly syntax helped us to prevent this from happening. You will get a ts error with the following code

let position = node.position;
position.x =  0; // Forbidden

Why we don’t copy and return a new Vec3 ? Because it will cause a lot of garbage, these Node APIs are very frequently used and will due to many minor even major GCs which can have visible performance impact. If user want to use and modify the position, we want this behavior to be visible by user

let position = node.position;
let newPos = new Vec3(position);
newPos.x =  0;

As for setter, it only means that the engine won’t touch your input data, so it’s safe to use it anywhere else

public set position (val: Readonly<Vec3>) {
    this.setPosition(val as Vec3);
}

In conclusion, the readonly syntax doesn’t mean the property is readonly, it only means how you should treat the returned value.

3 Likes

@pandamicro I really thank you for taking the time to answer this.

Thanks for explaining the intent behind this implementation.

Thank you that was helpful.

You are welcome

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.