Skip to content

Commit ce2ec22

Browse files
mini-bombactron
authored andcommitted
fix: retain the insertion order of SRI resources
This fixes an oversight where the order of <link rel=preload> statements was different than the order of insertion into the SriBuilder. This was caused by the usage of BTreeMap, which internally reordered the entries in lexicographic order - Preload types first, then ModulePreloads, sorted by the lexicographic ordering of strings in case of any conflicts. This was likely not the intended result. This issue was mitigated by replacing the BTreeMap with a Vec, and manually implementing checks for identical keys.
1 parent fa82f21 commit ce2ec22

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

src/pipelines/rust/sri.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ use crate::common::html_rewrite::Document;
22
use crate::config::CrossOrigin;
33
use crate::processing::integrity::{IntegrityType, OutputDigest};
44
use anyhow::Context;
5-
use std::collections::BTreeMap;
65
use std::fmt::{Display, Formatter};
76
use std::future::Future;
87
use std::path::Path;
98

10-
#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
9+
#[derive(Clone, Debug, PartialEq, Eq)]
1110
pub enum SriType {
1211
Preload,
1312
ModulePreload,
@@ -75,9 +74,13 @@ impl SriBuilder {
7574
"recording SRI record - type: {:?}. name: {name}, value: {digest:?}",
7675
self.r#type,
7776
);
78-
self.result
79-
.integrities
80-
.insert((r#type, name), SriEntry { digest, options });
77+
let key = SriKey { r#type, name };
78+
let entry = SriEntry { digest, options };
79+
if let Some(record) = self.result.integrities.iter_mut().find(|(k, _)| k == &key) {
80+
record.1 = entry;
81+
} else {
82+
self.result.integrities.push((key, entry));
83+
}
8184
}
8285

8386
Ok(())
@@ -86,7 +89,7 @@ impl SriBuilder {
8689

8790
#[derive(Clone, Debug, Default)]
8891
pub struct SriResult {
89-
pub integrities: BTreeMap<(SriType, String), SriEntry>,
92+
pub integrities: Vec<(SriKey, SriEntry)>,
9093
}
9194

9295
#[derive(Clone, Debug, Default)]
@@ -121,6 +124,12 @@ impl Display for SriOptions {
121124
}
122125
}
123126

127+
#[derive(Clone, Debug, PartialEq, Eq)]
128+
pub struct SriKey {
129+
pub r#type: SriType,
130+
pub name: String,
131+
}
132+
124133
#[derive(Clone, Debug)]
125134
pub struct SriEntry {
126135
pub digest: OutputDigest,
@@ -135,7 +144,7 @@ impl SriResult {
135144
base: impl Display,
136145
cross_origin: CrossOrigin,
137146
) -> anyhow::Result<()> {
138-
for ((r#type, name), SriEntry { digest, options }) in &self.integrities {
147+
for (SriKey { r#type, name }, SriEntry { digest, options }) in &self.integrities {
139148
if let Some(integrity) = digest.to_integrity_value() {
140149
let preload = format!(
141150
r#"

0 commit comments

Comments
 (0)