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