export function deepEqual()

in packages/@aws-cdk/cloudformation-diff/lib/diff/util.ts [19:81]


export function deepEqual(lvalue: any, rvalue: any): boolean {
  if (lvalue === rvalue) {
    return true;
  }
  // CloudFormation allows passing strings into boolean-typed fields
  if (((typeof lvalue === 'string' && typeof rvalue === 'boolean') ||
      (typeof lvalue === 'boolean' && typeof rvalue === 'string')) &&
      lvalue.toString() === rvalue.toString()) {
    return true;
  }
  // allows a numeric 10 and a literal "10" to be equivalent;
  // this is consistent with CloudFormation.
  if ((typeof lvalue === 'string' || typeof rvalue === 'string') &&
      safeParseFloat(lvalue) === safeParseFloat(rvalue)) {
    return true;
  }
  if (typeof lvalue !== typeof rvalue) {
    return false;
  }
  if (Array.isArray(lvalue) !== Array.isArray(rvalue)) {
    return false;
  }
  if (Array.isArray(lvalue) /* && Array.isArray(rvalue) */) {
    if (lvalue.length !== rvalue.length) {
      return false;
    }
    for (let i = 0 ; i < lvalue.length ; i++) {
      if (!deepEqual(lvalue[i], rvalue[i])) {
        return false;
      }
    }
    return true;
  }
  if (typeof lvalue === 'object' /* && typeof rvalue === 'object' */) {
    if (lvalue === null || rvalue === null) {
      // If both were null, they'd have been ===
      return false;
    }
    const keys = Object.keys(lvalue);
    if (keys.length !== Object.keys(rvalue).length) {
      return false;
    }
    for (const key of keys) {
      if (!rvalue.hasOwnProperty(key)) {
        return false;
      }
      if (key === 'DependsOn') {
        if (!dependsOnEqual(lvalue[key], rvalue[key])) {
          return false;
        }
        // check differences other than `DependsOn`
        continue;
      }
      if (!deepEqual(lvalue[key], rvalue[key])) {
        return false;
      }
    }
    return true;
  }
  // Neither object, nor array: I deduce this is primitive type
  // Primitive type and not ===, so I deduce not deepEqual
  return false;
}