Skip to content

v3.1.3

Choose a tag to compare

@windischb windischb released this 19 Apr 09:34
· 40 commits to develop since this release
558c35d

Cocoar.JsEval v3.1.3

Cocoar.JsEval.TsDefinition now emits valid TypeScript — and stops shipping a 10-year-old standard library.

This release is a pure fix-up of Cocoar.JsEval.TsDefinition. No API additions, no changes to any other package. Three latent renderer bugs silently produced .d.ts output that the TypeScript compiler refuses — so anyone piping GetTsDefinitions() into Monaco's worker, ts.createProgram, or an IDE language service has been running with partially broken IntelliSense and never knew.

The failure 3.1.2 and earlier users were hitting

A probe of the full default module set's output (ran ts.createSourceFile over every non-lib. file produced by GetTsDefinitions()):

Before 3.1.3:
  AngleSharp.d.ts   10 parse diagnostics
  Cocoar.d.ts       93 parse diagnostics
  Dapper.d.ts       46 parse diagnostics
  SqlKata.d.ts      91 parse diagnostics
  System.d.ts      465 parse diagnostics
  → 5 of 9 files unusable to any real TypeScript consumer

The errors were invisible at the C# side — the renderer returned strings, nobody ever fed them through a TS parser to verify — but any consumer who did got a silently-degraded IntelliSense experience, missing completions for every affected type. This release lands those files clean:

After 3.1.3:
  → 9 of 9 files parse with zero diagnostics

What 3.1.3 does

Three independent renderer bugs, all fixed:

  • Task<T> / ValueTask<T> emitted the generic argument twice. NormalizeTypeName baked <T> into the returned string; BuildTypeString appended it again from TypeDefinition.GenericArguments. Result: Promise<T><T> — a parse error. The fix brings the handling in line with every other generic type: NormalizeTypeName returns the bare wrapper ("Promise"), and the caller owns generic-arg composition once.

  • ref T parameters and return types leaked the .NET ByRef suffix & into the TS output. Properties like Current: T& on Span<T>.Enumerator tripped TypeScript's intersection operator (which needs a right-hand operand). The existing ByRef check used Type.FullName.EndsWith('&'), but FullName is null for generic type parameters — so ref T on a method return silently slipped through. Now uses Type.IsByRef || Type.IsPointer with GetElementType() to unwrap — the spec-correct path.

  • Name-colliding types were declared twice in the same namespace. TypeDefinition.FromType has an internal FriendlyName-based cache; distinct Type inputs that collapse to the same friendly name return the same TypeDefinition reference. The renderer was adding that reference to namespace.Types on every encounter — System.d.ts alone emitted 40+ duplicate declarations (Type, Attribute, AdjustmentRule, RuntimeTypeHandle, …). Dedup'd on add.

Also in 3.1.3: lib.es5.d.ts / lib.es2015.core.d.ts stop shipping

Those were vendored copies of a very old TypeScript standard library (predating TS 4.x — the Microsoft copyright header in the file dates to the original 1.x-era bundle), historically shipped as a convenience for Monaco integrations. Two problems:

  1. Stale. A decade behind current TypeScript. Anyone using them as their Monaco source would be missing every post-ES5-core addition.
  2. Shadowing risk. Monaco's own TypeScript language service loads its own version-matched libs internally. Stacking ours on top could override fresher types — exactly the wrong default.

Neither this package nor any other Cocoar.JsEval.* package reads these files; they were pass-through resources. Dropping them removes ~4,940 lines of dead weight from the binary.

global.d.ts (hand-written, declares JsEval-specific globals — fetch, NewObject, exit, require) is unchanged and still ships.

Compatibility

Breaking for consumers who were reading lib.es5.d.ts / lib.es2015.core.d.ts directly from GetTsDefinitions(). If your code does:

var defs = tsDefService.GetTsDefinitions();
var lib5 = defs["lib.es5.d.ts"];   // ← KeyNotFoundException in 3.1.3

…you have two supported migration paths:

Path A — trust Monaco's own libs (recommended). Monaco ships a version-matched set automatically. Don't inject anything from us.

Path B — embed fresh ES libs from the upcoming Cocoar.JsEval.TypeScript.V8 package. That package exposes EmbeddedResources.LibFiles — a 97-file, TS 6.0.2, ES-only set with no DOM surface. Usable even if you don't use the V8 transpiler itself:

using Cocoar.JsEval.TypeScript.V8.Internal;  // (coming in 3.2.0)

foreach (var (name, content) in EmbeddedResources.LibFiles)
    monacoEditor.LanguageService.AddExtraLib(content, $"ts:filename/{name}");

NormalizeTypeName contract change (direct callers only). For Task<T> / ValueTask<T> the method now returns "Promise" instead of "Promise<T>" — the caller is expected to append the generic args from TypeDefinition.GenericArguments. Non-generic Task / ValueTask still return "Promise<void>" (unchanged; that comes from TypeMappings, not GenericTypeMappings). Consumers who use the bundled TypeScriptRenderer see no change — the final rendered .d.ts output for Task<string> is still Promise<string>, just composed once instead of twice.

Tests

Three new regression tests in JsEval.Tests.Engine/TsDefinitionTests.cs lock in the fixes:

  • Render_TaskOfT_DoesNotProduceDoubleGenerics — asserts Promise<string> is present and >< (double-generics marker) is absent
  • Render_RefReturn_DoesNotLeakAmpersand — asserts no &; or &> sequences anywhere in the output (uses a RefReturningSample type with ref int methods)
  • GetTsDefinitions_DoesNotShipLibFiles — asserts lib.es5.d.ts / lib.es2015.core.d.ts are absent from the output

The three pre-existing Task*_MapsToPromise* tests were updated to reflect the new NormalizeTypeName contract ("Promise" instead of "Promise<string>"); end-to-end rendering is verified via the new regression tests that exercise the full BuildTypeString path.

Full suite: 306 tests green (Engine 140, Linq 119, TypeScript 29, Modules 18 — Fetch excluded as usual since it needs network).

Packages

Package Changed in 3.1.3
Cocoar.JsEval.TsDefinition ✅ three renderer fixes + stop shipping stale lib files
Cocoar.JsEval no change
Cocoar.JsEval.Engine no change
Cocoar.JsEval.Linq no change
Cocoar.JsEval.TypeScript no change
All modules no change