You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Improve error messages for cases when circular dependencies cause symbols with metadata be undefined at the time when they are captured #9334
Current behavior
If a component (A) imports and uses a service/component (B) from a barrel containing the exports of both A and B, and A appears before B in the barrel, the imported value of B is undefined and results in the following errors when that service/component is used:
If B is a service:
EXCEPTION: TypeError: Cannot read property 'parameters' of undefined
EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'parameters' of undefined
If B is a component:
EXCEPTION: Unexpected directive value 'undefined' on the View of component 'FeatureComponent'
EXCEPTION: Error: Uncaught (in promise): Unexpected directive value 'undefined' on the View of component 'FeatureComponent'
I'm guessing that when importing from a barrel, the exported modules are processed topdown and if the module matches the importing module it thinks there is a circular dependency and just short-circuits with undefined.
Expected/desired behavior
I'd expect:
the module to import correctly, regardless of the order of exports in the barrel.
the service error message above to be less cryptic like the component message (maybe separate issue?)
some kind of proper warning/error when a circular depedency is encountered (false positive or otherwise)
If this issue can't be fixed in angular, I'd suggest:
A warning in the angular styleguide/glossary on barrels that ordering of exports may cause circular-dependency related errors.
Potentially stricter guidelines on how barrels are used that prevents this use case from happening.
changed the title [-]Certain ordering barrels result in circular dependency false positive and cryptic error message[/-][+]Certain ordering in barrels result in circular dependency false positive and cryptic error message[/+]on Jun 18, 2016
After further investigation, I've narrowed this down to the fact that the typescript compiler configuration compiles down to commonjs modules by default:
tsconfig.json
{
"compilerOptions": {
..
"module": "commonjs"
..
Setting it to system fixes this issue and kind of makes sense considering we're using systemJS to load angular by default.
Perhaps the angular.io docs and angular-CLI can be updated to use system instead of commonjs?
This is an inherent issue with commonJS modules, but not one we can really do much about, unfortunately.
ES6 modules (and SystemJS, because it implements the same semantics) have support for this, but we can't (yet) mandate either of those as browser support is not in place yet.
CommonJS is the defacto for NPM, and thus we can't use System there (nor can we mandate that everybody use SystemJS modules). We do ship ES6 modules alongside the commonJS code (see the /esm subdirectory), and I'd expect we'll eventually move the CLI to use those.
Our best advice on this is to avoid circular dependencies where possible.
changed the title [-]Certain ordering in barrels result in circular dependency false positive and cryptic error message[/-][+]Improve error messages for cases when circular dependencies cause symbols with metadata be undefined at the time when they are captured [/+]on Jun 22, 2016
The issue remains that it's not obvious that the ordering of exports in a barrel will cause circular dependency problems.
In the example plunk, it's clear that there is no real circular dependency between the feature and other component.
Unless the developer already has deep knowledge of how module import resolution works for commonjs, they will not know that:
when importing from a barrel, the module importer will short circuit and return undefined when it comes across a reference to the importing module itself.
a specific ordering in barrels is required where module dependencies are exported before their dependants.
I believe docs will still be needed detailing this if we can't allow arbitrary ordering.
I might test this case out in node instead of systemjs to see if the behaviour is caused commonjs or systemjs loading commonjs
Reacted by Mateo Tibaquirá, Philip Paetz, Colin, Łukasz Godziejewski, André Waltert, Layton Miller, Yao Lu, spicemix, Maksim Popov, Matthias Müller and 1 more
I agree that we should improve the error messages though as they don't give a clue as to what went wrong.
The good news is that now we've got clear error messages for undefined providers (a provider gets undefined in the circular dependency case): https://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=preview - the error is Error: One or more of providers for "App" were not defined: [?]..
Since the imports of directives on a component level is gone we don't need to worry about this case.
To sum up: we can't do much about circular deps and error messages were clarified.
Activity
[-]Certain ordering barrels result in circular dependency false positive and cryptic error message[/-][+]Certain ordering in barrels result in circular dependency false positive and cryptic error message[/+]Blasz commentedon Jun 18, 2016
After further investigation, I've narrowed this down to the fact that the typescript compiler configuration compiles down to
commonjsmodules by default:tsconfig.json
Setting it to
systemfixes this issue and kind of makes sense considering we're using systemJS to load angular by default.Perhaps the angular.io docs and angular-CLI can be updated to use
systeminstead ofcommonjs?robwormald commentedon Jun 19, 2016
This is an inherent issue with commonJS modules, but not one we can really do much about, unfortunately.
ES6 modules (and SystemJS, because it implements the same semantics) have support for this, but we can't (yet) mandate either of those as browser support is not in place yet.
CommonJS is the defacto for NPM, and thus we can't use System there (nor can we mandate that everybody use SystemJS modules). We do ship ES6 modules alongside the commonJS code (see the /esm subdirectory), and I'd expect we'll eventually move the CLI to use those.
Our best advice on this is to avoid circular dependencies where possible.
[-]Certain ordering in barrels result in circular dependency false positive and cryptic error message[/-][+]Improve error messages for cases when circular dependencies cause symbols with metadata be undefined at the time when they are captured [/+]IgorMinar commentedon Jun 22, 2016
Another way to work around this is by using
forwardRefwhich delays the dereferencing of the component type and allows us to get the right instance:http://plnkr.co/edit/YMhas7tEHskSZGOcHSTd?p=preview
The same works for services.
I agree that we should improve the error messages though as they don't give a clue as to what went wrong.
pkozlowski-opensource commentedon Jun 22, 2016
I will have a look at those error messages as I was tackling similar cases recently.
Blasz commentedon Jun 22, 2016
The issue remains that it's not obvious that the ordering of exports in a barrel will cause circular dependency problems.
In the example plunk, it's clear that there is no real circular dependency between the feature and other component.
Unless the developer already has deep knowledge of how module import resolution works for commonjs, they will not know that:
I believe docs will still be needed detailing this if we can't allow arbitrary ordering.
I might test this case out in node instead of systemjs to see if the behaviour is caused commonjs or systemjs loading commonjs
pkozlowski-opensource commentedon Aug 30, 2016
Yeh, @robwormald is totally right here....
The good news is that now we've got clear error messages for undefined providers (a provider gets undefined in the circular dependency case): https://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=preview - the error is
Error: One or more of providers for "App" were not defined: [?]..Since the imports of directives on a component level is gone we don't need to worry about this case.
To sum up: we can't do much about circular deps and error messages were clarified.
maliksahil commentedon Jul 25, 2017
Is there a way or tool that detects circular dependencies? Unfortunately in a large project it is very difficult to detect circular dependencies.
KostyaTretyak commentedon Aug 29, 2017
@maliksahil, to avoid circular dependency, just don't:
Instead, use directly path to the file:
This does not apply to the modules that you import from the
node_modules.angular-automatic-lock-bot commentedon Sep 12, 2019
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.