function copyElement(source, maxDepth) {
    // Simple values
    if (!isObject(source)) {
      return source;
    }

    // Already copied values
    var index = stackSource.indexOf(source);
    if (index !== -1) {
      return stackDest[index];
    }

    if (isWindow(source) || isScope(source)) {
      throw ngMinErr('cpws',
        'Can\'t copy! Making copies of Window or Scope instances is not supported.');
    }

    var needsRecurse = false;
    var destination = copyType(source);

    if (destination === undefined) {
      destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
      needsRecurse = true;
    }

    stackSource.push(source);
    stackDest.push(destination);

    return needsRecurse
      ? copyRecurse(source, destination, maxDepth)
      : destination;
  }
@name $browser#defer
@param {function()} fn A function, who's execution should be deferred.
@param {number=} [delay=0] Number of milliseconds to defer the function execution.
@param {string=} [taskType=DEFAULT_TASK_TYPE] The type of task that is deferred.
@returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.

@description
Executes a fn asynchronously via `setTimeout(fn, delay)`.

Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
`setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
via `$browser.defer.flush()`.