_registerAtomic(op, val) {
    if (this[slicedSymbol]) {
      return;
    }
    if (op === '$set') {
      // $set takes precedence over all other ops.
      // mark entire array modified.
      this[arrayAtomicsSymbol] = { $set: val };
      cleanModifiedSubpaths(this[arrayParentSymbol], this[arrayPathSymbol]);
      this._markModified();
      return this;
    }

    const atomics = this[arrayAtomicsSymbol];

    // reset pop/shift after save
    if (op === '$pop' && !('$pop' in atomics)) {
      const _this = this;
      this[arrayParentSymbol].once('save', function() {
        _this._popped = _this._shifted = null;
      });
    }

    // check for impossible $atomic combos (Mongo denies more than one
    // $atomic op on a single path
    if (atomics.$set || Object.keys(atomics).length && !(op in atomics)) {
      // a different op was previously registered.
      // save the entire thing.
      this[arrayAtomicsSymbol] = { $set: this };
      return this;
    }

    let selector;

    if (op === '$pullAll' || op === '$addToSet') {
      atomics[op] || (atomics[op] = []);
      atomics[op] = atomics[op].concat(val);
    } else if (op === '$pullDocs') {
      const pullOp = atomics['$pull'] || (atomics['$pull'] = {});
      if (val[0] instanceof ArraySubdocument) {
        selector = pullOp['$or'] || (pullOp['$or'] = []);
        Array.prototype.push.apply(selector, val.map(v => {
          return v.toObject({
            transform: (doc, ret) => {
              if (v == null || v.$__ == null) {
                return ret;
              }

              Object.keys(v.$__.activePaths.getStatePaths('default')).forEach(path => {
                mpath.unset(path, ret);

                _minimizePath(ret, path);
              });

              return ret;
            },
            virtuals: false
          });
        }));
      } else {
        selector = pullOp['_id'] || (pullOp['_id'] = { $in: [] });
        selector['$in'] = selector['$in'].concat(val);
      }
    } else if (op === '$push') {
      atomics.$push = atomics.$push || { $each: [] };
      if (val != null && utils.hasUserDefinedProperty(val, '$each')) {
        atomics.$push = val;
      } else {
        if (val.length === 1) {
          atomics.$push.$each.push(val[0]);
        } else if (val.length < 10000) {
          atomics.$push.$each.push(...val);
        } else {
          for (const v of val) {
            atomics.$push.$each.push(v);
          }
        }
      }
    } else {
      atomics[op] = val;
    }

    return this;
  }
Register an atomic operation with the parent.

@param {Array} op operation
@param {any} val
@method _registerAtomic
@api private
@memberOf MongooseArray