function cb(err) {
    if (err) {
      return fn(err);
    }

    let count = array && array.length;
    let error;

    if (!count) {
      return fn();
    }
    if (options && options.updateValidator) {
      return fn();
    }
    if (!utils.isMongooseDocumentArray(array)) {
      array = new MongooseDocumentArray(array, _this.path, scope);
    }

    // handle sparse arrays, do not use array.forEach which does not
    // iterate over sparse elements yet reports array.length including
    // them :(

    function callback(err) {
      if (err != null) {
        error = err;
      }
      --count || fn(error);
    }

    for (let i = 0, len = count; i < len; ++i) {
      // sidestep sparse entries
      let doc = array[i];
      if (doc == null) {
        --count || fn(error);
        continue;
      }

      // If you set the array index directly, the doc might not yet be
      // a full fledged mongoose subdoc, so make it into one.
      if (!(doc instanceof Subdocument)) {
        const Constructor = getConstructor(_this.casterConstructor, array[i]);
        doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
      }

      if (options != null && options.validateModifiedOnly && !doc.$isModified()) {
        --count || fn(error);
        continue;
      }

      doc.$__validate(null, options, callback);
    }
  }
Performs local validations first, then validations on each embedded doc

@api private