Skip to content

Component/attribute inheritance and precedence for primitives #5484

@mrxz

Description

@mrxz

Description:

The inheritance and precedences of values for a primitive is currently as follows:

  • AttrValue (anything explicitly set on an element)
  • Primitive mappings
  • Mixins
  • Primitive defaults
  • Schema defaults

This is handled during entity and component initialization, but later updates can easily 'break' things. For example a resetProperty completely ignores mixins. Clobbering a multi-prop component wipes primitive defaults and mappings, yet retains mixins. There's a difference between initializing a primitive with a mixin and adding that mixin later. Some of these are fixed in #5474, but a lot of this logic for primitives lives outside of components. Effectively the precedence is:

  • AttrValue (incl. initial primitive mappings, mixins(!) and defaults)
  • Mixins
  • Schema defaults

Especially the way mixins are handled causes unintuitive inconsistencies like the fact that a mixin at init time on a primitive can result in a different outcome compared to that mixin being added post initialization.

However, there are benefits to the current behaviour, despite its inconsistencies. Because it's all combined into the AttrValue of a component, it allows the user to "subtract" from it. Take the following example:

// HTML
// <a-camera></a-camera>
cameraEl.removeAttribute('wasd-controls'); // Gets rid of the wasd-controls

Which is also documented and also an answer on StackOverflow. So it's a given that users do depend on this behaviour.

At the same time users might be surprised why the following behaves inconsistently:

// HTML
// <a-mixin id="blue" material="color: blue"></a-mixin>
// <a-box></a-box>
boxEl.setAttribute('mixin', 'blue');
// <a-image src="url(some-image.jpg)"></a-image>
imageEl.setAttribute('mixin', 'blue');

Only the box turns blue, while the image doesn't get "tinted" blue.

Personally I would be for enforcing the full inheritance at all times. This should avoid many inconsistent and unitive situations. But it won't allow any "subtracting", as in, the primitive can't be reduced beyond what it is by default. That would be a breaking change in behaviour, though.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions