fix(core): support `Attribute` DI decorator in `deps` section of a token (#37085)
This commit fixes a bug when `Attribute` DI decorator is used in the `deps` section of a token that uses a factory function. The problem appeared because the `Attribute` DI decorator was not handled correctly while injecting factory function attributes. Closes #36479 PR Close #37085
This commit is contained in:
parent
a965589eb8
commit
f5cbf0bb54
|
@ -176,6 +176,57 @@
|
||||||
"packages/core/src/change_detection/differs/default_keyvalue_differ.ts",
|
"packages/core/src/change_detection/differs/default_keyvalue_differ.ts",
|
||||||
"packages/core/src/change_detection/differs/keyvalue_differs.ts"
|
"packages/core/src/change_detection/differs/keyvalue_differs.ts"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di.ts",
|
||||||
|
"packages/core/src/di/index.ts",
|
||||||
|
"packages/core/src/di/injectable.ts",
|
||||||
|
"packages/core/src/di/jit/injectable.ts",
|
||||||
|
"packages/core/src/di/jit/environment.ts",
|
||||||
|
"packages/core/src/di/injector_compatibility.ts",
|
||||||
|
"packages/core/src/di/injector.ts",
|
||||||
|
"packages/core/src/di/metadata.ts",
|
||||||
|
"packages/core/src/render3/instructions/di.ts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di.ts",
|
||||||
|
"packages/core/src/di/index.ts",
|
||||||
|
"packages/core/src/di/injectable.ts",
|
||||||
|
"packages/core/src/di/jit/injectable.ts",
|
||||||
|
"packages/core/src/di/jit/environment.ts",
|
||||||
|
"packages/core/src/di/injector_compatibility.ts",
|
||||||
|
"packages/core/src/di/metadata.ts",
|
||||||
|
"packages/core/src/render3/instructions/di.ts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di.ts",
|
||||||
|
"packages/core/src/di/index.ts",
|
||||||
|
"packages/core/src/di/injectable.ts",
|
||||||
|
"packages/core/src/di/jit/injectable.ts",
|
||||||
|
"packages/core/src/di/jit/util.ts",
|
||||||
|
"packages/core/src/di/metadata.ts",
|
||||||
|
"packages/core/src/render3/instructions/di.ts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di.ts",
|
||||||
|
"packages/core/src/di/index.ts",
|
||||||
|
"packages/core/src/di/metadata.ts",
|
||||||
|
"packages/core/src/render3/instructions/di.ts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di.ts",
|
||||||
|
"packages/core/src/di/index.ts",
|
||||||
|
"packages/core/src/di/reflective_injector.ts",
|
||||||
|
"packages/core/src/di/metadata.ts",
|
||||||
|
"packages/core/src/render3/instructions/di.ts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di.ts",
|
||||||
|
"packages/core/src/di/index.ts",
|
||||||
|
"packages/core/src/di/reflective_injector.ts",
|
||||||
|
"packages/core/src/di/reflective_provider.ts",
|
||||||
|
"packages/core/src/di/metadata.ts",
|
||||||
|
"packages/core/src/render3/instructions/di.ts"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"packages/core/src/di/injectable.ts",
|
"packages/core/src/di/injectable.ts",
|
||||||
"packages/core/src/di/jit/injectable.ts"
|
"packages/core/src/di/jit/injectable.ts"
|
||||||
|
@ -184,6 +235,16 @@
|
||||||
"packages/core/src/di/injector_compatibility.ts",
|
"packages/core/src/di/injector_compatibility.ts",
|
||||||
"packages/core/src/di/injector.ts"
|
"packages/core/src/di/injector.ts"
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di/injector_compatibility.ts",
|
||||||
|
"packages/core/src/di/injector.ts",
|
||||||
|
"packages/core/src/di/null_injector.ts"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"packages/core/src/di/injector_compatibility.ts",
|
||||||
|
"packages/core/src/di/injector.ts",
|
||||||
|
"packages/core/src/di/r3_injector.ts"
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"packages/core/src/di/injector_token.ts",
|
"packages/core/src/di/injector_token.ts",
|
||||||
"packages/core/src/di/injector.ts"
|
"packages/core/src/di/injector.ts"
|
||||||
|
|
|
@ -25,6 +25,7 @@ export {
|
||||||
SWITCH_COMPILE_INJECTABLE__POST_R3__ as ɵSWITCH_COMPILE_INJECTABLE__POST_R3__,
|
SWITCH_COMPILE_INJECTABLE__POST_R3__ as ɵSWITCH_COMPILE_INJECTABLE__POST_R3__,
|
||||||
} from './di/injectable';
|
} from './di/injectable';
|
||||||
export {INJECTOR_IMPL__POST_R3__ as ɵINJECTOR_IMPL__POST_R3__} from './di/injector';
|
export {INJECTOR_IMPL__POST_R3__ as ɵINJECTOR_IMPL__POST_R3__} from './di/injector';
|
||||||
|
export {CREATE_ATTRIBUTE_DECORATOR__POST_R3__ as ɵCREATE_ATTRIBUTE_DECORATOR__POST_R3__} from './di/metadata';
|
||||||
export {
|
export {
|
||||||
NG_INJ_DEF as ɵNG_INJ_DEF,
|
NG_INJ_DEF as ɵNG_INJ_DEF,
|
||||||
NG_PROV_DEF as ɵNG_PROV_DEF,
|
NG_PROV_DEF as ɵNG_PROV_DEF,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {makeParamDecorator} from '../util/decorators';
|
import {makeParamDecorator} from '../util/decorators';
|
||||||
|
import {ɵɵinjectAttribute} from '../render3/instructions/di';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -274,11 +274,25 @@ export interface Attribute {
|
||||||
attributeName: string;
|
attributeName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CREATE_ATTRIBUTE_DECORATOR__PRE_R3__(): AttributeDecorator {
|
||||||
|
return makeParamDecorator(
|
||||||
|
'Attribute',
|
||||||
|
(attributeName?: string) => ({attributeName}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CREATE_ATTRIBUTE_DECORATOR__POST_R3__(): AttributeDecorator {
|
||||||
|
return makeParamDecorator(
|
||||||
|
'Attribute',
|
||||||
|
(attributeName?: string) =>
|
||||||
|
({attributeName, __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName!)}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const CREATE_ATTRIBUTE_DECORATOR_IMPL = CREATE_ATTRIBUTE_DECORATOR__PRE_R3__;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute decorator and metadata.
|
* Attribute decorator and metadata.
|
||||||
*
|
*
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export const Attribute: AttributeDecorator =
|
export const Attribute: AttributeDecorator = CREATE_ATTRIBUTE_DECORATOR_IMPL();
|
||||||
makeParamDecorator('Attribute', (attributeName?: string) => ({attributeName}));
|
|
||||||
|
|
|
@ -2771,6 +2771,38 @@ describe('di', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('attribute tokens', () => {
|
||||||
|
it('should be able to provide an attribute token', () => {
|
||||||
|
const TOKEN = new InjectionToken<string>('Some token');
|
||||||
|
function factory(token: string): string {
|
||||||
|
return token + ' with factory';
|
||||||
|
}
|
||||||
|
@Component({
|
||||||
|
selector: 'my-comp',
|
||||||
|
template: '...',
|
||||||
|
providers: [{
|
||||||
|
provide: TOKEN,
|
||||||
|
deps: [[new Attribute('token')]],
|
||||||
|
useFactory: factory,
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
class MyComp {
|
||||||
|
constructor(@Inject(TOKEN) readonly token: string) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({template: `<my-comp token='token'></my-comp>`})
|
||||||
|
class WrapperComp {
|
||||||
|
@ViewChild(MyComp) myComp!: MyComp;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [MyComp, WrapperComp]});
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(WrapperComp);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.componentInstance.myComp.token).toBe('token with factory');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should not cause cyclic dependency if same token is requested in deps with @SkipSelf', () => {
|
it('should not cause cyclic dependency if same token is requested in deps with @SkipSelf', () => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-comp',
|
selector: 'my-comp',
|
||||||
|
|
Loading…
Reference in New Issue