From f43ea7a6bb2a6c44f91506c32004241d3cbb24ae Mon Sep 17 00:00:00 2001 From: Max Hirschhorn Date: Tue, 18 Sep 2018 21:10:36 -0400 Subject: SERVER-35154 Propagate JS exceptions through ScopedThread#join(). This makes it so that if the ScopedThread exited due to an uncaught JavaScript exception, then calling .join() or .returnData() on it throws a JavaScript exception with the error message and stacktrace intact. --- jstests/core/mr_tolerates_js_exception.js | 38 +++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'jstests/core/mr_tolerates_js_exception.js') diff --git a/jstests/core/mr_tolerates_js_exception.js b/jstests/core/mr_tolerates_js_exception.js index 47536a3cc3f..20e96eb47dc 100644 --- a/jstests/core/mr_tolerates_js_exception.js +++ b/jstests/core/mr_tolerates_js_exception.js @@ -1,7 +1,11 @@ -// @tags: [does_not_support_stepdowns] - /** - * Test that the mapReduce command fails gracefully when user-provided JavaScript code throws. + * Test that the mapReduce command fails gracefully when user-provided JavaScript code throws and + * that the user gets back a JavaScript stacktrace. + * + * @tags: [ + * does_not_support_stepdowns, + * requires_scripting, + * ] */ (function() { "use strict"; @@ -20,18 +24,32 @@ emit(this.a, 1); }, reduce: function(key, value) { - throw 42; + (function myFunction() { + throw new Error("Intentionally thrown inside reduce function"); + })(); }, out: {inline: 1} }); assert.commandFailedWithCode(cmdOutput, ErrorCodes.JSInterpreterFailure, tojson(cmdOutput)); + assert(/Intentionally thrown inside reduce function/.test(cmdOutput.errmsg), + () => "mapReduce didn't include the message from the exception thrown: " + + tojson(cmdOutput)); + assert(/myFunction@/.test(cmdOutput.errmsg), + () => "mapReduce didn't return the JavaScript stacktrace: " + tojson(cmdOutput)); + assert( + !cmdOutput.hasOwnProperty("stack"), + () => "mapReduce shouldn't return JavaScript stacktrace separately: " + tojson(cmdOutput)); + assert(!cmdOutput.hasOwnProperty("originalError"), + () => "mapReduce shouldn't return wrapped version of the error: " + tojson(cmdOutput)); // Test that the command fails with a JS interpreter failure error when the map function // throws. cmdOutput = db.runCommand({ mapReduce: coll.getName(), map: function() { - throw 42; + (function myFunction() { + throw new Error("Intentionally thrown inside map function"); + })(); }, reduce: function(key, value) { return Array.sum(value); @@ -39,4 +57,14 @@ out: {inline: 1} }); assert.commandFailedWithCode(cmdOutput, ErrorCodes.JSInterpreterFailure, tojson(cmdOutput)); + assert(/Intentionally thrown inside map function/.test(cmdOutput.errmsg), + () => "mapReduce didn't include the message from the exception thrown: " + + tojson(cmdOutput)); + assert(/myFunction@/.test(cmdOutput.errmsg), + () => "mapReduce didn't return the JavaScript stacktrace: " + tojson(cmdOutput)); + assert( + !cmdOutput.hasOwnProperty("stack"), + () => "mapReduce shouldn't return JavaScript stacktrace separately: " + tojson(cmdOutput)); + assert(!cmdOutput.hasOwnProperty("originalError"), + () => "mapReduce shouldn't return wrapped version of the error: " + tojson(cmdOutput)); }()); -- cgit v1.2.1