|
|
@@ -11,45 +11,34 @@ var Value = module.exports = function Value(){
|
|
|
if(this.constructor == Value) throw new Error("Never create instances of this! Use the static helpers only.");
|
|
|
}, klass = Value, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
|
|
|
|
|
|
-/**
|
|
|
- * Takes an array and returns a new array with the same contents.
|
|
|
- * consumed is emptied.
|
|
|
- * @method consume
|
|
|
- * @namespace mungedb-aggregate.pipeline.Value
|
|
|
- * @param consumed Array The array to be copied, emptied.
|
|
|
- **/
|
|
|
-klass.consume = function consume(consumed) {
|
|
|
- return consumed.splice(0);
|
|
|
-};
|
|
|
-
|
|
|
-// PRIVATE STUFF
|
|
|
-function getTypeVerifier(type, IClass, isStrict) {
|
|
|
- return function verifyType(value) {
|
|
|
- if (typeof(value) != type) throw new Error("typeof value is not: " + type + "; actual: " + typeof(value));
|
|
|
- if (typeof(IClass) == "function" && !(isStrict ? value.constructor == IClass : value instanceof IClass)) throw new Error("instanceof value is not: " + IClass.name + "; actual: " + value.constructor.name);
|
|
|
- return value;
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-// STATIC MEMBERS
|
|
|
-klass.verifyNumber = getTypeVerifier("number", Number); //NOTE: replaces #getDouble(), #getInt(), and #getLong()
|
|
|
-klass.verifyString = getTypeVerifier("string", String);
|
|
|
-klass.verifyDocument = getTypeVerifier("object", Object, true); //TODO: change to verifyObject? since we're not using actual Document instances
|
|
|
-klass.verifyArray = getTypeVerifier("object", Array, true);
|
|
|
-klass.verifyDate = getTypeVerifier("object", Date, true);
|
|
|
-klass.verifyRegExp = getTypeVerifier("object", RegExp, true); //NOTE: renamed from #getRegex()
|
|
|
-//TODO: klass.verifyOid = ...?
|
|
|
-//TODO: klass.VerifyTimestamp = ...?
|
|
|
-klass.verifyBool = getTypeVerifier("boolean", Boolean, true);
|
|
|
+var Document; // loaded lazily below //TODO: a dirty hack; need to investigate and clean up
|
|
|
|
|
|
+//SKIPPED: ValueStorage -- probably not required; use JSON?
|
|
|
+//SKIPPED: createIntOrLong -- not required; use Number
|
|
|
+//SKIPPED: operator <Array>[] -- not required; use arr[i]
|
|
|
+//SKIPPED: operator <Object>[] -- not required; use obj[key]
|
|
|
+//SKIPPED: operator << -- not required
|
|
|
+//SKIPPED: addToBsonObj -- not required; use obj[key] = <val>
|
|
|
+//SKIPPED: addToBsonArray -- not required; use arr.push(<val>)
|
|
|
+
|
|
|
+/** Coerce a value to a bool using BSONElement::trueValue() rules.
|
|
|
+ * Some types unsupported. SERVER-6120
|
|
|
+ * @method coerceToBool
|
|
|
+ * @static
|
|
|
+ */
|
|
|
klass.coerceToBool = function coerceToBool(value) {
|
|
|
if (typeof(value) == "string") return true;
|
|
|
return !!value; // including null or undefined
|
|
|
};
|
|
|
+
|
|
|
+/** Coercion operators to extract values with fuzzy type logic.
|
|
|
+ * These currently assert if called on an unconvertible type.
|
|
|
+ * TODO: decided how to handle unsupported types.
|
|
|
+ */
|
|
|
klass.coerceToInt =
|
|
|
klass.coerceToLong =
|
|
|
klass.coerceToDouble =
|
|
|
-klass._coerceToNumber = function _coerceToNumber(value) { //NOTE: replaces .coerceToInt(), .coerceToLong(), and .coerceToDouble()
|
|
|
+klass._coerceToNumber = function _coerceToNumber(value) {
|
|
|
if (value === null) return 0;
|
|
|
switch (typeof(value)) {
|
|
|
case "undefined":
|
|
|
@@ -75,8 +64,9 @@ klass.coerceToDate = function coerceToDate(value) {
|
|
|
if (value instanceof Date) return value;
|
|
|
throw new Error("can't convert from BSON type " + typeof(value) + " to Date; uassert code 16006");
|
|
|
};
|
|
|
-//TODO: klass.coerceToTimeT = ...? try to use as Date first rather than having coerceToDate return Date.parse or dateObj.getTime() or similar
|
|
|
-//TODO: klass.coerceToTm = ...?
|
|
|
+//SKIPPED: coerceToTimeT -- not required; just use Date
|
|
|
+//SKIPPED: coerceToTm -- not required; just use Date
|
|
|
+//SKIPPED: tmToISODateString -- not required; just use Date
|
|
|
klass.coerceToString = function coerceToString(value) {
|
|
|
if (value === null) return "";
|
|
|
switch (typeof(value)) {
|
|
|
@@ -90,79 +80,23 @@ klass.coerceToString = function coerceToString(value) {
|
|
|
throw new Error("can't convert from BSON type " + typeof(value) + " to String; uassert code 16007");
|
|
|
}
|
|
|
};
|
|
|
+//SKIPPED: coerceToTimestamp
|
|
|
|
|
|
-
|
|
|
-klass.canonicalize = function canonicalize(x) {
|
|
|
- var xType = typeof(x);
|
|
|
- if(xType == "object") xType = x === null ? "null" : x.constructor.name;
|
|
|
- switch (xType) {
|
|
|
- case "MinKey":
|
|
|
- return -1;
|
|
|
- case "MaxKey":
|
|
|
- return 127;
|
|
|
- case "EOO":
|
|
|
- case "undefined":
|
|
|
- case undefined:
|
|
|
- return 0;
|
|
|
- case "jstNULL":
|
|
|
- case "null":
|
|
|
- case "Null":
|
|
|
- return 5;
|
|
|
- case "NumberDouble":
|
|
|
- case "NumberInt":
|
|
|
- case "NumberLong":
|
|
|
- case "number":
|
|
|
- return 10;
|
|
|
- case "Symbol":
|
|
|
- case "string":
|
|
|
- return 15;
|
|
|
- case "Object":
|
|
|
- return 20;
|
|
|
- case "Array":
|
|
|
- return 25;
|
|
|
- case "Binary":
|
|
|
- return 30;
|
|
|
- case "ObjectId":
|
|
|
- return 35;
|
|
|
- case "ObjectID":
|
|
|
- return 35;
|
|
|
- case "boolean":
|
|
|
- case "Boolean":
|
|
|
- return 40;
|
|
|
- case "Date":
|
|
|
- case "Timestamp":
|
|
|
- return 45;
|
|
|
- case "RegEx":
|
|
|
- case "RegExp":
|
|
|
- return 50;
|
|
|
- case "DBRef":
|
|
|
- return 55;
|
|
|
- case "Code":
|
|
|
- return 60;
|
|
|
- case "CodeWScope":
|
|
|
- return 65;
|
|
|
- default:
|
|
|
- // Default value for Object
|
|
|
- return 20;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
+/**
|
|
|
+ * Helper function for Value.compare
|
|
|
+ * @method cmp
|
|
|
+ * @static
|
|
|
+ */
|
|
|
klass.cmp = function cmp(l, r){
|
|
|
return l < r ? -1 : l > r ? 1 : 0;
|
|
|
};
|
|
|
|
|
|
-//TODO: klass.coerceToTimestamp = ...?
|
|
|
-
|
|
|
-/**
|
|
|
- * Compare two Values.
|
|
|
- *
|
|
|
+/** Compare two Values.
|
|
|
* @static
|
|
|
* @method compare
|
|
|
- * @param rL left value
|
|
|
- * @param rR right value
|
|
|
- * @returns an integer less than zero, zero, or an integer greater than zero, depending on whether rL < rR, rL == rR, or rL > rR
|
|
|
- **/
|
|
|
-var Document; // loaded lazily below //TODO: a dirty hack; need to investigate and clean up
|
|
|
+ * @returns an integer less than zero, zero, or an integer greater than zero, depending on whether lhs < rhs, lhs == rhs, or lhs > rhs
|
|
|
+ * Warning: may return values other than -1, 0, or 1
|
|
|
+ */
|
|
|
klass.compare = function compare(l, r) {
|
|
|
//NOTE: deviation from mongo code: we have to do some coercing for null "types" because of javascript
|
|
|
var lt = l === null ? "null" : typeof(l),
|
|
|
@@ -219,24 +153,96 @@ klass.compare = function compare(l, r) {
|
|
|
|
|
|
};
|
|
|
|
|
|
-//NOTE: not implementing the sorter functions until we understand sorter needs better
|
|
|
-var _waitingOnSorter = function() {
|
|
|
- //TODO: When working on sorter, decide if this is needed
|
|
|
- throw new Error("Not implemented.");
|
|
|
-};
|
|
|
+//SKIPPED: hash_combine
|
|
|
+//SKIPPED: getWidestNumeric
|
|
|
+//SKIPPED: getApproximateSize
|
|
|
+//SKIPPED: toString
|
|
|
+//SKIPPED: operator <<
|
|
|
+//SKIPPED: serializeForSorter
|
|
|
+//SKIPPED: deserializeForSorter
|
|
|
|
|
|
-klass.serializeForSorter = function(value) {
|
|
|
- _waitingOnSorter();
|
|
|
-};
|
|
|
-klass.deserializeForSorter = function(value) {
|
|
|
- _waitingOnSorter();
|
|
|
-};
|
|
|
-klass.memUsageForSorter = function(value) {
|
|
|
- _waitingOnSorter();
|
|
|
+/**
|
|
|
+ * Takes an array and removes items and adds them to returned array.
|
|
|
+ * @method consume
|
|
|
+ * @static
|
|
|
+ * @param consumed {Array} The array to be copied, emptied.
|
|
|
+ **/
|
|
|
+klass.consume = function consume(consumed) {
|
|
|
+ return consumed.splice(0);
|
|
|
};
|
|
|
|
|
|
-//TODO: klass.hashCombine = ...?
|
|
|
-//TODO: klass.getWidestNumeric = ...?
|
|
|
-//TODO: klass.getApproximateSize = ...?
|
|
|
-//TODO: klass.addRef = ...?
|
|
|
-//TODO: klass.release = ...?
|
|
|
+//NOTE: DEVIATION FROM MONGO: these are inlined using the below code or perhaps not relevant since we are not boxing
|
|
|
+// missing(val): val == undefined
|
|
|
+// nullish(val): val == null || val == undefined
|
|
|
+// numeric(val): typeof val == "number"
|
|
|
+// getArrayLength(arr): arr.length
|
|
|
+// getString(val): val.toString() //NOTE: same for getStringData(val) I think
|
|
|
+// getOid
|
|
|
+// getBool
|
|
|
+// getDate
|
|
|
+// getTimestamp
|
|
|
+// getRegex(re): re.source
|
|
|
+// getRegexFlags(re): re.toString().slice(-re.toString().lastIndexOf('/') + 2)
|
|
|
+// getSymbol
|
|
|
+// getCode
|
|
|
+// getInt
|
|
|
+// getLong
|
|
|
+//NOTE: also, because of this we are not throwing if the type does not match like the mongo code would but maybe that's okay
|
|
|
+
|
|
|
+//SKIPPED: getType -- need this or something like it? would be some more stuff from bsontypes
|
|
|
+
|
|
|
+// from bsontypes
|
|
|
+klass.canonicalize = function canonicalize(x) {
|
|
|
+ var xType = typeof(x);
|
|
|
+ if (xType == "object") xType = x === null ? "null" : x.constructor.name;
|
|
|
+ switch (xType) {
|
|
|
+ case "MinKey":
|
|
|
+ return -1;
|
|
|
+ case "MaxKey":
|
|
|
+ return 127;
|
|
|
+ case "EOO":
|
|
|
+ case "undefined":
|
|
|
+ case undefined:
|
|
|
+ return 0;
|
|
|
+ case "jstNULL":
|
|
|
+ case "null":
|
|
|
+ case "Null":
|
|
|
+ return 5;
|
|
|
+ case "NumberDouble":
|
|
|
+ case "NumberInt":
|
|
|
+ case "NumberLong":
|
|
|
+ case "number":
|
|
|
+ return 10;
|
|
|
+ case "Symbol":
|
|
|
+ case "string":
|
|
|
+ return 15;
|
|
|
+ case "Object":
|
|
|
+ return 20;
|
|
|
+ case "Array":
|
|
|
+ return 25;
|
|
|
+ case "Binary":
|
|
|
+ return 30;
|
|
|
+ case "ObjectId":
|
|
|
+ return 35;
|
|
|
+ case "ObjectID":
|
|
|
+ return 35;
|
|
|
+ case "boolean":
|
|
|
+ case "Boolean":
|
|
|
+ return 40;
|
|
|
+ case "Date":
|
|
|
+ case "Timestamp":
|
|
|
+ return 45;
|
|
|
+ case "RegEx":
|
|
|
+ case "RegExp":
|
|
|
+ return 50;
|
|
|
+ case "DBRef":
|
|
|
+ return 55;
|
|
|
+ case "Code":
|
|
|
+ return 60;
|
|
|
+ case "CodeWScope":
|
|
|
+ return 65;
|
|
|
+ default:
|
|
|
+ // Default value for Object
|
|
|
+ return 20;
|
|
|
+ }
|
|
|
+};
|