 
   hasWaiters = -> waiters.length > 0
 
-  { whenDoneWith, hasWaiters, inTransaction, currentEventId, wrappedSubscribe }
+  flatDeps = {}
+  
+  dependsOn = (o, b) ->
+    if !flatDeps[o.id]?
+      flatDeps[o.id] = {}
+      collectDeps o, o
+    return flatDeps[o.id][b.id]
+  
+  collectDeps = (orig, o) ->
+    for dep in o.internalDeps()
+      flatDeps[orig.id][dep.id] = true
+      collectDeps(orig, dep)
+
+  flushDepCache = -> flatDeps = {}
+
+  { whenDoneWith, hasWaiters, inTransaction, currentEventId, wrappedSubscribe, dependsOn, flushDepCache }
 )()
 
 Bacon.EventStream = EventStream

    spawn = (event) ->
      child = makeObservable(f event.value())
      extraDeps.push(child)
      composite.add (unsubAll, unsubMe) -> child.subscribeInternal (event) ->
        if event.isEnd()
          _.remove(child, extraDeps)
          checkQueue()
          checkEnd(unsubMe)
          Bacon.noMore

    @method = method
    @args = args

  apply: (obs) ->
    that = @

    deps = _.cached (-> findDeps([that.context].concat(that.args)))
    obs.internalDeps = obs.internalDeps || deps
    obs.dependsOn = (b) -> UpdateBarrier.dependsOn.call(that, obs, b)
    obs.deps = deps

    obs.toString = (-> _.toString(that.context) + "." + _.toString(that.method) + "(" + _.map(_.toString, that.args) + ")")
