Skip to content

Commit fa76105

Browse files
fix: detect preprocessor in re-exported named exports (#6899)
Fixes #6894 The TypeScript parser now correctly detects preprocessor functions that are re-exported from other modules using named exports like: export { preprocessor } from "./other_module"; Previously, only function declarations were detected. Now the parser also checks ExportNamed AST nodes for any specifier named 'preprocessor'. This allows developers to easily reuse preprocessor functions across multiple scripts without the workaround of wrapping them in a new function. Added comprehensive tests covering: - Simple re-export: export { preprocessor } from "./other" - Re-export with renaming: export { preprocessor as preprocessor } - Mixed exports: export { foo, preprocessor, bar } - Negative case: exports without preprocessor
1 parent dc887e5 commit fa76105

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

backend/parsers/windmill-parser-ts/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,28 @@ pub fn parse_deno_signature(
255255
let mut symbol_table: HashMap<String, TypeDecl> = HashMap::new();
256256

257257
for item in ast {
258+
// Check for named exports (e.g., export { preprocessor } from "./other")
259+
if let ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(named_export)) = &item {
260+
if !has_preprocessor {
261+
for specifier in &named_export.specifiers {
262+
if let swc_ecma_ast::ExportSpecifier::Named(spec) = specifier {
263+
let export_name = match &spec.exported {
264+
Some(swc_ecma_ast::ModuleExportName::Ident(ident)) => ident.sym.as_ref(),
265+
Some(swc_ecma_ast::ModuleExportName::Str(s)) => s.value.as_ref(),
266+
None => match &spec.orig {
267+
swc_ecma_ast::ModuleExportName::Ident(ident) => ident.sym.as_ref(),
268+
swc_ecma_ast::ModuleExportName::Str(s) => s.value.as_ref(),
269+
},
270+
};
271+
if export_name == "preprocessor" {
272+
has_preprocessor = true;
273+
break;
274+
}
275+
}
276+
}
277+
}
278+
}
279+
258280
if let ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { decl, .. }))
259281
| ModuleItem::Stmt(Stmt::Decl(decl)) = item
260282
{

backend/parsers/windmill-parser-ts/tests/tests.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,4 +685,76 @@ mod tests {
685685
}
686686
);
687687
}
688+
689+
#[test]
690+
fn test_parse_with_preprocessor_reexport() {
691+
// Test case for issue #6894: preprocessor re-export should be detected
692+
let code = r#"
693+
export { preprocessor } from "./extract_user_info_from_jwt_token";
694+
695+
export async function main(param: string) {
696+
return param;
697+
}
698+
"#;
699+
let sig = parse_deno_signature(code, false, false, None).unwrap();
700+
assert_eq!(
701+
sig,
702+
MainArgSignature {
703+
star_args: false,
704+
star_kwargs: false,
705+
args: vec![Arg {
706+
name: "param".to_string(),
707+
otyp: None,
708+
typ: Typ::Str(None),
709+
default: None,
710+
has_default: false,
711+
oidx: None,
712+
}],
713+
no_main_func: Some(false),
714+
has_preprocessor: Some(true),
715+
}
716+
);
717+
}
718+
719+
#[test]
720+
fn test_parse_with_preprocessor_reexport_renamed() {
721+
// Test case for renamed re-exports
722+
let code = r#"
723+
export { preprocessor as preprocessor } from "./other";
724+
725+
export async function main(param: string) {
726+
return param;
727+
}
728+
"#;
729+
let sig = parse_deno_signature(code, false, false, None).unwrap();
730+
assert_eq!(sig.has_preprocessor, Some(true));
731+
}
732+
733+
#[test]
734+
fn test_parse_with_preprocessor_among_other_exports() {
735+
// Test case where preprocessor is one of many exports
736+
let code = r#"
737+
export { foo, preprocessor, bar } from "./utils";
738+
739+
export async function main(param: string) {
740+
return param;
741+
}
742+
"#;
743+
let sig = parse_deno_signature(code, false, false, None).unwrap();
744+
assert_eq!(sig.has_preprocessor, Some(true));
745+
}
746+
747+
#[test]
748+
fn test_parse_without_preprocessor_other_exports() {
749+
// Test case where there are exports but no preprocessor
750+
let code = r#"
751+
export { foo, bar } from "./utils";
752+
753+
export async function main(param: string) {
754+
return param;
755+
}
756+
"#;
757+
let sig = parse_deno_signature(code, false, false, None).unwrap();
758+
assert_eq!(sig.has_preprocessor, Some(false));
759+
}
688760
}

0 commit comments

Comments
 (0)