Skip to content

Fix fill-outline-color fallback for feature-state expressions#7420

Open
itisyb wants to merge 3 commits intomaplibre:mainfrom
itisyb:fix/fill-outline-color-feature-state-4234
Open

Fix fill-outline-color fallback for feature-state expressions#7420
itisyb wants to merge 3 commits intomaplibre:mainfrom
itisyb:fix/fill-outline-color-feature-state-4234

Conversation

@itisyb
Copy link
Copy Markdown
Contributor

@itisyb itisyb commented Apr 6, 2026

Summary

  • preserve fill-outline-color fallback to fill-color when feature-state is missing so fill rendering does not break during initial paint population
  • apply the same fallback behavior to both source and composite expression binders, and refresh it after paint updates so later fill-color changes stay in sync
  • add unit coverage for missing state, feature-state updates, fallback refreshes, and invalid color warnings

Testing

  • npm run lint -- src/data/program_configuration.ts src/data/program_configuration.test.ts
  • npm run test-unit -- src/data/program_configuration.test.ts

Notes

  • I attempted to add a render regression too, but npm run build-dev is currently blocked by unrelated existing TypeScript errors in src/data/bucket/line_bucket.ts and src/source/geojson_*, so this PR keeps the regression coverage focused on unit tests.

Fixes #4234

Keep fill-outline-color aligned with fill-color when feature-state is missing so fill layers do not break during initial render or later state updates.
@itisyb
Copy link
Copy Markdown
Contributor Author

itisyb commented Apr 6, 2026

Also created a small demo but don't think need to push/show for this case

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 6, 2026

Codecov Report

❌ Patch coverage is 90.56604% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.58%. Comparing base (789b3da) to head (e230a83).
⚠️ Report is 23 commits behind head on main.

Files with missing lines Patch % Lines
src/data/program_configuration.ts 90.56% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7420      +/-   ##
==========================================
- Coverage   92.86%   92.58%   -0.29%     
==========================================
  Files         288      289       +1     
  Lines       23998    24060      +62     
  Branches     5095     5118      +23     
==========================================
- Hits        22286    22276      -10     
- Misses       1712     1784      +72     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@HarelM
Copy link
Copy Markdown
Collaborator

HarelM commented Apr 6, 2026

Thanks for taking the time to open this PR.
I don't think there's an issue with building or render test as CI passes without any issues as far as I know.
From the initial post it's hard to understand what the changes are and why these are the right places to do them, can you elaborate a bit more on the solution?

@itisyb
Copy link
Copy Markdown
Contributor Author

itisyb commented Apr 7, 2026

Thanks for taking the time to open this PR. I don't think there's an issue with building or render test as CI passes without any issues as far as I know. From the initial post it's hard to understand what the charges are and why these are the right places to do them, can you elaborate a bit more on the solution?

Thanks for taking the time to open this PR. I don't think there's an issue with building or render test as CI passes without any issues as far as I know. From the initial post it's hard to understand what the charges are and why these are the right places to do them, can you elaborate a bit more on the solution?

Before the fix, there was a problem with how fill-outline-color was handled when using feature-state.

If the feature-state value was missing, the expression could return null. The rendering system didn’t treat that as “no value” - it treated it like an actual color. Then when packColor() tried to use it, it attempted to access color.r on null, which caused a runtime error: “Cannot read properties of null (reading 'r')”.

it already had a fallback rule where fill-outline-color defaults to fill-color if not specified. But that logic only applied in the constant (non–data-driven) case. In the feature-state (data-driven) path, that fallback wasn’t applied, so instead of defaulting correctly, it crashed.

paintVertexBuffer: VertexBuffer;

constructor(expression: SourceExpression, names: string[], type: string, PaintVertexArray: {
constructor(expression: SourceExpressionWithRawEvaluation, names: string[], type: string, zoom: number, fillColorFallback: FillColorFallback, PaintVertexArray: {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This looks too specific to fill color, are you sure this is the right place to add this code? I would expect to see this code in the fill bucket/fill program or something related to fill, and not in this "shared" program configuration code.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Seems like this is still relevant after the recent force-push...

@itisyb itisyb force-pushed the fix/fill-outline-color-feature-state-4234 branch from 6fe9302 to f32d290 Compare April 12, 2026 14:46
type CompositeExpressionWithRawEvaluation = ZoomDependentExpression<'composite'>;

function getFillColorFallback(layer: TypedStyleLayer, property: string): FillColorFallback {
return property === 'fill-outline-color' ? (layer.paint as any).get('fill-color').value : null;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a way to avoid this as any?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature-state with fill-outline-color breaks rendering

2 participants