engine icon indicating copy to clipboard operation
engine copied to clipboard

ScriptType does not support class syntax

Open AlexAPPi opened this issue 1 year ago • 4 comments

Script argument type conversion does not occur if both a property and a script attribute exist.

    class TestFailVec3 extends pc.ScriptType {
        vec;
        initialize() {
            console.log(this.vec);
        }
    }
    pc.registerScript(TestFailVec3, 'TestFailVec3');
    TestFailVec3.attributes.add('vec', { type: 'vec3', default: [0, 100, 0] });
    class TestOkVec3 extends pc.ScriptType {
        initialize() {
            console.log(this.vec);
        }
    }
    pc.registerScript(TestOkVec3, 'TestOkVec3');
    TestOkVec3.attributes.add('vec', { type: 'vec3', default: [0, 100, 0] });

image

AlexAPPi avatar Apr 30 '24 07:04 AlexAPPi

This also applies to other complex types: vec2, entity, ...

AlexAPPi avatar Apr 30 '24 07:04 AlexAPPi

Thanks @AlexAPPi, you've hit on an important point.

When an ES6 class members is defined, it is non configurable. Currently ScriptAttribute attempts to redefine the member using Object.defineProperty which effectively becomes a no-op. This prevents the type conversion and attribute events from working.

class Test { fail = 'should be overridden' }
Object.defineProperty(Test.prototype, 'fail',  { value: 100 });
test = new Test()
console.log(test.fail) // 'should be overridden'

I've created an editor repro here

For the time being, you'll need to avoid declaring attribute in the class body, or alternatively use the var MyClass = pc.createScript syntax. We plan on solving this limitation with the newer ESM Scripts

marklundin avatar Apr 30 '24 10:04 marklundin

At the moment, the issue can be very obscure, as it doesn't warn the developer. This can lead to bugs that are hard to debug. We should add a warning.

LeXXik avatar Apr 30 '24 10:04 LeXXik

Yep this is not ideal, but unfortunately I don't think this is possible to catch at run-time without instantiating the class first. A solution is to prevent users using the class notation or declaring members in the class body. Neither are ideal.

marklundin avatar Apr 30 '24 11:04 marklundin