src/mongo/scripting/mozjs/mongohelpers.js
// This function accepts an expression or function body and returns a function definition
This function accepts an expression or function body and returns a function definition
This function accepts an expression or function body and returns a function definition
function functionExpressionParser(fnSrc) {
        while (fnSrc.endsWith(";") || fnSrc != fnSrc.trimRight()) {
            fnSrc = fnSrc.slice(0, -1).trimRight();
        }
        var parseTree;
        try {
            parseTree = this.Reflect.parse(fnSrc);
        } catch (e) {
            if (e == 'SyntaxError: function statement requires a name') {
                return fnSrc;
            } else if (e == 'SyntaxError: return not in function') {
                return 'function() { ' + fnSrc + ' }';
            } else {
                throw (e);
            }
        }
        var lastStatement = parseTree.body.length - 1;
        var lastStatementType = parseTree.body[lastStatement].type;
        if (lastStatementType == 'ExpressionStatement') {
            var prevExprEnd = 0;
            var loc = parseTree.body[lastStatement].loc.start;
            if (lastStatement > 0) {
                prevExprEnd = parseTree.body[lastStatement - 1].loc.end;
                if (prevExprEnd.line != loc.line) {
                    prevExprEnd = 0;
                } else {
                    prevExprEnd = prevExprEnd.column;
                }
            }
            var lines = fnSrc.split('\n');
            var col = loc.column;
            var fnSrc;
            var tmpTree;
            var origLine = lines[loc.line - 1];
            while (col >= prevExprEnd) {
                var modLine = origLine.substr(0, col) + "return " + origLine.substr(col);
                lines[loc.line - 1] = modLine;
                fnSrc = '{ ' + lines.join('\n') + ' }';
                try {
                    tmpTree = this.Reflect.parse("function x() " + fnSrc);
                } catch (e) {
                    col -= 1;
                    continue;
                }
                break;
            }
            return "function() " + fnSrc;
        } else if (lastStatementType == 'FunctionDeclaration') {
            return fnSrc;
        } else {
            return 'function() { ' + fnSrc + ' }';
        }
    }
function functionExpressionParser ( fnSrc ) { while ( fnSrc . endsWith ( ";" ) || fnSrc != fnSrc . trimRight ( ) ) { fnSrc = fnSrc . slice ( 0 , - 1 ) . trimRight ( ) ; } var parseTree ; try { parseTree = this . Reflect . parse ( fnSrc ) ; } catch ( e ) { if ( e == 'SyntaxError: function statement requires a name' ) { return fnSrc ; } else if ( e == 'SyntaxError: return not in function' ) { return 'function() { ' + fnSrc + ' }' ; } else { throw ( e ) ; } } var lastStatement = parseTree . body . length - 1 ; var lastStatementType = parseTree . body [ lastStatement ] . type ; if ( lastStatementType == 'ExpressionStatement' ) { var prevExprEnd = 0 ; var loc = parseTree . body [ lastStatement ] . loc . start ; if ( lastStatement > 0 ) { prevExprEnd = parseTree . body [ lastStatement - 1 ] . loc . end ; if ( prevExprEnd . line != loc . line ) { prevExprEnd = 0 ; } else { prevExprEnd = prevExprEnd . column ; } } var lines = fnSrc . split ( '\n' ) ; var col = loc . column ; var fnSrc ; var tmpTree ; var origLine = lines [ loc . line - 1 ] ; while ( col >= prevExprEnd ) { var modLine = origLine . substr ( 0 , col ) + "return " + origLine . substr ( col ) ; lines [ loc . line - 1 ] = modLine ; fnSrc = '{ ' + lines . join ( '\n' ) + ' }' ; try { tmpTree = this . Reflect . parse ( "function x() " + fnSrc ) ; } catch ( e ) { col -= 1 ; continue ; } break ; } return "function() " + fnSrc ; } else if ( lastStatementType == 'FunctionDeclaration' ) { return fnSrc ; } else { return 'function() { ' + fnSrc + ' }' ; } }
This function accepts an expression or function body and returns a function definition
This function accepts an expression or function body and returns a function definition
// 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. // Input source is a series of expressions. we should prepend the last one with return // When we're actually doing the pre-pending of return later on we need to know // whether we've reached the beginning of the line, or the end of the 2nd-to-last // expression. // The parser has a weird behavior where sometimes if you have an expression like // ((x == 5)), it says that the expression string is "x == 5))", so we may need to // adjust where we prepend "return".