1
1
//! Searches, processes and uploads release files.
2
2
use std:: collections:: { BTreeMap , HashMap } ;
3
+ use std:: ffi:: OsStr ;
3
4
use std:: fmt:: { self , Display } ;
4
5
use std:: io:: BufWriter ;
5
6
use std:: path:: PathBuf ;
@@ -16,6 +17,7 @@ use rayon::ThreadPoolBuilder;
16
17
use sentry:: types:: DebugId ;
17
18
use sha1_smol:: Digest ;
18
19
use symbolic:: common:: ByteView ;
20
+ use symbolic:: debuginfo:: js;
19
21
use symbolic:: debuginfo:: sourcebundle:: {
20
22
SourceBundleErrorKind , SourceBundleWriter , SourceFileInfo , SourceFileType ,
21
23
} ;
@@ -29,6 +31,8 @@ use crate::utils::chunks::{upload_chunks, Chunk, ASSEMBLE_POLL_INTERVAL};
29
31
use crate :: utils:: fs:: { get_sha1_checksum, get_sha1_checksums, TempFile } ;
30
32
use crate :: utils:: progress:: { ProgressBar , ProgressBarMode , ProgressStyle } ;
31
33
34
+ use super :: file_search:: ReleaseFileMatch ;
35
+
32
36
/// Fallback concurrency for release file uploads.
33
37
static DEFAULT_CONCURRENCY : usize = 4 ;
34
38
@@ -239,6 +243,68 @@ pub struct SourceFile {
239
243
}
240
244
241
245
impl SourceFile {
246
+ pub fn from_release_file_match ( url : & str , mut file : ReleaseFileMatch ) -> SourceFile {
247
+ let ( ty, debug_id) = if sourcemap:: is_sourcemap_slice ( & file. contents ) {
248
+ (
249
+ SourceFileType :: SourceMap ,
250
+ std:: str:: from_utf8 ( & file. contents )
251
+ . ok ( )
252
+ . and_then ( js:: discover_sourcemap_embedded_debug_id) ,
253
+ )
254
+ } else if file
255
+ . path
256
+ . file_name ( )
257
+ . and_then ( OsStr :: to_str)
258
+ . map ( |x| x. ends_with ( "bundle" ) )
259
+ . unwrap_or ( false )
260
+ && sourcemap:: ram_bundle:: is_ram_bundle_slice ( & file. contents )
261
+ {
262
+ ( SourceFileType :: IndexedRamBundle , None )
263
+ } else if is_hermes_bytecode ( & file. contents ) {
264
+ // This is actually a big hack:
265
+ // For the react-native Hermes case, we skip uploading the bytecode bundle,
266
+ // and rather flag it as an empty "minified source". That way, it
267
+ // will get a SourceMap reference, and the server side processor
268
+ // should deal with it accordingly.
269
+ file. contents . clear ( ) ;
270
+ ( SourceFileType :: MinifiedSource , None )
271
+ } else {
272
+ // Here, we use MinifiedSource for historical reasons. We used to guess whether
273
+ // a JS file was a minified file or a source file, and we would treat these files
274
+ // differently when uploading or injecting them. However, the desired behavior is
275
+ // and has always been to treat all JS files the same, since users should be
276
+ // responsible for providing the file paths for only files they would like to have
277
+ // uploaded or injected. The minified file guessing furthermore was not reliable,
278
+ // since minification is not a necessary step in the JS build process.
279
+ //
280
+ // We use MinifiedSource here rather than Source because we want to treat all JS
281
+ // files the way we used to treat minified files only. To use Source, we would need
282
+ // to analyze all possible code paths that check this value, and update those as
283
+ // well. To keep the change minimal, we use MinifiedSource here.
284
+ (
285
+ SourceFileType :: MinifiedSource ,
286
+ std:: str:: from_utf8 ( & file. contents )
287
+ . ok ( )
288
+ . and_then ( js:: discover_debug_id) ,
289
+ )
290
+ } ;
291
+
292
+ let mut source_file = SourceFile {
293
+ url : url. into ( ) ,
294
+ path : file. path ,
295
+ contents : file. contents . into ( ) ,
296
+ ty,
297
+ headers : BTreeMap :: new ( ) ,
298
+ messages : vec ! [ ] ,
299
+ already_uploaded : false ,
300
+ } ;
301
+
302
+ if let Some ( debug_id) = debug_id {
303
+ source_file. set_debug_id ( debug_id. to_string ( ) ) ;
304
+ }
305
+ source_file
306
+ }
307
+
242
308
/// Calculates and returns the SHA1 checksum of the file.
243
309
pub fn checksum ( & self ) -> Result < Digest > {
244
310
get_sha1_checksum ( & * * self . contents )
@@ -753,6 +819,13 @@ fn print_upload_context_details(context: &UploadContext) {
753
819
) ;
754
820
}
755
821
822
+ fn is_hermes_bytecode ( slice : & [ u8 ] ) -> bool {
823
+ // The hermes bytecode format magic is defined here:
824
+ // https://github.com/facebook/hermes/blob/5243222ef1d92b7393d00599fc5cff01d189a88a/include/hermes/BCGen/HBC/BytecodeFileFormat.h#L24-L25
825
+ const HERMES_MAGIC : [ u8 ; 8 ] = [ 0xC6 , 0x1F , 0xBC , 0x03 , 0xC1 , 0x03 , 0x19 , 0x1F ] ;
826
+ slice. starts_with ( & HERMES_MAGIC )
827
+ }
828
+
756
829
#[ cfg( test) ]
757
830
mod tests {
758
831
use sha1_smol:: Sha1 ;
0 commit comments