URI-decode asset paths before writing them to the asset manifest (#112415)
This commit is contained in:
parent
ecdfa95340
commit
f8c9f72b94
@ -105,14 +105,12 @@ void main() {
|
|||||||
bundle: testAssetBundle,
|
bundle: testAssetBundle,
|
||||||
);
|
);
|
||||||
|
|
||||||
// we have the exact match for this scale, let's use it
|
|
||||||
assetImage.obtainKey(ImageConfiguration.empty)
|
assetImage.obtainKey(ImageConfiguration.empty)
|
||||||
.then(expectAsync1((AssetBundleImageKey bundleKey) {
|
.then(expectAsync1((AssetBundleImageKey bundleKey) {
|
||||||
expect(bundleKey.name, mainAssetPath);
|
expect(bundleKey.name, mainAssetPath);
|
||||||
expect(bundleKey.scale, 1.0);
|
expect(bundleKey.scale, 1.0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// we also have the exact match for this scale, let's use it
|
|
||||||
assetImage.obtainKey(ImageConfiguration(
|
assetImage.obtainKey(ImageConfiguration(
|
||||||
bundle: testAssetBundle,
|
bundle: testAssetBundle,
|
||||||
devicePixelRatio: 3.0,
|
devicePixelRatio: 3.0,
|
||||||
@ -122,7 +120,7 @@ void main() {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('When high-res device and high-res asset not present in bundle then return main variant', () {
|
test('When high-res device and high-res asset not present in bundle then return main variant', () {
|
||||||
const String mainAssetPath = 'assets/normalFolder/normalFile.png';
|
const String mainAssetPath = 'assets/normalFolder/normalFile.png';
|
||||||
|
|
||||||
final Map<String, List<String>> assetBundleMap =
|
final Map<String, List<String>> assetBundleMap =
|
||||||
|
@ -644,7 +644,12 @@ class ManifestAssetBundle implements AssetBundle {
|
|||||||
final List<_Asset> sortedKeys = jsonEntries.keys.toList()
|
final List<_Asset> sortedKeys = jsonEntries.keys.toList()
|
||||||
..sort((_Asset left, _Asset right) => left.entryUri.path.compareTo(right.entryUri.path));
|
..sort((_Asset left, _Asset right) => left.entryUri.path.compareTo(right.entryUri.path));
|
||||||
for (final _Asset main in sortedKeys) {
|
for (final _Asset main in sortedKeys) {
|
||||||
jsonObject[main.entryUri.path] = jsonEntries[main]!;
|
final String decodedEntryPath = Uri.decodeFull(main.entryUri.path);
|
||||||
|
final List<String> rawEntryVariantsPaths = jsonEntries[main]!;
|
||||||
|
final List<String> decodedEntryVariantPaths = rawEntryVariantsPaths
|
||||||
|
.map((String value) => Uri.decodeFull(value))
|
||||||
|
.toList();
|
||||||
|
jsonObject[decodedEntryPath] = decodedEntryVariantPaths;
|
||||||
}
|
}
|
||||||
return DevFSStringContent(json.encode(jsonObject));
|
return DevFSStringContent(json.encode(jsonObject));
|
||||||
}
|
}
|
||||||
|
@ -447,7 +447,7 @@ $assetsSection
|
|||||||
writePubspecFile('pubspec.yaml', 'test');
|
writePubspecFile('pubspec.yaml', 'test');
|
||||||
writePackagesFile('test_package:p/p/lib/');
|
writePackagesFile('test_package:p/p/lib/');
|
||||||
|
|
||||||
final List<String> assets = <String>['a/foo', 'a/foo[x]'];
|
final List<String> assets = <String>['a/foo', 'a/foo [x]'];
|
||||||
writePubspecFile(
|
writePubspecFile(
|
||||||
'p/p/pubspec.yaml',
|
'p/p/pubspec.yaml',
|
||||||
'test_package',
|
'test_package',
|
||||||
@ -457,7 +457,7 @@ $assetsSection
|
|||||||
writeAssets('p/p/', assets);
|
writeAssets('p/p/', assets);
|
||||||
const String expectedAssetManifest =
|
const String expectedAssetManifest =
|
||||||
'{"packages/test_package/a/foo":["packages/test_package/a/foo"],'
|
'{"packages/test_package/a/foo":["packages/test_package/a/foo"],'
|
||||||
'"packages/test_package/a/foo%5Bx%5D":["packages/test_package/a/foo%5Bx%5D"]}';
|
'"packages/test_package/a/foo [x]":["packages/test_package/a/foo [x]"]}';
|
||||||
|
|
||||||
await buildAndVerifyAssets(
|
await buildAndVerifyAssets(
|
||||||
assets,
|
assets,
|
||||||
|
@ -30,11 +30,11 @@ void main() {
|
|||||||
return parsedManifest;
|
return parsedManifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
group('AssetBundle asset variants (with POSIX-style paths)', () {
|
group('AssetBundle asset variants (with Unix-style paths)', () {
|
||||||
late final Platform platform;
|
late Platform platform;
|
||||||
late final FileSystem fs;
|
late FileSystem fs;
|
||||||
|
|
||||||
setUpAll(() {
|
setUp(() {
|
||||||
platform = FakePlatform();
|
platform = FakePlatform();
|
||||||
fs = MemoryFileSystem.test();
|
fs = MemoryFileSystem.test();
|
||||||
Cache.flutterRoot = Cache.defaultFlutterRoot(
|
Cache.flutterRoot = Cache.defaultFlutterRoot(
|
||||||
@ -87,10 +87,10 @@ flutter:
|
|||||||
);
|
);
|
||||||
|
|
||||||
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
||||||
final List<String> variantsForImage = manifest[image]!;
|
|
||||||
|
|
||||||
expect(variantsForImage, contains(image2xVariant));
|
expect(manifest, hasLength(2));
|
||||||
expect(variantsForImage, isNot(contains(imageNonVariant)));
|
expect(manifest[image], equals(<String>[image, image2xVariant]));
|
||||||
|
expect(manifest[imageNonVariant], equals(<String>[imageNonVariant]));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('Asset directories are recursively searched for assets', () async {
|
testWithoutContext('Asset directories are recursively searched for assets', () async {
|
||||||
@ -122,11 +122,40 @@ flutter:
|
|||||||
);
|
);
|
||||||
|
|
||||||
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
||||||
expect(manifest, contains(secondLevelImage));
|
expect(manifest, hasLength(2));
|
||||||
expect(manifest, contains(topLevelImage));
|
expect(manifest[topLevelImage], equals(<String>[topLevelImage]));
|
||||||
expect(manifest[secondLevelImage], hasLength(2));
|
expect(manifest[secondLevelImage], equals(<String>[secondLevelImage, secondLevel2xVariant]));
|
||||||
expect(manifest[secondLevelImage], contains(secondLevelImage));
|
});
|
||||||
expect(manifest[secondLevelImage], contains(secondLevel2xVariant));
|
|
||||||
|
testWithoutContext('Asset paths should never be URI-encoded', () async {
|
||||||
|
const String image = 'assets/normalFolder/i have URI-reserved_characters.jpg';
|
||||||
|
const String imageVariant = 'assets/normalFolder/3x/i have URI-reserved_characters.jpg';
|
||||||
|
|
||||||
|
final List<String> assets = <String>[
|
||||||
|
image,
|
||||||
|
imageVariant
|
||||||
|
];
|
||||||
|
|
||||||
|
for (final String asset in assets) {
|
||||||
|
final File assetFile = fs.file(asset);
|
||||||
|
assetFile.createSync(recursive: true);
|
||||||
|
assetFile.writeAsStringSync(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ManifestAssetBundle bundle = ManifestAssetBundle(
|
||||||
|
logger: BufferLogger.test(),
|
||||||
|
fileSystem: fs,
|
||||||
|
platform: platform,
|
||||||
|
);
|
||||||
|
|
||||||
|
await bundle.build(
|
||||||
|
packagesPath: '.packages',
|
||||||
|
flutterProject: FlutterProject.fromDirectoryTest(fs.currentDirectory),
|
||||||
|
);
|
||||||
|
|
||||||
|
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
||||||
|
expect(manifest, hasLength(1));
|
||||||
|
expect(manifest[image], equals(<String>[image, imageVariant]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -135,13 +164,7 @@ flutter:
|
|||||||
late final Platform platform;
|
late final Platform platform;
|
||||||
late final FileSystem fs;
|
late final FileSystem fs;
|
||||||
|
|
||||||
String correctPathSeparators(String path) {
|
setUp(() {
|
||||||
// The in-memory file system is strict about slashes on Windows being the
|
|
||||||
// correct way. See https://github.com/google/file.dart/issues/112.
|
|
||||||
return path.replaceAll('/', fs.path.separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
setUpAll(() {
|
|
||||||
platform = FakePlatform(operatingSystem: 'windows');
|
platform = FakePlatform(operatingSystem: 'windows');
|
||||||
fs = MemoryFileSystem.test(style: FileSystemStyle.windows);
|
fs = MemoryFileSystem.test(style: FileSystemStyle.windows);
|
||||||
Cache.flutterRoot = Cache.defaultFlutterRoot(
|
Cache.flutterRoot = Cache.defaultFlutterRoot(
|
||||||
@ -165,19 +188,16 @@ flutter:
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('Only images in folders named with device pixel ratios (e.g. 2x, 3.0x) should be considered as variants of other images', () async {
|
testWithoutContext('Variant detection works with windows-style filepaths', () async {
|
||||||
const String image = 'assets/image.jpg';
|
const List<String> assets = <String>[
|
||||||
const String image2xVariant = 'assets/2x/image.jpg';
|
r'assets\foo.jpg',
|
||||||
const String imageNonVariant = 'assets/notAVariant/image.jpg';
|
r'assets\2x\foo.jpg',
|
||||||
|
r'assets\somewhereElse\bar.jpg',
|
||||||
final List<String> assets = <String>[
|
r'assets\somewhereElse\2x\bar.jpg',
|
||||||
image,
|
|
||||||
image2xVariant,
|
|
||||||
imageNonVariant
|
|
||||||
];
|
];
|
||||||
|
|
||||||
for (final String asset in assets) {
|
for (final String asset in assets) {
|
||||||
final File assetFile = fs.file(correctPathSeparators(asset));
|
final File assetFile = fs.file(asset);
|
||||||
assetFile.createSync(recursive: true);
|
assetFile.createSync(recursive: true);
|
||||||
assetFile.writeAsStringSync(asset);
|
assetFile.writeAsStringSync(asset);
|
||||||
}
|
}
|
||||||
@ -194,46 +214,10 @@ flutter:
|
|||||||
);
|
);
|
||||||
|
|
||||||
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
||||||
final List<String> variantsForImage = manifest[image]!;
|
|
||||||
|
|
||||||
expect(variantsForImage, contains(image2xVariant));
|
expect(manifest, hasLength(2));
|
||||||
expect(variantsForImage, isNot(contains(imageNonVariant)));
|
expect(manifest['assets/foo.jpg'], equals(<String>['assets/foo.jpg', 'assets/2x/foo.jpg']));
|
||||||
});
|
expect(manifest['assets/somewhereElse/bar.jpg'], equals(<String>['assets/somewhereElse/bar.jpg', 'assets/somewhereElse/2x/bar.jpg']));
|
||||||
|
|
||||||
testWithoutContext('Asset directories are recursively searched for assets', () async {
|
|
||||||
const String topLevelImage = 'assets/image.jpg';
|
|
||||||
const String secondLevelImage = 'assets/folder/secondLevel.jpg';
|
|
||||||
const String secondLevel2xVariant = 'assets/folder/2x/secondLevel.jpg';
|
|
||||||
|
|
||||||
final List<String> assets = <String>[
|
|
||||||
topLevelImage,
|
|
||||||
secondLevelImage,
|
|
||||||
secondLevel2xVariant
|
|
||||||
];
|
|
||||||
|
|
||||||
for (final String asset in assets) {
|
|
||||||
final File assetFile = fs.file(correctPathSeparators(asset));
|
|
||||||
assetFile.createSync(recursive: true);
|
|
||||||
assetFile.writeAsStringSync(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ManifestAssetBundle bundle = ManifestAssetBundle(
|
|
||||||
logger: BufferLogger.test(),
|
|
||||||
fileSystem: fs,
|
|
||||||
platform: platform,
|
|
||||||
);
|
|
||||||
|
|
||||||
await bundle.build(
|
|
||||||
packagesPath: '.packages',
|
|
||||||
flutterProject: FlutterProject.fromDirectoryTest(fs.currentDirectory),
|
|
||||||
);
|
|
||||||
|
|
||||||
final Map<String, List<String>> manifest = await extractAssetManifestFromBundle(bundle);
|
|
||||||
expect(manifest, contains(secondLevelImage));
|
|
||||||
expect(manifest, contains(topLevelImage));
|
|
||||||
expect(manifest[secondLevelImage], hasLength(2));
|
|
||||||
expect(manifest[secondLevelImage], contains(secondLevelImage));
|
|
||||||
expect(manifest[secondLevelImage], contains(secondLevel2xVariant));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user