-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(core): parameter pointcut being mixed with its methodpointcut cou…
…nterpart
- Loading branch information
Nicolas
committed
Sep 15, 2024
1 parent
5d635e5
commit e4d7c01
Showing
54 changed files
with
1,458 additions
and
650 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export class ReflectError extends Error {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
export interface AspectOptions { | ||
readonly id?: string; | ||
} | ||
export interface AspectMetadata { | ||
id?: string; | ||
// TODO: add unique?: boolean flag | ||
readonly id: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import { AspectType, ASPECT_ID_SYMBOL } from '../aspect/aspect.type'; | ||
import { AspectType, getAspectMetadata } from '../aspect/aspect.type'; | ||
import { WeavingError } from './weaving.error'; | ||
|
||
export class AspectError extends WeavingError { | ||
constructor(aspect: AspectType, msg: string) { | ||
super(`[${aspect[ASPECT_ID_SYMBOL]}]: ${msg}`); | ||
super(`[${getAspectMetadata(aspect).id}]: ${msg}`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
import { ReflectError } from '@aspectjs/common'; | ||
|
||
/** | ||
* Error thrown during the weaving process meaning the weaver has illegal state. | ||
*/ | ||
export class WeavingError extends Error {} | ||
export class WeavingError extends ReflectError {} |
130 changes: 130 additions & 0 deletions
130
packages/core/src/jit/canvas/jit-abstract-method-canvas.strategy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import { PointcutType } from '../../pointcut/pointcut-target.type'; | ||
import { JitWeaverCanvasStrategy } from './jit-canvas.strategy'; | ||
|
||
import { | ||
MethodPropertyDescriptor, | ||
_copyPropsAndMeta, | ||
_defuseAbstract, | ||
assert, | ||
} from '@aspectjs/common/utils'; | ||
import { AdviceType } from '../../advice/advice-type.type'; | ||
import { JoinPoint } from '../../advice/joinpoint'; | ||
import { MutableAdviceContext } from '../../advice/mutable-advice.context'; | ||
import { AdviceEntry } from '../../advice/registry/advice-entry.model'; | ||
import { AdviceError } from '../../errors/advice.error'; | ||
import { CompiledSymbol } from '../../weaver/canvas/canvas-strategy.type'; | ||
import { renameFunction } from './canvas.utils'; | ||
|
||
/** | ||
* Canvas to advise method and parameters | ||
*/ | ||
export abstract class AbstractJitMethodCanvasStrategy< | ||
T extends PointcutType.METHOD | PointcutType.PARAMETER, | ||
X = unknown, | ||
> extends JitWeaverCanvasStrategy<T, X> { | ||
protected abstract getAdviceEntries<P extends AdviceType>( | ||
pointcutType: P, | ||
): AdviceEntry<T, X, P>[]; | ||
|
||
compile(ctxt: MutableAdviceContext<T, X>): CompiledSymbol<T, X> { | ||
// if method already compiled, it might also be linked. | ||
// Use the last known compiled symbol as a reference to avoid linking twice. | ||
let methodDescriptor = ctxt.target.getMetadata( | ||
'@ajs:compiledSymbol', | ||
() => ctxt.target.descriptor as CompiledSymbol<T, X>, | ||
)!; | ||
assert(!!methodDescriptor); | ||
|
||
// if no method compile advices, return method as is | ||
const adviceEntries = this.getAdviceEntries(AdviceType.COMPILE); | ||
if (!adviceEntries.length) { | ||
return methodDescriptor; | ||
} | ||
|
||
assert(!!ctxt.target.propertyKey); | ||
// if (!adviceEntries.length) { | ||
// return Reflect.getOwnPropertyDescriptor( | ||
// ctxt.target.proto, | ||
// ctxt.target.propertyKey, | ||
// ) as CompiledSymbol<T, X>; | ||
// } | ||
|
||
adviceEntries | ||
// prevent calling them twice. | ||
.filter((e) => !ctxt.target.getMetadata(`compiled_${e.id}`, () => false)) | ||
.forEach((entry) => { | ||
assert(typeof entry.advice === 'function'); | ||
Object.defineProperty( | ||
ctxt.target.proto, | ||
ctxt.target.propertyKey, | ||
methodDescriptor, | ||
); | ||
|
||
let newMethodDescriptor = entry.advice.call( | ||
entry.aspect, | ||
ctxt.asCompileContext(), | ||
) as CompiledSymbol<T, X>; | ||
|
||
if (newMethodDescriptor) { | ||
if (typeof newMethodDescriptor === 'function') { | ||
const surrogate = { | ||
fn: newMethodDescriptor, | ||
}; | ||
newMethodDescriptor = Object.getOwnPropertyDescriptor( | ||
surrogate, | ||
'fn', | ||
)! as CompiledSymbol<T, X>; | ||
} | ||
if (typeof newMethodDescriptor.value !== 'function') { | ||
throw new AdviceError( | ||
entry.aspect, | ||
entry.advice, | ||
ctxt.target, | ||
'should return void, a function, or a Method property descriptor', | ||
); | ||
} | ||
|
||
_copyPropsAndMeta(newMethodDescriptor.value, methodDescriptor.value); // copy static props | ||
methodDescriptor = newMethodDescriptor; | ||
} | ||
|
||
ctxt.target.defineMetadata(`compiled_${entry.id}`, true); | ||
}); | ||
ctxt.target.defineMetadata('@ajs:compiledSymbol', methodDescriptor); | ||
return methodDescriptor; | ||
} | ||
|
||
override callJoinpoint( | ||
ctxt: MutableAdviceContext<T, X>, | ||
originalSymbol: MethodPropertyDescriptor, | ||
): unknown { | ||
return (ctxt.value = _defuseAbstract(() => | ||
originalSymbol.value.call(ctxt.instance, ...ctxt.args!), | ||
)); | ||
} | ||
|
||
link( | ||
ctxt: MutableAdviceContext<T, X>, | ||
compiledSymbol: MethodPropertyDescriptor, | ||
joinpoint: (...args: any[]) => unknown, | ||
): CompiledSymbol<T, X> { | ||
compiledSymbol = wrapMethodDescriptor(ctxt, compiledSymbol, joinpoint); | ||
|
||
return compiledSymbol as CompiledSymbol<T, X>; | ||
} | ||
} | ||
|
||
function wrapMethodDescriptor<X>( | ||
ctxt: MutableAdviceContext<PointcutType.METHOD | PointcutType.PARAMETER, X>, | ||
descriptor: MethodPropertyDescriptor, | ||
joinpoint: JoinPoint, | ||
): CompiledSymbol<PointcutType.METHOD | PointcutType.PARAMETER, X> { | ||
return { | ||
...descriptor, | ||
value: renameFunction( | ||
joinpoint, | ||
ctxt.target.descriptor.value, | ||
`function ${String(ctxt.target.propertyKey)}$$advised`, | ||
), | ||
}; | ||
} |
Oops, something went wrong.