Repository navigation
Do not fail on a warning: gate Bun.Transpiler, FileSystemRouter and Worker on LogJsc::errors_to_js #45063
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Do not fail on a warning: gate Bun.Transpiler, FileSystemRouter and Worker on LogJsc::errors_to_js #45063
Changes from all commits
4e57d90
4d4d0b9
a26613f
4440546
67e94e0
aadaa7d
212aeb2
77a74c6
183ea3d
582f5fb
377f826
5441d85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -280,17 +280,6 @@ impl Config { | |
| break 'tsconfig; | ||
| } | ||
| self.tsconfig_buf = out.to_owned_slice().into(); | ||
|
|
||
| // TODO: JSC -> Ast conversion | ||
| // SAFETY: VirtualMachine::get() returns the live singleton on the JS thread. | ||
| let vm = VirtualMachine::get().as_mut(); | ||
| if let Ok(Some(parsed_tsconfig)) = TSConfigJSON::parse( | ||
| &mut self.log, | ||
| &bun_ast::Source::init_path_string(b"tsconfig.json", &self.tsconfig_buf[..]), | ||
| &mut vm.transpiler.resolver.caches.json, | ||
| ) { | ||
| self.tsconfig = Some(parsed_tsconfig); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -325,18 +314,6 @@ impl Config { | |
| break 'macros; | ||
| } | ||
| self.macros_buf = out.to_owned_slice().into(); | ||
| let source = | ||
| bun_ast::Source::init_path_string(b"macros.json", &self.macros_buf[..]); | ||
| // SAFETY: VirtualMachine::get() returns the live singleton on the JS thread. | ||
| let vm = VirtualMachine::get().as_mut(); | ||
| let Ok(Some(json)) = vm.transpiler.resolver.caches.json.parse_json( | ||
| &mut self.log, | ||
| &source, | ||
| bun_resolver::tsconfig_json::JsonMode::Json, | ||
| ) else { | ||
| break 'macros; | ||
| }; | ||
| self.macro_map = PackageJSON::parse_macros_json(json, &mut self.log, &source); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -582,6 +559,31 @@ impl Config { | |
| } | ||
| } | ||
|
|
||
| // `tsconfig` and `macro` are parsed after `logLevel` so that it covers their diagnostics. | ||
| if !self.tsconfig_buf.is_empty() { | ||
| // SAFETY: VirtualMachine::get() returns the live singleton on the JS thread. | ||
| let vm = VirtualMachine::get().as_mut(); | ||
| if let Ok(Some(parsed_tsconfig)) = TSConfigJSON::parse( | ||
| &mut self.log, | ||
| &bun_ast::Source::init_path_string(b"tsconfig.json", &self.tsconfig_buf[..]), | ||
| &mut vm.transpiler.resolver.caches.json, | ||
| ) { | ||
| self.tsconfig = Some(parsed_tsconfig); | ||
| } | ||
| } | ||
| if !self.macros_buf.is_empty() { | ||
| let source = bun_ast::Source::init_path_string(b"macros.json", &self.macros_buf[..]); | ||
| // SAFETY: VirtualMachine::get() returns the live singleton on the JS thread. | ||
| let vm = VirtualMachine::get().as_mut(); | ||
| if let Ok(Some(json)) = vm.transpiler.resolver.caches.json.parse_json( | ||
| &mut self.log, | ||
| &source, | ||
| bun_resolver::tsconfig_json::JsonMode::Json, | ||
| ) { | ||
| self.macro_map = PackageJSON::parse_macros_json(json, &mut self.log, &source); | ||
| } | ||
| } | ||
|
|
||
| self.tree_shaking = tree_shaking.unwrap_or(false); | ||
| self.trim_unused_imports = Some(trim_unused_imports.unwrap_or(self.tree_shaking)); | ||
| Ok(()) | ||
|
|
@@ -642,8 +644,7 @@ impl TransformTask { | |
| loader: Loader, | ||
| ) -> JSValue { | ||
| let config = transpiler.config.get(); | ||
| let mut log = bun_ast::Log::init(); | ||
| log.level = config.log.level; | ||
| let log = config.log.child(); | ||
|
|
||
| // SAFETY: `ManuallyDrop` keeps this bitwise copy from freeing what the | ||
| // wrapper owns; `run` re-aims its log and arena pointers. | ||
|
|
@@ -801,31 +802,27 @@ impl TransformTask { | |
| fn then(&mut self, promise: &mut JSPromise, global: &JSGlobalObject) -> JsResult<()> { | ||
| // The job drops this `TransformTask` (running its `Drop`: transpiler | ||
| // deref etc.) right after `then` returns. | ||
| if self.log.has_any() || self.err.is_some() { | ||
| let error_value: JsResult<JSValue> = 'brk: { | ||
| if let Some(err) = &self.err { | ||
| if !self.log.has_any() { | ||
| break 'brk bun_jsc::BuildMessage::create( | ||
| global, | ||
| bun_ast::Msg { | ||
| data: bun_ast::Data { | ||
| text: err.name().as_bytes().to_vec().into(), | ||
| ..Default::default() | ||
| }, | ||
| ..Default::default() | ||
| }, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| break 'brk self.log.to_js(global, format_args!("Transform failed")); | ||
| }; | ||
|
|
||
| promise.reject_with_async_stack(global, error_value)?; | ||
| return Ok(()); | ||
| } | ||
| let log_error = self | ||
| .log | ||
| .errors_to_js(global, format_args!("Transform failed")) | ||
| .transpose(); | ||
| let error_value: JsResult<JSValue> = match (log_error, &self.err) { | ||
| (Some(value), _) => value, | ||
| (None, Some(err)) => bun_jsc::BuildMessage::create( | ||
| global, | ||
| bun_ast::Msg { | ||
| data: bun_ast::Data { | ||
| text: err.name().as_bytes().to_vec().into(), | ||
| ..Default::default() | ||
| }, | ||
| ..Default::default() | ||
| }, | ||
| ), | ||
| (None, None) => return self.finish(promise, global), | ||
| }; | ||
|
|
||
| self.finish(promise, global) | ||
| promise.reject_with_async_stack(global, error_value)?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| fn finish(&mut self, promise: &mut JSPromise, global: &JSGlobalObject) -> JsResult<()> { | ||
|
|
@@ -923,12 +920,11 @@ impl JSTranspiler { | |
|
|
||
| config.from_js(global, config_arg, arena_ref)?; | ||
|
|
||
| if (config.log.warnings + config.log.errors) > 0 { | ||
| return Err(global.throw_value( | ||
| config | ||
| .log | ||
| .to_js(global, format_args!("Failed to create transpiler"))?, | ||
| )); | ||
| if let Some(value) = config | ||
| .log | ||
| .errors_to_js(global, format_args!("Failed to create transpiler"))? | ||
| { | ||
| return Err(global.throw_value(value)); | ||
| } | ||
|
Comment on lines
+923
to
928
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 (optional) Users who pass a Why this was flaggedA caller constructs Verification: Triggering condition: any
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is decision 2 in the Notes and it is open for a maintainer. An earlier version of this change printed the warnings of the |
||
|
|
||
| // SAFETY: VirtualMachine::get() returns the live singleton on the JS thread. | ||
|
|
@@ -941,11 +937,11 @@ impl JSTranspiler { | |
| ) { | ||
| Ok(t) => t, | ||
| Err(err) => { | ||
| let log = &mut config.log; | ||
| if (log.warnings + log.errors) > 0 { | ||
| return Err(global.throw_value( | ||
| log.to_js(global, format_args!("Failed to create transpiler"))?, | ||
| )); | ||
| if let Some(value) = config | ||
| .log | ||
| .errors_to_js(global, format_args!("Failed to create transpiler"))? | ||
| { | ||
| return Err(global.throw_value(value)); | ||
| } | ||
| return Err(global.throw_error(err, "Error creating transpiler")); | ||
| } | ||
|
|
@@ -979,11 +975,11 @@ impl JSTranspiler { | |
| transpiler.configure_linker_with_auto_jsx(false); | ||
| transpiler.options.env.behavior = options::EnvBehavior::disable; | ||
| if let Err(err) = transpiler.configure_defines() { | ||
| let log = &mut config.log; | ||
| if (log.warnings + log.errors) > 0 { | ||
| return Err( | ||
| global.throw_value(log.to_js(global, format_args!("Failed to load define"))?) | ||
| ); | ||
| if let Some(value) = config | ||
| .log | ||
| .errors_to_js(global, format_args!("Failed to load define"))? | ||
| { | ||
| return Err(global.throw_value(value)); | ||
| } | ||
| return Err(global.throw_error(err, "Failed to load define")); | ||
| } | ||
|
|
@@ -1237,7 +1233,7 @@ impl JSTranspiler { | |
| let loader: Option<Loader> = loader_from_js(global, loader_arg.to_js())?; | ||
|
|
||
| let arena = Arena::new(); | ||
| let mut log = bun_ast::Log::init(); | ||
| let mut log = self.config.get().log.child(); | ||
| // SAFETY: `arena` outlives every use through `self.transpiler` in this fn body; | ||
| // `_restore` (declared after `arena`/`log`, so dropped first) restores | ||
| // `prev_arena` and `&self.config.log` before either local drops. | ||
|
|
@@ -1261,17 +1257,13 @@ impl JSTranspiler { | |
|
|
||
| let parse_result = self.get_parse_result(arena_ref, code, loader, MacroJSCtx::ZERO); | ||
| let log_ref = self.transpiler.get().log_mut(); | ||
| if let Some(value) = log_ref.errors_to_js(global, format_args!("Parse error"))? { | ||
| return Err(global.throw_value(value)); | ||
| } | ||
| let Some(mut parse_result) = parse_result else { | ||
| if (log_ref.warnings + log_ref.errors) > 0 { | ||
| return Err(global.throw_value(log_ref.to_js(global, format_args!("Parse error"))?)); | ||
| } | ||
| return Err(global.throw(format_args!("Failed to parse"))); | ||
| }; | ||
|
|
||
| if (log_ref.warnings + log_ref.errors) > 0 { | ||
| return Err(global.throw_value(log_ref.to_js(global, format_args!("Parse error"))?)); | ||
| } | ||
|
|
||
| let exports_label = EncodedSlice::latin1(b"exports"); | ||
| let imports_label = EncodedSlice::latin1(b"imports"); | ||
| let named_imports_value = named_imports_to_js( | ||
|
|
@@ -1380,8 +1372,7 @@ impl JSTranspiler { | |
| // (`prev_bundler = this.transpiler`) and restores it on exit. `Transpiler` is not | ||
| // bitwise-copyable in Rust, so explicitly snapshot the fields the body mutates | ||
| // (`allocator`, `log`, `macro_context`) and restore them via RAII guard. | ||
| let mut log = bun_ast::Log::init(); | ||
| log.level = self.config.get().log.level; | ||
| let mut log = self.config.get().log.child(); | ||
| // SAFETY: `arena` outlives every use through `self.transpiler` in this fn body; | ||
| // `_restore` (declared after `arena`/`log`, so dropped first) restores | ||
| // `prev_arena`, `&self.config.log`, and `prev_macro_context` before either drops. | ||
|
|
@@ -1406,17 +1397,13 @@ impl JSTranspiler { | |
| let macro_js_ctx: MacroJSCtx = MacroJSCtx(js_ctx_value.0 as i64); | ||
| let parse_result = self.get_parse_result(arena_ref, code, loader, macro_js_ctx); | ||
| let log_ref = self.transpiler.get().log_mut(); | ||
| if let Some(value) = log_ref.errors_to_js(global, format_args!("Parse error"))? { | ||
| return Err(global.throw_value(value)); | ||
| } | ||
| let Some(parse_result) = parse_result else { | ||
| if (log_ref.warnings + log_ref.errors) > 0 { | ||
| return Err(global.throw_value(log_ref.to_js(global, format_args!("Parse error"))?)); | ||
| } | ||
| return Err(global.throw(format_args!("Failed to parse code"))); | ||
| }; | ||
|
|
||
| if (log_ref.warnings + log_ref.errors) > 0 { | ||
| return Err(global.throw_value(log_ref.to_js(global, format_args!("Parse error"))?)); | ||
| } | ||
|
|
||
| let mut buffer_writer = self.buffer_writer.replace(None).unwrap_or_else(|| { | ||
| let mut writer = JSPrinter::BufferWriter::init(); | ||
| bun_core::handle_oom(writer.buffer.grow_if_needed(code.len())); | ||
|
|
@@ -1531,7 +1518,7 @@ impl JSTranspiler { | |
| } | ||
|
|
||
| let arena = Arena::new(); | ||
| let mut log = bun_ast::Log::init(); | ||
| let mut log = self.config.get().log.child(); | ||
| // SAFETY: `arena` outlives every use through `self.transpiler` in this fn body; | ||
| // `_restore` (declared after `arena`/`log`, so dropped first) restores | ||
| // `prev_arena` and `&self.config.log` before either local drops. | ||
|
|
@@ -1594,20 +1581,13 @@ impl JSTranspiler { | |
| // (including the error paths). Compute the result, then reset | ||
| // unconditionally before returning. | ||
| let result = (|| -> JsResult<JSValue> { | ||
| if let Some(value) = log.errors_to_js(global, format_args!("Failed to scan imports"))? { | ||
| return Err(global.throw_value(value)); | ||
| } | ||
| if let Err(err) = scan_result { | ||
| if (log.warnings + log.errors) > 0 { | ||
| return Err(global | ||
| .throw_value(log.to_js(global, format_args!("Failed to scan imports"))?)); | ||
| } | ||
| return Err(global.throw_error(err, "Failed to scan imports")); | ||
| } | ||
|
|
||
| if (log.warnings + log.errors) > 0 { | ||
| return Err( | ||
| global.throw_value(log.to_js(global, format_args!("Failed to scan imports"))?) | ||
| ); | ||
| } | ||
|
|
||
| named_imports_to_js( | ||
| global, | ||
| self.scan_pass_result.get().import_records.as_slice(), | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.