Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions .changepacks/changepack_log_barrel_namespace_imports.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch"
},
"note": "A project module re-exporting Devup UI (export { Box, css } from '@devup-ui/react', export * from '@devup-ui/react', export { styled as s }, export * as Devup, a default export of an import, chains of barrels and the compat entry) now works: a file importing Box or css from it compiles exactly as if it imported from the package, following the barrel through the resolver (relative paths, tsconfig paths, package exports), and hasDevupUI sees such a file. Members read from a namespace or default import of the package (Devup['css'], const { css } = Devup, Devup.css as a value) compile where the build can follow them, `Devup.x` for a name the package compiles being read like the named import. New build errors, located at the use: what a barrel re-exports but the build cannot read (an unresolvable `export *` or module, a namespace of modules re-exporting the package) is an error where its name is used instead of a runtime crash, and a namespace member read by a key the build cannot know (Devup[key]), written, or destructured in a form it cannot follow (a rest, a computed key, a default value, a nested pattern, an exported declaration, or members mixed with ones that stay at runtime) is an error that names the members to read. A namespace passed on whole (Object.keys(Devup), spyOn(Devup, 'css'), export default Devup) is left as it is",
"date": "2026-10-01T00:00:00.000Z"
}
50 changes: 48 additions & 2 deletions bindings/devup-ui-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use css::file_map::{
use extractor::extract_style::extract_style_value::ExtractStyleValue;
use extractor::{
ExtractOption, ImportAlias, ModuleResolver, ResolvedModule, extract, extract_with_modules,
extract_without_source_map, has_devup_ui,
extract_without_source_map, has_devup_ui, has_devup_ui_through,
};
use rustc_hash::FxHashSet;
use sheet::StyleSheet;
Expand Down Expand Up @@ -549,6 +549,29 @@ fn call_module_resolver(
})
}

/// The resolver set by `setModuleResolver`, if any
#[cfg(not(tarpaulin_include))]
fn resolver_from_js() -> Option<Box<ModuleResolver>> {
let resolver = MODULE_RESOLVER.with_borrow(Clone::clone)?;
Some(Box::new(move |specifier: &str, importer: &str| {
call_module_resolver(&resolver, specifier, importer)
}))
}

/// [`has_devup_ui`], also true for a file reaching the package through a
/// project module when there is a resolver
fn has_devup_ui_in(
filename: &str,
code: &str,
package: &str,
resolver: Option<&ModuleResolver>,
) -> bool {
match resolver {
Some(resolver) => has_devup_ui_through(filename, code, package, resolver),
None => has_devup_ui(filename, code, package),
}
}

/// Extract with the resolver set by `setModuleResolver`, if any
#[cfg(not(tarpaulin_include))]
#[allow(clippy::too_many_arguments)]
Expand Down Expand Up @@ -730,7 +753,7 @@ pub fn get_theme_interface(
#[cfg(not(tarpaulin_include))]
#[must_use]
pub fn has_devup_ui_wasm(filename: &str, code: &str, package: &str) -> bool {
has_devup_ui(filename, code, package)
has_devup_ui_in(filename, code, package, resolver_from_js().as_deref())
}

#[cfg(test)]
Expand Down Expand Up @@ -1400,6 +1423,29 @@ mod tests {
));
}

#[test]
fn has_devup_ui_follows_a_barrel_only_with_a_resolver() {
let resolver = |specifier: &str, _: &str| {
(specifier == "./ui").then(|| ResolvedModule {
path: "/src/ui.ts".to_string(),
code: "export { Box } from '@devup-ui/react'".to_string(),
})
};
let code = "import { Box } from './ui';";
assert!(has_devup_ui_in(
"/src/app.tsx",
code,
"@devup-ui/react",
Some(&resolver)
));
assert!(!has_devup_ui_in(
"/src/app.tsx",
code,
"@devup-ui/react",
None
));
}

#[test]
#[serial]
fn test_output_single_css_mode() {
Expand Down
Loading
Loading