Summary
TracingChannel#traceCallback(fn, position, context, thisArg, ...args) should wrap the callback argument at the requested position while preserving all surrounding arguments. Perry currently ignores position and calls fn with a fixed (wrappedCallback, err, res) shape, so callback-last or callback-middle APIs receive the wrong arguments and extra arguments are dropped.
Node Behavior
Probe run with Node v25.9.0:
const { tracingChannel } = require("node:diagnostics_channel");
const ch = tracingChannel("tracecb-position");
const events = [];
ch.subscribe({
start: (ctx) => events.push("start:" + JSON.stringify(ctx)),
end: (ctx) => events.push("end:" + JSON.stringify(ctx)),
asyncStart: (ctx) => events.push("asyncStart:" + JSON.stringify(ctx.result)),
asyncEnd: (ctx) => events.push("asyncEnd:" + JSON.stringify(ctx.result)),
});
function target(a, cb, b, c) {
events.push("fn args:" + [a, typeof cb, b, c].join(","));
cb(null, "cb-value");
return "target-ret";
}
const ret = ch.traceCallback(target, 1, { ctx: true }, { tag: "this" },
"A", (err, value) => events.push("callback:" + err + ":" + value), "B", "C");
console.log("ret:", ret);
console.log(events.join("\n"));
Observed result:
ret: target-ret
start:{"ctx":true}
fn args:A,function,B,C
asyncStart:"cb-value"
callback:null:cb-value
asyncEnd:"cb-value"
end:{"ctx":true,"result":"cb-value"}
Perry Behavior
docs/runtime-parity.md lists tracingChannel.traceCallback(fn[, position[, context[, thisArg[, ...args]]]]).
crates/perry-runtime/src/node_submodules/diagnostics.rs::diag_trace_callback() takes fn_value, _position, context, this_arg, callback, err, and res.
- The
_position argument is not used.
- The inactive path calls
call_fn_value(fn_value, this_arg, &[callback, err, res]).
- The active path builds a wrapped callback and calls
call_fn_value(fn_value, this_arg, &[wrapped_value, err, res]).
- Existing trace-callback fixtures only exercise
position === 0.
Suggested PR Cut
Batch this with related issues in:
node:diagnostics_channel: tracing and store semantics parity cut (#3242)
Good batch candidates:
Do not batch with:
node:trace_events category tracing
- generic Promise scheduler rewrites unless required by this diagnostics-specific behavior
- worker/thread diagnostics subscriber policy changes
Acceptance
- parity/regression test proves a non-zero callback
position preserves arguments before and after the callback
traceCallback() forwards all provided args rather than only a fixed (callback, err, res) shape
- current tracing event ordering and
context.result / context.error updates remain Node-compatible
- inactive/no-subscriber fast path preserves the same argument behavior
- related known-failure/docs/manifest entries updated if touched
Summary
TracingChannel#traceCallback(fn, position, context, thisArg, ...args)should wrap the callback argument at the requestedpositionwhile preserving all surrounding arguments. Perry currently ignorespositionand callsfnwith a fixed(wrappedCallback, err, res)shape, so callback-last or callback-middle APIs receive the wrong arguments and extra arguments are dropped.Node Behavior
Probe run with Node v25.9.0:
Observed result:
Perry Behavior
docs/runtime-parity.mdliststracingChannel.traceCallback(fn[, position[, context[, thisArg[, ...args]]]]).crates/perry-runtime/src/node_submodules/diagnostics.rs::diag_trace_callback()takesfn_value,_position,context,this_arg,callback,err, andres._positionargument is not used.call_fn_value(fn_value, this_arg, &[callback, err, res]).call_fn_value(fn_value, this_arg, &[wrapped_value, err, res]).position === 0.Suggested PR Cut
Batch this with related issues in:
node:diagnostics_channel: tracing and store semantics parity cut(#3242)Good batch candidates:
Do not batch with:
node:trace_eventscategory tracingAcceptance
positionpreserves arguments before and after the callbacktraceCallback()forwards all provided args rather than only a fixed(callback, err, res)shapecontext.result/context.errorupdates remain Node-compatible