Dev Question: Inlining

Using a newer Haxe compiler version, it appears that switch statements are more strict. For example, the following does not compile:

switch (event.type) {
    
    case MouseEvent.MOUSE_DOWN:
    case MouseEvent.MOUSE_UP:
    default:

}

MOUSE_DOWN and MOUSE_UP are public static values, but are not inline.

Is there a problem with inlining these values?

I’m concerned about HTML5, which bloat in size if we inline too many values, but perhaps openfl.events.MouseEvent.MOUSE_DOWN is more verbose in plain JavaScript anyway, though is easier to minify.

On the flip-side, using inline causes reflection to fail (such as Reflect.field (MouseEvent, "MOUSE_DOWN")), which is perhaps fine in this case, but I am concerned about other methods (such as openfl.geom.Matrix which currently inline methods that could contribute to code size on JS as well as causing reflection to fail.

Does anyone have thoughts on this subject, and how we should approach inlining?

Thank you! :slight_smile:

If you can’t Reflect, then you can’t use a tweening engine straightforwardly. You can get around it by giving the function your own onUpdate(t:Float) call, but the average user may just get stuck on why tweening matrix rotate() doesn’t work.

(same as when DCE culls a field you were tweening, and the error message isn’t helpful)

The minifier can’t change the variable name without messing up reflection, so you get something like “a.MOUSE_DOWN,” which is 12 characters long. For comparison, “"mouseDown"” is 11.

Agreed. No one should need to access that particular field via reflection.

Actually, which version of Haxe did you test this on? I can reproduce it in version 3.2.0 but not 3.2.1.

I believe things were fine with Haxe 3.2.1, but newer source builds were more picky about inlining here.

Based on some of the things we found while researching performance for abstract enums, I feel its safe to use inline values for all the constant MOUSE_DOWN type values.

However, for reflection, and for support of overriding methods and properties, I have chosen not to inline core types. Primarily, this impacts Matrix3D and Vector3D, and a couple methods on other classes like Point and Matrix. I’m interested in what impact not-inlining has on file size output (for JavaScript) or on performance.

If there’s a compelling reason, I think we can consider inlining some core methods, but in general, I think it makes it harder to use the library, as one might unexpectedly not be allowed to override, or tween, or perform some other dynamic operation :smile:

Speaking of DCE, it would nice to consider what we might need to @:keep, or if we should just move ahead on openfl.js/lime.js files, so DCE is only run on user code.

Maybe we should request a tag to make inline use the old behavior.

@:allowReflection
public inline function rotate (theta:Float):Void {
    //...
}

That’s an interesting idea, like generate both the “real” function, but inline whenever it is used?

We’d still have the problem, though, of not being able to override

class CustomMatrix extends Matrix {
    
    public override function rotate (theta:Float):Void {
        
    }
    
}

Right. Since that’s how it currently works, they shouldn’t have trouble implementing it.