* fix(javascript): stop registering colliding and unreachable type globals
`Engine.RegisterType` exposes a .NET type under `Type.Name`. That name is not
always usable, and the type registrations are contributed by several
independent handlers whose sets overlap.
* `IDictionary<string, string>` and `IDictionary<string, object>` are both named
``IDictionary`2``, so the two registrations claimed the same global and the
later one silently won. Neither is reachable from a script: a backtick cannot
appear in an identifier.
* `byte[]` is named `Byte[]`, which is likewise unreachable.
* `DateTime`, `DateTimeOffset`, `TimeSpan`, `Guid` and `LogPersistenceMode` are
part of both the common type set and the default workflow variable descriptor
set, so each was constructed and assigned twice for every expression
evaluation.
`RegisterType` now skips types whose name is not usable as a JavaScript
identifier, and skips a type that is already registered under that name. Type
aliases used by the TypeScript definition endpoint are unaffected — they are
maintained by `ITypeAliasRegistry` and are independent of this registration.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0179sA2T7HuRfRfSc2JirFik
* fix(javascript): leave an already-occupied global name alone
`RegisterType` skipped a name only when it already held a `TypeReference` for the
same type, so anything else under that name was replaced. That includes a global
the host installed through the per-evaluation `configureEngine` callback,
`JintOptions.ConfigureEngine` or `JintOptions.RegisterType` — all of which run
before the built-in registrations, since those are contributed by handlers of
`EvaluatingJavaScript`. Silently overwriting a host global is surprising and the
host has no way to win.
`RegisterType` now leaves any occupied name alone. That keeps the duplicate
suppression the check was written for — registering the same type twice is still
a no-op, so the overlapping handlers stop describing the same types through
reflection on every evaluation — and additionally makes the host global win. It
also agrees with #7895, where the registrations move to engine construction and
every host extension point runs after them.
Two tests pin the behaviour: a host value set under a built-in type's name
survives the built-in registrations, and `RegisterType` installs a
`TypeReference` that a second registration leaves untouched.
The remark about unusable type names is tightened while here: ``IDictionary`2``
and `Byte[]` can be reached through bracket notation if they are registered, so
the reason to skip them is that they cannot be written as identifiers, and that
every constructed generic type of the same arity claims the same global.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0179sA2T7HuRfRfSc2JirFik
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>