/
githubmirror
/
servo
Обзор
Документация
Войти
/
githubmirror
/
servo
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
components/script/unminify.rs
133 строки
4 KB
Narfinger
script: Do not clone script data unnecessarily (#46072)
05 июл 2026, 18:44
Не верифицирован
05 июл 2026, 18:44
3fff0bb
Код
Авторство
О чём код?
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::env; use std::fs::{File, create_dir_all}; use std::io::{Error, ErrorKind, Read, Seek, Write}; use std::path::{Path, PathBuf}; use std::process::Command; use servo_url::ServoUrl; use tempfile::NamedTempFile; use uuid::Uuid; pub(crate) trait ScriptSource { fn unminified_dir(&self) -> Option<String>; fn extract_bytes(&self) -> &[u8]; fn rewrite_source(&mut self, source: String); fn url(&self) -> ServoUrl; fn is_external(&self) -> bool; } pub(crate) fn create_temp_files() -> Option<(NamedTempFile, File)> { // Write the minified code to a temporary file and pass its path as an argument // to js-beautify to read from. Meanwhile, redirect the process' stdout into // another temporary file and read that into a string. This avoids some hangs // observed on macOS when using direct input/output pipes with very large // unminified content. let (input, output) = (NamedTempFile::new(), tempfile::tempfile()); if let (Ok(input), Ok(output)) = (input, output) { Some((input, output)) } else { log::warn!("Error creating input and output temp files"); None } } #[derive(Debug)] pub(crate) enum BeautifyFileType { Css, Js, } pub(crate) fn execute_js_beautify(input: &Path, output: File, file_type: BeautifyFileType) -> bool { let mut cmd = Command::new("js-beautify"); match file_type { BeautifyFileType::Js => (), BeautifyFileType::Css => { cmd.arg("--type").arg("css"); }, } match cmd.arg(input).stdout(output).status() { Ok(status) => status.success(), _ => { log::warn!( "Failed to execute js-beautify --type {:?}, Will store unmodified script", file_type ); false }, } } pub fn create_output_file( unminified_dir: String, url: &ServoUrl, external: Option<bool>, ) -> Result<File, Error> { let path = PathBuf::from(unminified_dir); if url.scheme() == "data" { return Err(Error::new( ErrorKind::InvalidInput, "data URLs cannot be written as unminified files", )); } // Strip the query string from the URL before using it as a file path. // '?' is a reserved character on Windows and causes file creation to fail // silently. BeforeHost..AfterPath stops the slice before the '?' separator. let url_path = &url[url::Position::BeforeHost..url::Position::AfterPath]; let (base, has_name) = match url.as_str().ends_with('/') { true => (path.join(url_path).as_path().to_owned(), false), false => (path.join(url_path).parent().unwrap().to_owned(), true), }; create_dir_all(&base)?; let path = if external.unwrap_or(true) && has_name { // External. path.join(url_path) } else { // Inline file or url ends with '/' base.join(Uuid::new_v4().to_string()) }; debug!("Unminified files will be stored in {:?}", path); File::create(path) } pub(crate) fn unminify_js(script: &mut dyn ScriptSource) { let Some(unminified_dir) = script.unminified_dir() else { return; }; if let Some((mut input, mut output)) = create_temp_files() { input.write_all(script.extract_bytes()).unwrap(); if execute_js_beautify( input.path(), output.try_clone().unwrap(), BeautifyFileType::Js, ) { let mut script_content = String::new(); output.seek(std::io::SeekFrom::Start(0)).unwrap(); output.read_to_string(&mut script_content).unwrap(); script.rewrite_source(script_content); } } match create_output_file(unminified_dir, &script.url(), Some(script.is_external())) { Ok(mut file) => file.write_all(script.extract_bytes()).unwrap(), Err(why) => warn!("Could not store script {:?}", why), } } pub(crate) fn unminified_path(dir: &str) -> String { let mut path = env::current_dir().unwrap(); path.push(dir); path.into_os_string().into_string().unwrap() }