Skip to content

Commit a1ca2bd

Browse files
fix double association bug
1 parent ce1b1da commit a1ca2bd

File tree

5 files changed

+67
-42
lines changed

5 files changed

+67
-42
lines changed

src/utils/file_upload.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ impl<'a> TryFrom<&'a UploadContext<'_>> for LegacyUploadContext<'a> {
211211
}
212212
}
213213

214-
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
214+
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)]
215215
pub enum LogLevel {
216216
Warning,
217217
Error,
@@ -226,7 +226,7 @@ impl fmt::Display for LogLevel {
226226
}
227227
}
228228

229-
#[derive(Clone, Debug)]
229+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
230230
pub struct SourceFile {
231231
pub url: String,
232232
pub path: PathBuf,

src/utils/sourcemaps.rs

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -287,53 +287,78 @@ impl SourceMapProcessor {
287287
/// Collect references to sourcemaps in minified source files
288288
/// and saves them in `self.sourcemap_references`.
289289
fn collect_sourcemap_references(&mut self) {
290-
let sourcemaps = self
290+
// Collect available sourcemaps
291+
let sourcemaps: HashSet<_> = self
291292
.sources
292293
.iter()
293294
.map(|x| x.1)
294295
.filter(|x| x.ty == SourceFileType::SourceMap)
295296
.map(|x| x.url.clone())
296297
.collect();
297298

298-
for source in self.sources.values_mut() {
299-
// Skip everything but minified JS files.
300-
if source.ty != SourceFileType::MinifiedSource {
301-
continue;
302-
}
299+
let mut already_associated_sourcemaps = HashSet::new();
303300

304-
if self.sourcemap_references.contains_key(&source.url) {
305-
continue;
306-
}
307-
308-
let Ok(contents) = std::str::from_utf8(&source.contents) else {
309-
continue;
310-
};
301+
let unassociated_js_source_locations: HashMap<_, _> = self
302+
.sources
303+
.values_mut()
304+
.filter(|source| source.ty == SourceFileType::MinifiedSource)
305+
.filter(|source| !self.sourcemap_references.contains_key(&source.url))
306+
.filter_map(|source| {
307+
str::from_utf8(&source.contents.clone())
308+
.map(|contents| {
309+
(
310+
source,
311+
discover_sourcemaps_location(contents)
312+
.filter(|loc| !is_remote_sourcemap(loc))
313+
.map(String::from),
314+
)
315+
})
316+
.ok()
317+
})
318+
.collect();
311319

312-
// If this is a full external URL, the code below is going to attempt
313-
// to "normalize" it with the source path, resulting in a bogus path
314-
// like "path/to/source/dir/https://some-static-host.example.com/path/to/foo.js.map"
315-
// that can't be resolved to a source map file.
316-
// Instead, we pretend we failed to discover the location, and we fall back to
317-
// guessing the source map location based on the source location.
318-
let location =
319-
discover_sourcemaps_location(contents).filter(|loc| !is_remote_sourcemap(loc));
320-
let sourcemap_reference = match location {
321-
Some(url) => SourceMapReference::from_url(url.to_owned()),
322-
None => match guess_sourcemap_reference(&sourcemaps, &source.url) {
323-
Ok(target) => target,
324-
Err(err) => {
320+
// First pass: if location discovered, add to sourcemap_references
321+
unassociated_js_source_locations
322+
.iter()
323+
.filter_map(|(source, location)| location.as_ref().map(|location| (source, location)))
324+
.for_each(|(source, location)| {
325+
// Add location to already associated sourcemaps, so we cannot guess it again.
326+
already_associated_sourcemaps.insert(location.to_owned());
327+
328+
self.sourcemap_references.insert(
329+
source.url.clone(),
330+
Some(SourceMapReference::from_url(location.to_owned())),
331+
);
332+
});
333+
334+
// Second pass: for remaining sourcemaps, try to guess the location
335+
unassociated_js_source_locations
336+
.into_iter()
337+
.filter(|(_, location)| location.is_none())
338+
.for_each(|(source, _)| {
339+
let sourcemap_reference = guess_sourcemap_reference(&sourcemaps, &source.url)
340+
.inspect_err(|err| {
325341
source.warn(format!(
326342
"could not determine a source map reference ({err})"
327343
));
328-
self.sourcemap_references.insert(source.url.clone(), None);
329-
continue;
330-
}
331-
},
332-
};
344+
})
345+
.ok()
346+
.filter(|sourcemap_reference| {
347+
!already_associated_sourcemaps.contains(&sourcemap_reference.url)
348+
})
349+
.inspect(|sourcemap_reference| {
350+
// In practice, original_url is always set in guess_sourcemap_reference
351+
if let Some(original_url) =
352+
sourcemap_reference.original_url.as_ref().cloned()
353+
{
354+
// Add original url to already associated sourcemaps, so we cannot guess it again.
355+
already_associated_sourcemaps.insert(original_url);
356+
}
357+
});
333358

334-
self.sourcemap_references
335-
.insert(source.url.clone(), Some(sourcemap_reference));
336-
}
359+
self.sourcemap_references
360+
.insert(source.url.clone(), sourcemap_reference);
361+
});
337362
}
338363

339364
pub fn dump_log(&self, title: &str) {

tests/integration/_expected_outputs/sourcemaps/sourcemaps-inject-double-association/app.min.js

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/_expected_outputs/sourcemaps/sourcemaps-inject-double-association/app.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2e90f2e7-d739-5d15-a4f7-682a3acecf3e")}catch(e){}}();
1+
2+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f3aa1477-a45c-540a-9905-f6d9f6d1d7e1")}catch(e){}}();
23
!function(e,t){"use strict";function n(e){return document.querySelector(e)}function r(e,t){e.textContent=t}var o=n("#message");r(o,"Hello World!")}(window,document);
34
//# sourceMappingURL=app.min.js.map
45

5-
//# debugId=2e90f2e7-d739-5d15-a4f7-682a3acecf3e
6+
//# debugId=f3aa1477-a45c-540a-9905-f6d9f6d1d7e1

0 commit comments

Comments
 (0)