diff --git a/lib/init/eval.js b/lib/init/eval.js index 0f3f6fd1..064a89a1 100644 --- a/lib/init/eval.js +++ b/lib/init/eval.js @@ -239,7 +239,7 @@ function compile(code, tracker, filename, isIndirectEval, state, isStrict) { } // Return instrumented code - code = generate(ast, {retainLines: true, compact: true}).code; + code = generateCode(ast); // eslint-disable-line no-use-before-define if (DEBUG) { /* eslint-disable no-console */ @@ -260,11 +260,8 @@ function wrapInFunction(ast, internalPrefixNum) { internalVarNode(TRACKER_VAR_NAME_BODY, internalPrefixNum), internalVarNode(GET_SCOPE_ID_VAR_NAME_BODY, internalPrefixNum) ], - t.callExpression( - t.identifier('eval'), [ - t.stringLiteral(generate(ast, {retainLines: true, compact: true}).code) - ] - ) + // eslint-disable-next-line no-use-before-define + t.callExpression(t.identifier('eval'), [generateCodeStringNode(ast)]) ); } @@ -281,3 +278,28 @@ function wrapInFunctionCall(fnNode, externalPrefixNum) { function internalVarNode(name, prefixNum) { return t.identifier(`${INTERNAL_VAR_NAMES_PREFIX}${prefixNum || ''}_${name}`); } + +/** + * Generate code from AST. + * If debugging enabled, generates in a more readable form. + * @param {Object} ast - AST + * @returns {string} - Generated code + */ +const generateCode = DEBUG + ? ast => generate(ast).code + : ast => generate(ast, {retainLines: true, compact: true}).code; + +/** + * Generate a string literal AST node for a string of code generated from AST. + * If debugging enabled, generates a template literal instead with line breaks retained + * for greater readability. + * @param {Object} ast - AST + * @returns {Object} - String literal / template literal AST node + */ +const generateCodeStringNode = DEBUG + ? ast => t.templateLiteral([ + t.templateElement({ + raw: `\n${generateCode(ast).replace(/\\/g, '\\\\').replace(/`/g, '\\`')}\n` + }, true) + ], []) + : ast => t.stringLiteral(generateCode(ast));