Problem
Registry._getFunctionName() in packages/durabletask-js/src/worker/registry.ts has a fallback path that parses function names from fn.toString() when fn.name is empty. This parsing has two bugs:
-
Generator functions (function*() {}): The parser does fnStr.indexOf("function") + "function".length, landing right before the *. It then takes everything up to (, returning "*" as the name. Since "*" is truthy, it passes the if (!name) validation in addNamedOrchestrator, silently registering the orchestrator under name "*".
-
Arrow functions ((x) => x): indexOf("function") returns -1, so start = -1 + 8 = 7. The parser then slices from position 7 to the next (, producing garbage output.
Root Cause
The _getFunctionName fallback parser was written for regular function declarations only. It does not account for:
- The
* in generator function syntax
- Arrow functions that lack the
function keyword entirely
Proposed Fix
Three guards added to _getFunctionName:
- Return
"" when indexOf("function") returns -1 (arrow functions have no function keyword)
- Skip past
* and whitespace after the function keyword (generator functions)
- Return
"" when indexOf("(", start) returns -1 (malformed input safety)
Impact
Severity: Medium. When addOrchestrator(async function*(ctx) { ... }) is called with a truly anonymous generator (no variable assignment), the orchestrator registers under name "*". No error is thrown — the orchestrator silently never matches any scheduled orchestration. This only affects inline anonymous generators without variable assignment context (since JS engines infer fn.name from variable assignments).
Problem
Registry._getFunctionName()inpackages/durabletask-js/src/worker/registry.tshas a fallback path that parses function names fromfn.toString()whenfn.nameis empty. This parsing has two bugs:Generator functions (
function*() {}): The parser doesfnStr.indexOf("function") + "function".length, landing right before the*. It then takes everything up to(, returning"*"as the name. Since"*"is truthy, it passes theif (!name)validation inaddNamedOrchestrator, silently registering the orchestrator under name"*".Arrow functions (
(x) => x):indexOf("function")returns-1, sostart = -1 + 8 = 7. The parser then slices from position 7 to the next(, producing garbage output.Root Cause
The
_getFunctionNamefallback parser was written for regularfunctiondeclarations only. It does not account for:*in generator function syntaxfunctionkeyword entirelyProposed Fix
Three guards added to
_getFunctionName:""whenindexOf("function")returns-1(arrow functions have nofunctionkeyword)*and whitespace after thefunctionkeyword (generator functions)""whenindexOf("(", start)returns-1(malformed input safety)Impact
Severity: Medium. When
addOrchestrator(async function*(ctx) { ... })is called with a truly anonymous generator (no variable assignment), the orchestrator registers under name"*". No error is thrown — the orchestrator silently never matches any scheduled orchestration. This only affects inline anonymous generators without variable assignment context (since JS engines inferfn.namefrom variable assignments).