feat(swc): Allow removing filename from error output (#2498)

swc:
 - Add an option to exclude filename from error messages.
This commit is contained in:
Donny/강동윤 2021-10-21 13:45:12 +09:00 committed by GitHub
parent d83bde8ca5
commit ecf0d7507c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 107 additions and 54 deletions

12
Cargo.lock generated
View File

@ -194,9 +194,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.61" version = "0.3.62"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -1317,9 +1317,9 @@ dependencies = [
[[package]] [[package]]
name = "object" name = "object"
version = "0.26.2" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" checksum = "c821014c18301591b89b843809ef953af9e3df0496c232d5c0611b0a52aac363"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -2325,7 +2325,7 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]] [[package]]
name = "swc" name = "swc"
version = "0.76.1" version = "0.77.0"
dependencies = [ dependencies = [
"ahash", "ahash",
"anyhow", "anyhow",
@ -2473,7 +2473,7 @@ dependencies = [
[[package]] [[package]]
name = "swc_common" name = "swc_common"
version = "0.14.1" version = "0.14.2"
dependencies = [ dependencies = [
"ahash", "ahash",
"arbitrary", "arbitrary",

View File

@ -21,7 +21,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
name = "swc" name = "swc"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
version = "0.76.1" version = "0.77.0"
[lib] [lib]
name = "swc" name = "swc"

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
name = "swc_common" name = "swc_common"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
version = "0.14.1" version = "0.14.2"
[features] [features]
concurrent = ["parking_lot"] concurrent = ["parking_lot"]

View File

@ -139,6 +139,8 @@ pub struct EmitterWriter {
short_message: bool, short_message: bool,
teach: bool, teach: bool,
ui_testing: bool, ui_testing: bool,
skip_filename: bool,
} }
struct FileWithAnnotatedLines { struct FileWithAnnotatedLines {
@ -162,6 +164,7 @@ impl EmitterWriter {
short_message, short_message,
teach, teach,
ui_testing: false, ui_testing: false,
skip_filename: false,
} }
} }
} }
@ -179,6 +182,7 @@ impl EmitterWriter {
short_message, short_message,
teach, teach,
ui_testing: false, ui_testing: false,
skip_filename: false,
} }
} }
@ -187,6 +191,11 @@ impl EmitterWriter {
self self
} }
pub fn skip_filename(mut self, skip_filename: bool) -> Self {
self.skip_filename = skip_filename;
self
}
fn maybe_anonymized(&self, line_num: usize) -> String { fn maybe_anonymized(&self, line_num: usize) -> String {
if self.ui_testing { if self.ui_testing {
ANONYMIZED_LINE_NUM.to_string() ANONYMIZED_LINE_NUM.to_string()
@ -1011,7 +1020,9 @@ impl EmitterWriter {
// remember where we are in the output buffer for easy reference // remember where we are in the output buffer for easy reference
let buffer_msg_line_offset = buffer.num_lines(); let buffer_msg_line_offset = buffer.num_lines();
if !self.skip_filename {
buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber); buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber);
buffer.append( buffer.append(
buffer_msg_line_offset, buffer_msg_line_offset,
&format!( &format!(
@ -1022,6 +1033,8 @@ impl EmitterWriter {
), ),
Style::LineAndColumn, Style::LineAndColumn,
); );
}
for _ in 0..max_line_num_len { for _ in 0..max_line_num_len {
buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle); buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle);
} }

View File

@ -108,6 +108,7 @@
"stmts", "stmts",
"succ", "succ",
"sugg", "sugg",
"swcify",
"swcpack", "swcpack",
"swcrc", "swcrc",
"termcolor", "termcolor",
@ -115,7 +116,8 @@
"uncons", "uncons",
"Unexported", "Unexported",
"Unexporter", "Unexporter",
"unimpl" "unimpl",
"untrusted"
], ],
"flagWords": [ "flagWords": [
"actally" "actally"

View File

@ -160,3 +160,17 @@ it("should respect `inlineSourcesContent`", async () => {
expect(j).toHaveProperty('sourcesContent') expect(j).toHaveProperty('sourcesContent')
}); });
it("should respect `error.filename = false`", async () => {
const src = 'export default <h1>';
try {
await swc.transform(src, {
error: {
filename: false
}
})
} catch (e) {
expect(e).not.toContain("-->")
}
});

View File

@ -48,7 +48,7 @@ impl Task for MinifyTask {
type JsValue = JsObject; type JsValue = JsObject;
fn compute(&mut self) -> napi::Result<Self::Output> { fn compute(&mut self) -> napi::Result<Self::Output> {
try_with(self.c.cm.clone(), |handler| { try_with(self.c.cm.clone(), false, |handler| {
let fm = self.code.to_file(self.c.cm.clone()); let fm = self.code.to_file(self.c.cm.clone());
self.c.minify(fm, &handler, &self.opts) self.c.minify(fm, &handler, &self.opts)
@ -82,7 +82,8 @@ pub fn minify_sync(cx: CallContext) -> napi::Result<JsObject> {
let fm = code.to_file(c.cm.clone()); let fm = code.to_file(c.cm.clone());
let output = try_with(c.cm.clone(), |handler| c.minify(fm, &handler, &opts)).convert_err()?; let output =
try_with(c.cm.clone(), false, |handler| c.minify(fm, &handler, &opts)).convert_err()?;
complete_output(&cx.env, output) complete_output(&cx.env, output)
} }

View File

@ -38,7 +38,7 @@ impl Task for ParseTask {
type JsValue = JsString; type JsValue = JsString;
fn compute(&mut self) -> napi::Result<Self::Output> { fn compute(&mut self) -> napi::Result<Self::Output> {
let program = try_with(self.c.cm.clone(), |handler| { let program = try_with(self.c.cm.clone(), false, |handler| {
self.c.parse_js( self.c.parse_js(
self.fm.clone(), self.fm.clone(),
&handler, &handler,
@ -63,7 +63,7 @@ impl Task for ParseFileTask {
type JsValue = JsString; type JsValue = JsString;
fn compute(&mut self) -> napi::Result<Self::Output> { fn compute(&mut self) -> napi::Result<Self::Output> {
try_with(self.c.cm.clone(), |handler| { try_with(self.c.cm.clone(), false, |handler| {
self.c.run(|| { self.c.run(|| {
let fm = self let fm = self
.c .c
@ -125,7 +125,7 @@ pub fn parse_sync(cx: CallContext) -> napi::Result<JsString> {
FileName::Anon FileName::Anon
}; };
let program = try_with(c.cm.clone(), |handler| { let program = try_with(c.cm.clone(), false, |handler| {
c.run(|| { c.run(|| {
let fm = c.cm.new_source_file(filename, src); let fm = c.cm.new_source_file(filename, src);
c.parse_js( c.parse_js(
@ -150,7 +150,7 @@ pub fn parse_file_sync(cx: CallContext) -> napi::Result<JsString> {
let options: ParseOptions = cx.get_deserialized(1)?; let options: ParseOptions = cx.get_deserialized(1)?;
let program = { let program = {
try_with(c.cm.clone(), |handler| { try_with(c.cm.clone(), false, |handler| {
let fm = let fm =
c.cm.load_file(Path::new(path.as_str()?)) c.cm.load_file(Path::new(path.as_str()?))
.expect("failed to read program file"); .expect("failed to read program file");

View File

@ -35,7 +35,10 @@ impl Task for TransformTask {
type JsValue = JsObject; type JsValue = JsObject;
fn compute(&mut self) -> napi::Result<Self::Output> { fn compute(&mut self) -> napi::Result<Self::Output> {
try_with(self.c.cm.clone(), |handler| { try_with(
self.c.cm.clone(),
!self.options.config.error.filename,
|handler| {
self.c.run(|| match self.input { self.c.run(|| match self.input {
Input::Program(ref s) => { Input::Program(ref s) => {
let program: Program = let program: Program =
@ -49,9 +52,12 @@ impl Task for TransformTask {
self.c.process_js_file(fm, &handler, &self.options) self.c.process_js_file(fm, &handler, &self.options)
} }
Input::Source(ref s) => self.c.process_js_file(s.clone(), &handler, &self.options), Input::Source(ref s) => {
}) self.c.process_js_file(s.clone(), &handler, &self.options)
}
}) })
},
)
.convert_err() .convert_err()
} }
@ -93,7 +99,7 @@ where
options.config.adjust(Path::new(&options.filename)); options.config.adjust(Path::new(&options.filename));
} }
let output = try_with(c.cm.clone(), |handler| { let output = try_with(c.cm.clone(), !options.config.error.filename, |handler| {
c.run(|| { c.run(|| {
if is_module.get_value()? { if is_module.get_value()? {
let program: Program = let program: Program =

View File

@ -8,11 +8,11 @@ use std::{
use swc::try_with_handler; use swc::try_with_handler;
use swc_common::{errors::Handler, sync::Lrc, SourceMap}; use swc_common::{errors::Handler, sync::Lrc, SourceMap};
pub fn try_with<F, Ret>(cm: Lrc<SourceMap>, op: F) -> Result<Ret, Error> pub fn try_with<F, Ret>(cm: Lrc<SourceMap>, skip_filename: bool, op: F) -> Result<Ret, Error>
where where
F: FnOnce(&Handler) -> Result<Ret, Error>, F: FnOnce(&Handler) -> Result<Ret, Error>,
{ {
try_with_handler(cm, |handler| { try_with_handler(cm, skip_filename, |handler| {
// //
let result = catch_unwind(AssertUnwindSafe(|| op(handler))); let result = catch_unwind(AssertUnwindSafe(|| op(handler)));

View File

@ -290,7 +290,7 @@ impl SwcLoader {
impl Load for SwcLoader { impl Load for SwcLoader {
fn load(&self, name: &FileName) -> Result<ModuleData, Error> { fn load(&self, name: &FileName) -> Result<ModuleData, Error> {
try_with_handler(self.compiler.cm.clone(), |handler| { try_with_handler(self.compiler.cm.clone(), false, |handler| {
self.load_with_handler(&handler, name) self.load_with_handler(&handler, name)
}) })
} }

View File

@ -526,6 +526,9 @@ pub struct Config {
#[serde(default = "true_by_default")] #[serde(default = "true_by_default")]
pub inline_sources_content: bool, pub inline_sources_content: bool,
#[serde(default)]
pub error: ErrorConfig,
} }
/// Second argument of `minify`. /// Second argument of `minify`.
@ -988,6 +991,13 @@ fn default_jsonify_min_cost() -> usize {
1024 1024
} }
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct ErrorConfig {
#[serde(default = "true_by_default")]
pub filename: bool,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)] #[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")] #[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct GlobalPassOption { pub struct GlobalPassOption {

View File

@ -117,7 +117,7 @@ use crate::config::{
}; };
use anyhow::{bail, Context, Error}; use anyhow::{bail, Context, Error};
use atoms::JsWord; use atoms::JsWord;
use common::collections::AHashMap; use common::{collections::AHashMap, errors::EmitterWriter};
use config::{util::BoolOrObject, JsMinifyCommentOption, JsMinifyOptions}; use config::{util::BoolOrObject, JsMinifyCommentOption, JsMinifyOptions};
use dashmap::DashMap; use dashmap::DashMap;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -210,13 +210,19 @@ impl Write for LockedWriter {
/// Try operation with a [Handler] and prints the errors as a [String] wrapped /// Try operation with a [Handler] and prints the errors as a [String] wrapped
/// by [Err]. /// by [Err].
pub fn try_with_handler<F, Ret>(cm: Lrc<SourceMap>, op: F) -> Result<Ret, Error> pub fn try_with_handler<F, Ret>(
cm: Lrc<SourceMap>,
skip_filename: bool,
op: F,
) -> Result<Ret, Error>
where where
F: FnOnce(&Handler) -> Result<Ret, Error>, F: FnOnce(&Handler) -> Result<Ret, Error>,
{ {
let wr = Box::new(LockedWriter::default()); let wr = Box::new(LockedWriter::default());
let handler = Handler::with_emitter_writer(wr.clone(), Some(cm.clone())); let e_wr =
EmitterWriter::new(wr.clone(), Some(cm.clone()), false, true).skip_filename(skip_filename);
let handler = Handler::with_emitter(true, false, Box::new(e_wr));
let ret = swc_ecma_utils::HANDLER.set(&handler, || op(&handler)); let ret = swc_ecma_utils::HANDLER.set(&handler, || op(&handler));

View File

@ -2,12 +2,12 @@ use std::path::Path;
use swc::{config::Options, Compiler}; use swc::{config::Options, Compiler};
use testing::{NormalizedOutput, Tester}; use testing::{NormalizedOutput, Tester};
fn file(f: &str) -> NormalizedOutput { fn file(f: impl AsRef<Path>) -> NormalizedOutput {
Tester::new() Tester::new()
.print_errors(|cm, handler| -> Result<NormalizedOutput, _> { .print_errors(|cm, handler| -> Result<NormalizedOutput, _> {
let c = Compiler::new(cm.clone()); let c = Compiler::new(cm.clone());
let fm = cm.load_file(Path::new(f)).expect("failed to load file"); let fm = cm.load_file(f.as_ref()).expect("failed to load file");
let s = c.process_js_file( let s = c.process_js_file(
fm, fm,
&handler, &handler,

View File

@ -148,6 +148,7 @@ fn shopify_2_same_opt() {
input_source_map: InputSourceMap::Bool(false), input_source_map: InputSourceMap::Bool(false),
source_maps: None, source_maps: None,
inline_sources_content: false, inline_sources_content: false,
..Default::default()
}, },
skip_helper_injection: false, skip_helper_injection: false,
disable_hygiene: false, disable_hygiene: false,

View File

@ -19,7 +19,7 @@ pub fn minify_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
let c = compiler(); let c = compiler();
try_with_handler(c.cm.clone(), |handler| { try_with_handler(c.cm.clone(), false, |handler| {
let opts: JsMinifyOptions = opts.into_serde().context("failed to parse options")?; let opts: JsMinifyOptions = opts.into_serde().context("failed to parse options")?;
let fm = c.cm.new_source_file(FileName::Anon, s.into()); let fm = c.cm.new_source_file(FileName::Anon, s.into());
@ -38,7 +38,7 @@ pub fn parse_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
let c = compiler(); let c = compiler();
try_with_handler(c.cm.clone(), |handler| { try_with_handler(c.cm.clone(), false, |handler| {
let opts: ParseOptions = opts.into_serde().context("failed to parse options")?; let opts: ParseOptions = opts.into_serde().context("failed to parse options")?;
let fm = c.cm.new_source_file(FileName::Anon, s.into()); let fm = c.cm.new_source_file(FileName::Anon, s.into());
@ -64,7 +64,7 @@ pub fn print_sync(s: JsValue, opts: JsValue) -> Result<JsValue, JsValue> {
let c = compiler(); let c = compiler();
try_with_handler(c.cm.clone(), |_handler| { try_with_handler(c.cm.clone(), false, |_handler| {
let opts: Options = opts.into_serde().context("failed to parse options")?; let opts: Options = opts.into_serde().context("failed to parse options")?;
let program: Program = s.into_serde().context("failed to deserialize program")?; let program: Program = s.into_serde().context("failed to deserialize program")?;
@ -97,7 +97,7 @@ pub fn transform_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
let c = compiler(); let c = compiler();
try_with_handler(c.cm.clone(), |handler| { try_with_handler(c.cm.clone(), false, |handler| {
let opts: Options = opts.into_serde().context("failed to parse options")?; let opts: Options = opts.into_serde().context("failed to parse options")?;
let fm = c.cm.new_source_file( let fm = c.cm.new_source_file(