Unverified Commit cbe0ceaf authored by Andrew Kolos's avatar Andrew Kolos Committed by GitHub

consolidate AssetBundle::entries and AssetBundle::entryKinds into a new type,...

consolidate AssetBundle::entries and AssetBundle::entryKinds into a new type, `AssetBundleEntry` (#142029)

Part of work on https://github.com/flutter/flutter/pull/141194

The [`AssetBundle`](https://github.com/flutter/flutter/blob/0833929c997c8a9db11c1e0df9a731ab17b77606/packages/flutter_tools/lib/src/asset.dart#L80) class contains two members, `entries` and `entryKinds`. `entries` contains asset data indexed by asset key. `entryKinds` contains the "kinds" of these assets, again indexed by asset key.

**Change.** Rather than have two separate maps, this PR proposes combining these maps into one by wrapping the asset data and kind into a single data type `AssetBundleEntry`.

**Purpose.** In https://github.com/flutter/flutter/pull/141194, I am considering associating more information with an asset. In particular, what transformers are meant to be applied to it when copying it to the build output. Rather than adding another map member onto `AssetBundle` (e.g. `entryTransformers`), I decided to make things neater by introducing the `AssetBundleEntry` type.
parent 2bd5abf8
......@@ -14,7 +14,6 @@ import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/reporting/reporting.dart';
......@@ -37,9 +36,9 @@ Future<void> main(List<String> args) {
});
}
Future<void> writeFile(libfs.File outputFile, DevFSContent content) async {
Future<void> writeAssetFile(libfs.File outputFile, AssetBundleEntry asset) async {
outputFile.createSync(recursive: true);
final List<int> data = await content.contentsAsBytes();
final List<int> data = await asset.contentsAsBytes();
outputFile.writeAsBytesSync(data);
}
......@@ -73,9 +72,9 @@ Future<void> run(List<String> args) async {
}
final List<Future<void>> calls = <Future<void>>[];
assets.entries.forEach((String fileName, DevFSContent content) {
assets.entries.forEach((String fileName, AssetBundleEntry entry) {
final libfs.File outputFile = globals.fs.file(globals.fs.path.join(assetDir, fileName));
calls.add(writeFile(outputFile, content));
calls.add(writeAssetFile(outputFile, entry));
});
await Future.wait<void>(calls);
......
......@@ -77,14 +77,28 @@ enum AssetKind {
model,
}
abstract class AssetBundle {
Map<String, DevFSContent> get entries;
/// Contains all information about an asset needed by tool the to prepare and
/// copy an asset file to the build output.
@immutable
final class AssetBundleEntry {
const AssetBundleEntry(this.content, {
required this.kind,
});
Map<String, AssetKind> get entryKinds;
final DevFSContent content;
final AssetKind kind;
Future<List<int>> contentsAsBytes() => content.contentsAsBytes();
}
abstract class AssetBundle {
/// The files that were specified under the `assets` section in the pubspec,
/// indexed by asset key.
Map<String, AssetBundleEntry> get entries;
/// The files that were specified under the deferred components assets sections
/// in pubspec.
Map<String, Map<String, DevFSContent>> get deferredComponentsEntries;
/// in a pubspec, indexed by component name and asset key.
Map<String, Map<String, AssetBundleEntry>> get deferredComponentsEntries;
/// Additional files that this bundle depends on that are not included in the
/// output result.
......@@ -149,13 +163,10 @@ class ManifestAssetBundle implements AssetBundle {
final bool _splitDeferredAssets;
@override
final Map<String, DevFSContent> entries = <String, DevFSContent>{};
@override
final Map<String, AssetKind> entryKinds = <String, AssetKind>{};
final Map<String, AssetBundleEntry> entries = <String, AssetBundleEntry>{};
@override
final Map<String, Map<String, DevFSContent>> deferredComponentsEntries = <String, Map<String, DevFSContent>>{};
final Map<String, Map<String, AssetBundleEntry>> deferredComponentsEntries = <String, Map<String, AssetBundleEntry>>{};
@override
final List<File> inputFiles = <File>[];
......@@ -236,17 +247,24 @@ class ManifestAssetBundle implements AssetBundle {
// device.
_lastBuildTimestamp = DateTime.now();
if (flutterManifest.isEmpty) {
entries[_kAssetManifestJsonFilename] = DevFSStringContent('{}');
entryKinds[_kAssetManifestJsonFilename] = AssetKind.regular;
entries[_kAssetManifestJsonFilename] = AssetBundleEntry(
DevFSStringContent('{}'),
kind: AssetKind.regular,
);
final ByteData emptyAssetManifest =
const StandardMessageCodec().encodeMessage(<dynamic, dynamic>{})!;
entries[_kAssetManifestBinFilename] =
DevFSByteContent(emptyAssetManifest.buffer.asUint8List(0, emptyAssetManifest.lengthInBytes));
entryKinds[_kAssetManifestBinFilename] = AssetKind.regular;
entries[_kAssetManifestBinFilename] = AssetBundleEntry(
DevFSByteContent(
emptyAssetManifest.buffer.asUint8List(0, emptyAssetManifest.lengthInBytes),
),
kind: AssetKind.regular,
);
// Create .bin.json on web builds.
if (targetPlatform == TargetPlatform.web_javascript) {
entries[_kAssetManifestBinJsonFilename] = DevFSStringContent('""');
entryKinds[_kAssetManifestBinJsonFilename] = AssetKind.regular;
entries[_kAssetManifestBinJsonFilename] = AssetBundleEntry(
DevFSStringContent('""'),
kind: AssetKind.regular,
);
}
return 0;
}
......@@ -388,14 +406,16 @@ class ManifestAssetBundle implements AssetBundle {
final File variantFile = variant.lookupAssetFile(_fileSystem);
inputFiles.add(variantFile);
assert(variantFile.existsSync());
entries[variant.entryUri.path] ??= DevFSFileContent(variantFile);
entryKinds[variant.entryUri.path] ??= variant.assetKind;
entries[variant.entryUri.path] ??= AssetBundleEntry(
DevFSFileContent(variantFile),
kind: variant.kind,
);
}
}
// Save the contents of each deferred component image, image variant, and font
// asset in deferredComponentsEntries.
for (final String componentName in deferredComponentsAssetVariants.keys) {
deferredComponentsEntries[componentName] = <String, DevFSContent>{};
deferredComponentsEntries[componentName] = <String, AssetBundleEntry>{};
final Map<_Asset, List<_Asset>> assetsMap = deferredComponentsAssetVariants[componentName]!;
for (final _Asset asset in assetsMap.keys) {
final File assetFile = asset.lookupAssetFile(_fileSystem);
......@@ -419,7 +439,10 @@ class ManifestAssetBundle implements AssetBundle {
for (final _Asset variant in assetsMap[asset]!) {
final File variantFile = variant.lookupAssetFile(_fileSystem);
assert(variantFile.existsSync());
deferredComponentsEntries[componentName]![variant.entryUri.path] ??= DevFSFileContent(variantFile);
deferredComponentsEntries[componentName]![variant.entryUri.path] ??= AssetBundleEntry(
DevFSFileContent(variantFile),
kind: AssetKind.regular,
);
}
}
}
......@@ -434,8 +457,7 @@ class ManifestAssetBundle implements AssetBundle {
for (final _Asset asset in materialAssets) {
final File assetFile = asset.lookupAssetFile(_fileSystem);
assert(assetFile.existsSync(), 'Missing ${assetFile.path}');
entries[asset.entryUri.path] ??= DevFSFileContent(assetFile);
entryKinds[asset.entryUri.path] ??= asset.assetKind;
entries[asset.entryUri.path] ??= AssetBundleEntry(DevFSFileContent(assetFile), kind: asset.kind);
}
// Update wildcard directories we can detect changes in them.
......@@ -487,7 +509,7 @@ class ManifestAssetBundle implements AssetBundle {
@override
List<File> additionalDependencies = <File>[];
void _setIfChanged(String key, DevFSContent content, AssetKind assetKind) {
final DevFSContent? oldContent = entries[key];
final DevFSContent? oldContent = entries[key]?.content;
// In the case that the content is unchanged, we want to avoid an overwrite
// as the isModified property may be reset to true,
if (oldContent is DevFSByteContent && content is DevFSByteContent &&
......@@ -495,8 +517,10 @@ class ManifestAssetBundle implements AssetBundle {
return;
}
entries[key] = content;
entryKinds[key] = assetKind;
entries[key] = AssetBundleEntry(
content,
kind: assetKind,
);
}
static bool _compareIntLists(List<int> o1, List<int> o2) {
......@@ -530,16 +554,18 @@ class ManifestAssetBundle implements AssetBundle {
// the uncompressed strings to not incur decompression/decoding while making
// the comparison.
if (!entries.containsKey(_kNoticeZippedFile) ||
(entries[_kNoticeZippedFile] as DevFSStringCompressingBytesContent?)
(entries[_kNoticeZippedFile]?.content as DevFSStringCompressingBytesContent?)
?.equals(combinedLicenses) != true) {
entries[_kNoticeZippedFile] = DevFSStringCompressingBytesContent(
combinedLicenses,
// A zlib dictionary is a hinting string sequence with the most
// likely string occurrences at the end. This ends up just being
// common English words with domain specific words like copyright.
hintString: 'copyrightsoftwaretothisinandorofthe',
entries[_kNoticeZippedFile] = AssetBundleEntry(
DevFSStringCompressingBytesContent(
combinedLicenses,
// A zlib dictionary is a hinting string sequence with the most
// likely string occurrences at the end. This ends up just being
// common English words with domain specific words like copyright.
hintString: 'copyrightsoftwaretothisinandorofthe',
),
kind: AssetKind.regular,
);
entryKinds[_kNoticeZippedFile] = AssetKind.regular;
}
}
......@@ -564,7 +590,7 @@ class ManifestAssetBundle implements AssetBundle {
relativeUri: Uri(path: entryUri.pathSegments.last),
entryUri: entryUri,
package: null,
assetKind: AssetKind.font,
kind: AssetKind.font,
));
}
}
......@@ -592,7 +618,7 @@ class ManifestAssetBundle implements AssetBundle {
relativeUri: Uri(path: entryUri.pathSegments.last),
entryUri: entryUri,
package: null,
assetKind: AssetKind.shader,
kind: AssetKind.shader,
));
}
......@@ -992,7 +1018,7 @@ class ManifestAssetBundle implements AssetBundle {
entryUri: entryUri,
relativeUri: relativeUri,
package: attributedPackage,
assetKind: assetKind,
kind: assetKind,
),
);
}
......@@ -1105,7 +1131,7 @@ class ManifestAssetBundle implements AssetBundle {
relativeUri: assetUri,
package: attributedPackage,
originUri: originUri,
assetKind: assetKind,
kind: assetKind,
flavors: flavors,
);
}
......@@ -1129,7 +1155,7 @@ class ManifestAssetBundle implements AssetBundle {
entryUri: assetUri,
relativeUri: Uri(pathSegments: assetUri.pathSegments.sublist(2)),
package: attributedPackage,
assetKind: assetKind,
kind: assetKind,
originUri: originUri,
flavors: flavors,
);
......@@ -1152,7 +1178,7 @@ class _Asset {
required this.relativeUri,
required this.entryUri,
required this.package,
this.assetKind = AssetKind.regular,
this.kind = AssetKind.regular,
List<String>? flavors,
}): originUri = originUri ?? entryUri, flavors = flavors ?? const <String>[];
......@@ -1171,7 +1197,7 @@ class _Asset {
/// A platform-independent URL representing the entry for the asset manifest.
final Uri entryUri;
final AssetKind assetKind;
final AssetKind kind;
final List<String> flavors;
......@@ -1224,7 +1250,7 @@ class _Asset {
&& other.baseDir == baseDir
&& other.relativeUri == relativeUri
&& other.entryUri == entryUri
&& other.assetKind == assetKind
&& other.kind == kind
&& hasEquivalentFlavorsWith(other);
}
......@@ -1233,7 +1259,7 @@ class _Asset {
baseDir,
relativeUri,
entryUri,
assetKind,
kind,
...flavors,
]);
}
......
......@@ -29,7 +29,7 @@ import 'shader_compiler.dart';
Future<Depfile> copyAssets(
Environment environment,
Directory outputDirectory, {
Map<String, DevFSContent>? additionalContent,
Map<String, DevFSContent> additionalContent = const <String, DevFSContent>{},
required TargetPlatform targetPlatform,
BuildMode? buildMode,
required ShaderTarget shaderTarget,
......@@ -75,7 +75,7 @@ Future<Depfile> copyAssets(
final IconTreeShaker iconTreeShaker = IconTreeShaker(
environment,
assetBundle.entries[kFontManifestJson] as DevFSStringContent?,
assetBundle.entries[kFontManifestJson]?.content as DevFSStringContent?,
processManager: environment.processManager,
logger: environment.logger,
fileSystem: environment.fileSystem,
......@@ -95,18 +95,23 @@ Future<Depfile> copyAssets(
artifacts: environment.artifacts,
);
final Map<String, DevFSContent> assetEntries = <String, DevFSContent>{
final Map<String, AssetBundleEntry> assetEntries = <String, AssetBundleEntry>{
...assetBundle.entries,
...?additionalContent,
...additionalContent.map((String key, DevFSContent value) {
return MapEntry<String, AssetBundleEntry>(
key,
AssetBundleEntry(value, kind: AssetKind.regular),
);
}),
if (skslBundle != null)
kSkSLShaderBundlePath: skslBundle,
};
final Map<String, AssetKind> entryKinds = <String, AssetKind>{
...assetBundle.entryKinds,
kSkSLShaderBundlePath: AssetBundleEntry(
skslBundle,
kind: AssetKind.regular,
),
};
await Future.wait<void>(
assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
assetEntries.entries.map<Future<void>>((MapEntry<String, AssetBundleEntry> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
......@@ -116,14 +121,13 @@ Future<Depfile> copyAssets(
// and the native APIs will look for files this way.
final File file = environment.fileSystem.file(
environment.fileSystem.path.join(outputDirectory.path, entry.key));
final AssetKind assetKind = entryKinds[entry.key] ?? AssetKind.regular;
outputs.add(file);
file.parent.createSync(recursive: true);
final DevFSContent content = entry.value;
final DevFSContent content = entry.value.content;
if (content is DevFSFileContent && content.file is File) {
inputs.add(content.file as File);
bool doCopy = true;
switch (assetKind) {
switch (entry.value.kind) {
case AssetKind.regular:
break;
case AssetKind.font:
......@@ -149,7 +153,7 @@ Future<Depfile> copyAssets(
await (content.file as File).copy(file.path);
}
} else {
await file.writeAsBytes(await entry.value.contentsAsBytes());
await file.writeAsBytes(await entry.value.content.contentsAsBytes());
}
} finally {
resource.release();
......@@ -161,7 +165,7 @@ Future<Depfile> copyAssets(
// building as debug.
if (environment.defines[kDeferredComponents] == 'true' && buildMode != null) {
await Future.wait<void>(assetBundle.deferredComponentsEntries.entries.map<Future<void>>(
(MapEntry<String, Map<String, DevFSContent>> componentEntries) async {
(MapEntry<String, Map<String, AssetBundleEntry>> componentEntries) async {
final Directory componentOutputDir =
environment.projectDir
.childDirectory('build')
......@@ -169,7 +173,7 @@ Future<Depfile> copyAssets(
.childDirectory('intermediates')
.childDirectory('flutter');
await Future.wait<void>(
componentEntries.value.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
componentEntries.value.entries.map<Future<void>>((MapEntry<String, AssetBundleEntry> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
......@@ -186,7 +190,7 @@ Future<Depfile> copyAssets(
environment.fileSystem.path.join(outputDirectory.path, entry.key));
outputs.add(file);
file.parent.createSync(recursive: true);
final DevFSContent content = entry.value;
final DevFSContent content = entry.value.content;
if (content is DevFSFileContent && content.file is File) {
inputs.add(content.file as File);
if (!await iconTreeShaker.subsetFont(
......
......@@ -137,8 +137,7 @@ Future<AssetBundle?> buildAssets({
Future<void> writeBundle(
Directory bundleDir,
Map<String, DevFSContent> assetEntries,
Map<String, AssetKind> entryKinds, {
Map<String, AssetBundleEntry> assetEntries, {
Logger? loggerOverride,
required TargetPlatform targetPlatform,
required ImpellerStatus impellerStatus,
......@@ -178,7 +177,7 @@ Future<void> writeBundle(
// Limit number of open files to avoid running out of file descriptors.
final Pool pool = Pool(64);
await Future.wait<void>(
assetEntries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
assetEntries.entries.map<Future<void>>((MapEntry<String, AssetBundleEntry> entry) async {
final PoolResource resource = await pool.request();
try {
// This will result in strange looking files, for example files with `/`
......@@ -187,13 +186,12 @@ Future<void> writeBundle(
// platform channels in the framework will URI encode these values,
// and the native APIs will look for files this way.
final File file = globals.fs.file(globals.fs.path.join(bundleDir.path, entry.key));
final AssetKind assetKind = entryKinds[entry.key] ?? AssetKind.regular;
file.parent.createSync(recursive: true);
final DevFSContent devFSContent = entry.value;
final DevFSContent devFSContent = entry.value.content;
if (devFSContent is DevFSFileContent) {
final File input = devFSContent.file as File;
bool doCopy = true;
switch (assetKind) {
switch (entry.value.kind) {
case AssetKind.regular:
break;
case AssetKind.font:
......
......@@ -583,14 +583,13 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
await writeBundle(
globals.fs.directory(globals.fs.path.join('build', 'unit_test_assets')),
assetBundle.entries,
assetBundle.entryKinds,
targetPlatform: TargetPlatform.tester,
impellerStatus: impellerStatus,
);
}
}
bool _needRebuild(Map<String, DevFSContent> entries) {
bool _needRebuild(Map<String, AssetBundleEntry> entries) {
// TODO(andrewkolos): This logic might fail in the future if we change the
// schema of the contents of the asset manifest file and the user does not
// perform a `flutter clean` after upgrading.
......
......@@ -618,10 +618,10 @@ class DevFS {
// are in the same location in DevFS and the iOS simulator.
final String assetBuildDirPrefix = _asUriPath(getAssetBuildDirectory());
final String assetDirectory = getAssetBuildDirectory();
bundle.entries.forEach((String archivePath, DevFSContent content) {
bundle.entries.forEach((String archivePath, AssetBundleEntry entry) {
// If the content is backed by a real file, isModified will file stat and return true if
// it was modified since the last time this was called.
if (!content.isModified || bundleFirstUpload) {
if (!entry.content.isModified || bundleFirstUpload) {
return;
}
// Modified shaders must be recompiled per-target platform.
......@@ -635,9 +635,9 @@ class DevFS {
didUpdateFontManifest = true;
}
switch (bundle.entryKinds[archivePath]) {
switch (bundle.entries[archivePath]?.kind) {
case AssetKind.shader:
final Future<DevFSContent?> pending = shaderCompiler.recompileShader(content);
final Future<DevFSContent?> pending = shaderCompiler.recompileShader(entry.content);
pendingAssetBuilds.add(pending);
pending.then((DevFSContent? content) {
if (content == null) {
......@@ -654,7 +654,7 @@ class DevFS {
if (sceneImporter == null) {
break;
}
final Future<DevFSContent?> pending = sceneImporter.reimportScene(content);
final Future<DevFSContent?> pending = sceneImporter.reimportScene(entry.content);
pendingAssetBuilds.add(pending);
pending.then((DevFSContent? content) {
if (content == null) {
......@@ -670,8 +670,8 @@ class DevFS {
case AssetKind.regular:
case AssetKind.font:
case null:
dirtyEntries[deviceUri] = content;
syncedBytes += content.size;
dirtyEntries[deviceUri] = entry.content;
syncedBytes += entry.content.size;
if (!bundleFirstUpload) {
assetPathsToEvict.add(archivePath);
}
......
......@@ -884,7 +884,6 @@ class WebDevFS implements DevFS {
await writeBundle(
globals.fs.directory(getAssetBuildDirectory()),
bundle.entries,
bundle.entryKinds,
targetPlatform: TargetPlatform.web_javascript,
impellerStatus: ImpellerStatus.disabled,
);
......
......@@ -648,8 +648,7 @@ flutter:
await writeBundle(
directory,
<String, DevFSContent>{},
<String, AssetKind>{},
const <String, AssetBundleEntry>{},
loggerOverride: testLogger,
targetPlatform: TargetPlatform.android,
impellerStatus: ImpellerStatus.disabled,
......@@ -672,12 +671,9 @@ assets:
final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
await bundle.build(packagesPath: '.packages');
final DevFSStringContent? assetManifest = bundle.entries['AssetManifest.json']
as DevFSStringContent?;
final DevFSStringContent? fontManifest = bundle.entries['FontManifest.json']
as DevFSStringContent?;
final DevFSStringContent? license = bundle.entries['NOTICES']
as DevFSStringContent?;
final AssetBundleEntry? assetManifest = bundle.entries['AssetManifest.json'];
final AssetBundleEntry? fontManifest = bundle.entries['FontManifest.json'];
final AssetBundleEntry? license = bundle.entries['NOTICES'];
await bundle.build(packagesPath: '.packages');
......@@ -775,7 +771,6 @@ flutter:
await writeBundle(
output,
bundle.entries,
bundle.entryKinds,
loggerOverride: testLogger,
targetPlatform: TargetPlatform.android,
impellerStatus: ImpellerStatus.disabled,
......@@ -822,7 +817,6 @@ flutter:
await writeBundle(
output,
bundle.entries,
bundle.entryKinds,
loggerOverride: testLogger,
targetPlatform: TargetPlatform.web_javascript,
impellerStatus: ImpellerStatus.disabled,
......@@ -906,7 +900,6 @@ flutter:
await writeBundle(
output,
bundle.entries,
bundle.entryKinds,
loggerOverride: testLogger,
targetPlatform: TargetPlatform.web_javascript,
impellerStatus: ImpellerStatus.disabled,
......@@ -1081,8 +1074,8 @@ flutter:
final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
expect(await bundle.build(packagesPath: '.packages'), 0);
expect((bundle.entries['FontManifest.json']! as DevFSStringContent).string, '[]');
expect((bundle.entries['AssetManifest.json']! as DevFSStringContent).string, '{}');
expect((bundle.entries['FontManifest.json']!.content as DevFSStringContent).string, '[]');
expect((bundle.entries['AssetManifest.json']!.content as DevFSStringContent).string, '{}');
expect(testLogger.errorText, contains(
'package:foo has `uses-material-design: true` set'
));
......@@ -1153,10 +1146,10 @@ flutter:
final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
expect(await bundle.build(packagesPath: '.packages'), 0);
expect((bundle.entries['FontManifest.json']! as DevFSStringContent).string, '[]');
expect((bundle.entries['FontManifest.json']!.content as DevFSStringContent).string, '[]');
// The assets from deferred components and regular assets
// are both included in alphabetical order
expect((bundle.entries['AssetManifest.json']! as DevFSStringContent).string, '{"assets/apple.jpg":["assets/apple.jpg"],"assets/bar.jpg":["assets/bar.jpg"],"assets/foo.jpg":["assets/foo.jpg"],"assets/zebra.jpg":["assets/zebra.jpg"]}');
expect((bundle.entries['AssetManifest.json']!.content as DevFSStringContent).string, '{"assets/apple.jpg":["assets/apple.jpg"],"assets/bar.jpg":["assets/bar.jpg"],"assets/foo.jpg":["assets/foo.jpg"],"assets/zebra.jpg":["assets/zebra.jpg"]}');
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
......
......@@ -621,9 +621,14 @@ void main() {
return const CompilerOutput('lib/foo.dill', 0, <Uri>[]);
};
final FakeBundle bundle = FakeBundle()
..entries['foo.frag'] = DevFSByteContent(<int>[1, 2, 3, 4])
..entries['not.frag'] = DevFSByteContent(<int>[1, 2, 3, 4])
..entryKinds['foo.frag'] = AssetKind.shader;
..entries['foo.frag'] = AssetBundleEntry(
DevFSByteContent(<int>[1, 2, 3, 4]),
kind: AssetKind.shader,
)
..entries['not.frag'] = AssetBundleEntry(
DevFSByteContent(<int>[1, 2, 3, 4]),
kind: AssetKind.regular,
);
final UpdateFSReport report = await devFS.update(
mainUri: Uri.parse('lib/main.dart'),
......@@ -673,7 +678,10 @@ void main() {
return const CompilerOutput('lib/foo.dill', 0, <Uri>[]);
};
final FakeBundle bundle = FakeBundle()
..entries['FontManifest.json'] = DevFSByteContent(<int>[1, 2, 3, 4]);
..entries['FontManifest.json'] = AssetBundleEntry(
DevFSByteContent(<int>[1, 2, 3, 4]),
kind: AssetKind.regular,
);
final UpdateFSReport report = await devFS.update(
mainUri: Uri.parse('lib/main.dart'),
......@@ -745,13 +753,10 @@ class FakeBundle extends AssetBundle {
}
@override
Map<String, Map<String, DevFSContent>> get deferredComponentsEntries => <String, Map<String, DevFSContent>>{};
Map<String, Map<String, AssetBundleEntry>> get deferredComponentsEntries => <String, Map<String, AssetBundleEntry>>{};
@override
final Map<String, DevFSContent> entries = <String, DevFSContent>{};
@override
final Map<String, AssetKind> entryKinds = <String, AssetKind>{};
final Map<String, AssetBundleEntry> entries = <String, AssetBundleEntry>{};
@override
List<File> get inputFiles => <File>[];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment