use crate::schema::api;
use bun_collections::ArrayHashMap;
use crate::bundle_enums;
use crate::code_coverage_options::CodeCoverageOptions;
use crate::compile_target::CompileTarget;
use crate::global_cache::GlobalCache;
use crate::offline_mode::OfflineMode;
pub struct ContextData {
pub start_time: i128,
pub args: api::TransformOptions,
pub log: *mut bun_ast::Log,
pub positionals: Vec<Box<[u8]>>,
pub passthrough: Vec<Box<[u8]>>,
pub install: Option<Box<api::BunInstall>>,
pub debug: DebugOptions,
pub test_options: TestOptions,
pub bundler_options: BundlerOptions,
pub runtime_options: RuntimeOptions,
pub filters: Vec<Box<[u8]>>,
pub workspaces: bool,
pub if_present: bool,
pub parallel: bool,
pub sequential: bool,
pub no_exit_on_error: bool,
pub preloads: Vec<Box<[u8]>>,
pub has_loaded_global_config: bool,
}
impl Default for ContextData {
#[inline(always)]
fn default() -> Self {
Self {
start_time: 0,
args: api::TransformOptions::default(),
log: core::ptr::null_mut(),
positionals: Vec::new(),
passthrough: Vec::new(),
install: None,
debug: DebugOptions::default(),
test_options: TestOptions::default(),
bundler_options: BundlerOptions::default(),
runtime_options: RuntimeOptions::default(),
filters: Vec::new(),
workspaces: false,
if_present: false,
parallel: false,
sequential: false,
no_exit_on_error: false,
preloads: Vec::new(),
has_loaded_global_config: false,
}
}
}
impl ContextData {
#[inline]
pub unsafe fn log(&mut self) -> &mut bun_ast::Log {
debug_assert!(!self.log.is_null());
unsafe { &mut *self.log }
}
#[track_caller]
#[inline]
#[allow(clippy::mut_from_ref)]
pub unsafe fn log_mut(&self) -> &mut bun_ast::Log {
assert!(
!self.log.is_null(),
"ContextData::log_mut() before create_context_data()"
);
unsafe { &mut *self.log }
}
#[track_caller]
#[inline]
pub fn log_ref(&self) -> &bun_ast::Log {
assert!(
!self.log.is_null(),
"ContextData::log_ref() before create_context_data()"
);
unsafe { &*self.log }
}
pub const CREATE_SEE_CLI: () = ();
}
pub struct BundlerOptions {
pub outdir: Box<[u8]>,
pub outfile: Box<[u8]>,
pub metafile: Box<[u8]>,
pub metafile_md: Box<[u8]>,
pub root_dir: Box<[u8]>,
pub public_path: Box<[u8]>,
pub entry_naming: Box<[u8]>,
pub chunk_naming: Box<[u8]>,
pub asset_naming: Box<[u8]>,
pub server_components: bool,
pub react_fast_refresh: bool,
pub code_splitting: bool,
pub transform_only: bool,
pub inline_entrypoint_import_meta_main: bool,
pub minify_syntax: bool,
pub minify_whitespace: bool,
pub minify_identifiers: bool,
pub keep_names: bool,
pub ignore_dce_annotations: bool,
pub emit_dce_annotations: bool,
pub output_format: bundle_enums::Format,
pub bytecode: bool,
pub banner: Box<[u8]>,
pub footer: Box<[u8]>,
pub css_chunking: bool,
pub bake: bool,
pub bake_debug_dump_server: bool,
pub bake_debug_disable_minify: bool,
pub production: bool,
pub env_behavior: api::DotEnvBehavior,
pub env_prefix: Box<[u8]>,
pub elide_lines: Option<usize>,
pub compile: bool,
pub compile_target: CompileTarget,
pub compile_exec_argv: Option<Box<[u8]>>,
pub compile_autoload_dotenv: bool,
pub compile_autoload_bunfig: bool,
pub compile_autoload_tsconfig: bool,
pub compile_autoload_package_json: bool,
pub compile_executable_path: Option<Box<[u8]>>,
pub windows: bundle_enums::WindowsOptions,
pub allow_unresolved: Option<Vec<Box<[u8]>>>,
}
impl Default for BundlerOptions {
#[inline(always)]
fn default() -> Self {
Self {
outdir: Box::default(),
outfile: Box::default(),
metafile: Box::default(),
metafile_md: Box::default(),
root_dir: Box::default(),
public_path: Box::default(),
entry_naming: Box::from(&b"[dir]/[name].[ext]"[..]),
chunk_naming: Box::from(&b"./[name]-[hash].[ext]"[..]),
asset_naming: Box::from(&b"./[name]-[hash].[ext]"[..]),
server_components: false,
react_fast_refresh: false,
code_splitting: false,
transform_only: false,
inline_entrypoint_import_meta_main: false,
minify_syntax: false,
minify_whitespace: false,
minify_identifiers: false,
keep_names: false,
ignore_dce_annotations: false,
emit_dce_annotations: true,
output_format: bundle_enums::Format::Esm,
bytecode: false,
banner: Box::default(),
footer: Box::default(),
css_chunking: false,
bake: false,
bake_debug_dump_server: false,
bake_debug_disable_minify: false,
production: false,
env_behavior: api::DotEnvBehavior::disable,
env_prefix: Box::default(),
elide_lines: None,
compile: false,
compile_target: CompileTarget::default(),
compile_exec_argv: None,
compile_autoload_dotenv: true,
compile_autoload_bunfig: true,
compile_autoload_tsconfig: false,
compile_autoload_package_json: false,
compile_executable_path: None,
windows: bundle_enums::WindowsOptions::default(),
allow_unresolved: None,
}
}
}
pub type Context<'a> = &'a mut ContextData;
static GLOBAL_CLI_CTX: core::sync::atomic::AtomicPtr<ContextData> =
core::sync::atomic::AtomicPtr::new(core::ptr::null_mut());
#[inline]
pub unsafe fn set_global(ctx: *mut ContextData) {
GLOBAL_CLI_CTX.store(ctx, core::sync::atomic::Ordering::Release);
}
#[inline]
pub fn global_ptr() -> *mut ContextData {
GLOBAL_CLI_CTX.load(core::sync::atomic::Ordering::Acquire)
}
#[inline]
pub fn try_get<'a>() -> Option<&'a ContextData> {
let p = GLOBAL_CLI_CTX.load(core::sync::atomic::Ordering::Acquire);
unsafe { p.as_ref() }
}
pub struct DebugOptions {
pub dump_environment_variables: bool,
pub dump_limits: bool,
pub fallback_only: bool,
pub silent: bool,
pub hot_reload: HotReload,
pub global_cache: GlobalCache,
pub offline_mode_setting: Option<OfflineMode>,
pub run_in_bun: bool,
pub loaded_bunfig: bool,
pub use_system_shell: bool,
pub macros: MacroOptions,
pub editor: Box<[u8]>,
pub package_bundle_map: ArrayHashMap<Box<[u8]>, bundle_enums::BundlePackage>,
pub test_directory: Box<[u8]>,
pub output_file: Box<[u8]>,
}
impl Default for DebugOptions {
#[inline(always)]
fn default() -> Self {
Self {
dump_environment_variables: false,
dump_limits: false,
fallback_only: false,
silent: false,
hot_reload: HotReload::None,
global_cache: GlobalCache::auto,
offline_mode_setting: None,
run_in_bun: false,
loaded_bunfig: false,
use_system_shell: !cfg!(windows),
macros: MacroOptions::Unspecified,
editor: Box::default(),
package_bundle_map: ArrayHashMap::default(),
test_directory: Box::default(),
output_file: Box::default(),
}
}
}
pub enum MacroOptions {
Unspecified,
Disable,
Map(MacroMap),
}
pub type MacroImportReplacementMap = ArrayHashMap<Box<[u8]>, Box<[u8]>>;
pub type MacroMap = ArrayHashMap<Box<[u8]>, MacroImportReplacementMap>;
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum HotReload {
None,
Hot,
Watch,
}
pub struct TestOptions {
pub default_timeout_ms: u32,
pub update_snapshots: bool,
pub repeat_count: u32,
pub retry: u32,
pub run_todo: bool,
pub only: bool,
pub pass_with_no_tests: bool,
pub concurrent: bool,
pub randomize: bool,
pub seed: Option<u32>,
pub concurrent_test_glob: Option<Vec<Box<[u8]>>>,
pub bail: u32,
pub coverage: CodeCoverageOptions,
pub path_ignore_patterns: Vec<Box<[u8]>>,
pub path_ignore_patterns_from_cli: bool,
pub test_filter_pattern: Option<Box<[u8]>>,
pub test_filter_regex: Option<core::ptr::NonNull<()>>, pub max_concurrency: u32,
pub isolate: bool,
pub parallel: u32,
pub parallel_delay_ms: Option<u32>,
pub test_worker: bool,
pub changed: Option<Box<[u8]>>,
pub shard: Option<Shard>,
pub reporters: Reporters,
pub reporter_outfile: Option<Box<[u8]>>,
}
#[derive(Copy, Clone)]
pub struct Shard {
pub index: u32,
pub count: u32,
}
#[derive(Default, Copy, Clone)]
pub struct Reporters {
pub dots: bool,
pub only_failures: bool,
pub junit: bool,
}
impl TestOptions {
#[inline]
pub fn test_filter_regex(&self) -> Option<core::ptr::NonNull<()>> {
self.test_filter_regex
}
}
impl Default for TestOptions {
#[inline(always)]
fn default() -> Self {
Self {
default_timeout_ms: 5 * 1000,
update_snapshots: false,
repeat_count: 0,
retry: 0,
run_todo: false,
only: false,
pass_with_no_tests: false,
concurrent: false,
randomize: false,
seed: None,
concurrent_test_glob: None,
bail: 0,
coverage: CodeCoverageOptions::default(),
path_ignore_patterns: Vec::new(),
path_ignore_patterns_from_cli: false,
test_filter_pattern: None,
test_filter_regex: None,
max_concurrency: if bun_core::env::ENABLE_ASAN { 5 } else { 20 },
isolate: false,
parallel: 0,
parallel_delay_ms: None,
test_worker: false,
changed: None,
shard: None,
reporters: Reporters::default(),
reporter_outfile: None,
}
}
}
pub enum Debugger {
Unspecified,
Enable(DebuggerEnable),
}
impl Default for Debugger {
#[inline(always)]
fn default() -> Self {
Debugger::Unspecified
}
}
#[derive(Default)]
pub struct DebuggerEnable {
pub path_or_port: Box<[u8]>,
pub wait_for_connection: bool,
pub set_breakpoint_on_first_line: bool,
}
pub struct RuntimeOptions {
pub smol: bool,
pub debugger: Debugger,
pub if_present: bool,
pub redis_preconnect: bool,
pub sql_preconnect: bool,
pub eval: Eval,
pub preconnect: Vec<Box<[u8]>>,
pub experimental_http3_fetch: bool,
pub dns_result_order: Box<[u8]>,
pub expose_gc: bool,
pub preserve_symlinks_main: bool,
pub console_depth: Option<u16>,
pub cron_title: Box<[u8]>,
pub cron_period: Box<[u8]>,
pub cpu_prof: CpuProf,
pub heap_prof: HeapProf,
}
#[derive(Default)]
pub struct Eval {
pub script: Box<[u8]>,
pub eval_and_print: bool,
}
pub struct CpuProf {
pub enabled: bool,
pub name: Box<[u8]>,
pub dir: Box<[u8]>,
pub interval: u32,
pub md_format: bool,
pub json_format: bool,
}
impl Default for CpuProf {
#[inline(always)]
fn default() -> Self {
Self {
enabled: false,
name: Box::default(),
dir: Box::default(),
interval: 1000,
md_format: false,
json_format: false,
}
}
}
#[derive(Default)]
pub struct HeapProf {
pub enabled: bool,
pub text_format: bool,
pub name: Box<[u8]>,
pub dir: Box<[u8]>,
}
impl Default for RuntimeOptions {
#[inline(always)]
fn default() -> Self {
Self {
smol: false,
debugger: Debugger::Unspecified,
if_present: false,
redis_preconnect: false,
sql_preconnect: false,
eval: Eval::default(),
preconnect: Vec::new(),
experimental_http3_fetch: false,
dns_result_order: Box::from(&b"verbatim"[..]),
expose_gc: false,
preserve_symlinks_main: false,
console_depth: None,
cron_title: Box::default(),
cron_period: Box::default(),
cpu_prof: CpuProf::default(),
heap_prof: HeapProf::default(),
}
}
}