[BUGFIX] Make the custom tag system non-enumerable #1224
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently, the custom tag system relies on an enumerable "symbol"-like
key, which is then placed on the objects that need to use it. This is an
expensive system, since it means we need to do a brand check to see if
the function exists, which means crawling the prototype chain every time
we look up a tag for a property on an object.
This PR instead places the functions in a WeakMap. This means that in
general, we can check to see if the WeakMap has the value, and if so
then we can use the function directly. WeakMap lookup is generally
faster, as it means we don't have to walk the entire prototype chain of
a megamorphic object, so this should generally be more performant.
It does mean that the functions in question need to be bound to the
instance, which could impact performance, but the functions should still
be inline-able when called (since they are called independent of the
object), and given that usage of tag lookup with non-proxies likely
dominates over usage with proxies, it should matter less than the
savings from using a WeakMap.
Finally, this means that CUSTOM_TAG_FOR is not exposed at all, so there
cannot be any observable side-effects such as the ones causing the bug
in: ember-m3/ember-m3#957
Unrelated Changes
In addition, I did a quick refactor of the proxy handlers to extract
them as classes. This is important for performance (POJOs with methods
on the instance do not inline, even as proxy handlers), I just never got
around to it before.