adopted-ember-addons / ember-cp-validations

Ember computed property based validations

Home Page:https://adopted-ember-addons.github.io/ember-cp-validations/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[ember-source 3.13] Infinite loop causes stack overflow

patocallaghan opened this issue · comments

Environment

  • Ember Version: 3.13.0-beta.5
  • Ember CLI Version: 3.6.1
  • Ember CP Validations Version: master
  • Reproduction PR: #660

While preparing our app to be Ember 3.13-ready we've come across a number of infinite loops which cause our app to crash. I'm not exactly sure what the problem is but I think it has to do with the recent @tracked internal changes which are shipping with 3.13. The failing tests I've created in #660 here are passing in 3.12.0 but start failing when I bump to 3.13.0-beta.1.

Steps to Reproduce

I have a component called <MyComponent />. It has a computed property which is based on cheese which can be passed in and some validations on a passed in model, model.validations.isValid. The validations are nothing special and in my reproduction case are just using what where being used for tests in the ember-cp-validations repo.

import Component from '@ember/component';
import { and } from '@ember/object/computed';

export default Component.extend({
  myProp: and('cheese', 'model.validations.isValid')
});
{{this.myProp}}

If cheese is undefined it seems to cause an infinite loop in the model.validations.isValid part of the computed property.

Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at setupMandatorySetter (index.js:753)
    at tagForProperty (index.js:239)
    at ComputedProperty.get (index.js:3302)
    at Class.CPGETTER_FUNCTION [as username] (index.js:2639)
    at getPossibleMandatoryProxyValue (index.js:1764)
    at get (index.js:1837)
    at _getPath (index.js:1871)
    at Object.get (index.js:1821)
    at factory.js:489
    at Array.map (<anonymous>)

console.log-ing what is output on the _getPath line shows that it seems to be stuck in some sort of loop trying to retrieve the validation for the username, before it throws a stack overflow

image

Strangely, doing a few things here cause the infinite loop not to occur and the test to pass fine.

  1. Changing the template to call this.model.validations or this.model.validations.isValid first before this.myProp. Calling this.model doesn't resolve the infinite loop. Moving the this.model.... call AFTER this.myProp also doesn't solve the infinite loop.
{{this.model.validations.isValid}}
{{this.myProp}
  1. Changing the order of the and computed property resolves the infinite loop. Having the undefined cheese property second solves the problem.
myProp: and('model.validations.isValid', 'cheese')

While I reproduced this problem in tests it can also be seen in a running app. In my PR for demo purposes I've just added the following code to the index.hbs

<MyComponent @model={{model}}/>

This also results in an infinite loop and stack overflow which breaks rendering but with what looks like a different path than the test

index.js:613 Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at WeakMap.get (<anonymous>)
    at getName (index.js:613)
    at Function.classToString [as toString] (index.js:4158)
    at Class.toString (core_object.js:546)
    at Class.<anonymous> (factory.js:488)
    at index.js:3320
    at untrack (index.js:1742)
    at ComputedProperty.get (index.js:3319)
    at Class.CPGETTER_FUNCTION [as __ATTRS_RESULT_COLLECTION__] (index.js:2639)
    at getPossibleMandatoryProxyValue (index.js:1764)

This should be fixed by emberjs/ember.js#18406