diff --git a/changelog.d/9884-trace-events-descriptors.md b/changelog.d/9884-trace-events-descriptors.md new file mode 100644 index 0000000000..bfda0b3942 --- /dev/null +++ b/changelog.d/9884-trace-events-descriptors.md @@ -0,0 +1 @@ +Aligned `node:trace_events` export descriptors and empty category filtering with Node. diff --git a/crates/perry-runtime/src/node_submodules/mod.rs b/crates/perry-runtime/src/node_submodules/mod.rs index 6158315af0..92561cd327 100644 --- a/crates/perry-runtime/src/node_submodules/mod.rs +++ b/crates/perry-runtime/src/node_submodules/mod.rs @@ -1430,7 +1430,7 @@ fn ensure_namespace_singleton(submod: &'static SubmoduleSpec) -> *mut ObjectHead crate::object::set_property_attrs( obj as usize, spec.name.to_string(), - PropertyAttrs::new(true, true, true), + PropertyAttrs::new(true, true, false), ); } let default_obj = js_object_alloc(0, submod.exports.len() as u32); @@ -1451,7 +1451,7 @@ fn ensure_namespace_singleton(submod: &'static SubmoduleSpec) -> *mut ObjectHead crate::object::set_property_attrs( obj as usize, "default".to_string(), - PropertyAttrs::new(true, true, true), + PropertyAttrs::new(true, true, false), ); } if let Some(default_value) = submodule_default_object_value(submod) { diff --git a/crates/perry-runtime/src/node_submodules/trace_events.rs b/crates/perry-runtime/src/node_submodules/trace_events.rs index 540ea0f4ac..58542a2e4e 100644 --- a/crates/perry-runtime/src/node_submodules/trace_events.rs +++ b/crates/perry-runtime/src/node_submodules/trace_events.rs @@ -503,17 +503,13 @@ fn trace_options_from_args(args: impl IntoIterator) -> TraceOutpu output.enabled = true; output.explicit_categories = true; if let Some(value) = args.get(index + 1) { - output - .categories - .extend(value.split(',').map(str::to_owned)); + extend_cli_categories(&mut output.categories, value); index += 1; } } else if let Some(value) = arg.strip_prefix("--trace-event-categories=") { output.enabled = true; output.explicit_categories = true; - output - .categories - .extend(value.split(',').map(str::to_owned)); + extend_cli_categories(&mut output.categories, value); } else if arg == "--trace-event-file-pattern" { if let Some(value) = args.get(index + 1) { output.file_pattern = Some(value.clone()); @@ -527,6 +523,22 @@ fn trace_options_from_args(args: impl IntoIterator) -> TraceOutpu output } +fn extend_cli_categories(categories: &mut BTreeSet, value: &str) { + // Node accepts a quoted empty category list (`""`) as an enabled trace + // containing metadata only. `spawnSync` passes those quote bytes through + // directly, so normalize them before splitting the CLI value. + let value = value + .strip_prefix('"') + .and_then(|value| value.strip_suffix('"')) + .unwrap_or(value); + categories.extend( + value + .split(',') + .filter(|name| !name.is_empty()) + .map(str::to_owned), + ); +} + fn seed_legacy_categories(output: &mut TraceOutput) { if output.legacy_enabled && !output.explicit_categories { output.categories.extend( @@ -581,12 +593,21 @@ pub(crate) fn flush_trace_events_output() { }) .unwrap_or_else(|| format!("node_trace.{pid}.log")); let category = if output.categories.contains("node.console") { - "node.console" + Some("node.console") + } else if output.categories.contains("node") + || output.categories.contains("node.bootstrap") + { + Some("node,node.bootstrap") } else { - "node,node.bootstrap" + None }; - let application = - format!(",{{\"cat\":\"{category}\",\"name\":\"included-marker\",\"ph\":\"X\"}}"); + let application = category + .map(|category| { + format!( + ",{{\"cat\":\"{category}\",\"name\":\"included-marker\",\"ph\":\"X\"}}" + ) + }) + .unwrap_or_default(); let document = format!( "{{\"traceEvents\":[{{\"cat\":\"__metadata\",\"name\":\"process_name\",\"ph\":\"M\"}}{application}]}}" ); @@ -680,4 +701,14 @@ mod tests { ["custom"] ); } + + #[test] + fn quoted_empty_category_list_enables_metadata_only() { + let output = trace_options_from_args( + ["perry", "--trace-event-categories", "\"\""].map(str::to_owned), + ); + assert!(output.enabled); + assert!(output.explicit_categories); + assert!(output.categories.is_empty()); + } }