From eef047bc5ffece0c5136d4e940446796344da0c5 Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Tue, 11 Feb 2020 15:18:32 -0800 Subject: [PATCH] fix(forms): change Array.reduce usage to Array.forEach (#35349) There is currently a bug in Chrome 80 that makes Array.reduce not work according to spec. The functionality in forms that retrieves controls from FormGroups and FormArrays (`form.get`) relied on Array.reduce, so the Chrome bug broke forms for many users. This commit refactors our forms code to rely on Array.forEach instead of Array.reduce to fix forms while we are waiting for the Chrome fix to go live. See https://bugs.chromium.org/p/chromium/issues/detail?id=1049982. PR Close #35349 --- packages/forms/src/model.ts | 24 ++++++++++++++---------- packages/forms/src/validators.ts | 12 ++++++++---- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/forms/src/model.ts b/packages/forms/src/model.ts index 70c42481ea..ddbcfd76fc 100644 --- a/packages/forms/src/model.ts +++ b/packages/forms/src/model.ts @@ -52,17 +52,21 @@ function _find(control: AbstractControl, path: Array| string, del } if (Array.isArray(path) && path.length === 0) return null; - return path.reduce((v: AbstractControl | null, name) => { - if (v instanceof FormGroup) { - return v.controls.hasOwnProperty(name as string) ? v.controls[name] : null; + // Not using Array.reduce here due to a Chrome 80 bug + // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982 + let controlToFind: AbstractControl|null = control; + path.forEach((name: string | number) => { + if (controlToFind instanceof FormGroup) { + controlToFind = controlToFind.controls.hasOwnProperty(name as string) ? + controlToFind.controls[name] : + null; + } else if (controlToFind instanceof FormArray) { + controlToFind = controlToFind.at(name) || null; + } else { + controlToFind = null; } - - if (v instanceof FormArray) { - return v.at(name) || null; - } - - return null; - }, control); + }); + return controlToFind; } function coerceToValidator( diff --git a/packages/forms/src/validators.ts b/packages/forms/src/validators.ts index 116d306e86..0b7a171bf3 100644 --- a/packages/forms/src/validators.ts +++ b/packages/forms/src/validators.ts @@ -465,9 +465,13 @@ function _executeAsyncValidators(control: AbstractControl, validators: AsyncVali } function _mergeErrors(arrayOfErrors: ValidationErrors[]): ValidationErrors|null { - const res: {[key: string]: any} = - arrayOfErrors.reduce((res: ValidationErrors | null, errors: ValidationErrors | null) => { - return errors != null ? {...res !, ...errors} : res !; - }, {}); + let res: {[key: string]: any} = {}; + + // Not using Array.reduce here due to a Chrome 80 bug + // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982 + arrayOfErrors.forEach((errors: ValidationErrors | null) => { + res = errors != null ? {...res !, ...errors} : res !; + }); + return Object.keys(res).length === 0 ? null : res; }