Contents
- 🌳 SharedTree DDS Changes
- Reduce the bundle size of schema hashing (#28496)
- Simplify the alpha schema identity API (#28496)
- Unsafe array-to-tuple conversion is available for allowed schemas (#28502)
- Adds debug-only checks to facilitate root cause analysis of SharedTree bugs (#28435)
- Slightly faster SharedTree initialization (#28527)
- Use stable definition ordering in schema exports (#28544)
- Configure how much SharedTree edit history to retain (#28511)
- 🐛 Bug Fixes
- Binary summary blob contents can no longer include neighboring bytes in Node.js when a Buffer is a view into a larger allocation (#28485)
- Container dirty state now accounts for outstanding attachment blob work (#28459)
- Devtools ignores messages from other windows (#28503)
- Containers passed to startTelemetry are no longer kept in memory after they are disposed (#28515)
- TreeArrayNodes correctly handle null elements during iteration and removal (#28519)
🌳 SharedTree DDS Changes
Reduce the bundle size of schema hashing (#28496)
Schema hashing uses a browser-oriented SHA-256 implementation without Node.js Buffer compatibility dependencies. This reduces browser bundle size when using identifySchemaAlpha.
Change details
Commit: c98cc8b
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
Simplify the alpha schema identity API (#28496)
The alpha identifySchema function is renamed to identifySchemaAlpha. The alpha computeSchemaHash function is no longer exported. To check a schema against an expected hash, pass a schema identity to the view configuration:
const config = new TreeViewConfigurationAlpha({
schema: MySchema,
schemaIdentity: identifySchemaAlpha({ expectedHash: savedHash }),
});If the expected hash does not match, the view construction error includes the actual hash.
Change details
Commit: c98cc8b
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
Unsafe array-to-tuple conversion is available for allowed schemas (#28502)
The alpha API unsafeArrayToTuple is now exported from @fluidframework/tree/alpha and fluid-framework/alpha. It returns the original array with its type converted using UnionToTuple, allowing insertable content APIs to work when tuple type information has been lost. Prefer preserving the tuple type with as const when possible. The helper does not validate the array: if its element type includes a schema that is absent at runtime, TypeScript can accept content that fails at runtime.
See Why is my insertable content getting typed as never? for examples and an explanation of the runtime risks.
Change details
Commit: 1b88709
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
Adds debug-only checks to facilitate root cause analysis of SharedTree bugs (#28435)
This version adds additional runtime checks to detect errors in the rebasing (commit merging) layer. These checks can be used by application authors when faced with a SharedTree rebasing bug. For example:
import { RebaseValidation } from "@fluidframework/tree/alpha";
it("repro SharedTree bug", () => {
// Reproduce the SharedTree bug under strict rebase validation level.
RebaseValidation.runWithLevel(RebaseValidation.Level.Strict, () => {
// Buggy scenario
// ...
});
});Running the test with strict validation is more likely to yield actionable feedback for SharedTree maintainers.
These checks are tree-shaken out of production builds, so they have no impact on shipped applications.
There are three levels of checking available:
RebaseValidation.Level.None: No rebase validation is performed.RebaseValidation.Level.Cheap: A minimal amount of rebase validation is performed, with minimal performance overhead.RebaseValidation.Level.Strict: Extensive rebase validation is performed, with the highest performance overhead.
The level is set to RebaseValidation.Level.Cheap by default. Debug builds may therefore experience asserts in scenarios where they did not before. The level can be adjusted by calling RebaseValidation.setLevel or RebaseValidation.runWithLevel.
Change details
Commit: 2e08a3a
Affected packages:
- fluid-framework
- @fluidframework/tree
⬆️ Table of contents
Slightly faster SharedTree initialization (#28527)
TreeView.initialize() is now slightly faster for large schemas when debug-only checks are disabled or optimized out. See non-production conditional code for details on how bundlers remove these checks from production builds.
For a synthetic schema with 240 object types and 1,200 fields (five fields per object type), plus an array root allowing all 240 types, warm initialization took about 7% less time in a local benchmark:
| Measurement | Before | After |
|---|---|---|
TreeView.initialize([])
| 5.21 ms | 4.83 ms |
The tree was initialized with an empty array: these numbers measure schema-related initialization work, not loading 240 objects. Measurements used Node.js with debug-only checks disabled and exclude view creation. Results depend on the schema and environment.
Change details
Commit: 7402252
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
Use stable definition ordering in schema exports (#28544)
SharedTree JSON Schema exports and schema compatibility snapshots now write node definitions in a stable identifier order, independent of definition map insertion order and locale. Field and allowed-type ordering is unchanged.
Newly generated output may differ in definition ordering from older output. Existing compatibility snapshots remain usable without regeneration, and ordering alone does not change schema compatibility results. Schema hashes and persisted schema encoding are unchanged.
Change details
Commit: 30b0ce8
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
Configure how much SharedTree edit history to retain (#28511)
The existing alpha SharedTree retainHistory option now accepts a number in addition to a boolean. Pass a nonnegative safe integer to retain the newest specified number of available sequenced main-branch commits, true to retain all available history, or false or 0 to disable extra retention.
import { configuredSharedTree } from "fluid-framework/alpha";
const SharedTree = configuredSharedTree({ retainHistory: 20 });Collaboration and existing branches can require retaining more commits than the configured number. After loading a summary, trimming waits for the collaboration boundary to be reported. The count applies to sequenced commits, not file versions or snapshots. The policy is local to each SharedTree instance and is not persisted or sent to other clients. History that has already been removed cannot be recovered by increasing retention.
The existing boolean behavior is unchanged, and omitting retainHistory still defaults to false.
Change details
Commit: 9c5a7cc
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
🐛 Bug Fixes
Binary summary blob contents can no longer include neighboring bytes in Node.js when a Buffer is a view into a larger allocation (#28485)
In Node.js, binary summary blob content provided as a Buffer which covered only part of its underlying memory could be converted into an ArrayBuffer containing the underlying memory rather than just the blob's bytes. For example: a small pooled Buffer or the result of subarray. This affected snapshots produced from detached container summaries and files created via the ODSP driver from a detached summary, and could result in extra or unrelated bytes being stored with a blob.
Only the bytes belonging to the blob are now included. Browser environments were not affected.
Change details
Commit: c3f918b
Affected packages:
- @fluidframework/container-loader
- @fluidframework/odsp-driver
⬆️ Table of contents
Container dirty state now accounts for outstanding attachment blob work (#28459)
IContainer.isDirty and IFluidContainer.isDirty now include outstanding attachment blob work, not just operations. Previously, saved could fire during a blob upload, allowing hosts to dispose the container and lose the attachment. Do not dispose a container while isDirty is true.
Blob work ends when sharing succeeds, fails, or is cancelled. The saved event means no local work remains outstanding, not that every blob was shared successfully. Failed or cancelled handles may remain unusable; observe the handle's payloadShared and payloadShareFailed events for individual outcomes.
container.on("saved", () => container.dispose());Helpers waiting for saved now also wait for blob sharing to end. A stalled upload can keep them waiting indefinitely.
Blob coverage requires @fluidframework/container-loader from this release or later. Older loaders retain operation-only tracking; service clients such as @fluidframework/azure-client include a matching loader. Setting the runtime configuration flag Fluid.ContainerRuntime.DisableBlobAwareDirtyState to true restores operation-only dirty tracking. With either fallback, saved can fire while blob work remains outstanding.
Change details
Commit: b94b1f3
Affected packages:
- @fluidframework/container-definitions
- @fluidframework/container-runtime
- @fluidframework/fluid-static
- fluid-framework
⬆️ Table of contents
Devtools ignores messages from other windows (#28503)
Devtools now accepts window messages only from the application's own window. This prevents other windows from directly issuing devtools commands through window messaging.
Change details
Commit: e4a2759
Affected packages:
- @fluidframework/devtools-core
⬆️ Table of contents
Containers passed to startTelemetry are no longer kept in memory after they are disposed (#28515)
Previously, startTelemetry started a heartbeat timer that was never stopped. That timer kept the container, along with its telemetry producer and consumers, in memory for the lifetime of the process, even after the container was disposed. In Node.js, it also stopped the process from exiting. The heartbeat timer now stops when the container is disposed.
Change details
Commit: 917bf63
Affected packages:
- @fluidframework/fluid-telemetry
⬆️ Table of contents
TreeArrayNodes correctly handle null elements during iteration and removal (#28519)
Null elements in a TreeArrayNode are now handled correctly during iteration and by the alpha splice method. Previously, encountering a null element during iteration or removing one with splice incorrectly threw an out-of-bounds error.
Change details
Commit: 8defa17
Affected packages:
- @fluidframework/tree
- fluid-framework
⬆️ Table of contents
🛠️ Start Building Today!
Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!