A `WasmtimeImplScope` registers itself on its `OperationContext` through a single `WasmtimeScopeRef` decoration slot so interrupts can find it. When a second scope registered on the same opCtx (e.g. `$where` parsing acquiring a pooled scope while another scope was still registered), `WasmtimeScriptEngine::registerOperation()` silently overwrote the slot. The displaced scope kept its raw `_opCtx` back-pointer but lost the teardown that clears it when the opCtx is destroyed, so the scope's destructor dereferenced freed memory (ASan heap-use-after-free in `OperationContext::getClient()`).
Changes:
- `wasmtime_engine.cpp/.h`: `registerOperation()` severs a displaced scope's back-pointer (invokes its `onTeardown`) before overwriting the slot; `unregisterOperation()` now takes the scope and only clears the slot if that scope still owns it, so a stale unregister cannot wipe a newer registration.
- `engine.cpp`: `getPooledScope()` checks for interrupt before registering the operation on a scope, so an already-killed operation fails before partially setting up JS state; `ScopeCache::release()` unregisters scopes before pooling as defense-in-depth (covers the early-return paths that destroy a scope without resetting it).
- `scope_test_concurrency.cpp`: three regression tests. `SecondRegistrationSeversPreviousScopeBackPointer` deterministically reproduces the use-after-free before the fix under ASan; `GetPooledScopeThrowsOnInterruptedOpCtx` fails before the fix on any build.