fix(ivy): distinguish inherited injectable defs by token (#30855)

In older browsers such as IE10, inheritance of static properties on class
types is implemented by copying the properties. This makes hasOwnProperty
unreliable for checking if a static property is defined directly on a class
or is inherited. This causes problems when trying to read the
ngInjectableDef properties of inherited services, as in IE10 even inherited
definitions will appear to be local.

Instead, the 'token' property on ngInjectableDef can be leveraged to detect
when a definition is read which doesn't belong to the type itself.

PR Close #30855
This commit is contained in:
Alex Rickabaugh 2019-06-07 10:32:06 -07:00 committed by Andrew Kushnir
parent a4b4f35533
commit b2937b16c3
1 changed files with 9 additions and 1 deletions

View File

@ -190,7 +190,15 @@ export function ɵɵdefineInjector(options: {factory: () => any, providers?: any
* @param type A type which may have its own (non-inherited) `ngInjectableDef`.
*/
export function getInjectableDef<T>(type: any): ɵɵInjectableDef<T>|null {
return type && type.hasOwnProperty(NG_INJECTABLE_DEF) ? type[NG_INJECTABLE_DEF] : null;
const def = type[NG_INJECTABLE_DEF] as ɵɵInjectableDef<T>;
// The definition read above may come from a base class. `hasOwnProperty` is not sufficient to
// distinguish this case, as in older browsers (e.g. IE10) static property inheritance is
// implemented by copying the properties.
//
// Instead, the ngInjectableDef's token is compared to the type, and if they don't match then the
// property was not defined directly on the type itself, and was likely inherited. The definition
// is only returned if the type matches the def.token.
return def && def.token === type ? def : null;
}
/**