mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-28 10:30:09 +00:00
added context threading
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
3a9efe80f7
commit
9e400a7b8c
12
README.md
12
README.md
@ -486,6 +486,12 @@ This is the same as `VAR(..)` bud does a structural match (i.e. via `cmp(..)`).
|
||||
|
||||
Note that `VAR(..)` and `LIKE(..)` use the same namespace and can be used interchangeably depending on the type of matching desired.
|
||||
|
||||
`CONTEXT(pattern)`
|
||||
A context constructor, matches if `pattern` matches.
|
||||
|
||||
This is needed in case we need a way to access the pattern API from the root of the pattern when it's actually an object (see example below).
|
||||
|
||||
|
||||
Examples:
|
||||
```javascript
|
||||
var P = [VAR('x', ANY), VAR('x'), LIKE('x')]
|
||||
@ -496,6 +502,12 @@ cmp(P, [{}, {}, {}]) // -> false
|
||||
var o = {}
|
||||
// this succeeds because o === o and cmp(o, {}) is true...
|
||||
cmp(P, [o, o, {}]) // -> true
|
||||
|
||||
// and in case we need for P to explicitly be a pattern:
|
||||
P = CONTEXT(P)
|
||||
|
||||
// now we can use the pattern API directly from P:
|
||||
P.cmp([o, o, {}])
|
||||
```
|
||||
|
||||
### Miscellaneous patterns
|
||||
|
||||
62
diff.js
62
diff.js
@ -287,21 +287,31 @@ var LogicTypeClassPrototype = {
|
||||
|
||||
var LogicTypePrototype = {
|
||||
__context__: null,
|
||||
context: function(){
|
||||
return (this.__context__ = this.__context__ || {}) },
|
||||
context: function(context){
|
||||
var res = (this.__context__ == null || context != null) ?
|
||||
Object.create(this)
|
||||
: this
|
||||
res.__context__ = res.__context__ || context || {}
|
||||
return res
|
||||
},
|
||||
|
||||
__cmp__: function(obj, cmp, context){
|
||||
return false },
|
||||
// XXX need to track loops...
|
||||
cmp: function(obj, cmp, context){
|
||||
// XXX HACK???
|
||||
if(arguments.length < 3){
|
||||
return Diff.cmp(
|
||||
cmp instanceof Function ? this : this.context(cmp),
|
||||
obj)
|
||||
}
|
||||
|
||||
cmp = cmp || function(a, b){
|
||||
return a === b
|
||||
//|| a == b
|
||||
|| (a.__cmp__ && a.__cmp__(b, cmp, context))
|
||||
|| (b.__cmp__ && b.__cmp__(a, cmp, context)) }
|
||||
|
||||
// create a pattern context...
|
||||
var context = context || this.context()
|
||||
context = context || this.context().__context__
|
||||
|
||||
// cache...
|
||||
var cache = context.cache = context.cache || new Map()
|
||||
@ -503,11 +513,6 @@ object.makeConstructor('NOT', Object.assign(new LogicType(), {
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Will compare as true if one of the .members compares as true...
|
||||
//
|
||||
// XXX BUG:
|
||||
// cmp(OR(1,[2],3), 2)
|
||||
// -> true
|
||||
// ...this is likely due to [2] == 2 -> true
|
||||
var OR =
|
||||
module.OR =
|
||||
object.makeConstructor('OR', Object.assign(new LogicType(), {
|
||||
@ -542,12 +547,26 @@ object.makeConstructor('AND', Object.assign(new LogicType(), {
|
||||
},
|
||||
}))
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// XXX BUG:
|
||||
// CONTEXT([ANY, ANY, ANY]).cmp([1, 2, 3])
|
||||
// -> false
|
||||
var CONTEXT =
|
||||
module.CONTEXT =
|
||||
object.makeConstructor('CONTEX', Object.assign(new LogicType(), {
|
||||
__cmp__: function(obj, cmp, context){
|
||||
return cmp(this.pattern, obj) },
|
||||
__init__: function(pattern){
|
||||
this.pattern = arguments.length == 0 ? ANY : pattern
|
||||
},
|
||||
}))
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
var VAR =
|
||||
module.VAR =
|
||||
object.makeConstructor('VAR', Object.assign(new LogicType(), {
|
||||
__cmp__: function(obj, cmp, context){
|
||||
var context = context || this.context()
|
||||
var context = context || this.context().__context__
|
||||
var ns = context.ns = context.ns || {}
|
||||
var pattern = ns[this.name] =
|
||||
this.name in ns ?
|
||||
@ -573,7 +592,7 @@ var LIKE =
|
||||
module.LIKE =
|
||||
object.makeConstructor('LIKE', Object.assign(new VAR(), {
|
||||
__cmp__: function(obj, cmp, context){
|
||||
var context = context || this.context()
|
||||
var context = context || this.context().__context__
|
||||
|
||||
return VAR.prototype.__cmp__.call(this, obj, cmp, context)
|
||||
|| Diff.cmp(
|
||||
@ -1239,7 +1258,7 @@ module.Types = {
|
||||
// XXX might be a god idea to mix in default options (different
|
||||
// defaults per mode)...
|
||||
// XXX TEST: the format should survive JSON.parse(JSON.stringify(..))...
|
||||
diff: function(A, B, options, cache){
|
||||
diff: function(A, B, options, context){
|
||||
var that = this
|
||||
options = options ? Object.create(options) : {}
|
||||
options.as_object = options.as_object || []
|
||||
@ -1254,9 +1273,9 @@ module.Types = {
|
||||
|| b === that.ANY
|
||||
// logic patterns...
|
||||
|| (a instanceof LogicType
|
||||
&& a.cmp(b, cmp, cache))
|
||||
&& a.cmp(b, cmp, context))
|
||||
|| (b instanceof LogicType
|
||||
&& b.cmp(a, cmp, cache)) }
|
||||
&& b.cmp(a, cmp, context)) }
|
||||
// deep compare...
|
||||
var cmp = options.cmp = options.cmp
|
||||
|| function(a, b){
|
||||
@ -1267,12 +1286,15 @@ module.Types = {
|
||||
// see cache setup below...
|
||||
|| (diff(a, b) == null) }
|
||||
// cache...
|
||||
//cache = this.__cache = cache || this.__cache || new Map()
|
||||
cache = cache || new Map()
|
||||
context = context
|
||||
|| (A instanceof LogicType ? A.context().__context__
|
||||
: B instanceof LogicType ? B.context().__context__
|
||||
: {})
|
||||
cache = context.cache = context.cache || new Map()
|
||||
// cached diff...
|
||||
var diff = cache.diff = cache.diff || function(a, b){
|
||||
var l2 = cache.get(a) || new Map()
|
||||
var d = l2.get(b) || that.diff(a, b, options, cache)
|
||||
var d = l2.get(b) || that.diff(a, b, options, context)
|
||||
cache.set(a, l2.set(b, d))
|
||||
return d
|
||||
}
|
||||
@ -1326,8 +1348,8 @@ module.Types = {
|
||||
// are going to throw away anyway...
|
||||
// ...this would be possible with a live .walk(..) that would
|
||||
// report changes as it finds them...
|
||||
cmp: function(A, B, options){
|
||||
return this.diff(A, B, options) == null },
|
||||
cmp: function(A, B, options, context){
|
||||
return this.diff(A, B, options, context) == null },
|
||||
|
||||
// Patch (update) obj via diff...
|
||||
//
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user