Skip to content

Commit b2dd390

Browse files
fix(compiler): handle @Inject(TOKEN) on pipe constructor params (#231)
The extract_param_dependency function in pipe/decorator.rs was missing the "Inject" arm in its decorator match, causing @Inject(TOKEN) to be silently ignored. The injection token was then extracted from the TypeScript type annotation instead — which is undefined at runtime when the type is an interface. The same fix already exists in directive/decorator.rs and injectable/decorator.rs. This brings pipe/decorator.rs in line. Surfaced by Angular 20 which added an assertDefined(token) guard in the DI runtime that throws immediately on an undefined token, whereas Angular 19 would silently pass through.
1 parent fe0b0e6 commit b2dd390

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

crates/oxc_angular_compiler/src/pipe/decorator.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use oxc_str::Ident;
1414
use super::metadata::R3PipeMetadata;
1515
use crate::factory::R3DependencyMetadata;
1616
use crate::output::ast::{OutputExpression, ReadVarExpr};
17+
use crate::output::oxc_converter::convert_oxc_expression;
1718

1819
/// Extracted pipe metadata from a `@Pipe` decorator.
1920
///
@@ -264,16 +265,26 @@ fn extract_param_dependency<'a>(
264265
allocator: &'a Allocator,
265266
param: &oxc_ast::ast::FormalParameter<'a>,
266267
) -> R3DependencyMetadata<'a> {
267-
// Extract flags from decorators
268+
// Extract flags and @Inject token from decorators
268269
let mut optional = false;
269270
let mut skip_self = false;
270271
let mut self_ = false;
271272
let mut host = false;
273+
let mut inject_token: Option<OutputExpression<'a>> = None;
272274
let mut attribute_name: Option<Ident<'a>> = None;
273275

274276
for decorator in &param.decorators {
275277
if let Some(name) = get_decorator_name(&decorator.expression) {
276278
match name.as_str() {
279+
"Inject" => {
280+
// @Inject(TOKEN) - extract the token
281+
if let Expression::CallExpression(call) = &decorator.expression {
282+
if let Some(arg) = call.arguments.first() {
283+
inject_token =
284+
convert_oxc_expression(allocator, arg.to_expression(), None);
285+
}
286+
}
287+
}
277288
"Optional" => optional = true,
278289
"SkipSelf" => skip_self = true,
279290
"Self" => self_ = true,
@@ -291,8 +302,9 @@ fn extract_param_dependency<'a>(
291302
}
292303
}
293304

294-
// Extract the token (type annotation or parameter name)
295-
let token = extract_param_token(allocator, param);
305+
// 1. If @Inject(TOKEN) is present, use TOKEN
306+
// 2. Otherwise fall back to the type annotation
307+
let token = inject_token.or_else(|| extract_param_token(allocator, param));
296308

297309
// Handle @Attribute decorator
298310
if let Some(attr_name) = attribute_name {

0 commit comments

Comments
 (0)