summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer Jackson <spencer.jackson@mongodb.com>2017-08-11 14:30:40 -0400
committerSpencer Jackson <spencer.jackson@mongodb.com>2017-08-31 10:25:38 -0400
commit8024561b6a73b5b0b56200bdfa3233219ff7fb18 (patch)
treece8dd64e087f524a5310ac344b81ca70c3e846bd
parentebd0ec786e6986ecd407c48928e6866736675021 (diff)
downloadmongo-8024561b6a73b5b0b56200bdfa3233219ff7fb18.tar.gz
SERVER-30009: Allow JS functions to be terminated with ';'
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_initsync_jscore_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/replica_sets_resync_jscore_passthrough.yml1
-rw-r--r--jstests/core/function_string_representations.js38
-rw-r--r--src/mongo/scripting/mozjs/mongohelpers.js8
4 files changed, 48 insertions, 0 deletions
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_initsync_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_initsync_jscore_passthrough.yml
index ff498daba22..9d2017f2e70 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_initsync_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_initsync_jscore_passthrough.yml
@@ -15,6 +15,7 @@ selector:
- jstests/core/commands_that_do_not_write_do_not_accept_wc.js
- jstests/core/constructors.js
- jstests/core/eval_mr.js
+ - jstests/core/function_string_representations.js
- jstests/core/geo_big_polygon3.js
- jstests/core/geo_mapreduce.js
- jstests/core/geo_mapreduce2.js
diff --git a/buildscripts/resmokeconfig/suites/replica_sets_resync_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_resync_jscore_passthrough.yml
index 7694e0d9736..c15c82e0733 100644
--- a/buildscripts/resmokeconfig/suites/replica_sets_resync_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/replica_sets_resync_jscore_passthrough.yml
@@ -15,6 +15,7 @@ selector:
- jstests/core/commands_that_do_not_write_do_not_accept_wc.js
- jstests/core/constructors.js
- jstests/core/eval_mr.js
+ - jstests/core/function_string_representations.js
- jstests/core/geo_big_polygon3.js
- jstests/core/geo_mapreduce.js
- jstests/core/geo_mapreduce2.js
diff --git a/jstests/core/function_string_representations.js b/jstests/core/function_string_representations.js
new file mode 100644
index 00000000000..af66e9160a9
--- /dev/null
+++ b/jstests/core/function_string_representations.js
@@ -0,0 +1,38 @@
+/** Demonstrate that mapReduce can accept functions represented by strings.
+ * Some drivers do not have a type which represents a Javascript function. These languages represent
+ * the arguments to mapReduce as strings.
+ */
+
+(function() {
+ "use strict";
+
+ var col = db.function_string_representations;
+ col.drop();
+ assert.writeOK(col.insert({
+ _id: "abc123",
+ ord_date: new Date("Oct 04, 2012"),
+ status: 'A',
+ price: 25,
+ items: [{sku: "mmm", qty: 5, price: 2.5}, {sku: "nnn", qty: 5, price: 2.5}]
+ }));
+
+ var mapFunction = "function() {emit(this._id, this.price);}";
+ var reduceFunction = "function(keyCustId, valuesPrices) {return Array.sum(valuesPrices);}";
+ assert.commandWorked(col.mapReduce(mapFunction, reduceFunction, {out: "map_reduce_example"}));
+
+ // Provided strings may end with semicolons and/or whitespace
+ mapFunction += " ; ";
+ reduceFunction += " ; ";
+ assert.commandWorked(col.mapReduce(mapFunction, reduceFunction, {out: "map_reduce_example"}));
+
+ // $where exhibits the same behavior
+ var whereFunction = "function() {return this.price === 25;}";
+ assert.eq(1, col.find({$where: whereFunction}).itcount());
+
+ whereFunction += ";";
+ assert.eq(1, col.find({$where: whereFunction}).itcount());
+
+ // db.eval does not need to be tested, as it accepts code fragments, not functions.
+ // system.js does not need to be tested, as its contents types' are preserved, and
+ // strings are not promoted into functions.
+})();
diff --git a/src/mongo/scripting/mozjs/mongohelpers.js b/src/mongo/scripting/mozjs/mongohelpers.js
index b0b35bb2fe8..d3f743623a3 100644
--- a/src/mongo/scripting/mozjs/mongohelpers.js
+++ b/src/mongo/scripting/mozjs/mongohelpers.js
@@ -33,6 +33,14 @@
exportToMongoHelpers = {
// This function accepts an expression or function body and returns a function definition
'functionExpressionParser': function functionExpressionParser(fnSrc) {
+
+ // Ensure that a provided expression or function body is not terminated with a ';'.
+ // This ensures we interpret the input as a single expression, rather than a sequence
+ // of expressions, and can wrap it in parentheses.
+ while (fnSrc.endsWith(";") || fnSrc != fnSrc.trimRight()) {
+ fnSrc = fnSrc.slice(0, -1).trimRight();
+ }
+
var parseTree;
try {
parseTree = this.Reflect.parse(fnSrc);