Skip to content
Open
46 changes: 26 additions & 20 deletions src/ast/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,11 @@ pub struct Imports {
pub __promiseAll: Ref,
pub __MEMO_CACHE_SENTINEL: Ref,
pub __EARLY_RETURN_SENTINEL: Ref,
pub __glob: Ref,
}

impl Imports {
pub const ALL: [&'static [u8]; 27] = [
pub const ALL: [&'static [u8]; 28] = [
b"__name",
b"__require",
b"__export",
Expand Down Expand Up @@ -206,12 +207,13 @@ impl Imports {
b"__promiseAll",
b"__MEMO_CACHE_SENTINEL",
b"__EARLY_RETURN_SENTINEL",
b"__glob",
];

/// Rust stable cannot sort in `const`; precomputed here and verified by
/// the test in `tests` below.
#[cfg_attr(not(test), allow(dead_code))]
const ALL_SORTED: [&'static [u8]; 27] = [
const ALL_SORTED: [&'static [u8]; 28] = [
b"$$typeof",
b"__EARLY_RETURN_SENTINEL",
b"__MEMO_CACHE_SENTINEL",
Expand All @@ -222,6 +224,7 @@ impl Imports {
b"__export",
b"__exportDefault",
b"__exportValue",
b"__glob",
b"__jsonParse",
b"__legacyDecorateClassTS",
b"__legacyDecorateParamTS",
Expand All @@ -243,34 +246,35 @@ impl Imports {

/// When generating the list of runtime imports, we sort it for determinism.
/// This is a lookup table so we don't need to resort the strings each time
pub const ALL_SORTED_INDEX: [usize; 27] = [
15, // __name
24, // __require
pub const ALL_SORTED_INDEX: [usize; 28] = [
16, // __name
25, // __require
7, // __export
23, // __reExport
24, // __reExport
9, // __exportValue
8, // __exportDefault
14, // __merge
11, // __legacyDecorateClassTS
12, // __legacyDecorateParamTS
13, // __legacyMetadataTS
22, // __publicField
18, // __privateIn
17, // __privateGet
16, // __privateAdd
20, // __privateSet
19, // __privateMethod
15, // __merge
12, // __legacyDecorateClassTS
13, // __legacyDecorateParamTS
14, // __legacyMetadataTS
23, // __publicField
19, // __privateIn
18, // __privateGet
17, // __privateAdd
21, // __privateSet
20, // __privateMethod
6, // __decoratorStart
5, // __decoratorMetadata
25, // __runInitializers
26, // __runInitializers
4, // __decorateElement
0, // $$typeof
26, // __using
27, // __using
3, // __callDispose
10, // __jsonParse
21, // __promiseAll
11, // __jsonParse
22, // __promiseAll
2, // __MEMO_CACHE_SENTINEL
1, // __EARLY_RETURN_SENTINEL
10, // __glob
];

pub const NAME: &'static [u8] = b"bun:wrap";
Expand Down Expand Up @@ -306,6 +310,7 @@ impl Imports {
24 => self.__promiseAll,
25 => self.__MEMO_CACHE_SENTINEL,
26 => self.__EARLY_RETURN_SENTINEL,
27 => self.__glob,
_ => return None,
};
r.to_nullable()
Expand Down Expand Up @@ -341,6 +346,7 @@ impl Imports {
24 => Some(&mut self.__promiseAll),
25 => Some(&mut self.__MEMO_CACHE_SENTINEL),
26 => Some(&mut self.__EARLY_RETURN_SENTINEL),
27 => Some(&mut self.__glob),
_ => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions src/bundler/ParseTask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,7 @@ pub mod parse_worker {
// a worker-owned `Transpiler` that outlives the parse.
// SAFETY: ARENA — `topts` outlives `opts` (worker-owned for the bundle pass).
opts.allow_unresolved = unsafe { bun_collections::detach_ref(&topts.allow_unresolved) };
opts.glob_resolver = Some(crate::options::parser_glob_resolver);
// `Transpiler.macro_context` is `Option<bun_ast::Macro::MacroContext>`
// (same nominal type as `ParserOptions.macro_context`'s pointee). Reborrow
// through the raw `*mut Transpiler` so the `&mut MacroContext` is disjoint
Expand Down
41 changes: 41 additions & 0 deletions src/bundler/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,47 @@ pub fn validate_path(
// `&transpiler.options.allow_unresolved` straight through.
pub use bun_js_parser::options::AllowUnresolved;

/// `glob_resolver` for the parser's template-literal `require()` / `import()`
/// support: returns each match as a `./`- or `../`-prefixed relative specifier.
Comment thread
robobun marked this conversation as resolved.
pub fn parser_glob_resolver(source_dir: &[u8], pattern: &[u8]) -> Vec<Box<[u8]>> {
let mut out: Vec<Box<[u8]>> = Vec::new();
if !(pattern.starts_with(b"./") || pattern.starts_with(b"../")) {
return out;
}

let walker = match bun_glob::BunGlobWalker::init_with_cwd(
pattern, source_dir, true, false, true, false, true, None,
) {
Ok(Ok(w)) => w,
_ => return out,
};
let mut walker = Box::new(walker);
let mut iter = bun_glob::walk::Iterator::new(&mut *walker);
if iter.init().map(|m| m.is_err()).unwrap_or(true) {
return out;
}
loop {
match iter.next() {
Ok(Ok(Some(m))) => {
let p: &[u8] = &m;
let mut s: Vec<u8> = p
.iter()
.map(|&b| if cfg!(windows) && b == b'\\' { b'/' } else { b })
.collect();
if !(s.starts_with(b"./") || s.starts_with(b"../")) {
s.splice(0..0, b"./".iter().copied());
}
out.push(s.into_boxed_slice());
}
Ok(Ok(None)) => break,
// A mid-walk failure would otherwise emit a partial map whose
// keys can never cover the runtime specifier.
Comment thread
robobun marked this conversation as resolved.
Ok(Err(_)) | Err(_) => return Vec::new(),
}
}
out
}

// Canonical defs live in `bun_resolver::options` (lower tier; resolver is the
// runtime consumer of `.patterns`/`.abs_paths`/`.node_modules`). Re-export so
// `BundleOptions.external` and `Resolver.opts.external` are the SAME nominal
Expand Down
1 change: 1 addition & 0 deletions src/bundler/transpiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ impl<'a> Transpiler<'a> {
macro_context: None,
warn_about_unbundled_modules: !target.is_bun(),
allow_unresolved: &p_opts::AllowUnresolved::DEFAULT,
glob_resolver: None,
module_type: to_parser_module_type(this_parse.module_type),
output_format: p_opts::Format::Esm,
transform_only: self.options.transform_only,
Expand Down
Loading
Loading