Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflect.hasField returns false on property getters on the JavaScript target #11613

Closed
EliteMasterEric opened this issue Mar 18, 2024 · 2 comments

Comments

@EliteMasterEric
Copy link
Contributor

Reproduction

https://try.haxe.org/#8C3c6C77

Explanation

I have encountered some strange behavior with regards to Reflection against non-physical properties on the JavaScript target.

I am working on a fork of HScript, which needs to function properly on the HTML5 target. As part of variable resolution, I use Reflect.hasField to determine if I should resolve a field or throw a syntax error.

On the Eval target, Reflect.hasField('myValue') returns false, but Reflect.hasField('get_myValue') returns true. This allows me to determine if getProperty (which the docs state is slower than Reflect.field) is necessary.

However, Reflect.hasField('get_myValue') returns false on JavaScript, even though Reflect.getProperty('myValue') does succeed. This gives me no way to detect if getProperty will return a valid result or not (checking getProperty() == null won't work since there is no way to distinguish between "this value exists and is null" and "this value does not exist").

I cannot use Reflect.properties() or Reflect.hasProperty(), because no such functions do not exist for some reason.

Additional notes:

  • On both targets, Reflect.fields() does not include properties.
  • On the JavaScript target, enabling full DCE actually causes getProperty('myField') to fail, presumably because the getter function is getting culled. Getter and setter functions should definitely never get culled if the class itself has not been culled.
@back2dos
Copy link
Member

On the JavaScript target, enabling full DCE actually causes getProperty('myField') to fail, presumably because the getter function is getting culled. Getter and setter functions should definitely never get culled if the class itself has not been culled.

DCE is granular at field level by design.

If anything, the argument could be made that Reflect.getProperty should keep all properties on kept classes.

If you can, avoid reflection like the plague. More often than not, safer and faster alternatives are available. If not, you could either use addGlobalMetaData to whatever packages you wish with to perform reflection on, or add an onGenerate hook that marks all getters and setters with @:keep.

Additionally, there could be a Reflect.properties and Reflect.hasProperty. Made a JS implementation here: https://try.haxe.org/#5611215a

That said, I would yet again advise against using such a thing though ;)

@Simn
Copy link
Member

Simn commented Nov 19, 2024

We don't guarantee that output across all targets is identical with regards to reflection. Some targets care more than others about "looking good" and might avoid the generation of specific fields. Restricting this for the sake of reflection would not align with our goals.

@Simn Simn closed this as not planned Won't fix, can't repro, duplicate, stale Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants