revised .patch(..) and the .walk(..) protocol...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2018-07-26 14:52:44 +03:00
parent 5a0ddfdd68
commit 4afcdfb26e

90
diff.js
View File

@ -681,33 +681,57 @@ var Types = {
// Patch (update) obj via diff... // Patch (update) obj via diff...
// //
// XXX this needs to be able to replace obj or parts of it... // XXX should we check for patch integrity???
// XXX this does not work for: // bad patches would include:
// patch(diff(4,5), 4) // - including both a.b and a.b.c is a conflict.
patch: function(diff, obj, options){ patch: function(diff, obj, options){
var that = this var that = this
var NONE = diff.placeholders.NONE var NONE = diff.placeholders.NONE
var EMPTY = diff.placeholders.EMPTY var EMPTY = diff.placeholders.EMPTY
var options = diff.options var options = diff.options
this.walk(diff.diff, function(change){ // NOTE: in .walk(..) we always return the root object bing
// replace the object itself... // patched, this way the handlers have control over the
if(change.path.length == 0){ // patching process and it's results on all levels...
return change.B // ...and this is why we can just pop the last item and
} // return it...
// NOTE: this will do odd things for conflicting patches...
// a conflict can be for example patching both a.b and
// a.b.c etc.
return this
.walk(diff.diff, function(change){
// replace the object itself...
if(change.path.length == 0){
return change.B
}
var type = change.type || Object var type = change.type || Object
var target = change.path var parent
.slice(0, -1) var parent_key
.reduce(function(res, e){ var target = change.path
return res[e]}, obj) .slice(0, -1)
var key = change.path[change.path.length-1] .reduce(function(res, e){
parent = res
parent_key = e
return res[e]
}, obj)
var key = change.path[change.path.length-1]
// XXX this needs to be able to replace the target... // call the actual patch...
that.get(type).patch.call(that, target, key, change, options) var res = that.get(type).patch.call(that, target, key, change, obj, options)
})
return obj // replace the parent value...
if(parent){
parent[parent_key] = res
} else {
obj = res
}
return obj
})
.pop()
}, },
// Check if diff is applicable to obj... // Check if diff is applicable to obj...
@ -781,6 +805,12 @@ var Types = {
// .. // ..
// }, // },
// //
// // Patch the object...
// //
// patch: function(target, key, change, root, options){
// ..
// },
//
// // Reverse the change... // // Reverse the change...
// // // //
// reverse: function(change){ // reverse: function(change){
@ -882,7 +912,7 @@ Types.set(Object, {
// array item... // array item...
// XXX should this make this decision??? // XXX should this make this decision???
} else { } else {
return this.get(Array).patch.call(this, obj, key, change) this.get(Array).patch.call(this, obj, key, change)
} }
return obj return obj
}, },
@ -1166,12 +1196,26 @@ Types.set('Text', {
}, path) }, path)
}, },
// XXX // XXX this is not efficient...
// ...find a way to do all the changes in one go...
// XXX add object compatibility checks... // XXX add object compatibility checks...
patch: function(change, obj){ patch: function(obj, key, change){
// XXX var lines = obj.split(/\n/)
return obj // remove line...
if(!('B' in change) || change.B == this.NONE){
lines.splice(key, 1)
// insert line...
} else if(!('A' in change) || change.A == this.NONE){
lines.splice(key, 0, change.B)
// replace line...
} else {
obj.split(/\n/)[key] = change.B
}
return lines.join('\n')
}, },
}) })