Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions src/ast/s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,7 @@ pub struct Local {
pub kind: Kind, // = Kind::KVar
pub decls: G::DeclList, // = .{}
pub is_export: bool, // = false
/// The TypeScript compiler doesn't generate code for "import foo = bar"
/// statements where the import is never used.
pub was_ts_import_equals: bool, // = false

pub was_commonjs_export: bool, // = false
pub origin: LocalOrigin,
}

impl Default for Local {
Expand All @@ -254,8 +250,7 @@ impl Default for Local {
kind: Kind::default(),
decls: bun_alloc::AstAlloc::vec(),
is_export: false,
was_ts_import_equals: false,
was_commonjs_export: false,
origin: LocalOrigin::Normal,
}
}
}
Expand All @@ -271,7 +266,31 @@ impl Local {
}
self.kind == other.kind
&& self.is_export == other.is_export
&& self.was_commonjs_export == other.was_commonjs_export
&& self.origin.is_commonjs_export() == other.origin.is_commonjs_export()
}
}

/// Where an `S::Local` originated. `TsImportEquals` (from `import x = ...` in
/// TS) and `CommonJsExport` (from rewritten `exports.x = ...`) are set on
/// disjoint parse/visit paths, so a single local is never both.
Comment thread
robobun marked this conversation as resolved.
Outdated
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum LocalOrigin {
#[default]
Normal,
/// The TypeScript compiler doesn't generate code for "import foo = bar"
/// statements where the import is never used.
Comment thread
robobun marked this conversation as resolved.
Outdated
TsImportEquals,
CommonJsExport,
}

impl LocalOrigin {
#[inline]
pub fn is_ts_import_equals(self) -> bool {
matches!(self, Self::TsImportEquals)
}
#[inline]
pub fn is_commonjs_export(self) -> bool {
matches!(self, Self::CommonJsExport)
}
}

Expand Down
21 changes: 19 additions & 2 deletions src/bundler/OutputFile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,28 @@ impl Clone for OutputFile {

#[derive(Default, Clone, Copy)]
pub struct BakeExtra {
pub(crate) is_route: bool,
pub fully_static: bool,
pub route: BakeRouteKind,
pub bake_is_runtime: bool,
}

/// A server-side entry-point chunk is a route; `FullyStatic` additionally
/// means it has no transitive "use client" boundary. Non-route chunks are
/// never fully static.
#[derive(Default, Clone, Copy, PartialEq, Eq)]
pub enum BakeRouteKind {
#[default]
NotRoute,
Route,
FullyStaticRoute,
}

impl BakeRouteKind {
#[inline]
pub fn is_fully_static(self) -> bool {
matches!(self, Self::FullyStaticRoute)
}
}

pub type Index = bun_core::GenericIndex<u32, OutputFile>;
pub type IndexOptional = bun_core::GenericIndexOptional<u32, OutputFile>;

Expand Down
3 changes: 2 additions & 1 deletion src/bundler/bundle_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6252,7 +6252,8 @@ pub mod bv2_impl {
};

if resolve_result.flags.is_external() {
if resolve_result.flags.is_external_and_rewrite_import_path()
if resolve_result.flags.external_kind()
== bun_resolver::ExternalKind::ExternalRewritePath
&& !strings::eql_long(
resolve_result.path_pair.primary.text,
import_record.path.text,
Expand Down
2 changes: 1 addition & 1 deletion src/bundler/linker_context/convertStmtsForChunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ pub(crate) fn convert_stmts_for_chunk(
stmt = Stmt::alloc(copied, stmt.loc);
stmt.data.s_local_mut().unwrap().is_export = false;
} else if FeatureFlags::UNWRAP_COMMONJS_TO_ESM
&& s.was_commonjs_export
&& s.origin.is_commonjs_export()
&& wrap == WrapKind::Cjs
{
debug_assert!(s.decls.len() == 1);
Expand Down
12 changes: 8 additions & 4 deletions src/bundler/linker_context/generateChunksInParallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1240,9 +1240,13 @@ pub(crate) fn generate_chunks_in_parallel<const IS_DEV_SERVER: bool>(
if output_kind == options::OutputKind::EntryPoint
&& side == options::Side::Server
{
extra.is_route = true;
extra.fully_static = !static_route_visitor
.has_transitive_use_client(chunk.entry_point.source_index());
extra.route = if static_route_visitor
.has_transitive_use_client(chunk.entry_point.source_index())
{
BakeRouteKind::Route
} else {
BakeRouteKind::FullyStaticRoute
};
}

break 'brk extra;
Expand Down Expand Up @@ -1290,4 +1294,4 @@ pub(crate) fn generate_chunks_in_parallel<const IS_DEV_SERVER: bool>(

use crate::EntryPoint;
use crate::options::SourceMapOption;
use crate::output_file::BakeExtra;
use crate::output_file::{BakeExtra, BakeRouteKind};
3 changes: 1 addition & 2 deletions src/bundler/linker_context/generateCodeForFileInChunkJS.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,8 +970,7 @@ fn merge_adjacent_local_stmts(stmts: &mut Vec<Stmt>, _arena: &Bump) {
S::Local {
decls: Vec::move_from_list(clone),
is_export: before.is_export,
was_commonjs_export: before.was_commonjs_export,
was_ts_import_equals: before.was_ts_import_equals,
origin: before.origin,
kind: before.kind,
},
prev_loc,
Expand Down
4 changes: 3 additions & 1 deletion src/js_parser/p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8551,7 +8551,9 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
}
}
js_ast::StmtData::SLocal(local) => {
if local.was_commonjs_export || self.commonjs_named_exports.count() == 0 {
if local.origin.is_commonjs_export()
|| self.commonjs_named_exports.count() == 0
{
for decl in local.decls.slice() {
if let Some(value) = &decl.value {
if !matches!(value.data, js_ast::ExprData::EMissing(_))
Expand Down
3 changes: 1 addition & 2 deletions src/js_parser/parse/parse_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,8 +894,7 @@ impl<'a> Parser<'a> {
let _local = S::Local {
kind: local.kind,
is_export: local.is_export,
was_ts_import_equals: local.was_ts_import_equals,
was_commonjs_export: local.was_commonjs_export,
origin: local.origin,
decls: G::DeclList::init_one(G::Decl {
binding: decl.binding,
value: decl.value,
Expand Down
5 changes: 2 additions & 3 deletions src/js_parser/parse/parse_typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
for stmt in stmts.iter() {
match &stmt.data {
StmtData::SLocal(local) => {
if local.was_ts_import_equals && !local.is_export {
if local.origin.is_ts_import_equals() && !local.is_export {
import_equal_count += 1;
}
}
Expand Down Expand Up @@ -564,8 +564,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
kind,
decls,
is_export: opts.is_export,
was_ts_import_equals: true,
..Default::default()
origin: S::LocalOrigin::TsImportEquals,
},
loc,
))
Expand Down
2 changes: 1 addition & 1 deletion src/js_parser/scan/scan_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ impl<'a> ImportScanner<'a> {

// Remove unused import-equals statements, since those likely
// correspond to types instead of values
if st.was_ts_import_equals && !st.is_export && st.decls.len_u32() > 0 {
if st.origin.is_ts_import_equals() && !st.is_export && st.decls.len_u32() > 0 {
let decl = &st.decls.slice()[0];

// Skip to the underlying reference
Expand Down
2 changes: 1 addition & 1 deletion src/js_parser/visit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
if local.kind.is_using() {
continue;
}
if !local.is_export && !local.was_commonjs_export {
if !local.is_export && !local.origin.is_commonjs_export() {
let mut any_decl_in_const_values = local.kind == LocalKind::KConst;
let decls: &mut [Decl] = local.decls.slice_mut();
let mut end: usize = 0;
Expand Down
3 changes: 1 addition & 2 deletions src/js_parser/visit/visit_stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1472,9 +1472,8 @@ impl<'a, const TYPESCRIPT: bool, const SCAN_ONLY: bool> P<'a, TYPESCRIPT, SCAN_O
S::Local {
kind: S::Kind::KVar,
is_export: false,
was_commonjs_export: true,
origin: S::LocalOrigin::CommonJsExport,
decls,
..Default::default()
},
stmt.loc,
);
Expand Down
5 changes: 3 additions & 2 deletions src/resolver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ pub use tsconfig_json::TSConfigJSON;
pub use ::bun_install_types::resolver_hooks as install_types;
pub use resolver::{AnyResolveWatcher, BrowserMapPathKind, Bufs, Dirname, Resolver};
pub use result::{
DebugLogs, DirEntryResolveQueueItem, FlushMode, LoadResult, MatchResult, MatchStatus, PathPair,
PendingResolution, PendingResolutionTag, Result, ResultFlags, ResultUnion,
DebugLogs, DirEntryResolveQueueItem, ExternalKind, FlushMode, LoadResult, MatchResult,
MatchStatus, PathPair, PendingResolution, PendingResolutionTag, Result, ResultFlags,
ResultUnion,
};
pub use standalone_module_graph::StandaloneModuleGraph;

Expand Down
30 changes: 18 additions & 12 deletions src/resolver/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ pub use ::bun_options_types::global_cache::GlobalCache;
// inside `impl Resolver` resolve unchanged.
use crate::options;
use crate::result::{
DebugLogs, DirEntryResolveQueueItem, FlushMode, LoadResult, MatchResult, MatchStatus, PathPair,
PendingResolution, PendingResolutionTag, Result, ResultFlags, ResultUnion,
DebugLogs, DirEntryResolveQueueItem, ExternalKind, FlushMode, LoadResult, MatchResult,
MatchStatus, PathPair, PendingResolution, PendingResolutionTag, Result, ResultFlags,
ResultUnion,
};
use crate::standalone_module_graph::StandaloneModuleGraph;
use bun_alloc as allocators;
Expand Down Expand Up @@ -2163,8 +2164,11 @@ impl<'a> Resolver<'a> {
.is_success()
{
let mut flags = ResultFlags::default();
flags.set_is_external(match_result.is_external);
flags.set_is_external_and_rewrite_import_path(match_result.is_external);
flags.set_external_kind(if match_result.is_external {
ExternalKind::ExternalRewritePath
} else {
ExternalKind::NotExternal
});
return ResultUnion::Success(Result {
path_pair: match_result.path_pair,
dirname_fd: match_result.dirname_fd,
Expand Down Expand Up @@ -2342,12 +2346,13 @@ impl<'a> Resolver<'a> {
result.flags.is_from_node_modules() || res.is_node_module,
);
result.module_type = res.module_type;
result.flags.set_is_external(res.is_external);
// Potentially rewrite the import path if it's external that
// was remapped to a different path
result
.flags
.set_is_external_and_rewrite_import_path(result.flags.is_external());
result.flags.set_external_kind(if res.is_external {
ExternalKind::ExternalRewritePath
} else {
ExternalKind::NotExternal
});

if result.path_pair.primary.is_disabled && result.path_pair.secondary.is_none() {
return ResultUnion::Success(result);
Expand Down Expand Up @@ -2389,13 +2394,14 @@ impl<'a> Resolver<'a> {
result.file_fd = remapped.file_fd;
result.package_json = remapped.package_json;
result.module_type = remapped.module_type;
result.flags.set_is_external(remapped.is_external);

// Potentially rewrite the import path if it's external that
// was remapped to a different path
result.flags.set_is_external_and_rewrite_import_path(
result.flags.is_external(),
);
result.flags.set_external_kind(if remapped.is_external {
ExternalKind::ExternalRewritePath
} else {
ExternalKind::NotExternal
});

result.flags.set_is_from_node_modules(
result.flags.is_from_node_modules()
Expand Down
42 changes: 33 additions & 9 deletions src/resolver/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ impl Default for Result {
bitflags::bitflags! {
#[derive(Default, Clone, Copy)]
pub struct ResultFlags: u8 {
// `IS_EXTERNAL` / `REWRITE_IMPORT_PATH` together encode [`ExternalKind`];
// `REWRITE_IMPORT_PATH` is never set without `IS_EXTERNAL`.
Comment thread
robobun marked this conversation as resolved.
Outdated
const IS_EXTERNAL = 1 << 0;
const IS_EXTERNAL_AND_REWRITE_IMPORT_PATH = 1 << 1;
const REWRITE_IMPORT_PATH = 1 << 1;
const IS_STANDALONE_MODULE = 1 << 2;
// This is true when the package was loaded from within the node_modules directory.
const IS_FROM_NODE_MODULES = 1 << 3;
Expand All @@ -138,23 +140,45 @@ bitflags::bitflags! {
}
}

/// Whether a resolved path is external to the bundle, and if so whether the
/// import specifier should be rewritten to the resolved path. Stored in
/// [`ResultFlags`]; `ExternalRewritePath` implies `External`, so the pair of
/// bits is written via [`ResultFlags::set_external_kind`] only.
Comment thread
robobun marked this conversation as resolved.
Outdated
#[derive(Clone, Copy, PartialEq, Eq, Default)]
pub enum ExternalKind {
#[default]
NotExternal,
External,
ExternalRewritePath,
}

// Convenience accessors with field-style names.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
impl ResultFlags {
#[inline]
pub fn is_external(self) -> bool {
self.contains(Self::IS_EXTERNAL)
}
#[inline]
pub(crate) fn set_is_external(&mut self, v: bool) {
self.set(Self::IS_EXTERNAL, v)
}
#[inline]
pub fn is_external_and_rewrite_import_path(self) -> bool {
self.contains(Self::IS_EXTERNAL_AND_REWRITE_IMPORT_PATH)
pub fn external_kind(self) -> ExternalKind {
if self.contains(Self::REWRITE_IMPORT_PATH) {
debug_assert!(self.contains(Self::IS_EXTERNAL));
ExternalKind::ExternalRewritePath
} else if self.contains(Self::IS_EXTERNAL) {
ExternalKind::External
} else {
ExternalKind::NotExternal
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Comment thread
robobun marked this conversation as resolved.
#[inline]
pub(crate) fn set_is_external_and_rewrite_import_path(&mut self, v: bool) {
self.set(Self::IS_EXTERNAL_AND_REWRITE_IMPORT_PATH, v)
pub(crate) fn set_external_kind(&mut self, kind: ExternalKind) {
self.set(
Self::IS_EXTERNAL,
!matches!(kind, ExternalKind::NotExternal),
);
self.set(
Self::REWRITE_IMPORT_PATH,
matches!(kind, ExternalKind::ExternalRewritePath),
);
}
#[inline]
pub(crate) fn is_standalone_module(self) -> bool {
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/bake/production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,8 @@ fn build_with_vm(ctx: Context, cwd: &[u8], pt: &mut PerThread) -> crate::Result<
route.r#type.get(),
pt.output_file(main_file_route_index)
.bake_extra
.fully_static,
.route
.is_fully_static(),
)
.bits(),
),
Expand Down
Loading