diff --git a/javascript/extractor/lib/typescript/README.md b/javascript/extractor/lib/typescript/README.md new file mode 100644 index 00000000000..998cec250aa --- /dev/null +++ b/javascript/extractor/lib/typescript/README.md @@ -0,0 +1,18 @@ +TypeScript parser wrapper +------------------------- + +The TypeScript "parser wrapper" is a Node.js program launched from the JavaScript +extractor in order to extract TypeScript code. + +The two processes communicate via a command/response protocol via stdin/stdout. + +Debugging +--------- + +To debug the parser script: + +1. Launch an extraction process with the environment variable `SEMMLE_TYPESCRIPT_NODE_FLAGS` + set to `--inspect`, or `--inspect-brk` if you wish to pause on entry. + +2. Open VSCode and choose "Debug: Attach to Node process" from the command palette, and + choose the process that looks like the parser-wrapper. diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java index f798fc297a5..452b2e22eaf 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java @@ -1,6 +1,21 @@ package com.semmle.js.parser; -import ch.qos.logback.classic.Level; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.lang.ProcessBuilder.Redirect; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -21,21 +36,8 @@ import com.semmle.util.logging.LogbackUtils; import com.semmle.util.process.AbstractProcessBuilder; import com.semmle.util.process.Builder; import com.semmle.util.process.Env; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.lang.ProcessBuilder.Redirect; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; + +import ch.qos.logback.classic.Level; /** * The Java half of our wrapper for invoking the TypeScript parser. @@ -98,6 +100,13 @@ public class TypeScriptParser { */ public static final String TYPESCRIPT_RAM_RESERVE_SUFFIX = "TYPESCRIPT_RAM_RESERVE"; + /** + * An environment variable with additional VM arguments to pass to the Node process. + *

+ * Only --inspect or --inspect-brk may be used at the moment. + */ + public static final String TYPESCRIPT_NODE_FLAGS = "SEMMLE_TYPESCRIPT_NODE_FLAGS"; + /** The Node.js parser wrapper process, if it has been started already. */ private Process parserWrapperProcess; @@ -236,11 +245,24 @@ public class TypeScriptParser { int reserveMemoryMb = getMegabyteCountFromPrefixedEnv(TYPESCRIPT_RAM_RESERVE_SUFFIX, 400); File parserWrapper = getParserWrapper(); - - List cmd = getNodeJsRuntimeInvocation( - "--max_old_space_size=" + (mainMemoryMb + reserveMemoryMb), - parserWrapper.getAbsolutePath() - ); + + String debugFlagString = Env.systemEnv().getNonEmpty(TYPESCRIPT_NODE_FLAGS); + List debugFlags = new ArrayList<>(); + if (debugFlagString != null) { + for (String flag : debugFlagString.split(" ")) { + if (!flag.startsWith("--inspect") || flag.contains(":")) { + System.err.println("Ignoring unrecognized Node flag: '" + flag + "'"); + } else { + debugFlags.add(flag); + } + } + } + + List cmd = getNodeJsRuntimeInvocation(); + cmd.add("--max_old_space_size=" + (mainMemoryMb + reserveMemoryMb)); + cmd.addAll(debugFlags); + cmd.add(parserWrapper.getAbsolutePath()); + ProcessBuilder pb = new ProcessBuilder(cmd); parserWrapperCommand = StringUtil.glue(" ", cmd); pb.environment().put("SEMMLE_TYPESCRIPT_MEMORY_THRESHOLD", "" + mainMemoryMb);