         get: -> value
         set: (newValue) =>
           if newValue isnt value
+            @unobserveMutations value, obj[@id], keypath
             value = newValue
             callback() for callback in callbacks[keypath].slice() when callback in callbacks[keypath]
             @observeMutations newValue, obj[@id], keypath

        map.pointers[ref].push keypath

  unobserveMutations: (obj, ref, keypath) ->
    if Array.isArray obj and obj[@id]?
      if keypaths = @weakReference(obj).pointers?[ref]
        idx = keypaths.indexOf(keypath)
        if idx >= 0
          keypaths.splice idx, 1

  observe: (obj, keypath, callback) ->
    callbacks = @weakReference(obj).callbacks

  weakReference: (obj) ->
    unless obj.hasOwnProperty @id
      id = @counter++
      Object.defineProperty obj, @id, value: id

    @weakmap[obj[@id]] or= callbacks: {}

  cleanupWeakReference: (ref, id) ->
    unless Object.keys(ref.callbacks).length
      unless Object.keys(ref.pointers).length
        delete @weakmap[id]

  stubFunction: (obj, fn) ->
    original = obj[fn]
