Skip to content

Commit 1f2cf2a

Browse files
lauraharkercopybara-github
authored andcommitted
Gzip the result of CompilerOptions::setTypedAstOutputFile
PiperOrigin-RevId: 515467692
1 parent 84b8137 commit 1f2cf2a

File tree

5 files changed

+36
-22
lines changed

5 files changed

+36
-22
lines changed

src/com/google/javascript/jscomp/AbstractCommandLineRunner.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import java.util.Map;
8484
import java.util.Set;
8585
import java.util.logging.Level;
86+
import java.util.zip.GZIPInputStream;
8687
import java.util.zip.ZipEntry;
8788
import java.util.zip.ZipInputStream;
8889
import org.jspecify.nullness.Nullable;
@@ -142,6 +143,8 @@ public abstract class AbstractCommandLineRunner<A extends Compiler, B extends Co
142143
+ "%outname% in the value.");
143144

144145
static final String WAITING_FOR_INPUT_WARNING = "The compiler is waiting for input via stdin.";
146+
// Use an 8MiB buffer since the concatenated TypedAst file can be very large.
147+
private static final int GZIPPED_TYPEDAST_BUFFER_SIZE = 8 * 1024 * 1024;
145148

146149
@GwtIncompatible("Unnecessary")
147150
private final CommandLineConfig config;
@@ -1417,8 +1420,8 @@ private void initWithTypedAstFilesystem(
14171420
List<SourceFile> sources,
14181421
CompilerOptions options,
14191422
String filename) {
1420-
try (BufferedInputStream typedAstListStream =
1421-
new BufferedInputStream(new FileInputStream(filename))) {
1423+
try (GZIPInputStream typedAstListStream =
1424+
new GZIPInputStream(new FileInputStream(filename), GZIPPED_TYPEDAST_BUFFER_SIZE)) {
14221425
compiler.initWithTypedAstFilesystem(externs, sources, options, typedAstListStream);
14231426
} catch (IOException e) {
14241427
compiler.report(JSError.make(COULD_NOT_DESERIALIZE_AST, filename));
@@ -1428,8 +1431,8 @@ private void initWithTypedAstFilesystem(
14281431
@GwtIncompatible("Unnecessary")
14291432
private void initModulesWithTypedAstFilesystem(
14301433
List<SourceFile> externs, List<JSChunk> chunks, CompilerOptions options, String filename) {
1431-
try (BufferedInputStream typedAstListStream =
1432-
new BufferedInputStream(new FileInputStream(filename))) {
1434+
try (GZIPInputStream typedAstListStream =
1435+
new GZIPInputStream(new FileInputStream(filename), GZIPPED_TYPEDAST_BUFFER_SIZE)) {
14331436
compiler.initModulesWithTypedAstFilesystem(externs, chunks, options, typedAstListStream);
14341437
} catch (IOException e) {
14351438
compiler.report(JSError.make(COULD_NOT_DESERIALIZE_AST, filename));

src/com/google/javascript/jscomp/CompilerOptions.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,11 @@ public boolean getInstrumentForCoverageOnly() {
210210

211211
private @Nullable Path typedAstOutputFile = null;
212212

213-
/** Sets file to output in-progress TypedAST format to. DO NOT USE! */
213+
/**
214+
* Sets file to output in-progress TypedAST format to. DO NOT USE!
215+
*
216+
* <p>The "TypedAST format" is currently a gzipped TypedAst proto but this is not stable.
217+
*/
214218
public void setTypedAstOutputFile(@Nullable Path file) {
215219
this.typedAstOutputFile = file;
216220
}

src/com/google/javascript/jscomp/serialization/SerializeTypedAstPass.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.nio.file.Files;
2626
import java.nio.file.Path;
2727
import java.util.function.Consumer;
28+
import java.util.zip.GZIPOutputStream;
2829

2930
/**
3031
* A compiler pass intended to serialize the types in the AST.
@@ -41,6 +42,12 @@ public final class SerializeTypedAstPass implements CompilerPass {
4142
this.consumer = astConsumer;
4243
}
4344

45+
/**
46+
* Serializes a TypedAst to the given output stream.
47+
*
48+
* <p>Unlike {@link #createFromPath(AbstractCompiler, Path)}, this method does not automatically
49+
* gzip the TypedAST. The "out" parameter may or may not already be a GZIPOutputStream.
50+
*/
4451
public static SerializeTypedAstPass createFromOutputStream(AbstractCompiler c, OutputStream out) {
4552
Consumer<TypedAst> toOutputStream =
4653
ast -> {
@@ -53,10 +60,11 @@ public static SerializeTypedAstPass createFromOutputStream(AbstractCompiler c, O
5360
return new SerializeTypedAstPass(c, toOutputStream);
5461
}
5562

63+
/** Serializes a gzipped TypedAst to the specified outputPath */
5664
public static SerializeTypedAstPass createFromPath(AbstractCompiler compiler, Path outputPath) {
5765
Consumer<TypedAst> toPath =
5866
ast -> {
59-
try (OutputStream out = Files.newOutputStream(outputPath)) {
67+
try (OutputStream out = new GZIPOutputStream(Files.newOutputStream(outputPath))) {
6068
TypedAst.List.newBuilder().addTypedAsts(ast).build().writeTo(out);
6169
} catch (IOException e) {
6270
throw new IllegalArgumentException("Cannot create TypedAst output file", e);

src/com/google/javascript/jscomp/serialization/TypedAstDeserializer.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,11 @@ private static void deserializeTypedAsts(
401401
int tag = codedInput.readTag();
402402
if (WireFormat.getTagFieldNumber(tag) != TypedAst.List.TYPED_ASTS_FIELD_NUMBER
403403
|| WireFormat.getTagWireType(tag) != WireFormat.WIRETYPE_LENGTH_DELIMITED) {
404-
throw new InvalidProtocolBufferException("Unexpected tag " + tag);
404+
throw new InvalidProtocolBufferException(
405+
"Unexpected field number "
406+
+ WireFormat.getTagFieldNumber(tag)
407+
+ " or wire type "
408+
+ WireFormat.getTagWireType(tag));
405409
}
406410
codedInput.readMessage(typedAstBuilder, ExtensionRegistry.getEmptyRegistry());
407411
TypedAst typedAst = typedAstBuilder.build();

test/com/google/javascript/jscomp/integration/TypedAstIntegrationTest.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@
4343
import com.google.javascript.rhino.Node;
4444
import com.google.javascript.rhino.StaticSourceFile.SourceKind;
4545
import java.io.FileInputStream;
46-
import java.io.FileNotFoundException;
4746
import java.io.IOException;
4847
import java.io.InputStream;
4948
import java.io.SequenceInputStream;
5049
import java.nio.file.Files;
5150
import java.nio.file.Path;
5251
import java.util.ArrayList;
52+
import java.util.Collections;
53+
import java.util.zip.GZIPInputStream;
5354
import org.junit.Before;
5455
import org.junit.Test;
5556
import org.junit.runner.RunWith;
@@ -739,22 +740,16 @@ private void precompileLibrary(SourceFile... files) throws IOException {
739740
}
740741

741742
/** Converts the list of paths into an input stream sequentially reading all the given files */
742-
private static InputStream toInputStream(ArrayList<Path> typedAsts) {
743-
InputStream inputStream = null;
743+
private static InputStream toInputStream(ArrayList<Path> typedAsts) throws IOException {
744+
ArrayList<InputStream> inputShards = new ArrayList<>();
744745
for (Path typedAst : typedAsts) {
745-
FileInputStream inputShard;
746-
try {
747-
inputShard = new FileInputStream(typedAst.toFile());
748-
} catch (FileNotFoundException ex) {
749-
throw new AssertionError(ex);
750-
}
751-
if (inputStream == null) {
752-
inputStream = inputShard;
753-
} else {
754-
inputStream = new SequenceInputStream(inputStream, inputShard);
755-
}
746+
// Each shard is a gzipped TypedAst proto.
747+
// NOTE: while it's generally possible to concatenate individually gzipped files
748+
// (https://stackoverflow.com/questions/8005114/fast-concatenation-of-multiple-gzip-files)
749+
// it doesn't seem to work to wrap a SequenceInputStream in a GZIPInputStream directly.
750+
inputShards.add(new GZIPInputStream(new FileInputStream(typedAst.toFile())));
756751
}
757-
return inputStream;
752+
return new SequenceInputStream(Collections.enumeration(inputShards));
758753
}
759754

760755
private Node parseExpectedCode(String... files) {

0 commit comments

Comments
 (0)