Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: impl GlobalGraph build hook #246

Merged
merged 4 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/aop-decorator/src/AspectMetaBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class AspectMetaBuilder {
return aspectList;
}

private static getAllMethods(clazz): PropertyKey[] {
static getAllMethods(clazz): PropertyKey[] {
const methodSet = new Set<string>();
function getMethods(obj) {
if (obj) {
Expand Down
3 changes: 3 additions & 0 deletions core/aop-runtime/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export * from './src/EggPrototypeCrossCutHook';
export * from './src/EggObjectAopHook';
export * from './src/LoadUnitAopHook';

export * from './src/CrossCutGraphHook';
export * from './src/PointCutGraphHook';
63 changes: 63 additions & 0 deletions core/aop-runtime/src/CrossCutGraphHook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { AspectMetaBuilder, CrosscutInfo, CrosscutInfoUtil } from '@eggjs/aop-decorator';
import { GraphNode } from '@eggjs/tegg-common-util';
import {
ClassProtoDescriptor,
GlobalGraph,
ProtoDependencyMeta,
ProtoNode,
} from '@eggjs/tegg-metadata';

export function crossCutGraphHook(globalGraph: GlobalGraph) {
for (const moduleNode of globalGraph.moduleGraph.nodes.values()) {
for (const crossCutProtoNode of moduleNode.val.protos) {
const protoNodes = findCrossCuttedClazz(globalGraph, crossCutProtoNode);
if (!protoNodes) continue;
Comment on lines +13 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify protoNodes Existence Check

After ensuring that findCrossCuttedClazz always returns an array, the check if (!protoNodes) at line 14 can be simplified since protoNodes will always be an array. You can check if the array is empty instead.

Apply this diff to refine the condition:

-    if (!protoNodes) continue;
+    if (protoNodes.length === 0) continue;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const protoNodes = findCrossCuttedClazz(globalGraph, crossCutProtoNode);
if (!protoNodes) continue;
const protoNodes = findCrossCuttedClazz(globalGraph, crossCutProtoNode);
if (protoNodes.length === 0) continue;

for (const crossCuttedProtoNode of protoNodes) {
const crossCuttedModuleNode = globalGraph.findModuleNode(crossCuttedProtoNode.val.proto.instanceModuleName);
if (!crossCuttedModuleNode) continue;
globalGraph.addInject(
crossCuttedModuleNode,
crossCuttedProtoNode,
crossCutProtoNode,
crossCutProtoNode.val.proto.name);
}
}
}
}

function findCrossCuttedClazz(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
const proto = protoNode.val.proto;
if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
return;
}
if (!CrosscutInfoUtil.isCrosscutAdvice(proto.clazz)) {
return;
Comment on lines +28 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure findCrossCuttedClazz Always Returns an Array

In the findCrossCuttedClazz function, when the conditions are not met, the function returns undefined due to the return; statements at lines 31 and 34. This can lead to potential issues when you check if (!protoNodes) at line 14 in crossCutGraphHook. To maintain consistency and avoid runtime errors, it's better to return an empty array instead of undefined.

Apply this diff to ensure consistent return values:

 function findCrossCuttedClazz(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
   const proto = protoNode.val.proto;
   if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
-    return;
+    return [];
   }
   if (!CrosscutInfoUtil.isCrosscutAdvice(proto.clazz)) {
-    return;
+    return [];
   }
   const crosscutInfoList = CrosscutInfoUtil.getCrosscutInfoList(proto.clazz);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function findCrossCuttedClazz(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
const proto = protoNode.val.proto;
if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
return;
}
if (!CrosscutInfoUtil.isCrosscutAdvice(proto.clazz)) {
return;
function findCrossCuttedClazz(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
const proto = protoNode.val.proto;
if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
return [];
}
if (!CrosscutInfoUtil.isCrosscutAdvice(proto.clazz)) {
return [];
}

}
const crosscutInfoList = CrosscutInfoUtil.getCrosscutInfoList(proto.clazz);
const result: GraphNode<ProtoNode, ProtoDependencyMeta>[] = [];
// eslint-disable-next-line no-labels
crosscut: for (const crosscutInfo of crosscutInfoList) {
for (const protoNode of globalGraph.protoGraph.nodes.values()) {
if (checkClazzMatchCrossCut(protoNode, crosscutInfo)) {
Comment on lines +40 to +41
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid Variable Shadowing for Clarity

In the inner loop of findCrossCuttedClazz, the variable protoNode is redeclared, which shadows the parameter protoNode of the function. This can cause confusion and potential errors. Consider renaming the inner loop variable to improve code clarity.

Apply this diff to rename the loop variable:

-    for (const protoNode of globalGraph.protoGraph.nodes.values()) {
-      if (checkClazzMatchCrossCut(protoNode, crosscutInfo)) {
+    for (const candidateProtoNode of globalGraph.protoGraph.nodes.values()) {
+      if (checkClazzMatchCrossCut(candidateProtoNode, crosscutInfo)) {

Remember to update all usages of protoNode within this loop to candidateProtoNode.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const protoNode of globalGraph.protoGraph.nodes.values()) {
if (checkClazzMatchCrossCut(protoNode, crosscutInfo)) {
for (const candidateProtoNode of globalGraph.protoGraph.nodes.values()) {
if (checkClazzMatchCrossCut(candidateProtoNode, crosscutInfo)) {

result.push(protoNode);
// eslint-disable-next-line no-labels
break crosscut;
}
Comment on lines +38 to +45
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor to Eliminate Labeled Breaks

The use of labels (crosscut:) and labeled breaks (break crosscut;) is generally discouraged as it can make the code harder to read and maintain. You can refactor the code to eliminate the need for labels by using functions or other control flow mechanisms.

Here's how you could refactor the code:

-function findCrossCuttedClazz(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
  // ... existing code ...
-  // eslint-disable-next-line no-labels
-  crosscut: for (const crosscutInfo of crosscutInfoList) {
-    for (const candidateProtoNode of globalGraph.protoGraph.nodes.values()) {
-      if (checkClazzMatchCrossCut(candidateProtoNode, crosscutInfo)) {
-        result.push(candidateProtoNode);
-        // eslint-disable-next-line no-labels
-        break crosscut;
-      }
-    }
+  for (const crosscutInfo of crosscutInfoList) {
+    const matchedNodes = Array.from(globalGraph.protoGraph.nodes.values()).filter(candidateProtoNode =>
+      checkClazzMatchCrossCut(candidateProtoNode, crosscutInfo)
+    );
+    result.push(...matchedNodes);
   }
   return result;
 }

This refactoring removes the labeled break by collecting all matched nodes and avoids breaking out of nested loops.

Committable suggestion was skipped due to low confidence.

}
}
return result;
}

function checkClazzMatchCrossCut(protoNode: GraphNode<ProtoNode>, crosscutInfo: CrosscutInfo) {
const proto = protoNode.val.proto;
if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
return;
}
const allMethods = AspectMetaBuilder.getAllMethods(proto.clazz);
for (const method of allMethods) {
if (crosscutInfo.pointcutInfo.match(proto.clazz, method)) {
return true;
}
}
return false;
}
54 changes: 54 additions & 0 deletions core/aop-runtime/src/PointCutGraphHook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { AspectMetaBuilder, PointcutAdviceInfoUtil } from '@eggjs/aop-decorator';
import { PrototypeUtil, QualifierUtil } from '@eggjs/core-decorator';
import { GraphNode } from '@eggjs/tegg-common-util';
import {
ClassProtoDescriptor,
GlobalGraph,
ProtoDependencyMeta,
ProtoNode,
} from '@eggjs/tegg-metadata';
import assert from 'node:assert';

export function pointCutGraphHook(globalGraph: GlobalGraph) {
for (const moduleNode of globalGraph.moduleGraph.nodes.values()) {
for (const pointCuttedProtoNode of moduleNode.val.protos) {
const pointCutAdviceProtoList = findPointCutAdvice(globalGraph, pointCuttedProtoNode);
if (!pointCutAdviceProtoList) continue;
Comment on lines +15 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify condition by checking array length

With findPointCutAdvice modified to always return an array, you can simplify the condition in line 15 by checking if the array is empty.

Apply this diff:

-      if (!pointCutAdviceProtoList) continue;
+      if (pointCutAdviceProtoList.length === 0) continue;

This makes the code more readable and avoids potential issues with falsy values other than undefined.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const pointCutAdviceProtoList = findPointCutAdvice(globalGraph, pointCuttedProtoNode);
if (!pointCutAdviceProtoList) continue;
const pointCutAdviceProtoList = findPointCutAdvice(globalGraph, pointCuttedProtoNode);
if (pointCutAdviceProtoList.length === 0) continue;

for (const pointCutAdviceProto of pointCutAdviceProtoList) {
globalGraph.addInject(
moduleNode,
pointCuttedProtoNode,
pointCutAdviceProto,
pointCutAdviceProto.val.proto.name);
}
}
}
}

function findPointCutAdvice(globalGraph: GlobalGraph, protoNode: GraphNode<ProtoNode, ProtoDependencyMeta>) {
const proto = protoNode.val.proto;
if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
return;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure consistent return types in findPointCutAdvice

Currently, findPointCutAdvice returns undefined if the prototype is not a class prototype descriptor. For consistency and to simplify downstream code, consider returning an empty array instead. This allows you to avoid undefined checks when iterating over the results.

Apply this diff:

  if (!ClassProtoDescriptor.isClassProtoDescriptor(proto)) {
-    return;
+    return [];
  }

This ensures that the function always returns an array, making it easier to handle in the calling code.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return;
return [];

}
const result: Set<GraphNode<ProtoNode, ProtoDependencyMeta>> = new Set();
const allMethods = AspectMetaBuilder.getAllMethods(proto.clazz);
for (const method of allMethods) {
const adviceInfoList = PointcutAdviceInfoUtil.getPointcutAdviceInfoList(proto.clazz, method);
for (const { clazz } of adviceInfoList) {
const property = PrototypeUtil.getProperty(clazz);
assert(property, 'not found property');
const injectProto = globalGraph.findDependencyProtoNode(protoNode.val.proto, {
objName: property.name,
refName: property.name,
qualifiers: [
...property?.qualifiers ?? [],
...QualifierUtil.getProtoQualifiers(clazz),
Comment on lines +44 to +45
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify qualifiers array construction

In lines 44-45, to handle the possibility that property.qualifiers is undefined, you can default it to an empty array when spreading. This removes the need for optional chaining and ensures the spread operator functions correctly.

Apply this diff:

           qualifiers: [
-              ...property?.qualifiers ?? [],
+              ...(property.qualifiers ?? []),
               ...QualifierUtil.getProtoQualifiers(clazz),
           ],

This change simplifies the code and improves readability by making the handling of potential undefined values explicit.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
...property?.qualifiers ?? [],
...QualifierUtil.getProtoQualifiers(clazz),
...(property.qualifiers ?? []),
...QualifierUtil.getProtoQualifiers(clazz),

],
});
if (injectProto) {
result.add(injectProto);
}
}
}
return Array.from(result);
}
12 changes: 11 additions & 1 deletion core/aop-runtime/test/aop-runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ import { EggPrototypeLifecycleUtil, LoadUnitFactory, LoadUnitLifecycleUtil } fro
import type { LoadUnitInstance } from '@eggjs/tegg-types';
import { CrosscutAdviceFactory } from '@eggjs/aop-decorator';
import { CoreTestHelper, EggTestContext } from '../../test-util';
import { CallTrace, Hello, crosscutAdviceParams, pointcutAdviceParams } from './fixtures/modules/hello_succeed/Hello';
import { Hello } from './fixtures/modules/hello_succeed/Hello';
import { crosscutAdviceParams } from './fixtures/modules/hello_cross_cut/HelloCrossCut';
import { pointcutAdviceParams } from './fixtures/modules/hello_point_cut/HelloPointCut';
import { EggObjectAopHook } from '../src/EggObjectAopHook';
import { LoadUnitAopHook } from '../src/LoadUnitAopHook';
import { EggPrototypeCrossCutHook } from '../src/EggPrototypeCrossCutHook';
import { crossCutGraphHook } from '../src/CrossCutGraphHook';
import { pointCutGraphHook } from '../src/PointCutGraphHook';
import { CallTrace } from './fixtures/modules/hello_cross_cut/CallTrace';

describe('test/aop-runtime.test.ts', () => {
describe('succeed call', () => {
Expand All @@ -31,6 +36,11 @@ describe('test/aop-runtime.test.ts', () => {
modules = await CoreTestHelper.prepareModules([
path.join(__dirname, '..'),
path.join(__dirname, 'fixtures/modules/hello_succeed'),
path.join(__dirname, 'fixtures/modules/hello_point_cut'),
path.join(__dirname, 'fixtures/modules/hello_cross_cut'),
], [
crossCutGraphHook,
pointCutGraphHook,
]);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { AccessLevel, SingletonProto } from "@eggjs/core-decorator";

export interface CallTraceMsg {
className: string;
methodName: string;
id: number;
name: string;
result?: string;
adviceParams?: any;
}

@SingletonProto({
accessLevel: AccessLevel.PUBLIC,
})
export class CallTrace {
msgs: Array<CallTraceMsg> = [];

addMsg(msg: CallTraceMsg) {
this.msgs.push(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import assert from 'node:assert';
import { AccessLevel, Inject } from '@eggjs/core-decorator';
import { Advice, Crosscut } from '@eggjs/aop-decorator';
import { AdviceContext, IAdvice, PointcutType } from '@eggjs/tegg-types';
import { Hello } from '../hello_succeed/Hello';
import { CallTrace } from './CallTrace';

export const crosscutAdviceParams = {
cross: Math.random().toString(),
cut: Math.random().toString(),
};

@Crosscut({
type: PointcutType.CLASS,
clazz: Hello,
methodName: 'hello',
}, { adviceParams: crosscutAdviceParams })
@Advice({
accessLevel: AccessLevel.PUBLIC,
})
export class CrosscutAdvice implements IAdvice<Hello, string> {
@Inject()
callTrace: CallTrace;

async beforeCall(ctx: AdviceContext<Hello, {}>): Promise<void> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid using '{}' as a type; specify an explicit interface

Using {} as a type is discouraged because it represents any non-nullable value, which can lead to unclear code and potential type safety issues. Instead, define a specific interface or type that accurately represents the expected structure.

Consider defining an explicit type for the context parameters:

interface BeforeCallParams {
  // Define the expected properties here
}

async beforeCall(ctx: AdviceContext<Hello, BeforeCallParams>): Promise<void> {
🧰 Tools
🪛 Biome

[error] 25-25: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, crosscutAdviceParams);
this.callTrace.addMsg({
className: CrosscutAdvice.name,
methodName: 'beforeCall',
id: ctx.that.id,
name: ctx.args[0],
adviceParams: ctx.adviceParams,
});
}

async afterReturn(ctx: AdviceContext<Hello>, result: any): Promise<void> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Specify the type parameter for 'AdviceContext'

For consistency and better type safety, explicitly provide the second type parameter for AdviceContext in the afterReturn method. This enhances code clarity and ensures consistent typing across your methods.

Update the method signature:

-async afterReturn(ctx: AdviceContext<Hello>, result: any): Promise<void> {
+async afterReturn(ctx: AdviceContext<Hello, AfterReturnParams>, result: any): Promise<void> {

Define the AfterReturnParams interface appropriately.

Committable suggestion was skipped due to low confidence.

assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, crosscutAdviceParams);
this.callTrace.addMsg({
className: CrosscutAdvice.name,
methodName: 'afterReturn',
id: ctx.that.id,
name: ctx.args[0],
result,
adviceParams: ctx.adviceParams,
});
}

async afterFinally(ctx: AdviceContext<Hello>): Promise<void> {
assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, crosscutAdviceParams);
this.callTrace.addMsg({
className: CrosscutAdvice.name,
methodName: 'afterFinally',
id: ctx.that.id,
name: ctx.args[0],
adviceParams: ctx.adviceParams,
});
}

async around(ctx: AdviceContext<Hello>, next: () => Promise<any>): Promise<any> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Provide specific types for 'next' and return value in 'around' method

The next function and the return type are currently typed as any. To enhance type safety and readability, specify the expected return type.

Update the method signature:

-async around(ctx: AdviceContext<Hello>, next: () => Promise<any>): Promise<any> {
+async around(ctx: AdviceContext<Hello, AroundParams>, next: () => Promise<string>): Promise<string> {

Ensure that AroundParams reflects the expected structure.

Committable suggestion was skipped due to low confidence.

assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, crosscutAdviceParams);
ctx.args[0] = `withCrosscutAroundParam(${ctx.args[0]})`;
const result = await next();
return `withCrossAroundResult(${result}${JSON.stringify(ctx.adviceParams)})`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "hello-cross-cut",
"eggModule": {
"name": "helloCrossCut"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import assert from 'node:assert';
import { AccessLevel, Inject } from '@eggjs/core-decorator';
import { Advice } from '@eggjs/aop-decorator';
import { AdviceContext, IAdvice } from '@eggjs/tegg-types';
import { Hello } from '../hello_succeed/Hello';
import { CallTrace } from '../hello_cross_cut/CallTrace';

export const pointcutAdviceParams = {
point: Math.random().toString(),
cut: Math.random().toString(),
};

// 测试aop修改ctx的args的值
const TEST_CTX_ARGS_VALUE = 123;

@Advice({
accessLevel: AccessLevel.PUBLIC,
})
export class PointcutAdvice implements IAdvice<Hello> {
@Inject()
callTrace: CallTrace;

async beforeCall(ctx: AdviceContext<Hello>): Promise<void> {
assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, pointcutAdviceParams);
this.callTrace.addMsg({
className: PointcutAdvice.name,
methodName: 'beforeCall',
id: ctx.that.id,
name: ctx.args[0],
adviceParams: ctx.adviceParams,
});
ctx.args = [...ctx.args, TEST_CTX_ARGS_VALUE];
}

async afterReturn(ctx: AdviceContext<Hello>, result: any): Promise<void> {
assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, pointcutAdviceParams);
assert.deepStrictEqual(ctx.args[ctx.args.length - 1], TEST_CTX_ARGS_VALUE);
this.callTrace.addMsg({
className: PointcutAdvice.name,
methodName: 'afterReturn',
id: ctx.that.id,
name: ctx.args[0],
result,
adviceParams: ctx.adviceParams,
});
}

async afterThrow(ctx: AdviceContext<Hello, any>, error: Error): Promise<void> {
assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, pointcutAdviceParams);
this.callTrace.addMsg({
className: PointcutAdvice.name,
methodName: 'afterThrow',
id: ctx.that.id,
name: ctx.args[0],
result: error.message,
adviceParams: ctx.adviceParams,
});
}

async afterFinally(ctx: AdviceContext<Hello>): Promise<void> {
assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, pointcutAdviceParams);
this.callTrace.addMsg({
className: PointcutAdvice.name,
methodName: 'afterFinally',
id: ctx.that.id,
name: ctx.args[0],
adviceParams: ctx.adviceParams,
});
}

async around(ctx: AdviceContext<Hello>, next: () => Promise<any>): Promise<any> {
assert.ok(ctx.adviceParams);
assert.deepStrictEqual(ctx.adviceParams, pointcutAdviceParams);
ctx.args[0] = `withPointAroundParam(${ctx.args[0]})`;
const result = await next();
return `withPointAroundResult(${result}${JSON.stringify(pointcutAdviceParams)})`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "hello-point-cut",
"eggModule": {
"name": "helloPointCut"
}
}
Loading
Loading