Skip to content

Preserve nullable maps in generated players - #1018

Merged
Eli Pinkerton (wallstop) merged 4 commits into
mainfrom
codex/browser-serializer-acceptance
Oct 17, 2026
Merged

Eli Pinkerton (wallstop) merged 4 commits into
mainfrom
codex/browser-serializer-acceptance

Conversation

@wallstop

@wallstop Eli Pinkerton (wallstop) commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

DISCLOSURE: LLM-GENERATED TEXT

Why: Generated serializers reject nullable map values needed by retained consumer data.

What:

  • Preserve nullable map keys, values, and present defaults.
  • Add generated WebGL consumer acceptance with retained goldens.
  • Check enum conversion, random vectors, and spatial queries in browsers.
  • Document older reader limitations and browser qualification steps.

Refs #343, #637


Note

Medium Risk
Changes generated serialization wire semantics and presence for map entries; retained saves and mixed protobuf-net reader versions need the documented qualification before rollout.

Overview
Extends the WProto generator so Dictionary / IDictionary map members can use nullable keys and values, with presence driven by HasValue (present zeros and default structs stay on the wire; null values omit; nullable keys must be present or read/write fails). MapMember and Shape.Underlying were updated accordingly, and WPROTO003 now documents nullable map halves while repeated elements stay non-nullable.

Adds qualification: differential and golden-byte tests against protobuf-net oracles, fast runtime tests, and a WebGL IL2CPP browser consumer (run-browser-consumer.py + Playwright) that runs retained-map goldens plus enum/RNG/spatial safety checks with manifest-bound identity and negative controls. Docs and CHANGELOG describe nullable map wire rules and older protobuf-net reader limits for nullable enum/struct map values.

Reviewed by Cursor Bugbot for commit 5763bf6. Bugbot is set up for automated code reviews on this repo. Configure here.

Why: WebGL needs direct checks for generated serialization and safe memory replacements.

How: Build an isolated Release IL2CPP consumer with High stripping and single-threaded code. Bind source and player inputs, require generated formatters, and run each case in a fresh Chromium context. Retain failed attempts and verify corrupt-byte and stale-source controls.

What: Cover retained maps, nullable presence, enum widths, WyRandom vectors, and both R-trees. Add 13 runner controls to the contract suite.

Validation: Both changed-file preflight modes, full spelling and documentation checks, strict MkDocs, member ordering, 13 Python controls, and 13 registry controls pass. The exploratory legacy browser profile passes 23 cases and two negative controls. Generated browser acceptance remains pending on this commit.

Refs #343, #637
The fresh generated WebGL consumer exposed WPROTO003 errors for nullable
map halves. Unwrap their wire shapes while retaining nullable local and
collection types, emit presence for present defaults, and refuse absent
nullable keys before dictionary insertion. Rebuild the shipped generator.

Pin literal bytes, duplicate message merging, malformed entries, nullable
keys, and interface/read-only maps. Both oracle writers match generated
bytes. The pinned v2 reader loses nullable enum/struct values from its own
bytes on .NET 9; freeze those losses explicitly rather than claiming full
v2 reader equivalence. Generated readers retain the encoded values.

Validation: complete Release generator suites pass 1382/1382 (v3) and
1351/1351 (v2), without skips. All eight formerly failing nullable-map
diagnostic compilation controls pass. Unity source typechecks and member
ordering pass. Unity 6000.4.6f1 compiles and passes all eight new PlayMode
cases. Both changed-file preflights pass, including shipped DLL comparison;
full spelling, documentation links, and Markdown lint pass.

Refs #343, #637.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 920edcc. Configure here.

A caller-defined IReadOnlyDictionary can enumerate a null nullable key,
although Dictionary rejects insertion of one. Generated writes previously
returned true for that keyless entry, which generated reads then refused.
Return false before writing the entry and document the refusal.

The new regression fails before the guard (one failure, two valid-key
controls passing), then all three cases pass with the rebuilt shipped DLL.
Full Release suites pass 1385/1385 v3 and 1354/1354 v2 without skips.
Both preflight modes, member order, full spelling, documentation links,
Markdown lint and strict MkDocs pass. Unity 6000.4.6f1 recompiles cleanly.

The preceding 920edcc generated WebGL player passes all 23 cases and both
negative controls, with zero browser errors. Its final assembly manifests
require generated dispatch and SINGLE_THREADED. A new final-head player
will qualify this guard; the preceding player is retained separately.

Refs #343, #637. Addresses PR #1018 review comment 4297918648.
@wallstop
Eli Pinkerton (wallstop) enabled auto-merge (squash) October 16, 2026 22:18
@wallstop
Eli Pinkerton (wallstop) merged commit c5ce8ed into main Oct 17, 2026
30 checks passed
@wallstop
Eli Pinkerton (wallstop) deleted the codex/browser-serializer-acceptance branch October 17, 2026 02:09
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.

1 participant