perf(template-engine): cache Expression-trigger compile verdicts under the trigger-surface key — unchanged expressions compile once per process (plan R2-05 T3)

This commit is contained in:
Joseph Doherty
2026-07-13 09:46:36 -04:00
parent 06d79f6516
commit d233ecbe8f
2 changed files with 42 additions and 11 deletions
@@ -149,6 +149,29 @@ public class ScriptCompilerTests
Assert.Contains("forbidden", error, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void CheckExpressionSyntax_SameExpressionTwice_SecondCallIsCacheHit()
{
ScriptCompileVerdictCache.Clear();
ValidationService.CheckExpressionSyntax("Attributes[\"Temp\"] != null");
var hitsBefore = ScriptCompileVerdictCache.Hits;
var error = ValidationService.CheckExpressionSyntax("Attributes[\"Temp\"] != null");
Assert.Null(error);
Assert.Equal(hitsBefore + 1, ScriptCompileVerdictCache.Hits); // FAILS today: no cache use
}
[Fact]
public void CheckExpressionSyntax_ScriptSurfaceVerdict_NotReusedForTriggerSurface()
{
// "Notify != null" resolves on ScriptCompileSurface (Notify is a script global,
// ScriptCompileSurface.cs:53) but NOT on TriggerCompileSurface — a shared
// code-only cache entry would wrongly report the trigger expression clean.
ScriptCompileVerdictCache.Clear();
Assert.True(new ScriptCompiler().TryCompile("Notify != null", "S").IsSuccess); // warms the SCRIPT-surface entry
var error = ValidationService.CheckExpressionSyntax("Notify != null");
Assert.NotNull(error); // green today (no cache), and MUST STAY green after T3 — the T2 key makes it structural
}
[Fact]
public void CheckExpressionSyntax_MultipleForbiddenApis_ReportsAll()
{