Skip to content

Stub polyfill for summaryDelayLoadedModule for cases where the client never summarizes#27611

Open
TommyBrosman wants to merge 3 commits into
microsoft:mainfrom
TommyBrosman:tbrosman/summarizer-polyfill
Open

Stub polyfill for summaryDelayLoadedModule for cases where the client never summarizes#27611
TommyBrosman wants to merge 3 commits into
microsoft:mainfrom
TommyBrosman:tbrosman/summarizer-polyfill

Conversation

@TommyBrosman

@TommyBrosman TommyBrosman commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

There are cases where a particular client will never summarize (for example, if summarization occurs on the server). We can provide a polyfill for these cases, which can save > 39 KiB parse size.

Related: #27597 enforces the fact that summaryDelayLoadedModule's declarations are only used in the delay-load path. This is an important invariant that allows us to safely polyfill the module without the risk of code outside of the guarded delay load path consuming declarations from summaryDelayLoadedModule.

Description

  • Stub polyfill implementation matching summary/summaryDelayLoadedModule/index.ts
  • Type tests to keep it in sync with the true implementation

Reviewer Guidance

  • The polyfill is not intended to be shipped as part of a compiled package. Is there a better pattern for exposing it that doesn't require the application code to make a copy?

Todo

  • Add a type assertion around the shape of the stub vs. the real implementation

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Hi! Thank you for opening this PR. Want me to review it?

Based on the diff (131 lines, 2 files), I've queued these reviewers:

  • Correctness — logic errors, race conditions, lifecycle issues
  • Security — vulnerabilities, secret exposure, injection
  • API Compatibility — breaking changes, release tags, type design
  • Performance — algorithmic regressions, memory leaks
  • Testing — coverage gaps, hollow tests

How this works

  • Adjust the reviewer set by ticking/unticking boxes above. Reviewer toggles alone don't trigger anything.

  • Tick Start review below to dispatch the review fleet.

  • After review finishes, tick Start review again to request another run — it auto-resets after each dispatch.

  • This comment updates as new commits land; your reviewer selections are preserved.

  • Start review

@TommyBrosman TommyBrosman marked this pull request as ready for review June 29, 2026 17:08
Copilot AI review requested due to automatic review settings June 29, 2026 17:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

@github-actions

Copy link
Copy Markdown
Contributor

Bundle size comparison

Base commit: e7d9f8079e0560e979d0d70a8e198a4efc655a4e
Head commit: b9c25b4f70c5b436e83c048224a593ad2c25bad0

Notable changes

No bundles changed by ≥ 500 bytes parsed.

Per-bundle deltas

@fluid-example/bundle-size-tests

  • azureClient.js: parsed 618933 → 619113 (+180), gzip 164788 → 164859 (+71)
  • odspClient.js: parsed 591767 → 591947 (+180), gzip 158880 → 158948 (+68)
  • aqueduct.js: parsed 525463 → 525622 (+159), gzip 140685 → 140739 (+54)
  • fluidFramework.js: parsed 392069 → 392471 (+402), gzip 111118 → 111428 (+310)
  • sharedTree.js: parsed 381456 → 381851 (+395), gzip 108519 → 108817 (+298)
  • containerRuntime.js: parsed 303813 → 303951 (+138), gzip 83189 → 83222 (+33)
  • sharedString.js: parsed 175984 → 175991 (+7), gzip 49445 → 49453 (+8)
  • experimentalSharedTree.js: parsed 160798 → 160798 (0), gzip 45804 → 45804 (0)
  • matrix.js: parsed 159845 → 159852 (+7), gzip 45411 → 45418 (+7)
  • loader.js: parsed 145221 → 145235 (+14), gzip 39052 → 39067 (+15)
  • odspDriver.js: parsed 104431 → 104452 (+21), gzip 32647 → 32657 (+10)
  • directory.js: parsed 66616 → 66623 (+7), gzip 18532 → 18540 (+8)
  • 748.js: parsed 58793 → 58793 (0), gzip 17826 → 17826 (0)
  • map.js: parsed 46709 → 46716 (+7), gzip 14310 → 14318 (+8)
  • odspPrefetchSnapshot.js: parsed 45650 → 45664 (+14), gzip 15275 → 15284 (+9)
  • 594.js: parsed 44493 → 44493 (0), gzip 13744 → 13744 (0)
  • summarizerDelayLoadedModule.js: parsed 30753 → 30753 (0), gzip 7767 → 7767 (0)
  • socketModule.js: parsed 26486 → 26493 (+7), gzip 7883 → 7891 (+8)
  • createNewModule.js: parsed 12480 → 12480 (0), gzip 4786 → 4786 (0)
  • summaryModule.js: parsed 3797 → 3797 (0), gzip 1860 → 1860 (0)
  • connectionState.js: parsed 724 → 724 (0), gzip 429 → 429 (0)
  • sharedTreeAttributes.js: parsed 666 → 673 (+7), gzip 432 → 442 (+10)
  • debugAssert.js: parsed 429 → 429 (0), gzip 299 → 299 (0)
  • FluidFramework-HashFallback.js: parsed 422 → 422 (0), gzip 316 → 316 (0)

TommyBrosman added a commit to TommyBrosman/FluidFramework that referenced this pull request Jun 30, 2026
The summarizer is already factored into a delay-loaded leaf module
(summary/summaryDelayLoadedModule/index.js), but its implementation classes
(Summarizer, RunningSummarizer, ...) are also part of the package's public API,
so the ~28 KB subgraph is pinned into every bundle that touches that API. For a
single-chunk mobile bundle that summarizes server-side and never instantiates a
client summarizer, this is dead weight.

Add the stub-polyfill (the "summarizer approach"):
- summary/summaryDelayLoadedModuleStub.ts: re-exports the same value symbols; the
  classes throw on construction (fail fast), constants keep real values. From
  PR microsoft#27611.
- test/summary/summaryDelayLoadedModuleStub.spec.ts: compile-time requireAssignableTo
  (both directions) keeping the stub's value exports in sync with the real module.
- Wire NormalModuleReplacementPlugin into the encapsulated-no-tree scenario to
  redirect both the await-import seam and the public-API value re-exports to the
  stub, so the real subgraph never enters the bundle. Public API names remain
  exported (as throwing stubs).

Bundle impact (encapsulated-no-tree, single chunk): 585,184 -> 546,425 B parsed
(-38,759), 151,269 -> 142,246 B gzip (-9,023). The 28,215 B summaryDelayLoadedModule
subgraph plus ~10 KB of terser dead-code elimination of now-unreachable code. 957
container-runtime tests pass (the real module is unchanged and still exercised by
the test suite).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants