amarkes / br-mask

MIT License
116 stars 56 forks source link

fix angular9 ivy onNgModelChange loop infinito #45

Closed vitorTheDev closed 4 years ago

vitorTheDev commented 4 years ago

Utilizando angular 9.1.2 com ivy habilitado encontrei o erro:

RangeError: Maximum call stack size exceeded
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:191)
    at SafeSubscriber.next (Subscriber.js:122)
    at Subscriber._next (Subscriber.js:72)
    at Subscriber.next (Subscriber.js:49)
    at EventEmitter.next (Subject.js:39)
    at EventEmitter.emit (core.js:37079)
    at FormControlName.viewToModelUpdate (forms.js:8394)
    at forms.js:3538
    at forms.js:4954
    at Array.forEach (<anonymous>)

Ao investigar, identifiquei que o evento onNgModelChange estava sendo executado em loop infinitamente, causando travamentos. Consegui resolver o erro ao remover o evento. Em meus testes não encontrei nenhum efeito colateral desta remoção, porém seria interessante revisar/testar.

Angular: 9.1.2
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.901.2
@angular-devkit/build-angular     0.901.2
@angular-devkit/build-optimizer   0.901.2
@angular-devkit/build-webpack     0.901.2
@angular-devkit/core              9.1.2
@angular-devkit/schematics        9.1.2
@angular/cdk                      9.2.1
@angular/material                 9.2.1
@ngtools/webpack                  9.1.2
@schematics/angular               8.3.22
@schematics/update                0.901.2
rxjs                              6.5.4
typescript                        3.8.3
webpack                           4.42.0

System:

   Android SDK Tools : 26.1.1 (D:\aaProgramas2\Android\Sdk\)
   NodeJS            : v12.14.1 (D:\aaProgramas2\node-dir\node.exe)
   npm               : 6.14.2
   OS                : Windows 10
Ionic:

   Ionic CLI                     : 6.9.3
   Ionic Framework               : @ionic/angular 5.0.7
   @angular-devkit/build-angular : 0.901.2
   @angular-devkit/schematics    : 9.1.2
   @angular/cli                  : 9.1.2
   @ionic/angular-toolkit        : 2.2.0
vitorTheDev commented 4 years ago

Após estudar mais o problema, cheguei a conclusão que o problema era que o método setValueInFormControl chamava a função AbstractControl.setValue. Porém na verdade a classe AbstractControl não implementa a função setValue, e sim a classe FormControl. Na implementação do FormControl.setValue, existe um parâmetro emitViewToModelChange, que, por padrão, é considerado true, e dita se o evento ngModelChange será emitido. Por isso, a função setValueInFormControl dispara o evento ngModelChange, e no listener onNgModelChange a função setValueInFormControl é executada novamente, criando um loop infinito de execução levando ao RangeError: Maximum call stack size exceeded.

A partir desta análise, voltei o evento onNgModelChange #7533131, e em seguida adicionei um parâmetro opcional na função setValueInFormControl #3f93c2a para que seja possível executar a função sem disparar o evento ngModelChange, o que resolve o problema.

ludufre commented 4 years ago

@netd777 ótimo! Funcionou perfeitamente. @amarkes poderia fazer o merge?

amarkes commented 4 years ago

has done