code: async function fullyResolved(value) {
    value = await Promise.resolve(value);
    if (Array.isArray(value)) {
      return fullyResolveKeys(/** @type {!Array} */ (value));
    }
  
    if (value && typeof value === 'object') {
      return fullyResolveKeys(/** @type {!Object} */ (value));
    }
  
    if (typeof value === 'function') {
      return fullyResolveKeys(/** @type {!Object} */ (value));
    }
  
    return value;
  }
docs: Returns a promise that will be resolved with the input value in a
  fully-resolved state. If the value is an array, each element will be fully
  resolved. Likewise, if the value is an object, all keys will be fully
  resolved. In both cases, all nested arrays and objects will also be
  fully resolved.  All fields are resolved in place; the returned promise will
  resolve on {@code value} and not a copy.
  
  Warning: This function makes no checks against objects that contain
  cyclical references:
  
  var value = {};
  value['self'] = value;
  promise.fullyResolved(value);  // Stack overflow.
  
  @param {*} value The value to fully resolve.
  @return {!Thenable} A promise for a fully resolved version
  of the input value.