Skip to content

Commit e2bd08e

Browse files
authored
[native_assets_cli] Prevent EncodedAsset and Metadata hashcode changing (#2131)
Closes: #2045 We have two types of classes in the semantic API: 1. Pure views on top of a JSON. These classes are mirrored by a builder class. Objects from these classes cannot be passed from input to output in hooks. These classes do not override `hashCode` and `operator ==`. Examples: `CodeConfig`, `BuildInput`. 2. Data classes that eagerly copy all fields out of the JSON. These classes have a public constructor with it's constituent fields. Objects from these classes may be passed from input to output in hooks. These classes do override `hashCode` and `operator ==`. Examples: `CodeAsset`, `Architecture`, `OS`, `DataAsset`. This changes `Metadata` and `EncodedAsset` to follow pattern 2 fully: * All data is copied on construction. * The map accessors do not allow modification. This means the `hashCode` and `operator ==` are now correct. We could consider changing `Metadata` and `EncodedAsset` to pattern 1, but I didn't want to refactor that code in this PR. For more details: * #2045
1 parent 781fc27 commit e2bd08e

File tree

5 files changed

+29
-17
lines changed

5 files changed

+29
-17
lines changed

pkgs/native_assets_cli/lib/src/config.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ String _jsonChecksum(Map<String, Object?> json) {
151151
final class BuildInput extends HookInput {
152152
Map<String, Metadata> get metadata => {
153153
for (final entry in (_syntaxBuildInput.dependencyMetadata ?? {}).entries)
154-
entry.key: Metadata.fromJson(entry.value),
154+
entry.key: Metadata(entry.value),
155155
};
156156

157157
@override

pkgs/native_assets_cli/lib/src/encoded_asset.dart

+17-7
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,36 @@ final class EncodedAsset {
1313
final String type;
1414

1515
/// The json encoding of the asset.
16-
final Map<String, Object?> encoding;
16+
final UnmodifiableMapView<String, Object?> encoding;
1717

1818
/// The path of this object in a larger JSON.
1919
///
2020
/// If provided, used for more precise error messages.
2121
final List<Object>? jsonPath;
2222

23-
EncodedAsset(this.type, this.encoding, {this.jsonPath});
23+
EncodedAsset._(this.type, this.encoding, {this.jsonPath});
24+
25+
EncodedAsset(this.type, Map<String, Object?> encoding, {this.jsonPath})
26+
: encoding = UnmodifiableMapView(
27+
// It would be better if `encoding` would be deep copied.
28+
// https://github.com/dart-lang/native/issues/2045
29+
Map.of(encoding),
30+
);
2431

2532
/// Decode an [EncodedAsset] from json.
2633
factory EncodedAsset.fromJson(
2734
Map<String, Object?> json, [
2835
List<Object>? path,
2936
]) {
3037
final syntax_ = syntax.Asset.fromJson(json);
31-
return EncodedAsset(syntax_.type, {
32-
for (final key in json.keys)
33-
if (key != _typeKey) key: json[key],
34-
}, jsonPath: path);
38+
return EncodedAsset._(
39+
syntax_.type,
40+
UnmodifiableMapView({
41+
for (final key in json.keys)
42+
if (key != _typeKey) key: json[key],
43+
}),
44+
jsonPath: path,
45+
);
3546
}
3647

3748
/// Encode this [EncodedAsset] tojson.
@@ -42,7 +53,6 @@ final class EncodedAsset {
4253
@override
4354
String toString() => 'EncodedAsset($type, $encoding)';
4455

45-
// TODO(https://github.com/dart-lang/native/issues/2045): Fix this.
4656
@override
4757
int get hashCode => Object.hash(type, const DeepCollectionEquality().hash);
4858

pkgs/native_assets_cli/lib/src/metadata.dart

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import 'package:collection/collection.dart';
66

77
class Metadata {
8-
final Map<String, Object?> metadata;
9-
10-
const Metadata(this.metadata);
11-
12-
factory Metadata.fromJson(Map<String, Object?>? jsonMap) =>
13-
Metadata(jsonMap ?? {});
8+
final UnmodifiableMapView<String, Object?> metadata;
9+
10+
Metadata(Map<String, Object?> metadata)
11+
: metadata = UnmodifiableMapView(
12+
// It would be better if `jsonMap` would be deep copied.
13+
// https://github.com/dart-lang/native/issues/2045
14+
Map.of(metadata),
15+
);
1416

1517
Map<String, Object?> toJson() => metadata;
1618

pkgs/native_assets_cli/test/build_input_test.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ void main() async {
3030
packageName = 'my_package';
3131
packageRootUri = tempUri.resolve('$packageName/');
3232
metadata = {
33-
'bar': const Metadata({
33+
'bar': Metadata({
3434
'key': 'value',
3535
'foo': ['asdf', 'fdsa'],
3636
}),
37-
'foo': const Metadata({'key': 321}),
37+
'foo': Metadata({'key': 321}),
3838
};
3939

4040
inputJson = {

pkgs/native_assets_cli/test/model/metadata_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'package:native_assets_cli/native_assets_cli.dart';
66
import 'package:test/test.dart';
77

88
void main() {
9-
const metadata = Metadata({
9+
final metadata = Metadata({
1010
'key': 'value',
1111
'my_list': [1, 2, 3],
1212
'my_map': {3: 4, 'foo': 'bar'},

0 commit comments

Comments
 (0)