Skip to content
Permalink
Browse files

fix(ivy): incorrect injectable name logged in warning message on IE (#…

…34305)

When we log DI errors we get the name of the provider via `SomeClass.name`. In IE functions that inherit from other functions don't have their own `name`, but they take the `name` from the lowest parent in the chain, before `Function`. I've added some changes to fall back to parsing out the function name from the function's string form.

PR Close #34305
  • Loading branch information
crisbeto authored and kara committed Dec 11, 2019
1 parent d83599d commit 60d1d5efa1de26655e2b67b5ddda37db093dbbef
@@ -223,17 +223,34 @@ export function getInheritedInjectableDef<T>(type: any): ɵɵInjectableDef<T>|nu
(type[NG_PROV_DEF_FALLBACK] && type[NG_PROV_DEF_FALLBACK]()));

if (def) {
const typeName = getTypeName(type);
// TODO(FW-1307): Re-add ngDevMode when closure can handle it
// ngDevMode &&
console.warn(
`DEPRECATED: DI is instantiating a token "${type.name}" that inherits its @Injectable decorator but does not provide one itself.\n` +
`This will become an error in v10. Please add @Injectable() to the "${type.name}" class.`);
`DEPRECATED: DI is instantiating a token "${typeName}" that inherits its @Injectable decorator but does not provide one itself.\n` +
`This will become an error in v10. Please add @Injectable() to the "${typeName}" class.`);
return def;
} else {
return null;
}
}

/** Gets the name of a type, accounting for some cross-browser differences. */
function getTypeName(type: any): string {
// `Function.prototype.name` behaves differently between IE and other browsers. In most browsers
// it'll always return the name of the function itself, no matter how many other functions it
// inherits from. On IE the function doesn't have its own `name` property, but it takes it from
// the lowest level in the prototype chain. E.g. if we have `class Foo extends Parent` most
// browsers will evaluate `Foo.name` to `Foo` while IE will return `Parent`. We work around
// the issue by converting the function to a string and parsing its name out that way via a regex.
if (type.hasOwnProperty('name')) {
return type.name;
}

const match = ('' + type).match(/^function\s*([^\s(]+)/);
return match === null ? '' : match[1];
}

/**
* Read the injector def type in a way which is immune to accidentally reading inherited value.
*
@@ -137,6 +137,9 @@
{
"name": "getOwnDefinition"
},
{
"name": "getTypeName"
},
{
"name": "getUndecoratedInjectableFactory"
},

0 comments on commit 60d1d5e

Please sign in to comment.
You can’t perform that action at this time.