Skip to content

Commit 8bd38e1

Browse files
Brooooooklynclaude
andauthored
fix(angular): fix 3 compiler divergences from Angular reference (#30)
fix(angular): fix 3 compiler divergences from Angular reference (#30) 1. Standalone @case/@default blocks now produce "Unrecognized block" error and UnknownBlock node instead of being silently dropped. 2. @case blocks with extra parameters now report error but still parse using the first parameter, matching Angular's error recovery behavior. 3. Unexpected i18n metadata types on conditional blocks now panic with a descriptive message instead of being silently ignored. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a387e4e commit 8bd38e1

3 files changed

Lines changed: 319 additions & 234 deletions

File tree

crates/oxc_angular_compiler/src/pipeline/ingest.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,7 +2351,8 @@ fn ingest_if_block<'a>(
23512351

23522352
// Extract i18n placeholder metadata from the branch
23532353
// Angular checks that branch.i18n is a BlockPlaceholder type
2354-
let i18n_placeholder = convert_i18n_meta_to_placeholder(branch.i18n);
2354+
let i18n_placeholder =
2355+
convert_i18n_meta_to_placeholder(branch.i18n, &mut job.diagnostics, branch.source_span);
23552356

23562357
// Infer tag name from single root element for content projection
23572358
let tag_name =
@@ -2932,7 +2933,8 @@ fn ingest_switch_block<'a>(
29322933

29332934
// Extract i18n placeholder metadata from the group
29342935
// Angular checks that group.i18n is a BlockPlaceholder type
2935-
let i18n_placeholder = convert_i18n_meta_to_placeholder(group.i18n);
2936+
let i18n_placeholder =
2937+
convert_i18n_meta_to_placeholder(group.i18n, &mut job.diagnostics, group.source_span);
29362938

29372939
// Infer tag name from single root element for content projection
29382940
let tag_name =
@@ -3082,7 +3084,11 @@ fn ingest_defer_view<'a>(
30823084
// Convert i18n metadata to placeholder, matching Angular's ingestDeferView which passes
30833085
// i18nMeta through to createTemplateOp. This enables propagate_i18n_blocks to wrap the
30843086
// deferred template with i18nStart/i18nEnd when inside an i18n context.
3085-
let i18n_placeholder = convert_i18n_meta_to_placeholder(i18n);
3087+
let i18n_placeholder = convert_i18n_meta_to_placeholder(
3088+
i18n,
3089+
&mut job.diagnostics,
3090+
source_span.unwrap_or(oxc_span::SPAN),
3091+
);
30863092

30873093
let template_op = CreateOp::Template(TemplateOp {
30883094
base: CreateOpBase { source_span, ..Default::default() },
@@ -4201,15 +4207,29 @@ fn ingest_host_event<'a>(job: &mut HostBindingCompilationJob<'a>, event: R3Bound
42014207
/// is specifically a BlockPlaceholder type and extract its start_name/close_name.
42024208
///
42034209
/// Ported from Angular's i18n handling in `ingest.ts` (lines 531-537, 1088-1094).
4204-
fn convert_i18n_meta_to_placeholder(i18n: Option<I18nMeta<'_>>) -> Option<I18nPlaceholder<'_>> {
4210+
fn convert_i18n_meta_to_placeholder<'a>(
4211+
i18n: Option<I18nMeta<'a>>,
4212+
diagnostics: &mut std::vec::Vec<OxcDiagnostic>,
4213+
source_span: oxc_span::Span,
4214+
) -> Option<I18nPlaceholder<'a>> {
42054215
match i18n {
42064216
Some(I18nMeta::Node(I18nNode::BlockPlaceholder(bp))) => {
42074217
Some(I18nPlaceholder::new(bp.start_name, Some(bp.close_name)))
42084218
}
42094219
Some(I18nMeta::BlockPlaceholder(bp)) => {
42104220
Some(I18nPlaceholder::new(bp.start_name, Some(bp.close_name)))
42114221
}
4212-
_ => None,
4222+
// Reference: ingest.ts lines 533-537, 587-591
4223+
// Angular throws an assertion error for unexpected i18n metadata types.
4224+
// We report a diagnostic instead to avoid crashing the process.
4225+
Some(_) => {
4226+
diagnostics.push(
4227+
OxcDiagnostic::error("Unhandled i18n metadata type for conditional block")
4228+
.with_label(source_span),
4229+
);
4230+
None
4231+
}
4232+
None => None,
42134233
}
42144234
}
42154235

0 commit comments

Comments
 (0)