fix(swc-plugin): preserve step function names in stack traces after bundler minification#1743
fix(swc-plugin): preserve step function names in stack traces after bundler minification#1743TooTallNate wants to merge 2 commits intomainfrom
Conversation
…undler minification
Add Object.defineProperty(fn, 'name', { value, configurable: true }) to the
IIFE step registration so the original function name survives bundler name
mangling (e.g. Turbopack renaming errorStepFn to eD). V8 uses the .name
property for stack traces, so this ensures 'at errorStepFn (...)' appears
instead of 'at eD (...)'.
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 1 step💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express workflow with 25 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express workflow with 10 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 25 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 50 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 10 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 25 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) workflow with 50 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express stream pipeline with 5 transform steps (1MB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) 10 parallel streams (1MB each)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) fan-out fan-in 10 streams (1MB each)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
❌ Some benchmark jobs failed:
Check the workflow run for details. |
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests💻 Local Development (76 failed)express-stable (76 failed):
🌍 Community Worlds (98 failed)mongodb (15 failed):
redis (15 failed):
turso (68 failed):
Details by Category✅ ▲ Vercel Production
❌ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
🦋 Changeset detectedLatest commit: 190c267 The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR updates the @workflow/swc-plugin step-mode transform so inline step registration IIFEs explicitly set the registered function’s .name, preserving human-readable step names in stack traces even after bundler minification/mangling.
Changes:
- Emit
Object.defineProperty(__wf_fn, "name", { value: "<original>", configurable: true })inside inline step registration IIFEs. - Thread the original function name through
create_inline_step_registration(...)call sites. - Update SWC transform fixture snapshots (and add a changeset) to reflect the new emitted code.
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/swc-plugin-workflow/transform/src/lib.rs | Extend inline step registration codegen to define the function name property using the original step name. |
| .changeset/preserve-step-fn-names.md | Publish a patch changeset for the SWC plugin behavior change. |
| packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs. |
| packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs for error fixtures. |
| packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs for error fixtures. |
| packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs for error fixtures. |
| packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs for error fixtures. |
| packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs for error fixtures. |
| packages/swc-plugin-workflow/transform/tests/errors/conflicting-directives/output-step.js | Update expected transformed output to include Object.defineProperty(..., "name", ...) in step IIFEs for error fixtures. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Nathan Rajlich <n@n8.io>
Summary
Object.defineProperty(fn, "name", { value: "originalName", configurable: true })to the IIFE step registration in the SWC pluginerrorStepFn→eD)Motivation
When bundlers like Turbopack minify module-internal function names, the step function references registered in the
globalThismap point to functions with mangled.nameproperties. This causes stack traces to showat eD (...)instead ofat errorStepFn (...), breaking the e2e test"basic step error preserves message and stack trace".V8 uses the function's
.nameproperty for stack trace frames. By explicitly setting it viaObject.definePropertyin the registration IIFE, we ensure the original name is preserved regardless of bundler renaming.Test plan
Object.definePropertycall)errorStepFnappears in stack traces with Turbopack prod builds