Skip to content

Conversation

@dmarcos
Copy link
Member

@dmarcos dmarcos commented Jul 4, 2017

…te on component initialization (fix #2829)

The following call to getAttribute returns the data object of the component (this happens due to one of the perf optimization to reduce unnecessary object copies) that gets modified and then passed to the setAttribute method.

var position = el.getAttribute('position');
position += 1;
el.setAttribute('position', position);

the oldData object was constructed before building the data object resulting in the oldData to actually contain the current data. The condition that checks if the component should be updated (oldData !== data) was failing because the objects were identical.

Two fundamental changes in this PR:

  1. The oldData object is built after the data object is constructed to contain the actual previous data.
  2. The update method receives undefined on first call when the component initializes. The core components have been modified to comply.

@ngokevin
Copy link
Member

ngokevin commented Jul 5, 2017

Can we avoid making oldData undefined on the first call? It's extra work to check and opens up for potential for lots of bugs in components (e.g., not accounting it could be both undefined or an object). Can we separate the internal old data versus the public one?

@dmarcos
Copy link
Member Author

dmarcos commented Jul 5, 2017

Old Data being undefined it what makes sense to me? What do you pass to update on first call, when the component has been just initialized?

@ngokevin
Copy link
Member

ngokevin commented Jul 5, 2017

Empty data makes just as much sense. And it's backwards incompatible and puts less type checking effort and less potential bugs for component authors.

What do we return where?

@dmarcos
Copy link
Member Author

dmarcos commented Jul 5, 2017

What about components that don't have an object as schema data type like visible for instance? If the default is false people might do things like if (oldData) {...}

@ngokevin
Copy link
Member

ngokevin commented Jul 5, 2017

undefined works better for single-prop schemas. I think that was the current behavior.

@dmarcos
Copy link
Member Author

dmarcos commented Jul 6, 2017

Ok, I'll revert back to passing {} on multi prop schemas and undefined on single property

@dmarcos dmarcos force-pushed the fix2829 branch 2 times, most recently from 71645a7 to f0f6ff6 Compare July 8, 2017 06:19
Copy link
Member

@ngokevin ngokevin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+wc

var isSinglePropSchema;
var oldData;
var skipTypeChecking;
var oldData = this.oldData;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can initialize this in the component constructor as undefined.

delete el.initializingComponents[this.name];
// Play the component if the entity is playing.
// We pass empty object to multiple property schemas and single property schemas that parse to objects like position, rotation, scale
// undefined is passed to the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment stopped suddenly

this.update(oldData);
// Play the component if the entity is playing.
if (el.isPlaying) { this.play(); }
this.oldData = extendProperties({}, this.data, isSinglePropSchema);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Store current data as previous data for future updates.

if (!skipTypeChecking && utils.deepEqual(oldData, this.data)) { return; }
if (!skipTypeChecking && utils.deepEqual(this.oldData, this.data)) { return; }

this.oldData = extendProperties({}, this.data, isSinglePropSchema);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Store current data as previous data for future updates.

// 1. Default values (lowest precendence).
if (isSinglePropSchema) {
data = schema.default;
data = typeof schema.default === 'object' ? utils.extend({}, schema.default) : schema.default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clone default value if object so components don't share object.

@ngokevin
Copy link
Member

Can also update the PR description for future reference.

@dmarcos dmarcos merged commit d6d6201 into aframevr:master Jul 14, 2017
feiss added a commit to supermedium/aframe-environment-component that referenced this pull request Jul 16, 2017
handle undefined oldData initially (fixes side effect of aframevr/aframe#2840)
@nwoltman
Copy link

Is there going to be a 0.6.1 patch release for this bug fix?

@ngokevin
Copy link
Member

yeah

ngokevin pushed a commit that referenced this pull request Jul 19, 2017
PiTiLeZarD pushed a commit to PiTiLeZarD/aframe-environment-component-v2 that referenced this pull request May 11, 2022
handle undefined oldData initially (fixes side effect of aframevr/aframe#2840)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Entity.setAttribute('position') Not Always Effective

3 participants