   composeAttributes: (attributes) ->
     return if !attributes?
     for key, value of attributes
-      @attributes[key] = if value? then value else undefined
+      if value?
+        @attributes[key] = value
+      else
+        delete @attributes[key]
 
   toString: ->
     attr_str = ""

    if !other
      return false
    return @text == other.text and this.attributesMatch(other)
 
  toString: ->
    return "{#{@text}, #{super()}}"


    if @startLength != other.startLength or @endLength != other.endLength
      console.warn("Start/end Len mismatch!")
      return false

    if @deltas.length != other.deltas.length
      console.warn("Array len mismatch: " + @deltas.join("/") + other.deltas.join(", "))
      return false

    if @deltas.length == 0
      return true

    for i in [0..@deltas.length - 1]
      if typeof(@deltas[i]) != "object"
        console.warn("Delta is not an object: #{@delta[i]}")
        return false

      if typeof(other.deltas[i]) != "object"
        console.warn("Other delta is not an object: #{@delta[i]}")
        return false

      if !@deltas[i].isEqual(other.deltas[i])
        console.warn("Mismatch!" + other.deltas.join(", "))
        return false
    return true

  @isInsert: (change) ->
    return JetInsert.isInsert(change)

