mgechev / aspect.js

JavaScript library for aspect-oriented programming using modern syntax.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Sequencing of the decorators calls (multiple advices calling)

vladimir-prishchep opened this issue · comments

Problem

@Wove()
class Example {
    foo() {
        console.log('within foo');
    }
    bar() {
        console.log('within bar');
    }
}

const example = new Example();

setTimeout(() => {
    example.foo();
    example.bar();
}, 1e3);

class Aspect {
    @beforeMethod({ classNamePattern: /^(Example)$/, methodNamePattern: /^foo/})
    beforeFoo() {
        console.log('before foo');
    }

    @afterMethod({ classNamePattern: /^(Example)$/, methodNamePattern: /^bar/})
    afterBar() {
        console.log('before bar');
    }
}

In such code beforeFoo() advice will be executed twice, despite foo() is called once.
It is because of the sequencing of the decorators functions calls (@Wove, @beforeMethod, @afterMethod). If move Example class declaration after Aspect class, it will be no problem (@Wove decorator will be executed after @beforeMethod and @afterMethod).

Possible Solution

As a fast variant it could be solved by returning from woveTarget() func of the joint_points classes if jointpoint was already __woven__. For method_call jointpoint:

protected woveTarget(proto: any, key:string, advice: Advice, woveMetadata: any) {
    // Add this:
    if (proto[key].__woven__) {
        return;
    }

    let className = proto.constructor.name;
    let bak = proto[key];
    let self = this;
    proto[key] = function () {
      let metadata = self.getMetadata(className, key, bak, arguments, this, woveMetadata);
      return advice.wove(bak, metadata);
    };
    proto[key].__woven__ = true;
}

Thanks for reporting the issue and for the suggestion. I'll proceed with a fix as soon as possible.

@vladimir-prishchep would you test against this branch. The issue should be resolved.

@mgechev I checked the branch, fix works. Thanks a lot for a quick response and the same fast fix. Cool tool and the same cool maintenance!