Skip to content

chore(mapbox): Remove internal deck mode from MapboxLayer#9955

Merged
chrisgervang merged 21 commits intomasterfrom
chr/mapbox-deck-utils-cleanup
Jan 27, 2026
Merged

chore(mapbox): Remove internal deck mode from MapboxLayer#9955
chrisgervang merged 21 commits intomasterfrom
chr/mapbox-deck-utils-cleanup

Conversation

@chrisgervang
Copy link
Collaborator

@chrisgervang chrisgervang commented Jan 22, 2026

Summary

Simplify the mapbox module by removing the internal deck mode from MapboxLayer. Since MapboxLayer is no longer a public API (only MapboxOverlay is exported), the internal deck mode code paths are no longer needed.

Changes

  • Remove isExternal flag from UserData (always true now)
  • Remove internal deck creation branch in getDeckInstance
  • Remove updateLayers function (only used for internal mode)
  • Make deck prop required in MapboxLayer and getDeckInstance
  • Simplify MapboxLayer and MapboxLayerGroup to access map.__deck directly
  • Remove gl parameter from getDeckInstance - gl is passed at Deck construction time in mapbox-overlay.ts
  • Remove always-true if (deck.props.gl === gl) condition
  • Simplify afterRender by removing isExternal check (always runs non-mapbox layers draw)
  • Remove internal deck mode test

Test plan

  • TypeScript compiles without errors
  • Prettier/ESLint checks pass
  • Existing MapboxOverlay tests continue to pass
  • Manual testing with mapbox-gl/maplibre-gl maps

🤖 Generated with Claude Code


Note

Streamlines the Mapbox integration by eliminating MapboxLayer's internal Deck path and standardizing on a single external Deck managed via MapboxOverlay.

  • Simplifies getDeckInstance to require a deck (no gl), syncs view state with the map, and updates afterRender to always draw non-Mapbox layers/views
  • Removes internal layer bookkeeping (isExternal, addLayer/removeLayer/updateLayer/updateLayers) and related logic
  • Updates MapboxLayer/MapboxLayerGroup to read map.__deck directly; MapboxLayer no longer accepts a deck prop
  • Adjusts MapboxOverlay interleaved setup to construct Deck with gl and hand it to getDeckInstance; resolve-layers no longer passes deck when creating MapboxLayer
  • Deletes docs/api-reference/mapbox/mapbox-layer.md; cleans up examples to only show MapboxOverlay; fixes a minor docs snippet
  • Updates tests to initialize Deck on the map via getDeckInstance and removes the internal mode test

Written by Cursor Bugbot for commit 9ba6e0e. This will update automatically on new commits. Configure here.

MapboxLayer is no longer a public API (only MapboxOverlay is exported),
so the internal deck mode code paths are no longer needed.

Changes:
- Remove `isExternal` flag from UserData (always true now)
- Remove internal deck creation branch in getDeckInstance
- Remove `updateLayers` function (only used for internal mode)
- Make `deck` prop required in getDeckInstance
- Simplify MapboxLayer and MapboxLayerGroup to read map.__deck directly
- Only MapboxOverlay calls getDeckInstance for initialization
- Update tests to simulate MapboxOverlay flow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the chr/mapbox-deck-utils-cleanup branch from a4ab3d8 to 58d3716 Compare January 22, 2026 07:26
@coveralls
Copy link

coveralls commented Jan 22, 2026

Coverage Status

coverage: 91.101% (-0.01%) from 91.114%
when pulling 9ba6e0e on chr/mapbox-deck-utils-cleanup
into 50df2f2 on master.

chrisgervang and others added 8 commits January 21, 2026 23:32
…roup

Replace `this.deck` field with a getter that reads from `map.__deck`
directly. This avoids potential stale references and simplifies the
lifecycle - `onAdd` no longer needs to capture the deck instance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Since MapboxLayer and MapboxLayerGroup are internal classes only used
by MapboxOverlay, and MapboxOverlay always sets up map.__deck before
adding these layers, __deck is guaranteed to exist when the map is set.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Since __deck is guaranteed on MapWithDeck, we can access it directly
through the map rather than through a getter.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These assertions just verified getDeckInstance set map.__deck, which
is obvious and doesn't test any MapboxLayer behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The first test should create Deck without gl option to test the case
where deck has its own gl context. This matches the original test
behavior where deck.props.gl !== map's gl.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The resolveLayers test now calls getDeckInstance to set up map.__deck
before resolving layers, since MapboxLayer.onAdd expects it to be set.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove `gl` parameter from getDeckInstance - now obtained internally from map.painter.context.gl
- Remove always-true `if (deck.props.gl === gl)` condition since deck is always created without gl and getDeckInstance sets it
- Move WebGL1 compatibility warning from MapboxOverlay to getDeckInstance
- Simplify MapboxOverlay._onAddInterleaved - just creates Deck with user props
- Update tests to not pass gl when creating Deck instances

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang changed the title chore(mapbox): Remove internal deck mode from MapboxLayer chore(mapbox): Remove internal deck mode from MapboxLayer Jan 22, 2026
}
TestScatterplotLayer.layerName = 'TestScatterplotLayer';

test('MapboxLayer#onAdd, onRemove, setProps', t => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here's an analysis of what the deleted test covered and whether it's tested elsewhere:

Deleted Test Aspect Coverage Status
MapboxLayer constructor doesn't throw ✅ Covered in remaining "external Deck" tests
Deck is initialized internally ❌ Internal mode only - removed feature
Layer added to deck.props.layers ❌ Internal mode only - removed feature
mapbox view exists ✅ Covered at mapbox-layer.spec.ts:60
Parameters set correctly ✅ Covered at mapbox-layer.spec.ts:62 and MapboxOverlay tests
viewState synced from map ✅ Covered in MapboxOverlay tests (lines 47-56, 75-84, 108-117, etc.)
Layer removed from deck ❌ Internal mode only - removed feature
Deck reused across layers ❌ Internal mode only - map.__deck reuse is implicit
setProps updates layers ❌ Internal mode only - removed feature
Map render doesn't throw ✅ Covered in remaining tests
Deck finalized on map remove ❌ Internal mode only - MapboxOverlay tests cover external finalization

Summary: The uncovered aspects were all specific to the internal deck mode which was removed. The external deck mode (now the only mode) is well covered by:

Remaining MapboxLayer "external Deck" tests (3 tests)
MapboxOverlay tests (which is the public API, ~10 tests covering interleaved mode with viewState, parameters, layers, finalization)

@chrisgervang
Copy link
Collaborator Author

Hey @zbigg, I realized a complex set of code paths in MapboxOverlay are no longer necessary now that MapboxLayer is private. This change should be transparent to the user

chrisgervang and others added 2 commits January 22, 2026 00:31
The gl prop must be set when constructing Deck, not via setProps after
construction. Move gl retrieval and WebGL1 compatibility warning back to
mapbox-overlay.ts where the Deck is constructed, and remove redundant gl
handling from getDeckInstance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Parameters are already merged when creating Deck in mapbox-overlay.ts,
so the merge in getDeckInstance is redundant.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
deck.needsRedraw({clearRedrawFlags: true});
}

function updateLayers(deck: Deck): void {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

only used for internal mode

function afterRender(deck: Deck, map: Map): void {
const {mapboxLayers, isExternal} = deck.userData as UserData;

if (isExternal) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

its always external

Copy link
Collaborator

Choose a reason for hiding this comment

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

note, i've merged #9944 so expect conflict here. But it should be straightforward - hasNonMapboxLayers and deps disappeared.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

all good! claude fixed the merge conflicts

updateLayers(deck);
}

export function updateLayer(deck: Deck, layer: MapboxLayer<any>): void {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

only used for internal mode

customRender?.('');
}
};
deckProps.parameters = {...getDefaultParameters(map, true), ...deckProps.parameters};
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

redundant since MapboxOverlay does this too

slot?: 'bottom' | 'middle' | 'top';
beforeId?: string;
map: Map | null;
deck: Deck | null;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't need this since map.__deck will always be set

/* Mapbox v3 Standard style */
slot?: 'bottom' | 'middle' | 'top';
map: Map | null;
deck: Deck | null;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't need this since map.__deck will always be set

chrisgervang and others added 6 commits January 22, 2026 00:47
The deck prop was vestigial from the old code where it was passed to
getDeckInstance. Now MapboxLayer accesses the deck via map.__deck,
so the prop is no longer needed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Missed this usage when removing the deck prop from MapboxLayerProps.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove mapbox-layers test app directory and update index.html links.
The mapbox-layers-react app was already deleted in a previous commit.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
MapboxLayer is no longer part of the public API. Updated the doc to
add a deprecation notice and migration guide pointing to MapboxOverlay.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
MapboxLayer is internal-only and should not be documented as a public
API. Removed the doc file and updated references in whats-new.md and
test README.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the chr/mapbox-deck-utils-cleanup branch from 6eb7c18 to 3cc9e49 Compare January 22, 2026 08:59
Copy link

@cursor cursor bot left a comment

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 1 potential issue.

@chrisgervang chrisgervang force-pushed the chr/mapbox-deck-utils-cleanup branch from 44d4b58 to c9393de Compare January 22, 2026 19:13
Tests now create Deck with default parameters merged, matching how
MapboxOverlay._onAddInterleaved creates the Deck. This is needed
because getDeckInstance no longer merges default parameters.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the chr/mapbox-deck-utils-cleanup branch from c9393de to f810939 Compare January 22, 2026 19:24
Copy link
Collaborator

@felixpalmer felixpalmer left a comment

Choose a reason for hiding this comment

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

Thanks for taking the time to cleanup - this module is often a source of hard to debug code, so the fewer lines we have, the better

@chrisgervang chrisgervang force-pushed the chr/mapbox-deck-utils-cleanup branch from 940534b to 8eeaa9f Compare January 27, 2026 02:08
Instead of tracking MapboxLayer instances in a Set, use map.getLayer()
to check if a deck layer has a corresponding MapboxLayer on the map.
This simplifies the code since resolve-layers already creates MapboxLayer
instances with the same ID as the deck layer.

Ref: #9944

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the chr/mapbox-deck-utils-cleanup branch from 8eeaa9f to e6d0a0a Compare January 27, 2026 02:14
Resolve conflict in deck-utils.ts by keeping the refactored afterRender
function that uses map.getLayer() instead of isExternal flag.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang
Copy link
Collaborator Author

I've tested this on the website, in the maplibre test app, and the basemap browser.. all appears functional. I'm tempted to ship this in 9.2 as a patch.. any objections?

- Add gl parameter to onAdd for consistency with CustomLayerInterface
- Add null guard in render() for safety, matching MapboxLayerGroup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang merged commit 914c3d2 into master Jan 27, 2026
6 checks passed
@chrisgervang chrisgervang deleted the chr/mapbox-deck-utils-cleanup branch January 27, 2026 05:52
@chrisgervang chrisgervang added this to the v9.2 patch releases milestone Feb 2, 2026
felixpalmer pushed a commit that referenced this pull request Feb 10, 2026
* chore(mapbox): Remove internal deck mode from MapboxLayer

MapboxLayer is no longer a public API (only MapboxOverlay is exported),
so the internal deck mode code paths are no longer needed.

Changes:
- Remove `isExternal` flag from UserData (always true now)
- Remove internal deck creation branch in getDeckInstance
- Remove `updateLayers` function (only used for internal mode)
- Make `deck` prop required in getDeckInstance
- Simplify MapboxLayer and MapboxLayerGroup to read map.__deck directly
- Only MapboxOverlay calls getDeckInstance for initialization
- Update tests to simulate MapboxOverlay flow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Use getter for deck in MapboxLayer and MapboxLayerGroup

Replace `this.deck` field with a getter that reads from `map.__deck`
directly. This avoids potential stale references and simplifies the
lifecycle - `onAdd` no longer needs to capture the deck instance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(mapbox): Keep non-null assertions in render method

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Make __deck non-optional in MapWithDeck type

Since MapboxLayer and MapboxLayerGroup are internal classes only used
by MapboxOverlay, and MapboxOverlay always sets up map.__deck before
adding these layers, __deck is guaranteed to exist when the map is set.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Remove deck getter, access map.__deck directly

Since __deck is guaranteed on MapWithDeck, we can access it directly
through the map rather than through a getter.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(mapbox): Remove trivial deck instance assertions

These assertions just verified getDeckInstance set map.__deck, which
is obvious and doesn't test any MapboxLayer behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(mapbox): Restore original test structure for external Deck

The first test should create Deck without gl option to test the case
where deck has its own gl context. This matches the original test
behavior where deck.props.gl !== map's gl.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(mapbox): Initialize map.__deck in tests before using MapboxLayer

The resolveLayers test now calls getDeckInstance to set up map.__deck
before resolving layers, since MapboxLayer.onAdd expects it to be set.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Consolidate gl context handling in getDeckInstance

- Remove `gl` parameter from getDeckInstance - now obtained internally from map.painter.context.gl
- Remove always-true `if (deck.props.gl === gl)` condition since deck is always created without gl and getDeckInstance sets it
- Move WebGL1 compatibility warning from MapboxOverlay to getDeckInstance
- Simplify MapboxOverlay._onAddInterleaved - just creates Deck with user props
- Update tests to not pass gl when creating Deck instances

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(mapbox): Pass gl at Deck construction time, not via setProps

The gl prop must be set when constructing Deck, not via setProps after
construction. Move gl retrieval and WebGL1 compatibility warning back to
mapbox-overlay.ts where the Deck is constructed, and remove redundant gl
handling from getDeckInstance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Remove redundant parameters merge in getDeckInstance

Parameters are already merged when creating Deck in mapbox-overlay.ts,
so the merge in getDeckInstance is redundant.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Remove unused deck prop from MapboxLayerProps

The deck prop was vestigial from the old code where it was passed to
getDeckInstance. Now MapboxLayer accesses the deck via map.__deck,
so the prop is no longer needed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore(mapbox): Remove unsupported mapbox-layers-react test app

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(mapbox): Remove deck prop from MapboxLayer in resolve-layers

Missed this usage when removing the deck prop from MapboxLayerProps.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore(mapbox): Remove unsupported mapbox-layers test apps

Remove mapbox-layers test app directory and update index.html links.
The mapbox-layers-react app was already deleted in a previous commit.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(mapbox): Update MapboxLayer doc to reflect internal-only status

MapboxLayer is no longer part of the public API. Updated the doc to
add a deprecation notice and migration guide pointing to MapboxOverlay.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(mapbox): Remove MapboxLayer doc and update references

MapboxLayer is internal-only and should not be documented as a public
API. Removed the doc file and updated references in whats-new.md and
test README.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(mapbox): Update tests to create Deck with default parameters

Tests now create Deck with default parameters merged, matching how
MapboxOverlay._onAddInterleaved creates the Deck. This is needed
because getDeckInstance no longer merges default parameters.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Remove mapboxLayers tracking from UserData

Instead of tracking MapboxLayer instances in a Set, use map.getLayer()
to check if a deck layer has a corresponding MapboxLayer on the map.
This simplifies the code since resolve-layers already creates MapboxLayer
instances with the same ID as the deck layer.

Ref: #9944

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Add null guard and consistent signature to MapboxLayer

- Add gl parameter to onAdd for consistency with CustomLayerInterface
- Add null guard in render() for safety, matching MapboxLayerGroup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.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.

4 participants