From a86ffd9b3526b70601e9c36bbb9b714a91fc3069 Mon Sep 17 00:00:00 2001 From: Brian Cavalier Date: Mon, 19 May 2014 22:17:32 -0400 Subject: [PATCH] Fix #11. Throw when move path is descendent of from --- lib/jsonPointer.js | 5 +++++ lib/patches.js | 4 ++++ test/jsonPatch-test.js | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/lib/jsonPointer.js b/lib/jsonPointer.js index d8761d0..9e0d996 100644 --- a/lib/jsonPointer.js +++ b/lib/jsonPointer.js @@ -6,6 +6,7 @@ exports.find = find; exports.join = join; exports.absolute = absolute; exports.parse = parse; +exports.contains = contains; exports.encodeSegment = encodeSegment; exports.decodeSegment = decodeSegment; exports.parseArrayIndex = parseArrayIndex; @@ -69,6 +70,10 @@ function parse(path) { return split(path).map(decodeSegment); } +function contains(a, b) { + return b.indexOf(a) === 0 && b[a.length] === separator; +} + /** * Decode a JSON Pointer path segment * @see http://tools.ietf.org/html/rfc6901#page-3 diff --git a/lib/patches.js b/lib/patches.js index 9449512..3cc62b3 100644 --- a/lib/patches.js +++ b/lib/patches.js @@ -284,6 +284,10 @@ function commuteRemove(remove, b) { * @param {object} change move operation */ function applyMove(x, change) { + if(jsonPointer.contains(change.path, change.from)) { + throw new InvalidPatchOperationError('move.from cannot be ancestor of move.path'); + } + var pto = find(x, change.path); var pfrom = find(x, change.from); diff --git a/test/jsonPatch-test.js b/test/jsonPatch-test.js index a95498c..46649c7 100644 --- a/test/jsonPatch-test.js +++ b/test/jsonPatch-test.js @@ -2,6 +2,7 @@ var buster = require('buster'); var assert = buster.referee.assert; var refute = buster.referee.refute; +var patches = require('../lib/patches'); var jsonPatch = require('../lib/jsonPatch'); var InvalidPatchOperationError = require('../lib/InvalidPatchOperationError'); @@ -109,6 +110,14 @@ buster.testCase('jsonPatch', { var result = jsonPatch.apply([{ op: 'move', path: '/y', from: '/x' }], a); assert.equals(result.y, 1); refute.defined(result.x); + }, + + '=>should not allow moving to ancestor path': function() { + var from = '/a/b/c'; + var to = '/a/b'; + assert.exception(function() { + patches.move.apply({ a: { b: { c: 1 }}}, { op: 'move', from: from, path: to }); + }); } },