Repository navigation
feat: share state symbols across module copies - #1
Merged
Merged
Conversation
Each state key was a module-local Symbol(), so a second copy of xception
in the same process (e.g. two bundled copies) could not read the cause,
severity, tags, namespace, meta or code of an instance created by the
other copy, and instanceof checks across copies failed.
Register every key with Symbol.for('xception.<name>') so all copies
resolve the same registry-global symbol.
alvis
marked this pull request as ready for review
October 1, 2026 19:59
alvis
added a commit
that referenced
this pull request
Oct 1, 2026
Each state key was a module-local Symbol(), so a second copy of xception
in the same process (e.g. two bundled copies) could not read the cause,
severity, tags, namespace, meta or code of an instance created by the
other copy, and instanceof checks across copies failed.
Register every key with Symbol.for('xception.<name>') so all copies
resolve the same registry-global symbol.
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.
📌
Every xception state key was a module-local
Symbol(), so when two copies of xception load in one process, as they do with two bundled copies, neither copy can read the other's state. This change registers every key asSymbol.for('xception.<name>'), which gives all copies the same symbols.🎯 Goal
An Xception keeps its cause, severity, tags, namespace, meta and code when another copy of xception in the same process reads, wraps or converts it.
✅ Requirements
$cause,$severity,$tags,$namespace,$meta,$codeand$brandsare the same symbols in every copy of the module.xception()from one copy, given an Xception from another copy, keeps that error's severity, tags, namespace and meta.TypeError: cause[$tags] is not iterable.instanceofstill works across copies forXceptionand for named subclasses.🧵 Context
theriety/core runs into this when a compiled runner bundles its own copy of xception next to the service's copy. In a check with two copies of xception 9.0.0:
error;theriety/core#665 works around this today with
patches/xception@9.0.0.patch, which makes the same change.🛠️ Implementation
src/symbols.ts: each state key isSymbol.for('xception.<name>'), so it is registry-global.spec/symbols.spec.ts: loads two independent module graphs withvi.resetModules()and tests real behavior across them. It checks that the classes really are separate and the symbols are shared; thatinstanceofworks forXceptionand for named subclasses; and that wrapping and converting a cause from the other copy keeps its severity, tags, namespace and meta.🧪 Verification
pnpm testatb96358b: 80/80 pass in 7 files.eslint --max-warnings 0 src specatb96358b: clean.tsc --noEmitatb96358b: the only error isspec/base.spec.ts:274(TS2345). The base9b8f086has the same error, so this change does not introduce it.b96358b.📋 Additional Notes
Publish review findings and the verdict as a separate PR review or comment. Never append them to the main PR description.
instanceofalready worked across copies before this change:Xceptionmatches onSymbol.for('xception')and named subclasses on their registered brand. The spec covers it as a regression check. The commit message says otherwise, and that commit is signed, so it is left as it is.Symbol.for, a class fromcreateXceptionClasswhose brand name equals an internal key (tags,cause,meta,code,severity,namespace,brands) can share a registry key with xception's own state.