   # Hello to the world of promises.
   run = false
   d = Q.defer()
+  assert not d.promise.done()
   d.promise.then (s, f) => (assert s is 'world'; run = true)
   d.success('world')
+  assert d.promise.done()
   assert run
 
 testhello_fail = ->

# Implementing angularjs promises, for fun and profit.

Q = {
  defer: () -> new Defer()
  fail: (value) ->
    d = Q.defer()
    d.fail(value)
    d.promise

  all: (promises) ->
    # from an array of promises, returns a 
    count = promises.length
    defer = Q.defer()
    if count == 0
      # short circuit.
      defer.success([])
      return defer.promise
    successes = (null for promise of promises)
    failures =  (null for promise of promises)
    hasFailure = false
    decrement = () ->
      count--
      if count == 0
        if hasFailure
          defer.failure(failures)
        else
          defer.success(successes)
    for index, promise of promises
      do (index) ->
        promise.then (s, f) ->
          successes[index] = s
          failures[index] = f
          if f isnt null
            hasFailure = true
          decrement()
    return defer.promise
}

STATE_NEW = 0
STATE_SUCCESS = 1
STATE_FAIL = 2

class Defer
  constructor: () ->
    @queued = []
    @value = null
    @state = STATE_NEW
    @promise = {
      then: (async) =>
        defer = new Defer()
        wrapped = (success, failure) =>
          try
            successValue = async(success, failure)
          catch e
            failValue = e

          if successValue? and successValue.is_promise
            # chaining the promise.
            successValue.then (s, f) ->
              if f isnt null
                defer.fail f
              else
                defer.success s
          else
            # non-promise value.
            if failValue?
              defer.fail(failValue)
            else
              defer.success(successValue)

        if @state is STATE_NEW
          @queued.push wrapped
        else
          @triggerOne wrapped
        return defer.promise
      is_promise: true
    }


  success: (value) ->
    # mark the given promise as success.
    if (operate = (@state is STATE_NEW))
      @value = value
      @state = STATE_SUCCESS
      @triggerAll()
    return operate

  fail: (value) ->
    # fail the given promise.
    if (operate = (@state is STATE_NEW))
      @value = value
      @state = STATE_FAIL
      @triggerAll()
    return operate

  triggerOne: (queue) ->
    if @state is STATE_SUCCESS
      queue(@value, null) # success mode.
    else
      queue(null, @value) # fail mode.

  triggerAll: =>
    for idx, queue of @queued
      @triggerOne(queue)


test = ->
  testall_empty()


testall_empty = ->
  run = false
  Q.all([]).then -> run = true
  assert(run)

testtimeout = ->
  run = false
  d = Q.defer()
  timeoutPromise = Q.timeout(d.promise, 50)
  timeoutPromise.then (s, f) ->
    assert f is 'timeout'
    run = true
  setTimeout (-> assert not run), 49
  setTimeout (-> assert run), 51

test()

