Angular and Zone for Digest

Demonstrates using Zone to avoid having to call $scope.apply() in Angular apps

HTML

<div ng-app="myApp" ng-controller="myController">
    {{timer.time | date:'HH:mm:ss'}}
</div>

JavaScript

var externalTimeObj = {
    time: new Date()
};

var digestCapture = null;

var digestZone = (function () {
    return {
        digest: function() { },
        onZoneEnter: function () {
            if (digestCapture) {
                zone.digest = digestCapture;
                zone.onZoneEnter = function() {};
            }
        },
        onZoneLeave: function () {
            zone.digest();
        }
    };
}());

var app = angular.module("myApp", []);
app.value("timerObj", externalTimeObj);
app.controller("myController", function($scope, timerObj) {
    $scope.timer = timerObj;
});
app.run(function($rootScope){
    digestCapture = function() {
        $rootScope.$digest();
    };        
});

// this is from https://github.com/angular/zone.js
function Zone(parentZone, data) {
  var zone = (arguments.length) ? Object.create(parentZone) : this;

  zone.parent = parentZone;

  Object.keys(data || {}).forEach(function(property) {
    zone[property] = data[property];
  });

  return zone;
}


Zone.prototype = {
  constructor: Zone,

  fork: function (locals) {
    return new Zone(this, locals);
  },

  bind: function (fn) {
    var zone = this.fork();
    return function zoneBoundFn() {
      var result = zone.run(fn, this, arguments);
      return result;
    };
  },

  run: function run (fn, applyTo, applyWith) {
    applyWith = applyWith || [];

    var oldZone = window.zone,
        result;

    window.zone = this;

    try {
      this.onZoneEnter();
      result = fn.apply(applyTo, applyWith);
    } catch (e) {
      if (zone.onError) {
        zone.onError(e);
      }
    } finally {
      this.onZoneLeave();
      window.zone = oldZone;
    }
    return result;
  },

  onZoneEnter: function () {},
  onZoneLeave: function () {}
};

Zone.patchFn = function (obj, fnNames) {
  fnNames.forEach(function (name) {
    var delegate = obj[name];
    zone[name] = function () {
      arguments[0] = zone.bind(arguments[0]);
      return delegate.apply(obj,...