text: /* Copyright 2013 Twitter, Inc. Licensed under The MIT License. http://opensource.org/licenses/MIT */
  
  define(
  
    [
      './utils'
    ],
  
    function(utils) {
      'use strict';
  
      var advice = {
  
        around: function(base, wrapped) {
          return function composedAround() {
            // unpacking arguments by hand benchmarked faster
            var i = 0, l = arguments.length, args = new Array(l + 1);
            args[0] = base.bind(this);
            for (; i < l; i++) {
              args[i + 1] = arguments[i];
            }
            return wrapped.apply(this, args);
          };
        },
  
        before: function(base, before) {
          var beforeFn = (typeof before == 'function') ? before : before.obj[before.fnName];
          return function composedBefore() {
            beforeFn.apply(this, arguments);
            return base.apply(this, arguments);
          };
        },
  
        after: function(base, after) {
          var afterFn = (typeof after == 'function') ? after : after.obj[after.fnName];
          return function composedAfter() {
            var res = (base.unbound || base).apply(this, arguments);
            afterFn.apply(this, arguments);
            return res;
          };
        },
  
        // a mixin that allows other mixins to augment existing functions by adding additional
        // code before, after or around.
        withAdvice: function() {
          ['before', 'after', 'around'].forEach(function(m) {
            this[m] = function(method, fn) {
  
              utils.mutateProperty(this, method, function() {
                if (typeof this[method] == 'function') {
                  this[method] = advice[m](this[method], fn);
                } else {
                  this[method] = fn;
                }
  
                return this[method];
              });
  
            };
          }, this);
        }
      };
  
      return advice;
    }
  );
  