aframevr / aframevr/aframe

Component/attribute inheritance and precedence for primitives

Open
#5,484 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
17.6k
Forks
4.4k
PR merge metrics
No merged PRs in 30d

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing primitive, entity, and component initialization, then inspect resetProperty and later mixin updates. Compare initialization-time and post-initialization mixin behavior, including primitive mappings, defaults, and attribute removal; done requires an agreed precedence model and behavior that is covered consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.