Skip to content

refactor: break up god-methods and god-files (epic #1094)#1241

Merged
nickna merged 6 commits into
mainfrom
epic-1094-god-methods
Jul 4, 2026
Merged

refactor: break up god-methods and god-files (epic #1094)#1241
nickna merged 6 commits into
mainfrom
epic-1094-god-methods

Conversation

@nickna

@nickna nickna commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Epic #1094 — break up god-methods and god-files

Pure mechanical extraction, no behaviour change. Interpreter and compiled output are
byte-identical; every change is a partial-class move or a semantics-preserving helper
extraction. Standalone compiled DLLs gain no SharpTS.dll dependency (no reflection
idioms were touched).

What changed, by sub-issue

#1142 — Extract realm/global state out of Interpreter.cs (3,065 → 1,978 lines)

  • New Interpreter.Realm.cs: the process-wide globals table (CreateGlobalsLookup + the
    ordering-sensitive PromiseConstructorSentinel/_globalConstants/RegExpConstructorObject
    static trio, kept together and in textual order so static-init ordering is preserved),
    plus the per-realm Symbol.for registry, Math, primitive prototypes, RegExp.prototype,
    and globalThis routing helpers.
  • The statement dispatch core and all Visit* handlers move next to their Execute* bodies
    in Interpreter.Statements.cs.

#1141 — Split the RuntimeEmitter mega-files

  • RuntimeEmitter.CoreUtilities.cs (4,454 lines, four unrelated concerns) split into
    RuntimeEmitter.Coercion.cs (JS ToString/stringify, ToNumber/ToInt32, IsTruthy) and
    RuntimeEmitter.Operators.cs (relational, typeof, instanceof, in, +, ==, ===); the
    console-format block folded into the existing RuntimeEmitter.ConsoleHelpers.cs. All 32
    emitter methods relocated verbatim; CoreUtilities.cs removed.
  • RuntimeEmitter.Objects.Properties.cs (5,222 → 3,090 lines): the whole Set* and Delete*
    emitter methods moved into RuntimeEmitter.Objects.SetProperty.cs and
    RuntimeEmitter.Objects.DeleteProperty.cs.
  • Deferred: extracting the per-receiver branches inside the 2,028-line EmitGetProperty
    into helpers. That method emits IL through method-scoped labels/locals shared across every
    receiver branch; slicing it risks silent IL corruption that tests may not surface. Left as a
    follow-up — the file-level split above already removes the god-file smell.

#1143 — Right-size ObjectBuiltIns/BuiltInModuleTypes

  • ObjectBuiltIns.cs (2,122 → 1,385 lines): the 21 Runtime* reflective property-descriptor
    helpers (invoked from compiled code) moved into ObjectBuiltIns.RuntimeDescriptors.cs,
    leaving the JS Object.* statics behind.
  • BuiltInModuleTypes.cs (2,399 → 697 lines): per-module type signatures split into
    BuiltInModuleTypes.System.cs (fs/process/child_process/worker_threads/cluster/vm) and
    BuiltInModuleTypes.NetworkStreams.cs (dns/net/tls/http/dgram + stream); dispatch stays put.
  • Deferred: converging the AST dispatch tables onto NodeRegistry/AstVisitorBase. The
    issue gates this on Epic 3 and describes it as "ideally source-generated" — a design change,
    not a mechanical move — so it is out of scope for this behaviour-preserving PR.

#1140 — Split the two type-checker god-methods

  • CheckCall (~675 → ~295 lines): the entire builtin/special-case dispatch prologue extracted
    verbatim into TryCheckBuiltinCall(call, out result), preserving exact check order (zero
    reordering). CheckCall now delegates to it, then runs the general callable-resolution path.
  • IsCompatibleCore: the clearly-delimited leading sections extracted into named
    TryRelate* helpers in the new TypeChecker.Compatibility.Relations.cs, mirroring the
    existing TryRelateDeferredMappedType pattern — TryRelateTypePredicate,
    TryRelateTypeParameters, TryRelateNeverUnknownObject, TryRelateNullUndefinedStrict,
    TryRelateLiteralTypes. Evaluation order is unchanged. The intricate, heavily-commented
    fall-through tail (iterator/generator/instance families) is deliberately left intact.

Validation

  • dotnet test: 15404 / 0.
  • SharpTS.Test262 (interpreter + compiled): baseline-green.
  • SharpTS.TypeScriptConformance (type-checker): 31 / 0, no baseline regression.

Closes #1140
Closes #1141
Closes #1142
Closes #1143

Deferred scope filed as follow-ups under the epic: #1242 (EmitGetProperty
per-receiver branch extraction) and #1243 (AST dispatch-table convergence).

Part of #1094.

nickna added 6 commits July 4, 2026 00:43
…partials (#1142)

Pure mechanical partial-class split of the 2,898-line Interpreter.cs, no
behaviour change:

- New Interpreter.Realm.cs holds the realm/global-state cluster: the process-
  wide globals table (CreateGlobalsLookup + the ordering-sensitive Promise/
  RegExp static trio, kept together and in textual order), the per-realm
  Symbol.for registry, Math, primitive prototypes, RegExp.prototype, and the
  globalThis routing helpers.
- The statement dispatch core and all Visit* handlers move next to their
  Execute* bodies in Interpreter.Statements.cs.

Interpreter.cs shrinks 2,898 -> 1,977 lines. dotnet test 15404/0.

Part of #1094.
…1141)

The 4,454-line CoreUtilities.cs mixed four unrelated emitters. Split into:
- RuntimeEmitter.Coercion.cs   - JS ToString/stringify, ToNumber/ToInt32, IsTruthy
- RuntimeEmitter.Operators.cs  - relational (<, <=), typeof, instanceof, in, +, ==, ===
- the console-format block folded into the existing RuntimeEmitter.ConsoleHelpers.cs

Pure partial-class method moves; no IL/behaviour change. All 32 emitter methods
(29 Emit* + 3 Declare*) relocated verbatim. dotnet test 15404/0.

Part of #1094.
…em (#1143)

Move the 21 Runtime* reflective property-descriptor helpers (invoked from
compiled code to define/read descriptors, prototypes, and extensibility on
arbitrary CLR/guest objects via reflection) out of the 2,122-line
ObjectBuiltIns.cs into ObjectBuiltIns.RuntimeDescriptors.cs, leaving the JS
Object.* statics behind. Class made partial; pure method move, no behaviour
change. dotnet test 15404/0.

Part of #1094.
…s.cs (#1141)

Move the whole property/index assignment emitters (EmitSetFieldsProperty,
EmitSetFieldsPropertyStrict, EmitSetProperty, EmitToLengthBoxed,
EmitSetPropertyStrict, EmitSetIndexStrict) into RuntimeEmitter.Objects.SetProperty.cs
and the delete-property emitters (EmitDeleteProperty, EmitDeletePropertyCore,
EmitDeletePropertyStrict) into RuntimeEmitter.Objects.DeleteProperty.cs.

Objects.Properties.cs shrinks 5,222 -> 3,090 lines. Pure partial-class method
moves; no IL/behaviour change. The per-receiver-branch extraction inside the
2,028-line EmitGetProperty (method-scoped shared labels/locals) is deliberately
left as a follow-up to avoid silent IL corruption.

Part of #1094.
Split the 2,399-line BuiltInModuleTypes.cs: per-module type signatures move into
BuiltInModuleTypes.System.cs (fs/process/child_process/worker_threads/cluster/vm)
and BuiltInModuleTypes.NetworkStreams.cs (dns/net/tls/http/dgram + stream). The
GetModuleTypes/GetPrimitiveTypes dispatch and small modules stay in the main file,
now 697 lines. Class made partial; pure method move, no behaviour change.

Part of #1094.
…#1140)

- CheckCall: extract the builtin/special-case dispatch prologue verbatim into
  TryCheckBuiltinCall(call, out result), preserving exact check order (zero
  reordering). CheckCall drops from ~675 to ~295 lines; it now delegates to the
  helper then runs the general callable-resolution path.
- IsCompatibleCore: extract the clearly-delimited leading sections into named
  TryRelate* helpers in the new TypeChecker.Compatibility.Relations.cs, mirroring
  the existing TryRelateDeferredMappedType pattern (TryRelateTypePredicate,
  TryRelateTypeParameters, TryRelateNeverUnknownObject, TryRelateNullUndefinedStrict,
  TryRelateLiteralTypes). Evaluation order unchanged; the intricate fall-through
  tail (iterator/generator/instance families) left intact.

dotnet test 15404/0, Test262 22/0/4-skip, TSConformance 31/0. No behaviour change.

Part of #1094.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment