
let Exedore = {
    after: function( targetObject, functionName, advice ) {
        Exedore.wrap( targetObject, functionName, function( originalFunction, args ) {
            let result = Exedore.next( targetObject, originalFunction, args );
            advice.apply( targetObject, [ originalFunction, args ] );
            return result;
        } );
    },

    around: function( functionName, advice, targetObject ) {
        let oldFunction = targetObject[ functionName ];
        targetObject[ functionName ] = function() {
            let args = Array.from( arguments );
            return advice.apply( targetObject, [ oldFunction, args ] );
        }
    },

    before: function( targetObject, functionName, advice ) {
        Exedore.wrap( targetObject, functionName, function( originalFunction, args ) {
            advice.apply( targetObject, [ originalFunction, args ] );
            return Exedore.next( targetObject, originalFunction, args );
        } );
    },

    next: function( contextObject, functionRef, args = [ ] ) {
        return functionRef.apply( contextObject, args );
    },

    wrap: function( targetObject, functionName, advice ) {
        Exedore.around( functionName, advice, targetObject );
    }
};

export default Exedore;

@@ -981,252 +981,1213 @@
     
-next: function( contextObject, functionRef, args = %5B %5D ) %7B%0A        return functionRef.apply( contextObject, args );%0A    %7D,%0A%0A    wrap: function( targetObject, functionName, advice ) %7B%0A        Exedore.around( functionName, advice, targetObject );
+// beforeClassMethod: function( targetConstructor, functionName, advice ) %7B%0A    //     Exedore.wrap( targetConstructor.prototype, functionName, function( originalFunction, args ) %7B%0A    //         advice.apply( this, %5B originalFunction, args %5D );%0A    //         return Exedore.next( this, originalFunction, args );%0A    //     %7D );%0A    // %7D,%0A%0A    next: function( contextObject, functionRef, args = %5B %5D ) %7B%0A        return functionRef.apply( contextObject, args );%0A    %7D,%0A%0A    wrap: function( targetObject, functionName, advice ) %7B%0A        Exedore.around( functionName, advice, targetObject );%0A        // TODO Experiment with the original %22match%22 function from Aop.js%0A        // If we go back to the original %22match%22 function from Aop.js, can we%0A        // wrap loose functions (e.g. private functions in a module) as well as%0A        // functions that are attached to an object?%0A    %7D,%0A%0A    wrapClassMethod: function( targetClass, functionName, advice ) %7B%0A        let originalMethod = targetClass.prototype%5B functionName %5D;%0A        targetClass.prototype%5B functionName %5D = function() %7B%0A            let args = Array.from( arguments );%0A            return advice.apply( this, %5B originalMethod, args %5D );%0A        %7D
 %0A   

Add "wrapClassMethod" for working with ES6 class methods