anchor.diff:            "Output mismatch at line $failureLine in "
             "file '${fileName}' of type ${outputType}.");
       });
  -  });
  +  }
  +
  +  expectedOutput.forEach(check);
  +}
  +
  +runTest(
  +    {Uri entryPoint,
  +    Map<String, String> memorySourceFiles: const <String, String>{},
  +    Uri packageConfig,
  +    Uri librariesSpecificationUri,
  +    List<String> options,
  +    SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
  +    bool useDataKinds: false}) async {
  +  OutputCollector collector = new OutputCollector();
  +  CompilationResult result = await runCompiler(
  +      entryPoint: entryPoint,
  +      memorySourceFiles: memorySourceFiles,
  +      packageConfig: packageConfig,
  +      librariesSpecificationUri: librariesSpecificationUri,
  +      options: options,
  +      outputProvider: collector,
  +      beforeRun: (Compiler compiler) {
  +        compiler.kernelLoader.forceSerialization = true;
  +      });
  +  Expect.isTrue(result.isSuccess);
  +  Map<OutputType, Map<String, String>> expectedOutput = collector.clear();
  +
  +  OutputCollector collector2 = new OutputCollector();
  +  CompilationResult result2 = await runCompiler(
  +      entryPoint: entryPoint,
  +      memorySourceFiles: memorySourceFiles,
  +      packageConfig: packageConfig,
  +      librariesSpecificationUri: librariesSpecificationUri,
  +      options: options,
  +      outputProvider: collector2,
  +      beforeRun: (Compiler compiler) {
  +        compiler.kernelLoader.forceSerialization = true;
  +        compiler.stopAfterClosedWorld = true;
  +      });
  +  Expect.isTrue(result2.isSuccess);
  +
  +  OutputCollector collector3 = new OutputCollector();
  +  CompilationResult result3 = await runCompiler(
  +      entryPoint: entryPoint,
  +      memorySourceFiles: memorySourceFiles,
  +      packageConfig: packageConfig,
  +      librariesSpecificationUri: librariesSpecificationUri,
  +      options: options,
  +      outputProvider: collector3,
  +      beforeRun: (Compiler compiler) {
  +        compiler.kernelLoader.forceSerialization = true;
  +        compiler.stopAfterTypeInference = true;
  +      });
  +  Expect.isTrue(result3.isSuccess);
  +
  +  finishCompileAndCompare(
  +      expectedOutput, collector2, result2.compiler, strategy,
  +      stoppedAfterClosedWorld: true);
  +  finishCompileAndCompare(
  +      expectedOutput, collector3, result3.compiler, strategy,
  +      stoppedAfterTypeInference: true);
  +}
  +
  +void checkData(List<int> data, List<int> newData) {
  +  Expect.equals(
  +      data.length, newData.length, "Reserialization data length mismatch.");
  +  for (int i = 0; i < data.length; i++) {
  +    if (data[i] != newData[i]) {
  +      print('Reserialization data mismatch at offset $i:');
  +      for (int j = i - 50; j < i + 50; j++) {
  +        if (0 <= j && j <= data.length) {
  +          String text;
  +          if (data[j] == newData[j]) {
  +            text = '${data[j]}';
  +          } else {
  +            text = '${data[j]} <> ${newData[j]}';
  +          }
  +          print('${j == i ? '> ' : '  '}$j: $text');
  +        }
  +      }
  +      break;
  +    }
  +  }
  +  Expect.listEquals(data, newData);
  +}
  +
  +JsClosedWorld cloneClosedWorld(Compiler compiler, JsClosedWorld closedWorld,
  +    SerializationStrategy strategy) {
  +  ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
  +  List<int> irData = strategy.serializeComponent(component);
  +  List<int> closedWorldData = strategy.serializeClosedWorld(closedWorld);
  +  print('data size: ${closedWorldData.length}');
  +
  +  ir.Component newComponent = strategy.deserializeComponent(irData);
  +  JsClosedWorld newClosedWorld = strategy.deserializeClosedWorld(
  +      compiler.options,
  +      compiler.reporter,
  +      compiler.environment,
  +      compiler.abstractValueStrategy,
  +      newComponent,
  +      closedWorldData);
  +  List<int> newClosedWorldData = strategy.serializeClosedWorld(newClosedWorld);
  +  checkData(closedWorldData, newClosedWorldData);
  +  return newClosedWorld;
   }
   
   GlobalTypeInferenceResults cloneInferenceResults(Compiler compiler,
       GlobalTypeInferenceResults results, SerializationStrategy strategy) {
     List<int> irData = strategy.unpackAndSerializeComponent(results);
   
  -  List worldData = strategy.serializeGlobalTypeInferenceResults(results);
  +  List<int> worldData = strategy.serializeGlobalTypeInferenceResults(results);
     print('data size: ${worldData.length}');
   
     ir.Component newComponent = strategy.deserializeComponent(irData);
  
positive.code:   '"toJsonDuration":'
  ];
  
  runTest(
      {Uri entryPoint,
      Map<String, String> memorySourceFiles: const <String, String>{},
      Uri packageConfig,
      Uri librariesSpecificationUri,
      List<String> options,
      SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
      bool useDataKinds: false}) async {
    OutputCollector collector1 = new OutputCollector();
    CompilationResult result1 = await runCompiler(
        entryPoint: entryPoint,
        memorySourceFiles: memorySourceFiles,
        packageConfig: packageConfig,
        librariesSpecificationUri: librariesSpecificationUri,
        options: options,
        outputProvider: collector1,
        beforeRun: (Compiler compiler) {
          compiler.kernelLoader.forceSerialization = true;
        });
    Expect.isTrue(result1.isSuccess);
  
    OutputCollector collector2 = new OutputCollector();
    CompilationResult result = await runCompiler(
        entryPoint: entryPoint,
        memorySourceFiles: memorySourceFiles,
        packageConfig: packageConfig,
        librariesSpecificationUri: librariesSpecificationUri,
        options: options,
        outputProvider: collector2,
        beforeRun: (Compiler compiler) {
          compiler.kernelLoader.forceSerialization = true;
          compiler.stopAfterTypeInference = true;
        });
    Expect.isTrue(result.isSuccess);
    Compiler compiler = result.compiler;
    GlobalTypeInferenceResults globalInferenceResults =
        compiler.globalInference.resultsForTesting;
    GlobalTypeInferenceResults newGlobalInferenceResults =
        cloneInferenceResults(compiler, globalInferenceResults, strategy);
  
    Map<OutputType, Map<String, String>> output = collector1.clear();
  
    compiler.generateJavaScriptCode(newGlobalInferenceResults);
    Map<OutputType, Map<String, String>> newOutput = collector2.clear();
  
    Expect.setEquals(output.keys, newOutput.keys, "Output type mismatch.");
  
    output.forEach((OutputType outputType, Map<String, String> fileMap) {
      Map<String, String> newFileMap = newOutput[outputType];
      Expect.setEquals(fileMap.keys, newFileMap.keys,
          "File mismatch for output type $outputType.");
      fileMap.forEach((String fileName, String code) {
  
negative.code: 
  import 'package:compiler/compiler_new.dart';
  import 'package:compiler/src/compiler.dart';
  import 'package:compiler/src/js_model/js_world.dart';
  import 'package:compiler/src/inferrer/types.dart';
  import 'package:compiler/src/serialization/strategies.dart';
  import 'package:expect/expect.dart';
  