Browse Source

Verify Jint's host contracts on every test run

The scripting integration defines several Jint extension points: the
ContentWrapper objects override GetOwnProperty, and the engine trusts the
answer without re-verifying it on the hot path. A hook that contradicts
another therefore fails silently in production - a key vanishes from every
enumeration, or a read resolves on the prototype for a property that
exists - which is the class of bug no assertion in this repository would
catch.

Jint 4.15.3 exposes its host-contract verifiers to the shipped Release
package through an AppContext switch, where before they were compiled out
unless you built the engine from source in Debug. A module initializer sets
it for this test assembly, so the verifiers run against the same NuGet
package production uses and report a violation as an ordinary test failure.
It must be set before the first use of any Jint type, which is exactly what
a module initializer guarantees.

Confirmed live rather than assumed: with a deliberately wrong
ProbeOwnProperty the run fails with "ContentFieldObject.ProbeOwnProperty
answered 'iv' with Missing but its GetOwnProperty reports Enumerable".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uV6H9cTntzsoKiaJRBn4f
pull/1326/head
Marko Lahma 1 month ago
parent
commit
22331acfcf
  1. 35
      backend/tests/Squidex.Domain.Apps.Core.Tests/TestHelpers/JintHostContractVerification.cs

35
backend/tests/Squidex.Domain.Apps.Core.Tests/TestHelpers/JintHostContractVerification.cs

@ -0,0 +1,35 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Runtime.CompilerServices;
namespace Squidex.Domain.Apps.Core.TestHelpers;
/// <summary>
/// Turns on Jint's host-contract verifiers for this test assembly.
/// </summary>
/// <remarks>
/// The scripting integration defines several Jint extension points - the ContentWrapper objects override
/// GetOwnProperty and ProbeOwnProperty, and the engine trusts both without re-verifying them on the hot
/// path. A hook that contradicts another therefore fails silently in production: a key vanishes from every
/// enumeration, or a read resolves on the prototype for a property that exists. With the switch on, Jint
/// recomputes the answer the fast paths exist to avoid and throws on the first disagreement, so these tests
/// are the checker.
/// <para>
/// It has to be set before the first use of any Jint type - the flag is read once at type initialization -
/// which is what the module initializer guarantees. Never turn it on in production: the verifiers
/// deliberately redo the work they check.
/// </para>
/// </remarks>
internal static class JintHostContractVerification
{
[ModuleInitializer]
internal static void Enable()
{
AppContext.SetSwitch("Jint.EnableHostContractVerification", true);
}
}
Loading…
Cancel
Save