Repository navigation
Pool: retire the legacy name-keyed object pool from engine internals - #1726
Merged
Merged
Conversation
…1688) The engine no longer uses `me.pool` for anything. Zero internal `pull` and zero internal `push`: the only two mentions left in `src/` are comments, and `legacy_pool` is imported by `index.ts` for the export and by `TMXObjectFactory.js` for the register bridge. All four of the issue's items: 1. `push(obj, throwOnError = false)`. It threw by default for any class that was never registered, and nothing at the call site made that visible, so the exception aborted whatever was running. Flipped rather than split, because the class is deprecated now and a second method would teach a new spelling on a retiring surface. 2. `atlas.js` and `TMXTileMap.js` construct their classes directly. That needed the module cycle broken first: `sprite.js` imported `loader.js` and `atlas.js`, and `class NineSliceSprite extends Sprite` reads `Sprite` at module-evaluation time, so importing either from inside the cycle threw. The ten cache read accessors moved to `loader/cache.js`, and the two `instanceof TextureAtlas` tests became `instanceof Texture2d && isAtlas`. 3. The Tiled name registry is split from the recycling pool. Built-in classes are DEFAULTS: they fill a name nothing else claimed, and a game's own class takes the name over whenever it registers. They keep their `me.`-prefixed aliases, which used to arrive only as a side effect of `pool.register`. 4. `me.pool` is deprecated, with a one-off notice per method naming both replacements. `Container` now returns a child to the typed pool that BUILT it, which is the question a generic caller has to ask: `createPool` stamps the owning pool on everything it builds. `Text` and `ColorLayer` gained typed pools, and with them two defects a recycled instance had: the settings-conditional fields leaked across a reuse, and every reset built a new canvas and metrics while stranding the previous canvas and its GPU texture. Also in here because the review found them: - `RenderTarget#toImageData()`, so `toBlob`/`toDataURL`/`toImageBitmap` stop throwing on WebGPU. Synchronous readback is not portable. - `scripts/check-declarations.ts`, gated in `pnpm types`. Nothing compiled against `build/*.d.ts`, so a whole class of defect was invisible: five of this change's own bugs were only found by looking there. - `registerTiledObjectClass` before the first map load was silently discarded. - 12 public members reached TypeScript as `any`, and `Body#collisionMask` was stripped from the published types while `PhysicsBody` required it. - The `trigger_level_change` flake: `_onTick` takes an absolute `performance.now()` stamp and ignores a delta outside `(0, 1000)`, so a hardcoded `1000` was a valid tick only while the page was under a second old. Examples move off the legacy pool too, and the old space-invaders example is removed rather than converted. Closes #1688 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
`packages/melonjs`'s own `lint` script is `eslint src tests`, so `scripts/` is only reached by the ROOT `pnpm lint`, which is what CI runs. The new file tripped `prefer-template` there and nowhere locally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The engine no longer uses
me.poolfor anything: zero internalpulland zero internalpush. The only two mentions left insrc/are comments, andlegacy_poolis imported byindex.tsfor the public export and byTMXObjectFactory.jsfor the register bridge that keepspool.registerworking.All four of the issue's items:
push(obj, throwOnError = false). It threw by default for any class never registered, and nothing at the call site made that visible, so the exception aborted whatever was running. Flipped rather than split, because the class is deprecated now and a second method would teach a new spelling on a retiring surface.atlas.jsandTMXTileMap.jsconstruct their classes directly. That needed the module cycle broken first:sprite.jsimportedloader.jsandatlas.js, andclass NineSliceSprite extends SpritereadsSpriteat module-evaluation time, so importing either from inside the cycle threw and took 271 of 319 spec files with it. The ten cache read accessors moved toloader/cache.js, and the twoinstanceof TextureAtlastests becameinstanceof Texture2d && isAtlas.me.poolis deprecated, with a one-off notice per method naming both replacements (getPool/createPoolto pool instances,registerTiledObjectClassto let a Tiled map name a class).Containernow returns a child to the typed pool that built it, which is the question a generic caller has to ask:createPoolstamps the owning pool on everything it builds, non-enumerably.TextandColorLayergained typed pools.Found by reviewing this change, and fixed here
me.-prefixed aliases. Those arrived only as a side effect ofpool.register, which registered the factory twice. Dropping the bootstrap registrations silently turned every map object classedme.Triggerinto a plainRenderable. The shippedplatformer/map1.tmxobject id 17 isme.Trigger.registerTiledObjectClassbefore the first map load was silently discarded, because the built-ins were flushed on the first object built and overwrote it.Textkept the previous label's state —fillStyle,strokeStyle,floating, and everything a game drives throughRenderable(alpha, tint, blend mode, transform, anchor, flip). It also rebuilt its canvas and metrics on every reset, stranding the previous canvas and its GPU texture.RenderTarget#toImageData(), sotoBlob/toDataURL/toImageBitmapstop throwing on a WebGPU target. Synchronous readback is not portable.scripts/check-declarations.ts, gated inpnpm types. Nothing compiled againstbuild/*.d.ts, so a whole class of defect was invisible: an@internalparser entry point had become public because two typedefs were inserted between its doc block and the function, andloader.GLTFDatahad disappeared from the public types. Five of this change's own bugs were only found by looking there.any, andBody#collisionMaskwas stripped from the published types while thePhysicsBodyinterface it implements required it.trigger_level_changeflake.Tween#_onTicktakes an absoluteperformance.now()stamp and ignores a delta outside(0, 1000), so the test's hardcoded1000was a valid tick only while the page was under a second old. Verified with 16 consecutive full-suite runs; it used to fail about one run in five.Breaking
pool.pull("Sprite"),pool.pull("Text"),pool.pull("Tween"),pool.pull("Particle")and the other nine built-in names now throw. Nine of the thirteen had recycling off, so the call was a plain construction behind a string key; the four that had it on all have a typed pool.pool.register(name, Class, true)no longer makes a class recyclable on container removal, andpool.register("Sprite", MySprite)no longer substitutes the class used bycreateSpriteFromNameor the Tiled image-layer loader. Registering your own names is unaffected.pool.push(obj)returnsfalsewhere it used to throw.RenderTarget#getImageDatais no longer part of the abstract contract (it stays on the canvas and WebGL targets), andWebGPURenderTarget#readPixelsis replaced bytoImageData.The old
space-invadersexample is removed rather than converted: it was carrying 25 of the gallery's pre-existing type errors on its own.Type of change
Checklist
pnpm lintpasses)pnpm testpasses)pnpm build)5 new spec files plus additions to 10 existing ones. Every behaviour here is mutation-tested: the fix was reverted and the test confirmed to fail. Beyond the suite, all 53 examples were swept for boot errors, the converted ones had their live scene trees inspected to confirm their Tiled classes really do instantiate (a registration that fails is silent, not a throw), and unmount/remount was exercised on each.
Related issues
Closes #1688
🤖 Generated with Claude Code
https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t