playcanvas / playcanvas/engine
ESM scripts, execution order issues with attributes.
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 16.8k
- Forks
- 2k
- Avg merge
- 4h 32m
- Merged PRs (30d)
- 222
Description
ESM scripts have unfortunately many issues, some conceptual, some functional.
One of the issue here, is that execution order for same conceptual thing "know when attribute changes", is different between classical and ESM scripts.
In example below, we simply want to change name of another entity, which we find in initialize. With classical script - very straight forward: find an entity, subscribe to attribute change, apply change on event.
With ESM, to react on attribute changes, we have to use set/get. But the setter will be executed before the initialize is executed, leading to friend to be undefined, because it is not yet found.
This very simple concept, and yet it is a hustle with ESM. What would be the suggestion here?
Here is a classic script:
var Test = pc.createScript('test');
Test.attributes.add('friendsName', { type: 'string', default: 'friend?' });
Test.prototype.initialize = function() {
// 1
this.friend = this.app.findByName('friend');
this.on('attr:friendsName', () => {
// 2
this.friend.name = this.friendsName;
});
};
And here is an ESM script
import { Script } from 'playcanvas';
export class Test extends Script {
static scriptName = 'test';
_friendsName = 'friend?';
initialize() {
// 2
this.friend = this.app.findByName('friend');
}
/**
* @attribute
* @type {string}
*/
set friendsName(value) {
// 1
this._friendsName = value;
this.friend.name = this._friendsName; // exception here, friend is undefined!
}
get friendsName() {
return this._friendsName;
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the ESM Script example and compare the friendsName setter with initialize() and the classic script's attribute-change handler. Trace when each lifecycle point runs and determine the intended execution-order contract. Done means the project has an agreed, documented behavior or implementation direction that prevents the setter from using an uninitialized friend.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100