Skip to content

Commit

Permalink
Do not warn about icon-image expressions evaluating to '' (#9380)
Browse files Browse the repository at this point in the history
* do not warn on empty icon image, treat it as unset

* clean up hasIcon condition in symbol bucket
  • Loading branch information
mourner authored Mar 5, 2020
1 parent 2374fe3 commit fa36168
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 9 deletions.
6 changes: 3 additions & 3 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export type CollisionArrays = {
export type SymbolFeature = {|
sortKey: number | void,
text: Formatted | void,
icon: ResolvedImage | void,
icon: ?ResolvedImage,
index: number,
sourceLayerIndex: number,
geometry: Array<Array<Point>>,
Expand Down Expand Up @@ -415,7 +415,7 @@ class SymbolBucket implements Bucket {
// this allows us to fire the styleimagemissing event if image evaluation returns null
// the only way to distinguish between null returned from a coalesce statement with no valid images
// and null returned because icon-image wasn't defined is to check whether or not iconImage.parameters is an empty object
const hasIcon = (iconImage.value.kind !== 'constant' || !!iconImage.value.value) && Object.keys(iconImage.parameters).length > 0;
const hasIcon = iconImage.value.kind !== 'constant' || !!iconImage.value.value || Object.keys(iconImage.parameters).length > 0;
const symbolSortKey = layout.get('symbol-sort-key');

this.features = [];
Expand Down Expand Up @@ -453,7 +453,7 @@ class SymbolBucket implements Bucket {
}
}

let icon: ResolvedImage | void;
let icon: ?ResolvedImage;
if (hasIcon) {
// Expression evaluation will automatically coerce to Image
// but plain string token evaluation skips that pathway so do the
Expand Down
8 changes: 3 additions & 5 deletions src/style-spec/expression/definitions/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@ export default class ImageExpression implements Expression {

evaluate(ctx: EvaluationContext) {
const evaluatedImageName = this.input.evaluate(ctx);
let available = false;

if (ctx.availableImages && ctx.availableImages.indexOf(evaluatedImageName) > -1) {
available = true;
}
const value = ResolvedImage.fromString(evaluatedImageName);
if (value && ctx.availableImages) value.available = ctx.availableImages.indexOf(evaluatedImageName) > -1;

return new ResolvedImage({name: evaluatedImageName, available});
return value;
}

eachChild(fn: (_: Expression) => void) {
Expand Down
3 changes: 2 additions & 1 deletion src/style-spec/expression/types/resolved_image.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export default class ResolvedImage {
return this.name;
}

static fromString(name: string): ResolvedImage {
static fromString(name: string): ResolvedImage | null {
if (!name) return null; // treat empty values as no image
return new ResolvedImage({name, available: false});
}

Expand Down
27 changes: 27 additions & 0 deletions test/unit/ui/map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,33 @@ test('Map', (t) => {
});
});

t.test('map does not fire `styleimagemissing` for empty icon values', (t) => {
const map = createMap(t);

map.on('load', () => {
map.on('idle', () => {
t.end();
});

map.addSource('foo', {
type: 'geojson',
data: {type: 'Point', coordinates: [0, 0]}
});
map.addLayer({
id: 'foo',
type: 'symbol',
source: 'foo',
layout: {
'icon-image': ['case', true, '', '']
}
});

map.on('styleimagemissing', ({id}) => {
t.fail(`styleimagemissing fired for value ${id}`);
});
});
});

t.end();
});

Expand Down

0 comments on commit fa36168

Please sign in to comment.