code: function when(value, fulfilled, rejected) {
          var defer = new Defer(), done = 0;    // wrap user's callback to catch exception
          // wrap user's callback to catch exception
          function _fulfilled(value) {
              try {
                  return fulfilled ? fulfilled.call(this, value) : // propagate
                  value;
              } catch (e) {
                  // can not use logger.error
                  // must expose to user
                  // print stack info for firefox/chrome
                  logError(e.stack || e);
                  return new Reject(e);
              }
          }
          function _rejected(reason) {
              try {
                  return rejected ? // error recovery
                  rejected.call(this, reason) : // propagate
                  new Reject(reason);
              } catch (e) {
                  // print stack info for firefox/chrome
                  logError(e.stack || e);
                  return new Reject(e);
              }
          }
          function finalFulfill(value) {
              if (done) {
                  logger.error('already done at fulfilled');
                  return;
              }
              if (value instanceof Promise) {
                  logger.error('assert.not(value instanceof Promise) in when');
                  return;
              }
              done = 1;
              defer.resolve(_fulfilled.call(this, value));
          }
          if (value instanceof Promise) {
              promiseWhen(value, finalFulfill, function (reason) {
                  if (done) {
                      logger.error('already done at rejected');
                      return;
                  }
                  done = 1;    // _reject may return non-Reject object for error recovery
                  // _reject may return non-Reject object for error recovery
                  defer.resolve(_rejected.call(this, reason));
              });
          } else {
              finalFulfill(value);
          }    // chained and leveled
               // wait for value's resolve
          // chained and leveled
          // wait for value's resolve
          return defer.promise;
      }
docs: wrap for promiseWhen wrap for promiseWhen