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

attributeBindings is now frozen in debug builds on v2.11, slice it before pushing #59

Merged

Conversation

bgentry
Copy link
Contributor

@bgentry bgentry commented Jan 24, 2017

As noted in the Ember v2.11 release notes, concatenated properties such as attributeBindings are frozen in debug builds. This means we cannot push directly onto the attributeBindings array without first copying it via slice.

Without this change, users may see errors like this when the attributeBindings.push() call is made:

Uncaught TypeError: Can't add property 2, object is not extensible

References:

@bgentry
Copy link
Contributor Author

bgentry commented Jan 24, 2017

I did try upgrading ember-test-selectors to ember-cli and ember v2.11: https://github.com/simplabs/ember-test-selectors/compare/master...bgentry:ember-cli-2.11-upgrade?expand=1

However, I did not encounter any failures like I was receiving in my app. I guess the failure case isn't being exercised by any existing tests. In my app, the error occurs when trying to push to a non-empty attributeBindings array with a value of ["type", "_value:value"]. So maybe a test should be added to cover that scenario.

Feel free to PR that upgrade branch if you'd like to use it as-is.

As noted in the Ember v2.11 release notes, concatenated properties such
as attributeBindings are frozen in debug builds. This means we cannot
push directly onto the attributeBindings array without first copying it
via slice.

Without this change, users may see errors like this when the
`attributeBindings.push()` call is made:

Uncaught TypeError: Can't add property 2, object is not extensible

References:

emberjs/ember.js#14389
emberjs/ember.js#14601
@bgentry bgentry force-pushed the fix-frozen-attribute-bindings-array branch from 951872c to 001b11e Compare January 24, 2017 19:49
@marcoow marcoow requested a review from Turbo87 January 25, 2017 08:16
@marcoow
Copy link
Member

marcoow commented Jan 25, 2017

Hm, somehow Travis doesn't seem to be running tests with 2.9, 2.10 and 2.11…

We certainly should have a test case in here that fails for 2.11 without these changes.

@Turbo87
Copy link
Collaborator

Turbo87 commented Jan 25, 2017

@rwjblue can I get your knowledge on this? freezing the attributeBindings sounds like they shouldn't be modified at all after or during init(). what is the purpose of freezing them?

@rwjblue
Copy link
Contributor

rwjblue commented Jan 25, 2017

attributeBindings, classNameBindings, classNames, etc are all mutable arrays that are stored on the components prototype. This means that mutating for one instance changes all instances (likely just changing for all future instances). To protect you (the user) from this, Ember used to slice these arrays for every component instance speculatively (when the majority of the time it is never mutated).

So in Ember 2.11 these arrays are now frozen in dev builds so that mutating causes an error. This allows us to remove the speculative slicing (reducing wasted Array allocations and related GC pressure).

It is still valid and supported to want to customize these arrays on a per instance basis (as long as it is done from within the constructor/init), but you have to slice (to create a new array instance) before mutating (to avoid the "mutating a frozen object" error messages).

@Turbo87
Copy link
Collaborator

Turbo87 commented Jan 25, 2017

@rwjblue okay, so what I'm understanding is: what we are doing is okay, as long as we slice and don't try to mutate. do we have to modify the field before or after the this._super() call in init(), or is that irrelevant?

@rwjblue
Copy link
Contributor

rwjblue commented Jan 25, 2017

We only look for the value after the constructor is completed, so it doesn't really matter about setting attributeBindings before or after calling super. In general, you should always call super before touching this (same rule as ES6 classes) which is what I would fall back on in this case.

@Turbo87
Copy link
Collaborator

Turbo87 commented Jan 25, 2017

@bgentry I've got a test case now that verifies that your PR succesfully fixes this issue. Thanks a lot!

@Turbo87 Turbo87 merged commit 1c03080 into mainmatter:master Jan 25, 2017
@bgentry bgentry deleted the fix-frozen-attribute-bindings-array branch January 25, 2017 16:37
@Turbo87 Turbo87 added the bug label Jan 25, 2017
@bgentry
Copy link
Contributor Author

bgentry commented Jan 25, 2017

Awesome, thanks all 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants