diff --git a/lib/json0.js b/lib/json0.js index dc3a405..36b21d9 100644 --- a/lib/json0.js +++ b/lib/json0.js @@ -29,7 +29,7 @@ var isArray = function(obj) { * @returns {boolean} */ var isObject = function(obj) { - return (!!obj) && (obj.constructor === Object); + return !!obj && obj.constructor === Object; }; /** @@ -66,7 +66,7 @@ json.create = function(data) { }; json.invertComponent = function(c) { - var c_ = {p: c.p}; + var c_ = { p: c.p }; // handle subtype ops if (c.t && subtypes[c.t]) { @@ -83,8 +83,8 @@ json.invertComponent = function(c) { if (c.na !== void 0) c_.na = -c.na; if (c.lm !== void 0) { - c_.lm = c.p[c.p.length-1]; - c_.p = c.p.slice(0,c.p.length-1).concat([c.lm]); + c_.lm = c.p[c.p.length - 1]; + c_.p = c.p.slice(0, c.p.length - 1).concat([c.lm]); } return c_; @@ -106,20 +106,21 @@ json.checkValidOp = function(op) { }; json.checkList = function(elem) { - if (!isArray(elem)) - throw new Error('Referenced element not a list'); + if (!isArray(elem)) throw new Error('Referenced element not a list'); }; json.checkObj = function(elem) { if (!isObject(elem)) { - throw new Error("Referenced element not an object (it was " + JSON.stringify(elem) + ")"); + throw new Error( + 'Referenced element not an object (it was ' + JSON.stringify(elem) + ')' + ); } }; // helper functions to convert old string ops to and from subtype ops function convertFromText(c) { c.t = 'text0'; - var o = {p: c.p.pop()}; + var o = { p: c.p.pop() }; if (c.si != null) o.i = c.si; if (c.sd != null) o.d = c.sd; c.o = [o]; @@ -133,6 +134,160 @@ function convertToText(c) { delete c.o; } +// not checking anything here, we should probably check that u: exists +// (only thing we care about at json0 top level), and then delegate +// to any subtypes if there is already subtype presence data +json.createPresence = function(presence) { + return presence; +}; + +// this needs more thinking/testing, looking a bit more carefully at +// how this is implemented in ot-rich-text, etc. +json.comparePresence = function(pres1, pres2) { + if (!pres1 || !pres2) { + return false; + } + if (!pres1.p || !pres2.p) { + return false; + } + if (pres1.t !== pres2.t) { + return false; + } + if (pres1.t && subtypes[pres1.t]) { + if (pres1.p[0] === pres2.p[0]) { + return subtypes[pres1.t].comparePresence(pres1, pres2); + } + } else return pres1 === pres2; +}; + +var transformPosition = function(cursor, op, isOwnOp) { + var cursor = clone(cursor); + + var opIsAncestor = cursor.length >= op.p.length; // true also if op is self + var opIsSibling = cursor.length === op.p.length; // true also if op is self + var opIsAncestorSibling = cursor.length >= op.p.length; // true also if op is self or sibling of self + var equalUpTo = -1; + for (var i = 0; i < op.p.length; i++) { + if (op.p[i] !== cursor[i]) { + opIsAncestor = false; + if (i < op.p.length - 1) { + opIsSibling = false; + opIsAncestorSibling = false; + } + } + if (equalUpTo === i - 1 && op.p[i] === cursor[i]) { + equalUpTo += 1; + } + } + + if (opIsSibling) { + if (op.sd) { + cursor[cursor.length - 1] = text.transformCursor( + cursor[cursor.length - 1], + [{ p: op.p[op.p.length - 1], d: op.sd }], + isOwnOp ? 'right' : 'left' + ); + } + if (op.si) { + cursor[cursor.length - 1] = text.transformCursor( + cursor[cursor.length - 1], + [{ p: op.p[op.p.length - 1], i: op.si }], + isOwnOp ? 'right' : 'left' + ); + } + } + + if (opIsAncestor) { + if (op.lm !== undefined) { + cursor[equalUpTo] = op.lm; + } + if (op.od && op.oi) { + cursor = op.p.slice(0, op.p.length); + } else if (op.od) { + cursor = op.p.slice(0, op.p.length - 1); + } else if (op.ld && op.li) { + cursor = op.p.slice(0, op.p.length); + } else if (op.ld) { + cursor = op.p.slice(0, op.p.length - 1); + } + } + + if (opIsAncestorSibling) { + var lastPathIdx = op.p.length - 1; + if ( + !opIsAncestor && + op.ld && + !op.li && + op.p[lastPathIdx] < cursor[lastPathIdx] + ) { + cursor[lastPathIdx] -= 1; + } else if (!op.ld && op.li && op.p[lastPathIdx] <= cursor[lastPathIdx]) { + cursor[lastPathIdx] += 1; + } + + // if move item in list from after to before + if ( + !opIsAncestor && + op.lm !== undefined && + op.p[lastPathIdx] > cursor[lastPathIdx] && + op.lm <= cursor[lastPathIdx] + ) { + cursor[lastPathIdx] += 1; + // if move item in list from before to after + } else if ( + !opIsAncestor && + op.lm !== undefined && + op.p[lastPathIdx] < cursor[lastPathIdx] && + op.lm >= cursor[lastPathIdx] + ) { + cursor[lastPathIdx] -= 1; + } + } + + return cursor; +}; + +json.transformCursor = function(cursor, op, isOwnOp) { + for (var i = 0; i < op.length; i++) { + cursor = transformPosition(cursor, op[i], isOwnOp); + } + return cursor; +}; + +// this is the key function, always run client-side, both on +// the client that creates a text-change, and on the clients +// that receive text-changes (ops). if there are no ops, just +// return presence, if there are ops, delegate to the subtype +// responsible for those ops (currently only ot-rich-text). +// I am making assumptions many places that all ops will be +// of the same subtype, not sure if this is a given. +// We're only concerned about the first level of object/array, +// not sure if the spec allows nesting of subtypes. +json.transformPresence = function(presence, ops, isOwn) { + if (op.length < 1) { + return presence; + } + ops.forEach(op => { + const opType = op.t; + const path = op.p && op.p[0]; + if (opType && subtypes[opType] && path) { + // No path given, or path does not match path in presence -- + // no need to transform path since no conflict + if (!presence.p || !presence.p[0] || presence.p[0] !== path) { + return presence; + } + // return result of running the subtype's transformPresence, + // but add path and type, which the subtype will not include + presence.cursor = subtypes[opType].transformCursor( + presence, + op, + isOwn + ).cursor; + } + }); + return presence; +}; + json.apply = function(snapshot, op) { json.checkValidOp(op); @@ -146,8 +301,7 @@ json.apply = function(snapshot, op) { var c = op[i]; // convert old string ops to use subtype for backwards compatibility - if (c.si != null || c.sd != null) - convertFromText(c); + if (c.si != null || c.sd != null) convertFromText(c); var parent = null; var parentKey = null; @@ -162,15 +316,14 @@ json.apply = function(snapshot, op) { elem = elem[key]; key = p; - if (parent == null) - throw new Error('Path invalid'); + if (parent == null) throw new Error('Path invalid'); } // handle subtype ops if (c.t && c.o !== void 0 && subtypes[c.t]) { elem[key] = subtypes[c.t].apply(elem[key], c.o); - // Number add + // Number add } else if (c.na !== void 0) { if (typeof elem[key] != 'number') throw new Error('Referenced element not a number'); @@ -188,14 +341,14 @@ json.apply = function(snapshot, op) { // List insert else if (c.li !== void 0) { json.checkList(elem); - elem.splice(key,0, c.li); + elem.splice(key, 0, c.li); } // List delete else if (c.ld !== void 0) { json.checkList(elem); // Should check the list element matches c.ld here too. - elem.splice(key,1); + elem.splice(key, 1); } // List move @@ -204,9 +357,9 @@ json.apply = function(snapshot, op) { if (c.lm != key) { var e = elem[key]; // Remove it... - elem.splice(key,1); + elem.splice(key, 1); // And insert it back. - elem.splice(c.lm,0,e); + elem.splice(c.lm, 0, e); } } @@ -224,9 +377,7 @@ json.apply = function(snapshot, op) { // Should check that elem[key] == c.od delete elem[key]; - } - - else { + } else { throw new Error('invalid / missing instruction in op'); } } @@ -257,19 +408,17 @@ json.incrementalApply = function(snapshot, op, _yield) { }; // Checks if two paths, p1 and p2 match. -var pathMatches = json.pathMatches = function(p1, p2, ignoreLast) { - if (p1.length != p2.length) - return false; +var pathMatches = (json.pathMatches = function(p1, p2, ignoreLast) { + if (p1.length != p2.length) return false; for (var i = 0; i < p1.length; i++) { - if (p1[i] !== p2[i] && (!ignoreLast || i !== p1.length - 1)) - return false; + if (p1[i] !== p2[i] && (!ignoreLast || i !== p1.length - 1)) return false; } return true; -}; +}); -json.append = function(dest,c) { +json.append = function(dest, c) { c = clone(c); if (dest.length === 0) { @@ -288,7 +437,10 @@ json.append = function(dest,c) { if (pathMatches(c.p, last.p)) { // handle subtype ops if (c.t && last.t && c.t === last.t && subtypes[c.t]) { - last.o = subtypes[c.t].compose(last.o, c.o); + last.o = subtypes[c.t].compose( + last.o, + c.o + ); // convert back to old string ops if (c.si != null || c.sd != null) { @@ -303,8 +455,12 @@ json.append = function(dest,c) { convertToText(last); } } else if (last.na != null && c.na != null) { - dest[dest.length - 1] = {p: last.p, na: last.na + c.na}; - } else if (last.li !== undefined && c.li === undefined && c.ld === last.li) { + dest[dest.length - 1] = { p: last.p, na: last.na + c.na }; + } else if ( + last.li !== undefined && + c.li === undefined && + c.ld === last.li + ) { // insert immediately followed by delete becomes a noop. if (last.ld !== undefined) { // leave the delete part of the replace @@ -312,7 +468,12 @@ json.append = function(dest,c) { } else { dest.pop(); } - } else if (last.od !== undefined && last.oi === undefined && c.oi !== undefined && c.od === undefined) { + } else if ( + last.od !== undefined && + last.oi === undefined && + c.oi !== undefined && + c.od === undefined + ) { last.oi = c.oi; } else if (last.oi !== undefined && c.od !== undefined) { // The last path component inserted something that the new component deletes (or replaces). @@ -332,7 +493,10 @@ json.append = function(dest,c) { } } else { // convert string ops back - if ((c.si != null || c.sd != null) && (last.si != null || last.sd != null)) { + if ( + (c.si != null || c.sd != null) && + (last.si != null || last.sd != null) + ) { convertToText(c); convertToText(last); } @@ -341,14 +505,14 @@ json.append = function(dest,c) { } }; -json.compose = function(op1,op2) { +json.compose = function(op1, op2) { json.checkValidOp(op1); json.checkValidOp(op2); var newOp = clone(op1); for (var i = 0; i < op2.length; i++) { - json.append(newOp,op2[i]); + json.append(newOp, op2[i]); } return newOp; @@ -363,7 +527,7 @@ json.normalize = function(op) { var c = op[i]; if (c.p == null) c.p = []; - json.append(newOp,c); + json.append(newOp, c); } return newOp; @@ -373,11 +537,9 @@ json.normalize = function(op) { json.commonLengthForOps = function(a, b) { var alen = a.p.length; var blen = b.p.length; - if (a.na != null || a.t) - alen++; + if (a.na != null || a.t) alen++; - if (b.na != null || b.t) - blen++; + if (b.na != null || b.t) blen++; if (alen === 0) return -1; if (blen === 0) return null; @@ -387,8 +549,7 @@ json.commonLengthForOps = function(a, b) { for (var i = 0; i < alen; i++) { var p = a.p[i]; - if (i >= blen || p !== b.p[i]) - return null; + if (i >= blen || p !== b.p[i]) return null; } return alen; @@ -396,7 +557,7 @@ json.commonLengthForOps = function(a, b) { // Returns true if an op can affect the given path json.canOpAffectPath = function(op, path) { - return json.commonLengthForOps({p:path}, op) != null; + return json.commonLengthForOps({ p: path }, op) != null; }; // transform c so it applies to a document with otherC applied. @@ -408,23 +569,25 @@ json.transformComponent = function(dest, c, otherC, type) { var cplength = c.p.length; var otherCplength = otherC.p.length; - if (c.na != null || c.t) - cplength++; + if (c.na != null || c.t) cplength++; - if (otherC.na != null || otherC.t) - otherCplength++; + if (otherC.na != null || otherC.t) otherCplength++; // if c is deleting something, and that thing is changed by otherC, we need to // update c to reflect that change for invertibility. - if (common2 != null && otherCplength > cplength && c.p[common2] == otherC.p[common2]) { + if ( + common2 != null && + otherCplength > cplength && + c.p[common2] == otherC.p[common2] + ) { if (c.ld !== void 0) { var oc = clone(otherC); oc.p = oc.p.slice(cplength); - c.ld = json.apply(clone(c.ld),[oc]); + c.ld = json.apply(clone(c.ld), [oc]); } else if (c.od !== void 0) { var oc = clone(otherC); oc.p = oc.p.slice(cplength); - c.od = json.apply(clone(c.od),[oc]); + c.od = json.apply(clone(c.od), [oc]); } } @@ -433,7 +596,10 @@ json.transformComponent = function(dest, c, otherC, type) { // backward compatibility for old string ops var oc = otherC; - if ((c.si != null || c.sd != null) && (otherC.si != null || otherC.sd != null)) { + if ( + (c.si != null || c.sd != null) && + (otherC.si != null || otherC.sd != null) + ) { convertFromText(c); oc = clone(otherC); convertFromText(oc); @@ -482,10 +648,14 @@ json.transformComponent = function(dest, c, otherC, type) { } } } else if (otherC.li !== void 0) { - if (c.li !== void 0 && c.ld === undefined && commonOperand && c.p[common] === otherC.p[common]) { + if ( + c.li !== void 0 && + c.ld === undefined && + commonOperand && + c.p[common] === otherC.p[common] + ) { // in li vs. li, left wins. - if (type === 'right') - c.p[common]++; + if (type === 'right') c.p[common]++; } else if (otherC.p[common] <= c.p[common]) { c.p[common]++; } @@ -493,8 +663,7 @@ json.transformComponent = function(dest, c, otherC, type) { if (c.lm !== void 0) { if (commonOperand) { // otherC edits the same list we edit - if (otherC.p[common] <= c.lm) - c.lm++; + if (otherC.p[common] <= c.lm) c.lm++; // changing c.from is handled above. } } @@ -509,9 +678,7 @@ json.transformComponent = function(dest, c, otherC, type) { var p = otherC.p[common]; var from = c.p[common]; var to = c.lm; - if (p < to || (p === to && from < to)) - c.lm--; - + if (p < to || (p === to && from < to)) c.lm--; } } @@ -531,7 +698,6 @@ json.transformComponent = function(dest, c, otherC, type) { } } } - } else if (otherC.lm !== void 0) { if (c.lm !== void 0 && cplength === otherCplength) { // lm vs lm, here we go! @@ -547,7 +713,8 @@ json.transformComponent = function(dest, c, otherC, type) { // they moved it! tie break. if (type === 'left') { c.p[common] = otherTo; - if (from === to) // ugh + if (from === to) + // ugh c.lm = otherTo; } else { return dest; @@ -559,7 +726,8 @@ json.transformComponent = function(dest, c, otherC, type) { else if (from === otherTo) { if (otherFrom > otherTo) { c.p[common]++; - if (from === to) // ugh, again + if (from === to) + // ugh, again c.lm++; } } @@ -568,15 +736,16 @@ json.transformComponent = function(dest, c, otherC, type) { if (to > otherFrom) { c.lm--; } else if (to === otherFrom) { - if (to > from) - c.lm--; + if (to > from) c.lm--; } if (to > otherTo) { c.lm++; } else if (to === otherTo) { // if we're both moving in the same direction, tie break - if ((otherTo > otherFrom && to > from) || - (otherTo < otherFrom && to < from)) { + if ( + (otherTo > otherFrom && to > from) || + (otherTo < otherFrom && to < from) + ) { if (type === 'right') c.lm++; } else { if (to > from) c.lm++; @@ -608,8 +777,7 @@ json.transformComponent = function(dest, c, otherC, type) { else if (p === to && from > to) c.p[common]++; } } - } - else if (otherC.oi !== void 0 && otherC.od !== void 0) { + } else if (otherC.oi !== void 0 && otherC.od !== void 0) { if (c.p[common] === otherC.p[common]) { if (c.oi !== void 0 && commonOperand) { // we inserted where someone else replaced @@ -629,15 +797,14 @@ json.transformComponent = function(dest, c, otherC, type) { if (c.oi !== void 0 && c.p[common] === otherC.p[common]) { // left wins if we try to insert at the same place if (type === 'left') { - json.append(dest,{p: c.p, od:otherC.oi}); + json.append(dest, { p: c.p, od: otherC.oi }); } else { return dest; } } } else if (otherC.od !== void 0) { if (c.p[common] == otherC.p[common]) { - if (!commonOperand) - return dest; + if (!commonOperand) return dest; if (c.oi !== void 0) { delete c.od; } else { @@ -647,11 +814,16 @@ json.transformComponent = function(dest, c, otherC, type) { } } - json.append(dest,c); + json.append(dest, c); return dest; }; -require('./bootstrapTransform')(json, json.transformComponent, json.checkValidOp, json.append); +require('./bootstrapTransform')( + json, + json.transformComponent, + json.checkValidOp, + json.append +); /** * Register a subtype for string operations, using the text0 type. @@ -660,4 +832,3 @@ var text = require('./text0'); json.registerSubtype(text); module.exports = json; - diff --git a/package.json b/package.json index b6c9df6..c7d133e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "ot-json0", - "version": "1.1.0", - "description": "JSON OT type", + "name": "@minervaproject/ot-json0", + "version": "1.3.0", + "description": "JSON OT type, fork of sharedb/ot-json0@1.2.0", "main": "lib/index.js", "directories": { "test": "test" @@ -17,7 +17,7 @@ }, "repository": { "type": "git", - "url": "git://github.com/ottypes/json0" + "url": "git://github.com/houshuang/json0" }, "keywords": [ "ot", diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..e13b328 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,172 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +cli-progress@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-2.1.1.tgz#45ee1b143487c19043a3262131ccb4676f87f032" + integrity sha512-TSJw3LY9ZRSis7yYzQ7flIdtQMbacd9oYoiFphJhI4SzgmqF0zErO+uNv0lbUjk1L4AGfHQJ4OVYYzW+JV66KA== + dependencies: + colors "^1.1.2" + string-width "^2.1.1" + +coffee-script@^1.7.1: + version "1.12.7" + resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53" + integrity sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw== + +colors@^1.1.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== + +commander@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" + integrity sha1-+mihT2qUXVTbvlDYzbMyDp47GgY= + +commander@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" + integrity sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM= + +debug@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.0.0.tgz#89bd9df6732b51256bc6705342bba02ed12131ef" + integrity sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8= + dependencies: + ms "0.6.2" + +diff@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.0.8.tgz#343276308ec991b7bc82267ed55bc1411f971666" + integrity sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY= + +escape-string-regexp@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" + integrity sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE= + +glob@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.3.tgz#e313eeb249c7affaa5c475286b0e115b59839467" + integrity sha1-4xPusknHr/qlxHUoaw4RW1mDlGc= + dependencies: + graceful-fs "~2.0.0" + inherits "2" + minimatch "~0.2.11" + +graceful-fs@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-2.0.3.tgz#7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0" + integrity sha1-fNLNsiiko/Nule+mzBQt59GhNtA= + +growl@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428" + integrity sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg= + +inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +jade@0.26.3: + version "0.26.3" + resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" + integrity sha1-jxDXl32NefL2/4YqgbBRPMslaGw= + dependencies: + commander "0.6.1" + mkdirp "0.3.0" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + integrity sha1-bUUk6LlV+V1PW1iFHOId1y+06VI= + +minimatch@~0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" + integrity sha1-x054BXT2PG+aCQ6Q775u9TpqdWo= + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= + +mkdirp@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" + integrity sha1-HXMHam35hs2TROFecfzAWkyavxI= + dependencies: + minimist "0.0.8" + +mocha@^1.20.1: + version "1.21.5" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-1.21.5.tgz#7c58b09174df976e434a23b1e8d639873fc529e9" + integrity sha1-fFiwkXTfl25DSiOx6NY5hz/FKek= + dependencies: + commander "2.3.0" + debug "2.0.0" + diff "1.0.8" + escape-string-regexp "1.0.2" + glob "3.2.3" + growl "1.8.1" + jade "0.26.3" + mkdirp "0.5.0" + +ms@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.6.2.tgz#d89c2124c6fdc1353d65a8b77bf1aac4b193708c" + integrity sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw= + +ot-fuzzer@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ot-fuzzer/-/ot-fuzzer-1.2.1.tgz#41f70305fdd1d55268f6cc169c14c0eb9e5fb31c" + integrity sha512-dOm+Wb1Mqrw8ql5ksiZFf3Bdsruj5r4mHaa3COqtbg0ClkGjxZXwMGgMLjWslq/b0maeiw5yvYwIdH6As4svHg== + dependencies: + cli-progress "^2.1.1" + seedrandom "^2.4.4" + +seedrandom@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.4.tgz#b25ea98632c73e45f58b77cfaa931678df01f9ba" + integrity sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA== + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0"