Skip to content

Commit e8bacd2

Browse files
committed
Merge rc/1.20 into rc/1.21.
2 parents bed1b74 + e0e6224 commit e8bacd2

File tree

1 file changed

+72
-7
lines changed

1 file changed

+72
-7
lines changed

javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,21 @@
3333
import java.io.OutputStreamWriter;
3434
import java.lang.ProcessBuilder.Redirect;
3535
import java.util.ArrayList;
36+
import java.util.Arrays;
37+
import java.util.Collections;
3638
import java.util.List;
3739

3840
/**
3941
* The Java half of our wrapper for invoking the TypeScript parser.
4042
*
4143
* <p>The Node.js half of the wrapper is expected to live at {@code
4244
* $SEMMLE_DIST/tools/typescript-parser-wrapper/main.js}; non-standard locations can be configured
43-
* using the property {@link #PARSER_WRAPPER_PATH_ENV_VAR}.
45+
* using the property {@value #PARSER_WRAPPER_PATH_ENV_VAR}.
46+
*
47+
* <p>The script launches the Node.js wrapper in the Node.js runtime, looking for {@code node}
48+
* on the {@code PATH} by default. Non-standard locations can be configured using the property
49+
* {@value #TYPESCRIPT_NODE_RUNTIME_VAR}, and additional arguments can be configured using the
50+
* property {@value #TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS_VAR}.
4451
*
4552
* <p>The script is started upon parsing the first TypeScript file and then is kept running in the
4653
* background, passing it requests for parsing files and getting JSON-encoded ASTs as responses.
@@ -52,6 +59,18 @@ public class TypeScriptParser {
5259
*/
5360
public static final String PARSER_WRAPPER_PATH_ENV_VAR = "SEMMLE_TYPESCRIPT_PARSER_WRAPPER";
5461

62+
/**
63+
* An environment variable that can be set to indicate the ___location of the Node.js runtime,
64+
* as an alternative to adding Node to the PATH.
65+
*/
66+
public static final String TYPESCRIPT_NODE_RUNTIME_VAR = "SEMMLE_TYPESCRIPT_NODE_RUNTIME";
67+
68+
/**
69+
* An environment variable that can be set to provide additional arguments to the Node.js runtime
70+
* each time it is invoked. Arguments should be separated by spaces.
71+
*/
72+
public static final String TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS_VAR = "SEMMLE_TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS";
73+
5574
/**
5675
* An environment variable that can be set to specify a timeout to use when verifying the
5776
* TypeScript installation, in milliseconds. Default is 10000.
@@ -91,6 +110,15 @@ public class TypeScriptParser {
91110

92111
private String nodeJsVersionString;
93112

113+
/** Command to launch the Node.js runtime. Initialised by {@link #verifyNodeInstallation}. */
114+
private String nodeJsRuntime;
115+
116+
/**
117+
* Arguments to pass to the Node.js runtime each time it is invoked.
118+
* Initialised by {@link #verifyNodeInstallation}.
119+
*/
120+
private List<String> nodeJsRuntimeExtraArgs = Collections.emptyList();
121+
94122
/** If non-zero, we use this instead of relying on the corresponding environment variable. */
95123
private int typescriptRam = 0;
96124

@@ -102,12 +130,16 @@ public void setTypescriptRam(int megabytes) {
102130
/**
103131
* Verifies that Node.js and TypeScript are installed and throws an exception otherwise.
104132
*
105-
* @param verbose if true, log the version strings and NODE_PATH.
133+
* @param verbose if true, log the Node.js executable path, version strings, and any additional arguments.
106134
*/
107135
public void verifyInstallation(boolean verbose) {
108136
verifyNodeInstallation();
109137
if (verbose) {
138+
System.out.println("Found Node.js at: " + nodeJsRuntime);
110139
System.out.println("Found Node.js version: " + nodeJsVersionString);
140+
if (!nodeJsRuntimeExtraArgs.isEmpty()) {
141+
System.out.println("Additional arguments for Node.js: " + nodeJsRuntimeExtraArgs);
142+
}
111143
}
112144
}
113145

@@ -117,7 +149,24 @@ public String verifyNodeInstallation() {
117149

118150
ByteArrayOutputStream out = new ByteArrayOutputStream();
119151
ByteArrayOutputStream err = new ByteArrayOutputStream();
120-
Builder b = new Builder(out, err, getParserWrapper().getParentFile(), "node", "--version");
152+
153+
// Determine where to find the Node.js runtime.
154+
String explicitNodeJsRuntime = Env.systemEnv().get(TYPESCRIPT_NODE_RUNTIME_VAR);
155+
if (explicitNodeJsRuntime != null) {
156+
// Use the specified Node.js executable.
157+
nodeJsRuntime = explicitNodeJsRuntime;
158+
} else {
159+
// Look for `node` on the PATH.
160+
nodeJsRuntime = "node";
161+
}
162+
163+
// Determine any additional arguments to be passed to Node.js each time it's called.
164+
String extraArgs = Env.systemEnv().get(TYPESCRIPT_NODE_RUNTIME_EXTRA_ARGS_VAR);
165+
if (extraArgs != null) {
166+
nodeJsRuntimeExtraArgs = Arrays.asList(extraArgs.split("\\s+"));
167+
}
168+
169+
Builder b = new Builder(getNodeJsRuntimeInvocation("--version"), out, err, getParserWrapper().getParentFile());
121170
b.expectFailure(); // We want to do our own logging in case of an error.
122171

123172
int timeout = Env.systemEnv().getInt(TYPESCRIPT_TIMEOUT_VAR, 10000);
@@ -144,6 +193,21 @@ public String verifyNodeInstallation() {
144193
}
145194
}
146195

196+
/**
197+
* Gets a command line to invoke the Node.js runtime.
198+
* Any arguments in {@link TypeScriptParser#nodeJsRuntimeExtraArgs}
199+
* are passed first, followed by those in {@code args}.
200+
*/
201+
private List<String> getNodeJsRuntimeInvocation(String ...args) {
202+
List<String> result = new ArrayList<>();
203+
result.add(nodeJsRuntime);
204+
result.addAll(nodeJsRuntimeExtraArgs);
205+
for(String arg : args) {
206+
result.add(arg);
207+
}
208+
return result;
209+
}
210+
147211
private static int getMegabyteCountFromPrefixedEnv(String suffix, int defaultValue) {
148212
String envVar = "SEMMLE_" + suffix;
149213
String value = Env.systemEnv().get(envVar);
@@ -172,10 +236,11 @@ private void setupParserWrapper() {
172236
int reserveMemoryMb = getMegabyteCountFromPrefixedEnv(TYPESCRIPT_RAM_RESERVE_SUFFIX, 400);
173237

174238
File parserWrapper = getParserWrapper();
175-
List<String> cmd = new ArrayList<>();
176-
cmd.add("node");
177-
cmd.add("--max_old_space_size=" + (mainMemoryMb + reserveMemoryMb));
178-
cmd.add(parserWrapper.getAbsolutePath());
239+
240+
List<String> cmd = getNodeJsRuntimeInvocation(
241+
"--max_old_space_size=" + (mainMemoryMb + reserveMemoryMb),
242+
parserWrapper.getAbsolutePath()
243+
);
179244
ProcessBuilder pb = new ProcessBuilder(cmd);
180245
parserWrapperCommand = StringUtil.glue(" ", cmd);
181246
pb.environment().put("SEMMLE_TYPESCRIPT_MEMORY_THRESHOLD", "" + mainMemoryMb);

0 commit comments

Comments
 (0)