Skip to content

Commit f610946

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Verify RequirementsManifest serialization round-trip.
Add `assertSerialization()` to `RequirementsManifest` to perform a byte-for-byte round trip (write -> read -> write) and ensure a canonical binary form. Insert debug assertions in the analysis driver and library context to validate manifests after updates when fine-grained dependencies are used. Import `dart:typed_data` and `package:collection/collection.dart` for serialization buffers and byte list equality. Motivation: enforce deterministic encoding to stabilize caches and dependency signatures. No effect in release builds (asserts stripped). Change-Id: I1f3b6342df8688c7cae00cf61634efe0cfd7c44a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444500 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent ed1d4a5 commit f610946

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,7 @@ class AnalysisDriver {
13831383
}
13841384

13851385
if (withFineDependencies) {
1386+
assert(requirements!.assertSerialization());
13861387
globalResultRequirements = null;
13871388
}
13881389

pkg/analyzer/lib/src/dart/analysis/library_context.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ class LibraryContext {
298298
);
299299
globalResultRequirements = null;
300300
requirements.removeReqForLibs(cycle.libraryUris);
301+
assert(requirements.assertSerialization());
301302

302303
bundleEntry = LinkedBundleEntry(
303304
apiSignature: cycle.nonTransitiveApiSignature,

pkg/analyzer/lib/src/fine/requirements.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:typed_data';
6+
57
import 'package:analyzer/dart/element/element.dart';
68
import 'package:analyzer/src/dart/element/element.dart';
79
import 'package:analyzer/src/dart/resolver/scope.dart';
@@ -13,6 +15,7 @@ import 'package:analyzer/src/fine/requirement_failure.dart';
1315
import 'package:analyzer/src/summary2/data_reader.dart';
1416
import 'package:analyzer/src/summary2/data_writer.dart';
1517
import 'package:analyzer/src/summary2/linked_element_factory.dart';
18+
import 'package:collection/collection.dart';
1619
import 'package:meta/meta.dart';
1720

1821
/// When using fine-grained dependencies, this variable might be set to
@@ -413,6 +416,31 @@ class RequirementsManifest {
413416
}
414417
}
415418

419+
/// Checks that this manifest can be written and read back without any
420+
/// changes, and that the binary form is exactly the same each time.
421+
///
422+
/// Used in `assert()` during debug runs to catch serialization issues.
423+
///
424+
/// Returns `true` if everything matches. Throws [StateError] if not.
425+
bool assertSerialization() {
426+
Uint8List manifestAsBytes(RequirementsManifest manifest) {
427+
var sink = BufferedSink();
428+
manifest.write(sink);
429+
return sink.takeBytes();
430+
}
431+
432+
var bytes = manifestAsBytes(this);
433+
434+
var readManifest = RequirementsManifest.read(SummaryDataReader(bytes));
435+
var bytes2 = manifestAsBytes(readManifest);
436+
437+
if (!const ListEquality<int>().equals(bytes, bytes2)) {
438+
throw StateError('Requirement manifest bytes are different.');
439+
}
440+
441+
return true;
442+
}
443+
416444
/// Returns the first unsatisfied requirement, or `null` if all requirements
417445
/// are satisfied.
418446
RequirementFailure? isSatisfied({

0 commit comments

Comments
 (0)