Skip to content

Fix Live Debugger returned arrow instrumentation#442

Draft
watson wants to merge 1 commit into
watson/fix-nested-functionsfrom
watson/fix-nested-functions2
Draft

Fix Live Debugger returned arrow instrumentation#442
watson wants to merge 1 commit into
watson/fix-nested-functionsfrom
watson/fix-nested-functions2

Conversation

@watson

@watson watson commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What and why?

Fix a Live Debugger transform bug that could emit invalid JavaScript when instrumenting a block-bodied function that returns an anonymous expression-bodied arrow.

For example, this input:

export const make = (cond) => {
    return () => cond ? a() : b();
};

Could generate output shaped like this before the fix, formatted here for readability:

return (
    $dd_rv1 = () => {
        const $dd_p0 = $dd_probes('src/utils.ts;<anonymous>');
        try {
            if ($dd_p0) $dd_entry($dd_p0, this);
            const $dd_rv0 =
                cond ? a() : b(),
                $dd_p1 ? $dd_return($dd_p1, $dd_rv1, this, {cond}) : $dd_rv1
            );

            if ($dd_p0) $dd_return($dd_p0, $dd_rv0, this);
            return $dd_rv0;
        } catch(e) {
            if ($dd_p0) $dd_throw($dd_p0, e, this);
            throw e;
        }
    }
);

In all-functions mode, both the inner arrow suffix and the outer return wrapper could be inserted at the same byte offset. The outer return-capture tail landed before the inner arrow suffix closed, leaving invalid JavaScript. Named-only mode avoided the issue by skipping the anonymous inner arrow.

How?

Change the outer return EXPR wrapper tail from appendLeft to appendRight at ret.argEnd, so an inner expression-body arrow suffix already queued at that offset is emitted first and closes the inner instrumentation before the outer return capture tail.

Add regression cases for block-bodied arrows and function declarations returning expression-bodied arrows, including a JSX mapping case, plus a block-bodied inner arrow control. The table continues to parse transformed output and now also asserts return instrumentation is still present.

watson commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jun 29, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 0160533 | Docs | Datadog PR Page | Give us feedback!

When a block-bodied function returned an anonymous expression-bodied arrow,
Live Debugger could queue the outer return wrapper at the same byte offset as
the inner arrow suffix. MagicString emitted the outer tail inside the inner
arrow instrumentation, producing invalid JavaScript.

Anchor the return-wrapper tail on the right side of the shared offset so the
inner arrow suffix closes first. Add regression coverage for returned arrows,
including JSX mapping, while asserting the output remains instrumented.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant