Skip to content

Commit

Permalink
Disable coercion of null values to string:null in Query#toString
Browse files Browse the repository at this point in the history
This also includes a refactoring of the query module's `encodeValue` function for clarity and easier modification later, if necessary. Comments included.

For persvr#76
  • Loading branch information
rkaw92 committed Dec 21, 2016
1 parent 7db4e49 commit 7986c6d
Showing 1 changed file with 44 additions and 25 deletions.
69 changes: 44 additions & 25 deletions query.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,37 +76,56 @@ function encodeString(s) {
return s;
}

/**
* Encode a value of a part's argument for use in an RQL string.
* @param {*} val - The value to encode.
* @returns {string} The encoded value, URI-safe.
*/
exports.encodeValue = function(val) {
var encoded;
if (val === null) val = 'null';
// Remember whether any encoding took place. The function force-encodes
// the value as a plain string at the end as a last resort.
var encoded = false;

// Try encoding the value. If it throws, go to our failsafe.
try {
if (val !== parser.converters["default"]('' + (
val.toISOString && val.toISOString() || val.toString()
))) {
var type = typeof val;
if(val instanceof RegExp){
// TODO: control whether to we want simpler glob() style
val = val.toString();
var i = val.lastIndexOf('/');
type = val.substring(i).indexOf('i') >= 0 ? "re" : "RE";
val = encodeString(val.substring(1, i));
encoded = true;
}
if(type === "object"){
type = "epoch";
val = val.getTime();
encoded = true;
}
if(type === "string") {
val = encodeString(val);
encoded = true;
}
val = [type, val].join(":");
// Check whether casting the value to a string and parsing it would
// result in the input value (i.e. if the value can be left prefix-less).
var stringVal = '' + ((val && val.toISOString) ? val.toISOString() : val);
var parsedStringVal = parser.converters["default"](stringVal);
if (val === parsedStringVal) {
return encodeString(String(val));
}
// Now, only non-trivial cases are left:
var type = typeof val;
if (val instanceof RegExp) {
// TODO: control whether to we want simpler glob() style
val = val.toString();
var i = val.lastIndexOf('/');
type = val.substring(i).indexOf('i') >= 0 ? "re" : "RE";
val = encodeString(val.substring(1, i));
encoded = true;
}
if (type === "object") {
// Assume it's a date - it's the only other object type we support:
type = "epoch";
val = val.getTime();
encoded = true;
}
if (type === "string") {
// It's a string, but it doesn't parse to its own exact value.
// This happens when the input is a String('null') for example -
// the auto-converter parses null to type null, so we need a prefix.
val = encodeString(val);
encoded = true;
}
val = [type, val].join(":");
} catch (conversionError) {
// The conversion necessity check has failed and we have not encoded the value. The next conditional block will take care of it.
}
if (!encoded && typeof val === "string") val = encodeString(val);
if (!encoded && typeof val === "string") {
val = encodeString(val);
}
val = String(val);
return val;
};

Expand Down

0 comments on commit 7986c6d

Please sign in to comment.