Registering an IReferenceResolver without interests gives it
ReferenceResolverInterests.All, and two of those flags - ObjectPropertyBase
and PrimitivePropertyBase - are the gate on the non-computed member-read
inline caches, the dense-array indexed-read lane and the member-call callee
lane. With All declared, every property read in every script has to be
routed through a Reference so the resolver gets offered the base, and all
three lanes stay off for the whole engine.
NullPropagation.TryPropertyReference returns false for every base that is
not null or undefined, so on those two situations the engine consulting it
can never change the result. Declaring only the three situations the
resolver actually answers - NullishPropertyBase, UnresolvableReference and
NonCallableCallee - is therefore observably identical and re-arms all three
lanes. Interests are documented as a subscription filter and not a promise:
a situation that is not subscribed to behaves exactly as if no resolver
were registered.
Jint also ships a built-in NullPropagatingReferenceResolver, which is
deliberately NOT adopted here: it declines unresolvable identifiers and
non-callable callees, where this resolver answers both, so swapping it in
would turn an undeclared-name read and a call on a nullish chain into
errors for existing tenant scripts.
The behaviour pins from the first commit cover exactly those edges and all
156 tests in Operations/Scripting still pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uV6H9cTntzsoKiaJRBn4f
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
Package provenance verified after restore: source is
https://api.nuget.org/v3/index.json and the nuspec repository commit is
a304aa5dacd340e2a5ff51e1ea0c465e38e50aa8, the v4.15.3 tag. Acornima moves
to 1.6.2 transitively; ParseErrorException, ScriptPreparationException and
JintException, which JintScriptEngine.MapException switches on, all still
exist, and so do Engine.Constraints.Reset, Options.Constraints.PromiseTimeout,
AllowClrWrite, EvaluateAsync(in Prepared<Script>, CancellationToken),
ObjectWrapper.Create and the ObjectInstance virtuals the ContentWrapper
family overrides.
No source change is needed for the upgrade itself: the whole backend
solution builds warning-clean and all 156 tests in Operations/Scripting,
including the behaviour pins added in the previous commit, pass unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uV6H9cTntzsoKiaJRBn4f
The Jint upgrade that follows re-arms three engine-wide inline cache gates.
Each of those changes is only worth making if it is observably identical, so
pin the behaviour first, against Jint 4.8.0:
- null propagation: undeclared identifier reads, nullish property chains,
calls over a nullish base, calls of a non-callable member (which return
the base), and that ordinary member reads/calls are unaffected;
- enum values crossing into script as their member name, including a
[Flags] combination and an enum member of a wrapped CLR object;
- JSON objects projected into script: own key order, JSON.stringify,
for..in, mutation (add/replace/delete) and the round trip back to
JsonValue;
- content field objects: `in`, hasOwnProperty, propertyIsEnumerable,
Object.keys, spread, JSON.stringify, and that all of them follow
deletes and additions;
- the context object: key enumeration, `in`, typeof per value, reads,
write-through to ScriptVars and delete.
All 156 tests in Operations/Scripting pass unchanged on 4.8.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016uV6H9cTntzsoKiaJRBn4f
MongoDB.Driver 3.x moved MONGODB-AWS into MongoDB.Driver.Authentication.AWS
and requires explicit registration. Without it, Atlas IAM connection strings
fail at startup with "Unable to create an authenticator".
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: use CREATE OR ALTER/REPLACE FUNCTION to prevent startup failure on restart
On application restart the hosted service fails with:
SqlException: There is already an object named 'json_exists' in the database.
The #if RELEASE guard in JsonFunction.cs skips DROP FUNCTION IF EXISTS
statements in release builds, so CREATE FUNCTION fails if the functions
already exist from a previous run.
Replace the DROP + CREATE pattern with idempotent alternatives:
- SQL Server: CREATE OR ALTER FUNCTION (supported since SQL Server 2016 SP1)
- MySQL: CREATE OR REPLACE FUNCTION
PostgreSQL was already using CREATE OR REPLACE FUNCTION correctly.
DROP FUNCTION IF EXISTS statements are removed from both SQL files.
* Move JSON function creation into EF Core migrations
- Replace SqlDialectInitializer startup logic with proper EF Core migrations
for all three providers (MySQL, SQL Server, Postgres)
- SQL Server: uses CREATE OR ALTER FUNCTION (idempotent, no DROP needed)
- MySQL: uses DROP FUNCTION IF EXISTS + CREATE FUNCTION in migration
- Remove SqlDialectInitializer registration from production ServiceExtensions
- Add migration tests: idempotency and upgrade-from-pre-migration-database
* Add Postgres migration tests; fix image tag for arm64 compatibility
* Replace DatabaseCreator+SqlDialectInitializer with DatabaseMigrator in test fixtures
- Test fixtures now use the same code path as production (MigrateAsync)
- DatabaseCreator and SqlDialectInitializer are no longer needed and deleted
- Functions are created via the AddJsonFunctions migration, not at every startup
* Fix missing Squidex.Infrastructure using in test fixtures
* Fix test fixtures: use EnsureCreated+Dialect.InitializeAsync and per-prefix migration history
Two bugs fixed in the EF Core test fixtures (PostgresFixture, MySqlFixture, SqlServerFixture):
1. Replace DatabaseMigrator with EnsureCreatedAsync + Dialect.InitializeAsync
TestDbContext* are test-only contexts with no EF migration files, so
DatabaseMigrator<TestDbContext*>.InitializeAsync called MigrateAsync which was
a complete no-op — no tables were ever created and all integration tests failed
with 'relation does not exist'.
EnsureCreatedAsync builds the schema directly from the EF Core model, which is
the correct approach for contexts without migrations. Dialect.InitializeAsync is
then called explicitly to create the database-specific JSON functions (json_exists
etc.) that EnsureCreated does not set up.
2. Add per-prefix MigrationsHistoryTable for named ContentDbContext registrations
DynamicTables.PrepareAsync calls MigrateAsync on the named ContentDbContext
(e.g. PostgresContentDbContext) to create per-app/schema dedicated tables such
as '__c5_ContentsAll'. The migration (AddInitial) reads TableName.Prefix to
build the table name at runtime.
All named contexts shared the default '__EFMigrationsHistory' table, so after
the first prefix ran AddInitial and recorded it, every subsequent prefix saw the
migration as already applied and skipped it — leaving its dedicated tables
uncreated and causing 'relation __cN_ContentsAll does not exist' failures in
all but the first dedicated-table test.
Setting options.MigrationsHistoryTable(\$"{name}MigrationHistory") gives each
prefix its own independent migration history, so AddInitial runs once per prefix
and creates the correct tables each time.
Also add *.lscache to .gitignore (C# language server cache files).
* Adding extra bindings for configmaps, secrets, and volumes
* Adding version increment and readme entries for new extraMount parameters
* Updaing index
* Adding missing chart files
* Fixing if-additionalSecrets binding
Adding clause to use default mongo connection only when mengodb dependency is enabled
* Upgrading helm chart to 2.1.1
* Switching 'additional' to documented 'extra' parameters; adding volume and secret mounting to worker instances
* Adding extra bindings for configmaps, secrets, and volumes
* Adding version increment and readme entries for new extraMount parameters
* Updaing index
* Adding missing chart files
* Fixing if-additionalSecrets binding
Adding clause to use default mongo connection only when mengodb dependency is enabled
* Upgrading helm chart to 2.1.1
* Adding extra bindings for configmaps, secrets, and volumes
* Adding version increment and readme entries for new extraMount parameters
* Updaing index
* Adding missing chart files
* Adding extra bindings for configmaps, secrets, and volumes
* Adding version increment and readme entries for new extraMount parameters
* Updaing index
* Menu
* Move to components.
* Show a marker for unsaved changes.
* User info field.
* User info implementation.
* Fix tests
* Update tests
* Update auth.
* Fix DB provider.
* User info
* Instructions.