From 1826e980f79c86467cfb4b44b6d7f57a066b21cb Mon Sep 17 00:00:00 2001 From: Wilson Lin Date: Tue, 21 Jul 2020 23:27:56 +1000 Subject: [PATCH] Fix JS finishing; temporarily remove friendly function --- src/lib.rs | 23 ++++-------------- src/proc/mod.rs | 60 +++++++++++++++++++++++++++------------------- src/unit/script.rs | 6 ++--- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 41464c2..73298ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,13 +16,12 @@ mod unit; pub fn in_place(code: &mut [u8], cfg: &Cfg) -> Result { let mut proc = Processor::new(code); - match process_content(&mut proc, cfg, Namespace::Html, None) { - Ok(()) => Ok(proc.finish()), - Err(e) => Err(Error { - error_type: e, + process_content(&mut proc, cfg, Namespace::Html, None) + .map_err(|error_type| Error { + error_type, position: proc.read_len(), - }), - } + })?; + proc.finish() } pub fn in_place_str<'s>(code: &'s mut str, cfg: &Cfg) -> Result<&'s str, Error> { @@ -50,15 +49,3 @@ pub fn copy(code: &[u8], cfg: &Cfg) -> Result, Error> { Err(e) => Err(e), } } - -pub fn with_friendly_error(code: &mut [u8], cfg: &Cfg) -> Result { - let mut proc = Processor::new(code); - match process_content(&mut proc, cfg, Namespace::Html, None) { - Ok(()) => Ok(proc.finish()), - Err(e) => Err(FriendlyError { - position: proc.read_len(), - message: e.message(), - code_context: format!("{:?}", proc), - }), - } -} diff --git a/src/proc/mod.rs b/src/proc/mod.rs index bf4b903..2cc4fbb 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -2,7 +2,7 @@ use core::fmt; use std::fmt::{Debug, Formatter}; use std::ops::{Index, IndexMut}; -use crate::err::{ErrorType, ProcessingResult}; +use crate::err::{Error, ErrorType, ProcessingResult}; use crate::proc::MatchAction::*; use crate::proc::MatchMode::*; use crate::proc::range::ProcessorRange; @@ -47,7 +47,7 @@ pub enum MatchAction { #[cfg(feature = "js-esbuild")] pub struct JsMinSection { - pub src_range: ProcessorRange, + pub src: ProcessorRange, pub result: TransformResult, } @@ -313,31 +313,43 @@ impl<'d> Processor<'d> { (self.script_wg.clone(), self.script_results.clone()) } - pub fn finish(self) -> usize { + // Since we consume the Processor, we must provide a full Error with positions. + #[cfg(not(feature = "js-esbuild"))] + pub fn finish(self) -> Result { debug_assert!(self.at_end()); - #[cfg(feature = "js-esbuild")] - { - self.script_wg.wait(); - let mut results = Arc::try_unwrap(self.script_results) - .unwrap_or_else(|_| panic!("failed to acquire script results")) - .into_inner() - .unwrap(); - if !results.is_empty() { - results.sort_unstable_by_key(|r| r.src_range.start); - let mut write_start = results[0].src_range.start; - for (i, res) in results.iter().enumerate() { - let min_code = res.result.js.trim(); - if min_code.len() < res.src_range.len() { - let write_end = write_start + min_code.len(); - self.code[write_start..write_end].copy_from_slice(min_code.as_bytes()); - let next_start = results.get(i + 1).map_or(self.write_next, |r| r.src_range.start); - self.code.copy_within(res.src_range.end..next_start, write_end); - write_start = write_end + (next_start - res.src_range.end); - }; - }; + Ok(self.write_next) + } + + // Since we consume the Processor, we must provide a full Error with positions. + #[cfg(feature = "js-esbuild")] + pub fn finish(self) -> Result { + debug_assert!(self.at_end()); + self.script_wg.wait(); + let mut results = Arc::try_unwrap(self.script_results) + .unwrap_or_else(|_| panic!("failed to acquire script results")) + .into_inner() + .unwrap(); + results.sort_unstable_by_key(|r| r.src.start); + // As we write minified JS code for sections from left to right, we will be shifting code + // towards the left as previous source JS code sections shrink. We need to keep track of + // the write pointer after previous compaction. + // If there are no script sections, then we get self.write_next which will be returned. + let mut write_next = results.get(0).map_or(self.write_next, |r| r.src.start); + for (i, JsMinSection { result, src }) in results.iter().enumerate() { + // Resulting minified JS to write. + let mut js = result.js.trim().as_bytes(); + // If minified result is actually longer than source, then write source instead. + // NOTE: We still need to write source as previous iterations may have shifted code down. + if js.len() >= src.len() { + js = &self[src]; }; + let write_end = write_next + js.len(); + self.code[write_next..write_end].copy_from_slice(js.as_bytes()); + let next_start = results.get(i + 1).map_or(self.write_next, |r| r.src.start); + self.code.copy_within(src.end..next_start, write_end); + write_next = write_end + (next_start - src.end); }; - self.write_next + Ok(write_next) } } diff --git a/src/unit/script.rs b/src/unit/script.rs index 111ab91..9fd1abf 100644 --- a/src/unit/script.rs +++ b/src/unit/script.rs @@ -37,12 +37,12 @@ pub fn process_script(proc: &mut Processor, cfg: &Cfg) -> ProcessingResult<()> { #[cfg(feature = "js-esbuild")] if cfg.minify_js { let (wg, results) = proc.new_script_section(); - let src_range = start.written_range(proc); + let src = start.written_range(proc); // TODO Optimise: Avoid copying to new Vec. - let src = Arc::new(proc[src_range].to_vec()); + let src = Arc::new(proc[src].to_vec()); esbuild_rs::transform(src, TRANSFORM_OPTIONS.clone(), move |result| { results.lock().unwrap().push(JsMinSection { - src_range, + src, result, }); drop(wg);