24
24
import static java .nio .charset .StandardCharsets .UTF_8 ;
25
25
26
26
import com .google .common .collect .ImmutableList ;
27
+ import com .google .common .collect .ImmutableMap ;
27
28
import com .google .common .collect .ImmutableSet ;
28
29
import com .google .javascript .jscomp .AbstractCompiler ;
29
30
import com .google .javascript .jscomp .AstValidator ;
34
35
import com .google .javascript .jscomp .SourceFile ;
35
36
import com .google .javascript .jscomp .colors .ColorRegistry ;
36
37
import com .google .javascript .jscomp .colors .StandardColors ;
38
+ import com .google .javascript .jscomp .parsing .parser .FeatureSet ;
37
39
import com .google .javascript .jscomp .serialization .TypedAstDeserializer .DeserializedAst ;
38
40
import com .google .javascript .rhino .IR ;
39
41
import com .google .javascript .rhino .InputId ;
@@ -76,6 +78,7 @@ public final class SerializeAndDeserializeAstTest extends CompilerTestCase {
76
78
private boolean parseInlineSourceMaps ;
77
79
private ImmutableList <String > runtimeLibraries = null ;
78
80
private Optional <PassFactory > preSerializePassFactory = Optional .empty ();
81
+ private boolean skipMatchingScriptFeaturesBeforeAndAfterSerialization = false ;
79
82
80
83
@ Override
81
84
protected CompilerPass getProcessor (Compiler compiler ) {
@@ -236,11 +239,13 @@ public void testCollapsePropertiesJsdoc() {
236
239
237
240
@ Test
238
241
public void testEmptyClassDeclaration () {
242
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
239
243
testSame ("class Foo {}" );
240
244
}
241
245
242
246
@ Test
243
247
public void testEmptyClassDeclarationWithExtends () {
248
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
244
249
testSame ("class Foo {} class Bar extends Foo {}" );
245
250
}
246
251
@@ -264,6 +269,7 @@ public void testClassDeclarationWithMethods() {
264
269
265
270
@ Test
266
271
public void testClassDeclarationWithFields () {
272
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
267
273
testSame (lines ("class Foo {" , " a = 1;" , " d;" , "}" ));
268
274
269
275
// Type checking will report computed property accesses as errors for a class,
@@ -283,6 +289,7 @@ public void testClassDeclarationWithFields() {
283
289
284
290
@ Test
285
291
public void testEmptyClassStaticBlock () {
292
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
286
293
testSame (
287
294
lines (
288
295
"class Foo {" , //
@@ -293,6 +300,7 @@ public void testEmptyClassStaticBlock() {
293
300
294
301
@ Test
295
302
public void testClassStaticBlock_variables () {
303
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
296
304
testSame (
297
305
lines (
298
306
"class Foo {" , //
@@ -306,6 +314,7 @@ public void testClassStaticBlock_variables() {
306
314
307
315
@ Test
308
316
public void testClassStaticBlock_function () {
317
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
309
318
testSame (
310
319
lines (
311
320
"class Foo {" , //
@@ -318,6 +327,7 @@ public void testClassStaticBlock_function() {
318
327
319
328
@ Test
320
329
public void testMultipleClassStaticBlocks () {
330
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
321
331
testSame (
322
332
lines (
323
333
"class Foo {" , //
@@ -372,11 +382,13 @@ public void testYieldAll() {
372
382
373
383
@ Test
374
384
public void testFunctionCallRestAndSpread () {
385
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
375
386
testSame ("function f(...x) {} f(...[1, 2, 3]);" );
376
387
}
377
388
378
389
@ Test
379
390
public void testFunctionDefaultAndDestructuringParameters () {
391
+ skipMatchingScriptFeaturesBeforeAndAfterSerialization = true ;
380
392
testSame ("function f([a, b], x = 0, {y, ...z} = {y: 1}) {}" );
381
393
}
382
394
@@ -806,10 +818,10 @@ private Result testAndReturnResult(Externs externs, Sources code, Expected expec
806
818
InputStream serializedStream = toInputStream (externs , code , expected );
807
819
Compiler serializingCompiler = getLastCompiler ();
808
820
809
- ImmutableList < SourceFile > externFiles =
810
- collectSourceFilesFromScripts ( serializingCompiler . getRoot (). getFirstChild ());
811
- ImmutableList <SourceFile > codeFiles =
812
- collectSourceFilesFromScripts (serializingCompiler . getRoot () .getSecondChild ());
821
+ Node oldRoot = serializingCompiler . getRoot ();
822
+
823
+ ImmutableList <SourceFile > externFiles = collectSourceFilesFromScripts ( oldRoot . getFirstChild ());
824
+ ImmutableList < SourceFile > codeFiles = collectSourceFilesFromScripts (oldRoot .getSecondChild ());
813
825
814
826
// NOTE: We need a fresh compiler instance in which to deserialize, because:
815
827
// 1. This is a better representation of what will happen in production use.
@@ -854,12 +866,54 @@ private Result testAndReturnResult(Externs externs, Sources code, Expected expec
854
866
855
867
Node expectedRoot = this .parseExpectedJs (expected );
856
868
assertNode (newSourceRoot ).isEqualIncludingJsDocTo (expectedRoot );
869
+ Node newRoot = IR .root (newExternsRoot , newSourceRoot );
870
+
857
871
new AstValidator (deserializingCompiler , /* validateScriptFeatures= */ true )
858
- .validateRoot (IR .root (newExternsRoot , newSourceRoot ));
872
+ .validateRoot (newRoot );
873
+
874
+ // TODO(b/394454662): Remove this condition once feature set with deserialization and parser are
875
+ // in sync.
876
+ if (!skipMatchingScriptFeaturesBeforeAndAfterSerialization ) {
877
+ assertFeatureSetsOfScriptsMatch (oldRoot , newRoot );
878
+ }
879
+
859
880
consumer = null ;
860
881
return new Result (ast , registry , newSourceRoot , deserializingCompiler );
861
882
}
862
883
884
+ private void assertFeatureSetsOfScriptsMatch (Node oldRoot , Node newRoot ) {
885
+ ImmutableMap <SourceFile , FeatureSet > featureSetsOfOldScripts = getFeatureSetsOfScripts (oldRoot );
886
+ ImmutableMap <SourceFile , FeatureSet > featureSetsOfNewScripts = getFeatureSetsOfScripts (newRoot );
887
+ assertThat (featureSetsOfNewScripts .keySet ()).isEqualTo (featureSetsOfOldScripts .keySet ());
888
+ for (SourceFile sourceFile : featureSetsOfOldScripts .keySet ()) {
889
+ FeatureSet oldFeatureSet = featureSetsOfOldScripts .get (sourceFile );
890
+ FeatureSet newFeatureSet = featureSetsOfNewScripts .get (sourceFile );
891
+ checkState (
892
+ oldFeatureSet .equals (newFeatureSet ),
893
+ "Feature sets of scripts do not match for file %s. Old: %s, New: %s" ,
894
+ sourceFile .getName (),
895
+ oldFeatureSet ,
896
+ newFeatureSet );
897
+ }
898
+ }
899
+
900
+ private ImmutableMap <SourceFile , FeatureSet > getFeatureSetsOfScripts (Node root ) {
901
+ ImmutableMap .Builder <SourceFile , FeatureSet > builder = ImmutableMap .builder ();
902
+ Node externsRoot = root .getFirstChild ();
903
+ Node sourceRoot = root .getSecondChild ();
904
+ for (Node script = externsRoot .getFirstChild (); script != null ; script = script .getNext ()) {
905
+ checkState (script .isScript ());
906
+ builder .put (
907
+ (SourceFile ) script .getStaticSourceFile (), (FeatureSet ) script .getProp (Node .FEATURE_SET ));
908
+ }
909
+ for (Node script = sourceRoot .getFirstChild (); script != null ; script = script .getNext ()) {
910
+ checkState (script .isScript ());
911
+ builder .put (
912
+ (SourceFile ) script .getStaticSourceFile (), (FeatureSet ) script .getProp (Node .FEATURE_SET ));
913
+ }
914
+ return builder .buildOrThrow ();
915
+ }
916
+
863
917
private ImmutableList <SourceFile > collectSourceFilesFromScripts (Node root ) {
864
918
ImmutableList .Builder <SourceFile > files = ImmutableList .builder ();
865
919
for (Node n = root .getFirstChild (); n != null ; n = n .getNext ()) {
0 commit comments