Skip to content

Commit d5a8a93

Browse files
authored
fix: fix merge qualifier (#250)
<!-- Thank you for your pull request. Please review below requirements. Bug fixes and new features should include tests and possibly benchmarks. Contributors guide: https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md 感谢您贡献代码。请确认下列 checklist 的完成情况。 Bug 修复和新功能必须包含测试,必要时请附上性能测试。 Contributors guide: https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md --> ##### Checklist <!-- Remove items that do not apply. For completed items, change [ ] to [x]. --> - [ ] `npm test` passes - [ ] tests and/or benchmarks are included - [ ] documentation is changed or added - [ ] commit message follows commit guidelines ##### Affected core subsystem(s) <!-- Provide affected core subsystem(s). --> ##### Description of change <!-- Provide a description of the change below this comment. --> <!-- - any feature? - close https://github.com/eggjs/egg/ISSUE_URL -->
1 parent 8acbcc4 commit d5a8a93

File tree

11 files changed

+90
-53
lines changed

11 files changed

+90
-53
lines changed

core/aop-runtime/src/PointCutGraphHook.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ function findPointCutAdvice(globalGraph: GlobalGraph, protoNode: GraphNode<Proto
4040
const injectProto = globalGraph.findDependencyProtoNode(protoNode.val.proto, {
4141
objName: property.name,
4242
refName: property.name,
43-
qualifiers: [
44-
...property?.qualifiers ?? [],
45-
...QualifierUtil.getProtoQualifiers(clazz),
46-
],
43+
qualifiers: QualifierUtil.mergeQualifiers(
44+
property?.qualifiers ?? [],
45+
QualifierUtil.getProtoQualifiers(clazz),
46+
),
4747
});
4848
if (injectProto) {
4949
result.add(injectProto);

core/core-decorator/src/util/QualifierUtil.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,21 @@ export class QualifierUtil {
8080
if (clazzQualifiers.length !== requestQualifiers.length) return false;
8181
return QualifierUtil.matchQualifiers(clazzQualifiers, requestQualifiers);
8282
}
83+
84+
static mergeQualifiers(...qualifiers: QualifierInfo[][]): QualifierInfo[] {
85+
const result: QualifierInfo[] = [];
86+
const temp: Record<QualifierAttribute, QualifierValue> = {};
87+
for (const qualifierList of qualifiers) {
88+
for (const { attribute, value } of qualifierList) {
89+
temp[attribute] = value;
90+
}
91+
}
92+
for (const key of Reflect.ownKeys(temp)) {
93+
result.push({
94+
attribute: key,
95+
value: temp[key],
96+
});
97+
}
98+
return result;
99+
}
83100
}

core/dynamic-inject-runtime/src/EggObjectFactoryPrototype.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ export class EggObjectFactoryPrototype implements EggPrototype {
3636

3737
constructor(clazz: EggProtoImplClass<EggObjectFactory>, loadUnit: LoadUnit, prototypeInfo: EggPrototypeInfo) {
3838
this.clazz = clazz;
39-
this.qualifiers = [
40-
...QualifierUtil.getProtoQualifiers(clazz),
41-
...(prototypeInfo.qualifiers ?? []),
42-
];
39+
this.qualifiers = QualifierUtil.mergeQualifiers(
40+
QualifierUtil.getProtoQualifiers(clazz),
41+
(prototypeInfo.qualifiers ?? []),
42+
);
4343
this.id = IdenticalUtil.createProtoId(loadUnit.id, NameUtil.getClassName(this.clazz));
4444
this.initType = prototypeInfo.initType;
4545
this.accessLevel = prototypeInfo.accessLevel;

core/metadata/src/impl/EggPrototypeBuilder.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ export class EggPrototypeBuilder {
5353
builder.injectType = PrototypeUtil.getInjectType(clazz);
5454
builder.injectObjects = PrototypeUtil.getInjectObjects(clazz) || [];
5555
builder.loadUnit = loadUnit;
56-
builder.qualifiers = [
57-
...QualifierUtil.getProtoQualifiers(clazz),
58-
...(ctx.prototypeInfo.qualifiers ?? []),
59-
];
56+
builder.qualifiers = QualifierUtil.mergeQualifiers(
57+
QualifierUtil.getProtoQualifiers(clazz),
58+
(ctx.prototypeInfo.qualifiers ?? []),
59+
);
6060
builder.properQualifiers = ctx.prototypeInfo.properQualifiers ?? {};
6161
builder.multiInstanceConstructorIndex = PrototypeUtil.getMultiInstanceConstructorIndex(clazz);
6262
builder.multiInstanceConstructorAttributes = PrototypeUtil.getMultiInstanceConstructorAttributes(clazz);
@@ -66,36 +66,36 @@ export class EggPrototypeBuilder {
6666
private tryFindDefaultPrototype(injectObject: InjectObject): EggPrototype {
6767
const propertyQualifiers = QualifierUtil.getProperQualifiers(this.clazz, injectObject.refName);
6868
const multiInstancePropertyQualifiers = this.properQualifiers[injectObject.refName as string] ?? [];
69-
return EggPrototypeFactory.instance.getPrototype(injectObject.objName, this.loadUnit, [
70-
...propertyQualifiers,
71-
...multiInstancePropertyQualifiers,
72-
]);
69+
return EggPrototypeFactory.instance.getPrototype(injectObject.objName, this.loadUnit, QualifierUtil.mergeQualifiers(
70+
propertyQualifiers,
71+
multiInstancePropertyQualifiers,
72+
));
7373
}
7474

7575
private tryFindContextPrototype(injectObject: InjectObject): EggPrototype {
7676
const propertyQualifiers = QualifierUtil.getProperQualifiers(this.clazz, injectObject.refName);
7777
const multiInstancePropertyQualifiers = this.properQualifiers[injectObject.refName as string] ?? [];
78-
return EggPrototypeFactory.instance.getPrototype(injectObject.objName, this.loadUnit, [
79-
...propertyQualifiers,
80-
...multiInstancePropertyQualifiers,
81-
{
78+
return EggPrototypeFactory.instance.getPrototype(injectObject.objName, this.loadUnit, QualifierUtil.mergeQualifiers(
79+
propertyQualifiers,
80+
multiInstancePropertyQualifiers,
81+
[{
8282
attribute: InitTypeQualifierAttribute,
8383
value: ObjectInitType.CONTEXT,
84-
},
85-
]);
84+
}],
85+
));
8686
}
8787

8888
private tryFindSelfInitTypePrototype(injectObject: InjectObject): EggPrototype {
8989
const propertyQualifiers = QualifierUtil.getProperQualifiers(this.clazz, injectObject.refName);
9090
const multiInstancePropertyQualifiers = this.properQualifiers[injectObject.refName as string] ?? [];
91-
return EggPrototypeFactory.instance.getPrototype(injectObject.objName, this.loadUnit, [
92-
...propertyQualifiers,
93-
...multiInstancePropertyQualifiers,
94-
{
91+
return EggPrototypeFactory.instance.getPrototype(injectObject.objName, this.loadUnit, QualifierUtil.mergeQualifiers(
92+
propertyQualifiers,
93+
multiInstancePropertyQualifiers,
94+
[{
9595
attribute: InitTypeQualifierAttribute,
9696
value: this.initType,
97-
},
98-
]);
97+
}],
98+
));
9999
}
100100

101101
private findInjectObjectPrototype(injectObject: InjectObject): EggPrototype {

core/metadata/src/model/ProtoDescriptorHelper.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,21 @@ export class ProtoDescriptorHelper {
9696
const res: ProtoDescriptor[] = [];
9797

9898
for (const obj of instanceProperty.objects) {
99-
let qualifiers = [
100-
...QualifierUtil.getProtoQualifiers(clazz),
101-
...obj.qualifiers,
102-
];
99+
let qualifiers = QualifierUtil.mergeQualifiers(
100+
QualifierUtil.getProtoQualifiers(clazz),
101+
obj.qualifiers,
102+
);
103103
qualifiers = ProtoDescriptorHelper.addDefaultQualifier(qualifiers, instanceProperty.initType, options.instanceModuleName);
104104
const injectObjects: InjectObjectDescriptor[] = PrototypeUtil.getInjectObjects(clazz)
105105
.map(t => {
106106
const qualifiers = QualifierUtil.getProperQualifiers(clazz, t.refName);
107107
const instanceQualifier = obj.properQualifiers?.[t.refName] ?? [];
108108
return {
109109
...t,
110-
qualifiers: [
111-
...qualifiers,
112-
...instanceQualifier,
113-
],
110+
qualifiers: QualifierUtil.mergeQualifiers(
111+
qualifiers,
112+
instanceQualifier,
113+
),
114114
};
115115
});
116116
res.push(new ClassProtoDescriptor({

core/metadata/src/model/graph/GlobalGraph.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { FrameworkErrorFormater } from 'egg-errors';
1212
import { EggPrototypeNotFound, MultiPrototypeFound } from '../../errors';
1313
import { GlobalModuleNodeBuilder } from './GlobalModuleNodeBuilder';
1414
import { ModuleDescriptor } from '../ModuleDescriptor';
15+
import { QualifierUtil } from '@eggjs/core-decorator';
1516

1617
export interface GlobalGraphOptions {
1718
// TODO next major version refactor to force strict
@@ -145,10 +146,10 @@ export class GlobalGraph {
145146
for (const node of this.protoGraph.nodes.values()) {
146147
if (node.val.selectProto({
147148
name: injectObject.objName,
148-
qualifiers: [
149-
...injectObject.qualifiers,
150-
...qualifiers,
151-
],
149+
qualifiers: QualifierUtil.mergeQualifiers(
150+
injectObject.qualifiers,
151+
qualifiers,
152+
),
152153
moduleName: proto.instanceModuleName,
153154
})) {
154155
result.push(node);
@@ -189,13 +190,13 @@ export class GlobalGraph {
189190
if (!loadUnitQualifier) {
190191
return this.findDependencyProtoNode(proto, {
191192
...injectObject,
192-
qualifiers: [
193-
...injectObject.qualifiers,
194-
{
193+
qualifiers: QualifierUtil.mergeQualifiers(
194+
injectObject.qualifiers,
195+
[{
195196
attribute: LoadUnitNameQualifierAttribute,
196197
value: proto.instanceModuleName,
197-
},
198-
],
198+
}],
199+
),
199200
});
200201
}
201202
throw FrameworkErrorFormater.formatError(new MultiPrototypeFound(injectObject.objName, injectObject.qualifiers));

core/runtime/src/impl/EggObjectUtil.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ export class EggObjectUtil {
5454
return target[p];
5555
}
5656
const obj = getObj();
57-
return obj[p];
57+
const val = obj[p];
58+
if (typeof val === 'function') {
59+
return val.bind(obj);
60+
}
61+
return val;
5862
},
5963
getOwnPropertyDescriptor(_target: {}, p: string | symbol): PropertyDescriptor | undefined {
6064
const obj = getObj();

plugin/dal/lib/TransactionalAOP.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Advice, AdviceContext, IAdvice } from '@eggjs/tegg/aop';
22
import { AccessLevel, EggProtoImplClass, ObjectInitType } from '@eggjs/tegg';
33
import { PropagationType } from '@eggjs/tegg/transaction';
4-
import assert from 'node:assert';
54
import { MysqlDataSource } from '@eggjs/dal-runtime';
65

76
export interface TransactionalParams {
@@ -17,7 +16,9 @@ export class TransactionalAOP implements IAdvice<EggProtoImplClass, Transactiona
1716
public async around(ctx: AdviceContext<EggProtoImplClass, TransactionalParams>, next: () => Promise<any>): Promise<void> {
1817
const { propagation, dataSourceGetter } = ctx.adviceParams!;
1918
const dataSource = dataSourceGetter();
20-
assert(propagation === PropagationType.REQUIRED, '事务注解目前只支持 REQUIRED 机制');
19+
if (propagation === PropagationType.ALWAYS_NEW) {
20+
return await dataSource.beginTransactionScope(next);
21+
}
2122
return await dataSource.beginTransactionScope(next);
2223
}
2324
}

plugin/tegg/lib/EggCompatibleProtoImpl.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ export class EggCompatibleProtoImpl implements EggPrototype {
7979
const name = ctx.prototypeInfo.name;
8080
const id = IdenticalUtil.createProtoId(loadUnit.id, name);
8181
const proto = new EggCompatibleProtoImpl(
82-
id, name, clazz, ctx.prototypeInfo.initType, loadUnit.id, [
83-
...QualifierUtil.getProtoQualifiers(clazz),
84-
...(ctx.prototypeInfo.qualifiers ?? []),
85-
],
82+
id, name, clazz, ctx.prototypeInfo.initType, loadUnit.id, QualifierUtil.mergeQualifiers(
83+
QualifierUtil.getProtoQualifiers(clazz),
84+
(ctx.prototypeInfo.qualifiers ?? []),
85+
),
8686
);
8787
return proto;
8888
}

plugin/tegg/test/ConstructorModuleConfig.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import mm from 'egg-mock';
22
import assert from 'assert';
33
import path from 'path';
4+
import { Foo } from './fixtures/apps/constructor-module-config/modules/module-with-config/foo';
45

56
describe('plugin/tegg/test/ModuleConfig.test.ts', () => {
67
let app;
@@ -37,4 +38,9 @@ describe('plugin/tegg/test/ModuleConfig.test.ts', () => {
3738
});
3839
});
3940
});
41+
42+
it('construct proxy should work', async () => {
43+
const foo: Foo = await app.getEggObject(Foo);
44+
foo.log();
45+
});
4046
});

0 commit comments

Comments
 (0)