UNPKG

modifyjs

Version:

Modify your objects with a mongo syntax.

153 lines (146 loc) 4.32 kB
import { isArray } from './helpers'; import { EJSON } from './ejson'; export var _f = { // XXX for _all and _in, consider building 'inquery' at compile time.. _type: function _type(v) { if (typeof v === "number") return 1; if (typeof v === "string") return 2; if (typeof v === "boolean") return 8; if (isArray(v)) return 4; if (v === null) return 10; if (v instanceof RegExp) // note that typeof(/x/) === "object" return 11; if (typeof v === "function") return 13; if (v instanceof Date) return 9; if (EJSON.isBinary(v)) return 5; return 3; // object // XXX support some/all of these: // 14, symbol // 15, javascript code with scope // 16, 18: 32-bit/64-bit integer // 17, timestamp // 255, minkey // 127, maxkey }, // deep equality test: use for literal document and array matches _equal: function _equal(a, b) { return EJSON.equals(a, b, { keyOrderSensitive: true }); }, // maps a type code to a value that can be used to sort values of // different types _typeorder: function _typeorder(t) { // http://www.mongodb.org/display/DOCS/What+is+the+Compare+Order+for+BSON+Types // XXX what is the correct sort position for Javascript code? // ('100' in the matrix below) // XXX minkey/maxkey return [-1, // (not a type) 1, // number 2, // string 3, // object 4, // array 5, // binary -1, // deprecated 6, // ObjectID 7, // bool 8, // Date 0, // null 9, // RegExp -1, // deprecated 100, // JS code 2, // deprecated (symbol) 100, // JS code 1, // 32-bit int 8, // Mongo timestamp 1 // 64-bit int ][t]; }, // compare two values of unknown type according to BSON ordering // semantics. (as an extension, consider 'undefined' to be less than // any other value.) return negative if a is less, positive if b is // less, or 0 if equal _cmp: function _cmp(a, b) { if (a === undefined) return b === undefined ? 0 : -1; if (b === undefined) return 1; var ta = this._type(a); var tb = this._type(b); var oa = this._typeorder(ta); var ob = this._typeorder(tb); if (oa !== ob) return oa < ob ? -1 : 1; if (ta !== tb) // XXX need to implement this if we implement Symbol or integers, or // Timestamp throw Error("Missing type coercion logic in _cmp"); if (ta === 7) { // ObjectID // Convert to string. ta = tb = 2; a = a.toHexString(); b = b.toHexString(); } if (ta === 9) { // Date // Convert to millis. ta = tb = 1; a = a.getTime(); b = b.getTime(); } if (ta === 1) // double return a - b; if (tb === 2) // string return a < b ? -1 : a === b ? 0 : 1; if (ta === 3) { // Object // this could be much more efficient in the expected case ... var to_array = function to_array(obj) { var ret = []; for (var key in obj) { ret.push(key); ret.push(obj[key]); } return ret; }; return this._cmp(to_array(a), to_array(b)); } if (ta === 4) { // Array for (var i = 0;; i++) { if (i === a.length) return i === b.length ? 0 : -1; if (i === b.length) return 1; var s = this._cmp(a[i], b[i]); if (s !== 0) return s; } } if (ta === 5) { // binary // Surprisingly, a small binary blob is always less than a large one in // Mongo. if (a.length !== b.length) return a.length - b.length; for (i = 0; i < a.length; i++) { if (a[i] < b[i]) return -1; if (a[i] > b[i]) return 1; } return 0; } if (ta === 8) { // boolean if (a) return b ? 0 : 1; return b ? -1 : 0; } if (ta === 10) // null return 0; if (ta === 11) // regexp throw Error("Sorting not supported on regular expression"); // XXX // 13: javascript code // 14: symbol // 15: javascript code with scope // 16: 32-bit integer // 17: timestamp // 18: 64-bit integer // 255: minkey // 127: maxkey if (ta === 13) // javascript code throw Error("Sorting not supported on Javascript code"); // XXX throw Error("Unknown type to sort"); } };