11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci  const obj1 = {a: 3, b: 5};
31cb0ef41Sopenharmony_ci  diffApply(obj1,
41cb0ef41Sopenharmony_ci    [
51cb0ef41Sopenharmony_ci      { "op": "remove", "path": ['b'] },
61cb0ef41Sopenharmony_ci      { "op": "replace", "path": ['a'], "value": 4 },
71cb0ef41Sopenharmony_ci      { "op": "add", "path": ['c'], "value": 5 }
81cb0ef41Sopenharmony_ci    ]
91cb0ef41Sopenharmony_ci  );
101cb0ef41Sopenharmony_ci  obj1; // {a: 4, c: 5}
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci  // using converter to apply jsPatch standard paths
131cb0ef41Sopenharmony_ci  // see http://jsonpatch.com
141cb0ef41Sopenharmony_ci  import {diff, jsonPatchPathConverter} from 'just-diff'
151cb0ef41Sopenharmony_ci  const obj2 = {a: 3, b: 5};
161cb0ef41Sopenharmony_ci  diffApply(obj2, [
171cb0ef41Sopenharmony_ci    { "op": "remove", "path": '/b' },
181cb0ef41Sopenharmony_ci    { "op": "replace", "path": '/a', "value": 4 }
191cb0ef41Sopenharmony_ci    { "op": "add", "path": '/c', "value": 5 }
201cb0ef41Sopenharmony_ci  ], jsonPatchPathConverter);
211cb0ef41Sopenharmony_ci  obj2; // {a: 4, c: 5}
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  // arrays
241cb0ef41Sopenharmony_ci  const obj3 = {a: 4, b: [1, 2, 3]};
251cb0ef41Sopenharmony_ci  diffApply(obj3, [
261cb0ef41Sopenharmony_ci    { "op": "replace", "path": ['a'], "value": 3 }
271cb0ef41Sopenharmony_ci    { "op": "replace", "path": ['b', 2], "value": 4 }
281cb0ef41Sopenharmony_ci    { "op": "add", "path": ['b', 3], "value": 9 }
291cb0ef41Sopenharmony_ci  ]);
301cb0ef41Sopenharmony_ci  obj3; // {a: 3, b: [1, 2, 4, 9]}
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  // nested paths
331cb0ef41Sopenharmony_ci  const obj4 = {a: 4, b: {c: 3}};
341cb0ef41Sopenharmony_ci  diffApply(obj4, [
351cb0ef41Sopenharmony_ci    { "op": "replace", "path": ['a'], "value": 5 }
361cb0ef41Sopenharmony_ci    { "op": "remove", "path": ['b', 'c']}
371cb0ef41Sopenharmony_ci    { "op": "add", "path": ['b', 'd'], "value": 4 }
381cb0ef41Sopenharmony_ci  ]);
391cb0ef41Sopenharmony_ci  obj4; // {a: 5, b: {d: 4}}
401cb0ef41Sopenharmony_ci*/
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_civar REMOVE = 'remove';
431cb0ef41Sopenharmony_civar REPLACE = 'replace';
441cb0ef41Sopenharmony_civar ADD = 'add';
451cb0ef41Sopenharmony_civar MOVE = 'move';
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_cifunction diffApply(obj, diff, pathConverter) {
481cb0ef41Sopenharmony_ci  if (!obj || typeof obj != 'object') {
491cb0ef41Sopenharmony_ci    throw new Error('base object must be an object or an array');
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  if (!Array.isArray(diff)) {
531cb0ef41Sopenharmony_ci    throw new Error('diff must be an array');
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  var diffLength = diff.length;
571cb0ef41Sopenharmony_ci  for (var i = 0; i < diffLength; i++) {
581cb0ef41Sopenharmony_ci    var thisDiff = diff[i];
591cb0ef41Sopenharmony_ci    var subObject = obj;
601cb0ef41Sopenharmony_ci    var thisOp = thisDiff.op;
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci    var thisPath = transformPath(pathConverter, thisDiff.path);
631cb0ef41Sopenharmony_ci    var thisFromPath = thisDiff.from && transformPath(pathConverter, thisDiff.from);
641cb0ef41Sopenharmony_ci    var toPath, toPathCopy, lastToProp, subToObject, valueToMove;
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    if (thisFromPath) {
671cb0ef41Sopenharmony_ci      // MOVE only, "fromPath" is effectively path and "path" is toPath
681cb0ef41Sopenharmony_ci      toPath = thisPath;
691cb0ef41Sopenharmony_ci      thisPath = thisFromPath;
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci      toPathCopy = toPath.slice();
721cb0ef41Sopenharmony_ci      lastToProp = toPathCopy.pop();
731cb0ef41Sopenharmony_ci      prototypeCheck(lastToProp);
741cb0ef41Sopenharmony_ci      if (lastToProp == null) {
751cb0ef41Sopenharmony_ci        return false;
761cb0ef41Sopenharmony_ci      }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci      var thisToProp;
791cb0ef41Sopenharmony_ci      while (((thisToProp = toPathCopy.shift())) != null) {
801cb0ef41Sopenharmony_ci        prototypeCheck(thisToProp);
811cb0ef41Sopenharmony_ci        if (!(thisToProp in subToObject)) {
821cb0ef41Sopenharmony_ci          subToObject[thisToProp] = {};
831cb0ef41Sopenharmony_ci        }
841cb0ef41Sopenharmony_ci        subToObject = subToObject[thisToProp];
851cb0ef41Sopenharmony_ci      }
861cb0ef41Sopenharmony_ci    }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci    var pathCopy = thisPath.slice();
891cb0ef41Sopenharmony_ci    var lastProp = pathCopy.pop();
901cb0ef41Sopenharmony_ci    prototypeCheck(lastProp);
911cb0ef41Sopenharmony_ci    if (lastProp == null) {
921cb0ef41Sopenharmony_ci      return false;
931cb0ef41Sopenharmony_ci    }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci    var thisProp;
961cb0ef41Sopenharmony_ci    while (((thisProp = pathCopy.shift())) != null) {
971cb0ef41Sopenharmony_ci      prototypeCheck(thisProp);
981cb0ef41Sopenharmony_ci      if (!(thisProp in subObject)) {
991cb0ef41Sopenharmony_ci        subObject[thisProp] = {};
1001cb0ef41Sopenharmony_ci      }
1011cb0ef41Sopenharmony_ci      subObject = subObject[thisProp];
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci    if (thisOp === REMOVE || thisOp === REPLACE || thisOp === MOVE) {
1041cb0ef41Sopenharmony_ci      var path = thisOp === MOVE ? thisDiff.from : thisDiff.path;
1051cb0ef41Sopenharmony_ci      if (!subObject.hasOwnProperty(lastProp)) {
1061cb0ef41Sopenharmony_ci        throw new Error(['expected to find property', path, 'in object', obj].join(' '));
1071cb0ef41Sopenharmony_ci      }
1081cb0ef41Sopenharmony_ci    }
1091cb0ef41Sopenharmony_ci    if (thisOp === REMOVE || thisOp === MOVE) {
1101cb0ef41Sopenharmony_ci      if (thisOp === MOVE) {
1111cb0ef41Sopenharmony_ci        valueToMove = subObject[lastProp];
1121cb0ef41Sopenharmony_ci      }
1131cb0ef41Sopenharmony_ci      Array.isArray(subObject) ? subObject.splice(lastProp, 1) : delete subObject[lastProp];
1141cb0ef41Sopenharmony_ci    }
1151cb0ef41Sopenharmony_ci    if (thisOp === REPLACE || thisOp === ADD) {
1161cb0ef41Sopenharmony_ci      subObject[lastProp] = thisDiff.value;
1171cb0ef41Sopenharmony_ci    }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    if (thisOp === MOVE) {
1201cb0ef41Sopenharmony_ci      subObject[lastToProp] = valueToMove;
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci  return subObject;
1241cb0ef41Sopenharmony_ci}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_cifunction transformPath(pathConverter, thisPath) {
1271cb0ef41Sopenharmony_ci  if(pathConverter) {
1281cb0ef41Sopenharmony_ci    thisPath = pathConverter(thisPath);
1291cb0ef41Sopenharmony_ci    if(!Array.isArray(thisPath)) {
1301cb0ef41Sopenharmony_ci      throw new Error([
1311cb0ef41Sopenharmony_ci        'pathConverter must return an array, returned:',
1321cb0ef41Sopenharmony_ci        thisPath,
1331cb0ef41Sopenharmony_ci      ].join(' '));
1341cb0ef41Sopenharmony_ci    }
1351cb0ef41Sopenharmony_ci  } else {
1361cb0ef41Sopenharmony_ci    if(!Array.isArray(thisPath)) {
1371cb0ef41Sopenharmony_ci      throw new Error([
1381cb0ef41Sopenharmony_ci        'diff path',
1391cb0ef41Sopenharmony_ci        thisPath,
1401cb0ef41Sopenharmony_ci        'must be an array, consider supplying a path converter']
1411cb0ef41Sopenharmony_ci        .join(' '));
1421cb0ef41Sopenharmony_ci    }
1431cb0ef41Sopenharmony_ci  }
1441cb0ef41Sopenharmony_ci  return thisPath;
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cifunction jsonPatchPathConverter(stringPath) {
1481cb0ef41Sopenharmony_ci  return stringPath.split('/').slice(1);
1491cb0ef41Sopenharmony_ci}
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_cifunction prototypeCheck(prop) {
1521cb0ef41Sopenharmony_ci  // coercion is intentional to catch prop values like `['__proto__']`
1531cb0ef41Sopenharmony_ci  if (prop == '__proto__' || prop == 'constructor' || prop == 'prototype') {
1541cb0ef41Sopenharmony_ci    throw new Error('setting of prototype values not supported');
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciexport {diffApply, jsonPatchPathConverter};
159