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
51 changes: 45 additions & 6 deletions crates/oxc_angular_compiler/src/component/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,21 @@ pub struct HmrTemplateCompileOutput {
/// constant references. Without this, the template may reference indices that don't
/// exist in the old component definition's consts array.
pub consts_js: Option<String>,

/// The number of element, text and container slots the template creates.
pub decls: u32,

/// The number of binding slots the template uses.
pub vars: u32,

/// The `ngContentSelectors` array as JavaScript code, when the template projects
/// content. It refers to a constant declared in `declarations_js`.
pub ng_content_selectors_js: Option<String>,

/// Non-fatal diagnostics the pipeline reported while compiling (warnings,
/// advice). Error-severity diagnostics are returned as `Err` instead, since
/// the emitted code cannot be trusted.
pub diagnostics: Vec<OxcDiagnostic>,
}

/// Compiled component information.
Expand Down Expand Up @@ -5490,11 +5505,14 @@ pub fn compile_template_for_hmr<'a>(
// OXC is a single-file compiler (local compilation mode): always use Full mode.
let mode = TemplateCompilationMode::Full;

let defer_block_deps_emit_mode = if options.jit {
DeferBlockDepsEmitMode::PerComponent
} else {
DeferBlockDepsEmitMode::PerBlock
};
// Defer-block dependency resolution needs component metadata this compile
// does not have, and PerBlock mode reports "unable to find a dependency
// function for this deferred block" for every `@defer` when its `blocks`
// map is not populated — nothing ever populates it here. Local compilation
// uses PerComponent (upstream handler.ts:1281); with no resolver available
// it still emits `ɵɵdefer` with a null dependencies argument, which is what
// PerBlock's empty map would have produced anyway.
let defer_block_deps_emit_mode = DeferBlockDepsEmitMode::PerComponent;

let enable_debug_locations = !options.advanced_optimizations;

Expand Down Expand Up @@ -5526,6 +5544,15 @@ pub fn compile_template_for_hmr<'a>(
// Collect any diagnostics from the compilation job
diagnostics.extend(job.diagnostics.into_iter());

// A pipeline error means the emitted code is already wrong — an update
// module must not be generated from it, and `decls`/`vars` may not be
// reliable (they default to 0 when slot allocation never ran, which would
// size the new TView incorrectly). Non-error diagnostics go out on the
// output so the caller can surface them.
if diagnostics.iter().any(|d| d.severity == oxc_diagnostics::Severity::Error) {
return Err(diagnostics);
}

let emitter = JsEmitter::new();

// Emit the template function
Expand Down Expand Up @@ -5604,7 +5631,19 @@ pub fn compile_template_for_hmr<'a>(
None
};

Ok(HmrTemplateCompileOutput { template_js, declarations_js, styles, consts_js })
let ng_content_selectors_js =
job.content_selectors.take().map(|selectors| emitter.emit_expression(&selectors));

Ok(HmrTemplateCompileOutput {
template_js,
declarations_js,
styles,
consts_js,
decls: job.root.decl_count.unwrap_or(0),
vars: job.root.vars.unwrap_or(0),
ng_content_selectors_js,
diagnostics,
})
}

/// Generate component compilation output for HMR.
Expand Down
19 changes: 14 additions & 5 deletions crates/oxc_angular_compiler/src/hmr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,18 @@
//! });
//!
//! // HMR Update Module (served by Vite middleware)
//! export default {
//! ɵcmp: /* compiled component definition */,
//! template: /* template function */,
//! };
//! export default function Cmp_UpdateMetadata(Cmp, ɵɵnamespaces) {
//! const i0 = ɵɵnamespaces[0];
//! Cmp.ɵcmp = {
//! ...Cmp.ɵcmp,
//! decls: /* new template's slot count */,
//! vars: /* new template's binding count */,
//! consts: /* new template's consts, or null */,
//! ngContentSelectors: /* new template's selectors, or undefined */,
//! template: /* new template function */,
//! tView: null,
//! };
//! }
//! ```

mod dependencies;
Expand All @@ -46,5 +54,6 @@ pub use dependencies::{
pub use initializer::{HmrDefinition, compile_hmr_initializer, compile_hmr_update_callback};
pub use styles::generate_style_update_module;
pub use update_module::{
HmrUpdateModuleOptions, generate_hmr_update_module, generate_hmr_update_module_from_js,
HmrTemplateFields, HmrUpdateModuleOptions, generate_hmr_update_module,
generate_hmr_update_module_from_js,
};
Loading
Loading