Skip to content

inject and directiveInject need bridging when used with Component.provides #23330

Closed
@mhevery

Description

@mhevery

Currently we generate inject for @Injectable and directiveInject for @Component and @Directive. This works fine since @Injectable declared as part of @NgModule does not need to see anything from the Element Injector Tree.

However this does not work in the case when @Injectable is used with @Component.providers (or @Component.viewProviders) because in that case the @Injectable can see into the Element Injector Tree.

Possible fixes are:

Mark services in @Component.providers using inject (:thumbsdown:)

non-starter as it breaks locality.

Have only one inject (:thumbsdown:)

This would require merging directiveInject into inject

Pros:

  • Easy to implement

Cons:

  • di will have to know about render3
  • Breaks tree shaking since any @Injectable will be pulling in at least some code of render3.

Have ComponentDefFeature which would patch inject to act like directiveInject only when @Component.providers are used (:thumbsup:)

Pros:

  • Tree shaking works as expected.
  • di does not need to know about render3 (needs to have a hook, see cons)

Cons:

  • di has to have a hook into which external render3 can connect in order to redirect inject into directiveInject. Since this is a private hook, it should be small cost.

Syntax

@Inejctable()
class SomeService {
  constructor(dep: SomeDep) {}
  static ngInjectableDef = defineInjectable({
   factory: () => new SomeService(inject(SomeDep));
  });
}

@Component({
  ...,
  provides: [SomeService]
})
class MyComponent {
  static ngComponentDef = defineCompoent({
    ...,
    provides: [SomeService],
    features: [ComponetProvidersFeature]
  });
}

ComponetProvidersFeature would than use some private API to patch the inject to go through the directiveInject in cases where the factory is called as a consequence of @Component.providers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimecore: difeatureIssue that requests a new feature

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions