Add support for custom class instance serialization#762
Merged
TooTallNate merged 24 commits intomainfrom Jan 19, 2026
Merged
Conversation
🦋 Changeset detectedLatest commit: fdbfb5e The changes in this PR will be included in the next version bump. This PR includes changesets to release 15 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 |
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests🌍 Community Worlds (22 failed)mongodb (1 failed):
redis (1 failed):
starter (19 failed):
turso (1 failed):
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
|
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
- Remove tests for `this` serialization in step functions since the SWC plugin forbids `this` usage in steps (ChainableService and thisSerializationWorkflow tests disabled with comment) - Use Symbol.for() directly in 99_e2e.ts instead of importing from 'workflow' to avoid pulling in server-side dependencies (node:async_hooks) when the file is bundled for the client Both Next.js turbopack and webpack builds now pass successfully.
This reverts commit 0fc1fae.
Use Symbol.for() directly in 99_e2e.ts instead of importing from 'workflow' to avoid pulling in server-side dependencies (node:async_hooks) when the file is bundled for the client in the workbench Next.js apps.
This is an internal function only used by SWC-generated code, which imports it from workflow/internal/class-serialization instead.
The SWC plugin specifically looks for the `Symbol.for('workflow-serialize')`
pattern in computed property names. Using a variable reference like
`[WORKFLOW_SERIALIZE]` doesn't work because the plugin does AST pattern
matching, not runtime evaluation.
… symbols
The SWC plugin now recognizes custom serialization classes using any of these patterns:
1. Direct Symbol.for() in class definition:
static [Symbol.for('workflow-serialize')](instance) { ... }
2. Imported symbols from 'workflow' package:
import { WORKFLOW_SERIALIZE } from 'workflow';
static [WORKFLOW_SERIALIZE](instance) { ... }
3. Local const defined with Symbol.for():
const MY_SYM = Symbol.for('workflow-serialize');
static [MY_SYM](instance) { ... }
4. Re-exported symbols from other modules
Added test fixtures for imported and local const patterns.
Sort classes_needing_serialization before iterating to ensure deterministic output ordering in test fixtures.
The serializer needs the classId property on the class to serialize instances (e.g., step return values). Previously this was only set in workflow mode by the SWC plugin, but step mode also needs it for serializing return values.
…d workflow modes - Move class registry to globalThis for isomorphic access in both contexts - Add WORKFLOW_CLASS_REGISTRY symbol to symbols.ts - Refactor class-serialization.ts to use globalThis-based registry that is lazily initialized (works in both step mode and VM workflow mode) - Update SWC plugin workflow mode to import and call registerSerializationClass() instead of manual classId assignment and globalThis[].set() calls - Add fallback in serialization.ts reviver to check VM's globalThis registry - Update test fixtures for the new import/call pattern This simplifies the code by using the same registerSerializationClass() function in both step and workflow modes, rather than generating different code for each.
Member
Author
|
Rebased, cleaned up a bit, removed docs for now (moved to a separate PR, which we can merge when we feel comfortable to publicly document). Going to merge this so we can continue to |
Merged
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Added support for custom class instance serialization across workflow/step boundaries.
What changed?
@workflow/serdepackage withWORKFLOW_SERIALIZEandWORKFLOW_DESERIALIZEsymbolsHow to test?
The PR includes a new e2e test
customSerializationWorkflowthat demonstrates the feature:Run the e2e test to verify that class instances are properly serialized and deserialized.
Why make this change?
Previously, user-defined class instances couldn't be passed between workflows and steps without losing their prototype chain and methods. This change allows developers to define custom serialization/deserialization logic for their classes, enabling proper reconstruction of instances with their full functionality intact when crossing workflow/step boundaries.