-
Notifications
You must be signed in to change notification settings - Fork 37
/
static_method.ts
60 lines (55 loc) · 2.06 KB
/
static_method.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { Precondition, JointPoint } from '../core/joint_point';
import { Advice } from '../core/advice';
import { Pointcut } from '../core/pointcut';
import { AspectRegistry, Targets, Aspect } from '../core/aspect';
import { MethodSelector } from './selectors';
import { MethodPrecondition } from './preconditions';
export class StaticMethodJointPoint extends JointPoint {
constructor(precondition: Precondition) {
super(precondition);
}
public getTarget(fn: Function): Object {
return fn;
}
public match(target: Object): string[] {
const keys = Object.getOwnPropertyNames(target);
const res = keys.filter(key => {
const descriptor = Object.getOwnPropertyDescriptor(target, key);
return (
this.precondition.assert({
classDefinition: target,
methodName: key,
}) && typeof descriptor.value === 'function'
);
});
return res;
}
protected woveTarget(fn: any, key: string, advice: Advice, woveMetadata: any) {
let className = fn.name;
let bak = fn[key];
let self = this;
fn[key] = function() {
let metadata = self.getMetadata(className, key, bak, arguments, this, woveMetadata);
return advice.wove(bak, metadata);
};
fn[key].__woven__ = true;
}
}
export function makeStaticMethodAdviceDecorator(constr: any) {
return function(...selectors: MethodSelector[]): MethodDecorator {
return function<T>(target: Object, prop: symbol | string, descriptor: TypedPropertyDescriptor<T>) {
let jointpoints = selectors.map(selector => {
return new StaticMethodJointPoint(new MethodPrecondition(selector));
});
let pointcut = new Pointcut();
pointcut.advice = <Advice>new constr(target, descriptor.value);
pointcut.jointPoints = jointpoints;
let aspectName = target.constructor.name;
let aspect = AspectRegistry.get(aspectName) || new Aspect();
aspect.pointcuts.push(pointcut);
AspectRegistry.set(aspectName, aspect);
Targets.forEach(({ target, config }) => aspect.wove(target, config));
return target;
};
};
}