You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(swc): dead code eliminate unreferenced private class members in workflow mode (#1671)
* feat(swc): dead code eliminate unreferenced private class members in workflow mode
After stripping 'use step' methods from a class body in workflow mode,
eliminate private members (both JS native #field/#method and TypeScript
private field/private method) that are no longer referenced by any
remaining public member.
The algorithm is iterative: references are seeded from public members,
then expanded through surviving private members until a fixed point,
enabling cascading elimination (e.g. a private field only referenced by
a private method that is itself unreferenced).
* test(swc): add fixture for JS native private member DCE (#field, #method)
* fix(swc): address review feedback on private member DCE
- Namespace JS native private names with # prefix to avoid collisions
with TS private members of the same name
- Track TS private member accesses on non-this receivers (e.g. a.x in
static methods) by maintaining a set of known TS-private names
- Use visit_children_with for full traversal including computed member
expressions
- Extract retain logic into shared retain_referenced_private_members()
helper used by both visit_mut_class_decl and visit_mut_class_expr
Copy file name to clipboardExpand all lines: packages/swc-plugin-workflow/spec.md
+54Lines changed: 54 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1164,6 +1164,60 @@ const obj = {
1164
1164
1165
1165
**Client mode**: Same as step mode — the getter body is hoisted for `stepId` assignment, original getter preserved.
1166
1166
1167
+
### Private member dead code elimination
1168
+
1169
+
In workflow mode, after stripping `"use step"` methods and getters from a class body, the plugin eliminates private class members that are no longer referenced by any remaining (non-private) member. This applies to both:
The algorithm is iterative: references are first collected from all public members, then the referenced set is expanded by scanning surviving private members' bodies for cross-references, repeating until the set stabilizes. This enables cascading elimination — a private field only referenced by a private method that is itself unreferenced will also be removed.
// private encryptionKeyPromise — ELIMINATED (only referenced by getEncryptionKey)
1208
+
// private getEncryptionKey() — ELIMINATED (only referenced by stripped getter)
1209
+
constructor(id) { this.id= id; }
1210
+
}
1211
+
// getter replaced with step proxy
1212
+
var __step_Run$value =globalThis[Symbol.for("WORKFLOW_USE_STEP")]("step_id");
1213
+
Object.defineProperty(Run.prototype, "value", {
1214
+
get() { return__step_Run$value.call(this); },
1215
+
configurable:true, enumerable:false
1216
+
});
1217
+
```
1218
+
1219
+
This optimization is critical for SDK classes like `Run` where private helper methods reference Node.js-only imports (encryption, world access, etc.) — eliminating them allows the downstream module-level DCE to also remove those imports from the workflow bundle.
0 commit comments