maplibre-gl 2.2.1 → 2.3.1-pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/generate-query-test-fixtures.ts +3 -2
- package/build/generate-struct-arrays.ts +0 -2
- package/build/generate-style-spec.ts +12 -17
- package/build/generate-typings.ts +11 -1
- package/build/rollup_plugins.ts +0 -4
- package/dist/maplibre-gl-csp-worker.js +1 -1
- package/dist/maplibre-gl-csp.js +1 -1
- package/dist/maplibre-gl-dev.js +376 -1402
- package/dist/maplibre-gl.d.ts +13 -16
- package/dist/maplibre-gl.js +4 -4
- package/dist/style-spec/index.d.ts +1768 -0
- package/package.json +14 -16
- package/src/data/array_types.g.ts +0 -5
- package/src/data/bucket/fill_bucket.ts +0 -2
- package/src/data/bucket/fill_extrusion_bucket.ts +0 -2
- package/src/data/bucket/symbol_bucket.test.ts +30 -19
- package/src/data/feature_position_map.ts +1 -2
- package/src/gl/framebuffer.ts +3 -2
- package/src/gl/index_buffer.ts +1 -2
- package/src/gl/vertex_buffer.ts +1 -2
- package/src/index.test.ts +9 -0
- package/src/index.ts +12 -4
- package/src/render/image_manager.ts +5 -7
- package/src/render/program/pattern.ts +0 -2
- package/src/render/program.ts +12 -9
- package/src/render/vertex_array_object.ts +1 -3
- package/src/source/geojson_worker_source.ts +0 -4
- package/src/source/query_features.ts +0 -3
- package/src/source/rtl_text_plugin.ts +3 -4
- package/src/source/source_cache.ts +0 -2
- package/src/source/tile_id.ts +8 -8
- package/src/source/worker.ts +0 -7
- package/src/source/worker_tile.ts +12 -3
- package/src/style/format_section_override.ts +1 -2
- package/src/style/properties.ts +1 -3
- package/src/style/style.ts +5 -5
- package/src/style/style_layer/custom_style_layer.ts +1 -2
- package/src/style/style_layer/symbol_style_layer.ts +1 -3
- package/src/style-spec/CHANGELOG.md +10 -0
- package/src/style-spec/composite.test.ts +7 -8
- package/src/style-spec/expression/compound_expression.ts +0 -4
- package/src/style-spec/expression/definitions/assertion.ts +2 -4
- package/src/style-spec/expression/definitions/case.ts +1 -2
- package/src/style-spec/expression/definitions/coalesce.ts +1 -3
- package/src/style-spec/expression/definitions/coercion.ts +2 -4
- package/src/style-spec/expression/definitions/match.ts +0 -3
- package/src/style-spec/expression/index.ts +13 -15
- package/src/style-spec/expression/parsing_context.ts +4 -4
- package/src/style-spec/expression/parsing_error.ts +2 -2
- package/src/style-spec/expression/values.ts +0 -2
- package/src/style-spec/feature_filter/feature_filter.test.ts +39 -2
- package/src/style-spec/function/convert.ts +1 -3
- package/src/style-spec/migrate/v8.test.ts +12 -14
- package/src/style-spec/migrate/v9.test.ts +2 -4
- package/src/style-spec/migrate.test.ts +6 -8
- package/src/style-spec/package.json +2 -1
- package/src/style-spec/types.g.ts +12 -17
- package/src/symbol/collision_index.ts +0 -3
- package/src/symbol/path_interpolator.ts +0 -2
- package/src/symbol/placement.ts +14 -9
- package/src/symbol/shaping.ts +0 -4
- package/src/symbol/symbol_layout.ts +56 -56
- package/src/ui/camera.ts +0 -10
- package/src/ui/control/geolocate_control.ts +4 -6
- package/src/ui/handler/handler_util.ts +1 -2
- package/src/ui/handler/scroll_zoom.ts +0 -2
- package/src/ui/handler_manager.ts +0 -2
- package/src/ui/map.test.ts +11 -0
- package/src/ui/map.ts +11 -0
- package/src/util/ajax.ts +1 -2
- package/src/util/color_ramp.ts +1 -2
- package/src/util/dictionary_coder.ts +1 -3
- package/src/util/dispatcher.ts +1 -4
- package/src/util/dom.ts +0 -3
- package/src/util/image.ts +1 -3
- package/src/util/struct_array.ts +0 -5
- package/src/util/task_queue.ts +1 -3
- package/src/util/web_worker_transfer.ts +5 -6
package/src/source/tile_id.ts
CHANGED
|
@@ -2,8 +2,6 @@ import {getTileBBox} from '@mapbox/whoots-js';
|
|
|
2
2
|
import EXTENT from '../data/extent';
|
|
3
3
|
import Point from '@mapbox/point-geometry';
|
|
4
4
|
import MercatorCoordinate from '../geo/mercator_coordinate';
|
|
5
|
-
|
|
6
|
-
import assert from 'assert';
|
|
7
5
|
import {register} from '../util/web_worker_transfer';
|
|
8
6
|
import {mat4} from 'gl-matrix';
|
|
9
7
|
|
|
@@ -14,9 +12,11 @@ export class CanonicalTileID {
|
|
|
14
12
|
key: string;
|
|
15
13
|
|
|
16
14
|
constructor(z: number, x: number, y: number) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
|
|
16
|
+
if (z < 0 || z > 25 || y < 0 || y >= Math.pow(2, z) || x < 0 || x >= Math.pow(2, z)) {
|
|
17
|
+
throw new Error(`x=${x}, y=${y}, z=${z} outside of bounds. 0<=x<${Math.pow(2, z)}, 0<=y<${Math.pow(2, z)} 0<=z<=25 `);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
20
|
this.z = z;
|
|
21
21
|
this.x = x;
|
|
22
22
|
this.y = y;
|
|
@@ -79,7 +79,7 @@ export class OverscaledTileID {
|
|
|
79
79
|
posMatrix: mat4;
|
|
80
80
|
|
|
81
81
|
constructor(overscaledZ: number, wrap: number, z: number, x: number, y: number) {
|
|
82
|
-
|
|
82
|
+
if (overscaledZ < z) throw new Error(`overscaledZ should be >= z; overscaledZ = ${overscaledZ}; z = ${z}`);
|
|
83
83
|
this.overscaledZ = overscaledZ;
|
|
84
84
|
this.wrap = wrap;
|
|
85
85
|
this.canonical = new CanonicalTileID(z, +x, +y);
|
|
@@ -95,7 +95,7 @@ export class OverscaledTileID {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
scaledTo(targetZ: number) {
|
|
98
|
-
|
|
98
|
+
if (targetZ > this.overscaledZ) throw new Error(`targetZ > this.overscaledZ; targetZ = ${targetZ}; overscaledZ = ${this.overscaledZ}`);
|
|
99
99
|
const zDifference = this.canonical.z - targetZ;
|
|
100
100
|
if (targetZ > this.canonical.z) {
|
|
101
101
|
return new OverscaledTileID(targetZ, this.wrap, this.canonical.z, this.canonical.x, this.canonical.y);
|
|
@@ -110,7 +110,7 @@ export class OverscaledTileID {
|
|
|
110
110
|
* when withWrap == false, implements the same as this.scaledTo(z).wrapped().key.
|
|
111
111
|
*/
|
|
112
112
|
calculateScaledKey(targetZ: number, withWrap: boolean): string {
|
|
113
|
-
|
|
113
|
+
if (targetZ > this.overscaledZ) throw new Error(`targetZ > this.overscaledZ; targetZ = ${targetZ}; overscaledZ = ${this.overscaledZ}`);
|
|
114
114
|
const zDifference = this.canonical.z - targetZ;
|
|
115
115
|
if (targetZ > this.canonical.z) {
|
|
116
116
|
return calculateKey(this.wrap * +withWrap, targetZ, this.canonical.z, this.canonical.x, this.canonical.y);
|
package/src/source/worker.ts
CHANGED
|
@@ -4,7 +4,6 @@ import StyleLayerIndex from '../style/style_layer_index';
|
|
|
4
4
|
import VectorTileWorkerSource from './vector_tile_worker_source';
|
|
5
5
|
import RasterDEMTileWorkerSource from './raster_dem_tile_worker_source';
|
|
6
6
|
import GeoJSONWorkerSource from './geojson_worker_source';
|
|
7
|
-
import assert from 'assert';
|
|
8
7
|
import {plugin as globalRTLTextPlugin} from './rtl_text_plugin';
|
|
9
8
|
import {enforceCacheSizeLimit} from '../util/tile_request_cache';
|
|
10
9
|
import {isWorker} from '../util/util';
|
|
@@ -121,7 +120,6 @@ export default class Worker {
|
|
|
121
120
|
loadTile(mapId: string, params: WorkerTileParameters & {
|
|
122
121
|
type: string;
|
|
123
122
|
}, callback: WorkerTileCallback) {
|
|
124
|
-
assert(params.type);
|
|
125
123
|
this.getWorkerSource(mapId, params.type, params.source).loadTile(params, callback);
|
|
126
124
|
}
|
|
127
125
|
|
|
@@ -132,21 +130,18 @@ export default class Worker {
|
|
|
132
130
|
reloadTile(mapId: string, params: WorkerTileParameters & {
|
|
133
131
|
type: string;
|
|
134
132
|
}, callback: WorkerTileCallback) {
|
|
135
|
-
assert(params.type);
|
|
136
133
|
this.getWorkerSource(mapId, params.type, params.source).reloadTile(params, callback);
|
|
137
134
|
}
|
|
138
135
|
|
|
139
136
|
abortTile(mapId: string, params: TileParameters & {
|
|
140
137
|
type: string;
|
|
141
138
|
}, callback: WorkerTileCallback) {
|
|
142
|
-
assert(params.type);
|
|
143
139
|
this.getWorkerSource(mapId, params.type, params.source).abortTile(params, callback);
|
|
144
140
|
}
|
|
145
141
|
|
|
146
142
|
removeTile(mapId: string, params: TileParameters & {
|
|
147
143
|
type: string;
|
|
148
144
|
}, callback: WorkerTileCallback) {
|
|
149
|
-
assert(params.type);
|
|
150
145
|
this.getWorkerSource(mapId, params.type, params.source).removeTile(params, callback);
|
|
151
146
|
}
|
|
152
147
|
|
|
@@ -159,8 +154,6 @@ export default class Worker {
|
|
|
159
154
|
} & {
|
|
160
155
|
type: string;
|
|
161
156
|
}, callback: WorkerTileCallback) {
|
|
162
|
-
assert(params.type);
|
|
163
|
-
assert(params.source);
|
|
164
157
|
|
|
165
158
|
if (!this.workerSources[mapId] ||
|
|
166
159
|
!this.workerSources[mapId][params.type] ||
|
|
@@ -8,7 +8,6 @@ import LineBucket from '../data/bucket/line_bucket';
|
|
|
8
8
|
import FillBucket from '../data/bucket/fill_bucket';
|
|
9
9
|
import FillExtrusionBucket from '../data/bucket/fill_extrusion_bucket';
|
|
10
10
|
import {warnOnce, mapObject} from '../util/util';
|
|
11
|
-
import assert from 'assert';
|
|
12
11
|
import ImageAtlas from '../render/image_atlas';
|
|
13
12
|
import GlyphAtlas from '../render/glyph_atlas';
|
|
14
13
|
import EvaluationParameters from '../style/evaluation_parameters';
|
|
@@ -105,7 +104,9 @@ class WorkerTile {
|
|
|
105
104
|
for (const family of layerFamilies[sourceLayerId]) {
|
|
106
105
|
const layer = family[0];
|
|
107
106
|
|
|
108
|
-
|
|
107
|
+
if (layer.source !== this.source) {
|
|
108
|
+
warnOnce(`layer.source = ${layer.source} does not equal this.source = ${this.source}`);
|
|
109
|
+
}
|
|
109
110
|
if (layer.minzoom && this.zoom < Math.floor(layer.minzoom)) continue;
|
|
110
111
|
if (layer.maxzoom && this.zoom >= layer.maxzoom) continue;
|
|
111
112
|
if (layer.visibility === 'none') continue;
|
|
@@ -189,7 +190,15 @@ class WorkerTile {
|
|
|
189
190
|
const bucket = buckets[key];
|
|
190
191
|
if (bucket instanceof SymbolBucket) {
|
|
191
192
|
recalculateLayers(bucket.layers, this.zoom, availableImages);
|
|
192
|
-
performSymbolLayout(
|
|
193
|
+
performSymbolLayout({
|
|
194
|
+
bucket,
|
|
195
|
+
glyphMap,
|
|
196
|
+
glyphPositions: glyphAtlas.positions,
|
|
197
|
+
imageMap: iconMap,
|
|
198
|
+
imagePositions: imageAtlas.iconPositions,
|
|
199
|
+
showCollisionBoxes: this.showCollisionBoxes,
|
|
200
|
+
canonical: this.tileID.canonical
|
|
201
|
+
});
|
|
193
202
|
} else if (bucket.hasPattern &&
|
|
194
203
|
(bucket instanceof LineBucket ||
|
|
195
204
|
bucket instanceof FillBucket ||
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
import type {Expression} from '../style-spec/expression/expression';
|
|
3
2
|
import type EvaluationContext from '../style-spec/expression/evaluation_context';
|
|
4
3
|
import type {Type} from '../style-spec/expression/types';
|
|
@@ -14,7 +13,7 @@ export default class FormatSectionOverride<T> implements Expression {
|
|
|
14
13
|
defaultValue: PossiblyEvaluatedPropertyValue<T>;
|
|
15
14
|
|
|
16
15
|
constructor(defaultValue: PossiblyEvaluatedPropertyValue<T>) {
|
|
17
|
-
|
|
16
|
+
if (defaultValue.property.overrides === undefined) throw new Error('overrides must be provided to instantiate FormatSectionOverride class');
|
|
18
17
|
this.type = defaultValue.property.overrides ? defaultValue.property.overrides.runtimeType : NullType;
|
|
19
18
|
this.defaultValue = defaultValue;
|
|
20
19
|
}
|
package/src/style/properties.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
import {clone, extend, easeCubicInOut} from '../util/util';
|
|
3
2
|
import * as interpolate from '../style-spec/util/interpolate';
|
|
4
3
|
import Color from '../style-spec/util/color';
|
|
@@ -488,7 +487,7 @@ export class DataConstantProperty<T> implements Property<T, T> {
|
|
|
488
487
|
}
|
|
489
488
|
|
|
490
489
|
possiblyEvaluate(value: PropertyValue<T, T>, parameters: EvaluationParameters): T {
|
|
491
|
-
|
|
490
|
+
if (value.isDataDriven()) throw new Error('Value should not be data driven');
|
|
492
491
|
return value.expression.evaluate(parameters);
|
|
493
492
|
}
|
|
494
493
|
|
|
@@ -668,7 +667,6 @@ export class CrossFadedProperty<T> implements Property<T, CrossFaded<T>> {
|
|
|
668
667
|
const constant = value.expression.evaluate(parameters, null, {}, canonical, availableImages);
|
|
669
668
|
return this._calculate(constant, constant, constant, parameters);
|
|
670
669
|
} else {
|
|
671
|
-
assert(!value.isDataDriven());
|
|
672
670
|
return this._calculate(
|
|
673
671
|
value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom - 1.0), parameters)),
|
|
674
672
|
value.expression.evaluate(new EvaluationParameters(Math.floor(parameters.zoom), parameters)),
|
package/src/style/style.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
|
|
3
1
|
import {Event, ErrorEvent, Evented} from '../util/evented';
|
|
4
2
|
import StyleLayer from './style_layer';
|
|
5
3
|
import createStyleLayer from './create_style_layer';
|
|
@@ -402,11 +400,13 @@ class Style extends Evented {
|
|
|
402
400
|
}
|
|
403
401
|
for (const id in this._updatedSources) {
|
|
404
402
|
const action = this._updatedSources[id];
|
|
405
|
-
|
|
403
|
+
|
|
406
404
|
if (action === 'reload') {
|
|
407
405
|
this._reloadSource(id);
|
|
408
406
|
} else if (action === 'clear') {
|
|
409
407
|
this._clearSource(id);
|
|
408
|
+
} else {
|
|
409
|
+
throw new Error(`Invalid action ${action}`);
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
412
|
|
|
@@ -677,9 +677,9 @@ class Style extends Evented {
|
|
|
677
677
|
setGeoJSONSourceData(id: string, data: GeoJSON.GeoJSON | string) {
|
|
678
678
|
this._checkLoaded();
|
|
679
679
|
|
|
680
|
-
|
|
680
|
+
if (this.sourceCaches[id] === undefined) throw new Error(`There is no source with this ID=${id}`);
|
|
681
681
|
const geojsonSource: GeoJSONSource = (this.sourceCaches[id].getSource() as any);
|
|
682
|
-
|
|
682
|
+
if (geojsonSource.type !== 'geojson') throw new Error(`geojsonSource.type is ${geojsonSource.type}, which is !== 'geojson`);
|
|
683
683
|
|
|
684
684
|
geojsonSource.setData(data);
|
|
685
685
|
this._changed = true;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import StyleLayer from '../style_layer';
|
|
2
2
|
import type Map from '../../ui/map';
|
|
3
|
-
import assert from 'assert';
|
|
4
3
|
import {mat4} from 'gl-matrix';
|
|
5
4
|
import {LayerSpecification} from '../../style-spec/types.g';
|
|
6
5
|
|
|
@@ -206,7 +205,7 @@ class CustomStyleLayer extends StyleLayer {
|
|
|
206
205
|
hasTransition() { return false; }
|
|
207
206
|
|
|
208
207
|
serialize(): LayerSpecification {
|
|
209
|
-
|
|
208
|
+
throw new Error('Custom layers cannot be serialized');
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
onAdd = (map: Map) => {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import StyleLayer from '../style_layer';
|
|
2
2
|
|
|
3
|
-
import assert from 'assert';
|
|
4
3
|
import SymbolBucket, {SymbolFeature} from '../../data/bucket/symbol_bucket';
|
|
5
4
|
import resolveTokens from '../../util/resolve_tokens';
|
|
6
5
|
import properties, {SymbolLayoutPropsPossiblyEvaluated, SymbolPaintPropsPossiblyEvaluated} from './symbol_style_layer_properties.g';
|
|
@@ -110,8 +109,7 @@ class SymbolStyleLayer extends StyleLayer {
|
|
|
110
109
|
}
|
|
111
110
|
|
|
112
111
|
queryIntersectsFeature(): boolean {
|
|
113
|
-
|
|
114
|
-
return false;
|
|
112
|
+
throw new Error('Should take a different path in FeatureIndex');
|
|
115
113
|
}
|
|
116
114
|
|
|
117
115
|
_setPaintOverrides() {
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 17.0.1
|
|
2
|
+
|
|
3
|
+
* Generated typings file as not created in the build process and was added in this version [#1470](https://github.com/maplibre/maplibre-gl-js/pull/1470)
|
|
4
|
+
|
|
5
|
+
## 17.0.0
|
|
6
|
+
|
|
7
|
+
### Breaking changes
|
|
8
|
+
|
|
9
|
+
* Renamed `ParsingError` to `ExpressionParsingError` as there were two with the same name and added typescript typings [1468](https://github.com/maplibre/maplibre-gl-js/pull/1468)
|
|
10
|
+
|
|
1
11
|
## 16.1.0
|
|
2
12
|
|
|
3
13
|
### ✨ Features and improvements
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
|
|
3
1
|
import composite from './composite';
|
|
2
|
+
import {LineLayerSpecification} from './types.g';
|
|
4
3
|
|
|
5
4
|
describe('composite', () => {
|
|
6
5
|
test('composites Mapbox vector sources', () => {
|
|
7
6
|
const result = composite({
|
|
8
|
-
'version': 7,
|
|
7
|
+
'version': 7 as any,
|
|
9
8
|
'sources': {
|
|
10
9
|
'mapbox-a': {
|
|
11
10
|
'type': 'vector',
|
|
@@ -34,13 +33,13 @@ describe('composite', () => {
|
|
|
34
33
|
}
|
|
35
34
|
});
|
|
36
35
|
|
|
37
|
-
expect(result.layers[0].source).toBe('a,b');
|
|
38
|
-
expect(result.layers[1].source).toBe('a,b');
|
|
36
|
+
expect((result.layers[0] as LineLayerSpecification).source).toBe('a,b');
|
|
37
|
+
expect((result.layers[1] as LineLayerSpecification).source).toBe('a,b');
|
|
39
38
|
});
|
|
40
39
|
|
|
41
40
|
test('does not composite vector + raster', () => {
|
|
42
41
|
const result = composite({
|
|
43
|
-
'version': 7,
|
|
42
|
+
'version': 7 as any,
|
|
44
43
|
'sources': {
|
|
45
44
|
'a': {
|
|
46
45
|
'type': 'vector',
|
|
@@ -59,7 +58,7 @@ describe('composite', () => {
|
|
|
59
58
|
|
|
60
59
|
test('incorrect url match', () => {
|
|
61
60
|
const result = composite({
|
|
62
|
-
'version': 7,
|
|
61
|
+
'version': 7 as any,
|
|
63
62
|
'sources': {
|
|
64
63
|
'a': {
|
|
65
64
|
'type': 'vector',
|
|
@@ -79,7 +78,7 @@ describe('composite', () => {
|
|
|
79
78
|
test('composites Mapbox vector sources with conflicting source layer names', () => {
|
|
80
79
|
expect(() => {
|
|
81
80
|
composite({
|
|
82
|
-
'version': 7,
|
|
81
|
+
'version': 7 as any,
|
|
83
82
|
'sources': {
|
|
84
83
|
'mapbox-a': {
|
|
85
84
|
'type': 'vector',
|
|
@@ -2,7 +2,6 @@ import {toString} from './types';
|
|
|
2
2
|
|
|
3
3
|
import ParsingContext from './parsing_context';
|
|
4
4
|
import EvaluationContext from './evaluation_context';
|
|
5
|
-
import assert from 'assert';
|
|
6
5
|
|
|
7
6
|
import type {Expression, ExpressionRegistry} from './expression';
|
|
8
7
|
import type {Type} from './types';
|
|
@@ -114,8 +113,6 @@ class CompoundExpression implements Expression {
|
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
|
|
117
|
-
assert(!signatureContext || signatureContext.errors.length > 0);
|
|
118
|
-
|
|
119
116
|
if (overloads.length === 1) {
|
|
120
117
|
context.errors.push(...signatureContext.errors);
|
|
121
118
|
} else {
|
|
@@ -142,7 +139,6 @@ class CompoundExpression implements Expression {
|
|
|
142
139
|
registry: ExpressionRegistry,
|
|
143
140
|
definitions: {[_: string]: Definition}
|
|
144
141
|
) {
|
|
145
|
-
assert(!CompoundExpression.definitions);
|
|
146
142
|
CompoundExpression.definitions = definitions;
|
|
147
143
|
for (const name in definitions) {
|
|
148
144
|
registry[name] = CompoundExpression;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
|
|
3
2
|
import {
|
|
4
3
|
ObjectType,
|
|
@@ -69,7 +68,7 @@ class Assertion implements Expression {
|
|
|
69
68
|
|
|
70
69
|
type = array(itemType, N);
|
|
71
70
|
} else {
|
|
72
|
-
|
|
71
|
+
if (!types[name]) throw new Error(`Types doesn't contain name = ${name}`);
|
|
73
72
|
type = types[name];
|
|
74
73
|
}
|
|
75
74
|
|
|
@@ -94,8 +93,7 @@ class Assertion implements Expression {
|
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
return null;
|
|
96
|
+
throw new Error();
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
eachChild(fn: (_: Expression) => void) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
|
|
3
2
|
import {BooleanType} from '../types';
|
|
4
3
|
|
|
@@ -48,7 +47,7 @@ class Case implements Expression {
|
|
|
48
47
|
const otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
|
|
49
48
|
if (!otherwise) return null;
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
if (!outputType) throw new Error('Can\'t infer output type');
|
|
52
51
|
return new Case((outputType as any), branches, otherwise);
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
|
|
3
1
|
import {checkSubtype, ValueType} from '../types';
|
|
4
2
|
import ResolvedImage from '../types/resolved_image';
|
|
5
3
|
|
|
@@ -34,7 +32,7 @@ class Coalesce implements Expression {
|
|
|
34
32
|
outputType = outputType || parsed.type;
|
|
35
33
|
parsedArgs.push(parsed);
|
|
36
34
|
}
|
|
37
|
-
|
|
35
|
+
if (!outputType) throw new Error('No output type');
|
|
38
36
|
|
|
39
37
|
// Above, we parse arguments without inferred type annotation so that
|
|
40
38
|
// they don't produce a runtime error for `null` input, which would
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
|
|
3
1
|
import {BooleanType, ColorType, NumberType, StringType, ValueType} from '../types';
|
|
4
2
|
import {Color, Padding, toString as valueToString, validateRGBA} from '../values';
|
|
5
3
|
import RuntimeError from '../runtime_error';
|
|
@@ -32,6 +30,7 @@ class Coercion implements Expression {
|
|
|
32
30
|
constructor(type: Type, args: Array<Expression>) {
|
|
33
31
|
this.type = type;
|
|
34
32
|
this.args = args;
|
|
33
|
+
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
static parse(args: ReadonlyArray<unknown>, context: ParsingContext): Expression {
|
|
@@ -39,8 +38,7 @@ class Coercion implements Expression {
|
|
|
39
38
|
return context.error('Expected at least one argument.') as null;
|
|
40
39
|
|
|
41
40
|
const name: string = (args[0] as any);
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
if (!types[name]) throw new Error(`Can't parse ${name} as it is not part of the known types`);
|
|
44
42
|
if ((name === 'to-boolean' || name === 'to-string') && args.length !== 2)
|
|
45
43
|
return context.error('Expected one argument.') as null;
|
|
46
44
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
|
|
3
2
|
import {typeOf} from '../values';
|
|
4
3
|
import {ValueType} from '../types';
|
|
@@ -92,8 +91,6 @@ class Match implements Expression {
|
|
|
92
91
|
const otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
|
|
93
92
|
if (!otherwise) return null;
|
|
94
93
|
|
|
95
|
-
assert(inputType && outputType);
|
|
96
|
-
|
|
97
94
|
if (input.type.kind !== 'value' && context.concat(1).checkSubtype(((inputType as any)), input.type)) {
|
|
98
95
|
return null;
|
|
99
96
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
|
|
3
2
|
import extend from '../util/extend';
|
|
4
|
-
import
|
|
3
|
+
import ExpressionParsingError from './parsing_error';
|
|
5
4
|
import ParsingContext from './parsing_context';
|
|
6
5
|
import EvaluationContext from './evaluation_context';
|
|
7
6
|
import CompoundExpression from './compound_expression';
|
|
@@ -135,7 +134,7 @@ export function isExpression(expression: unknown) {
|
|
|
135
134
|
*
|
|
136
135
|
* @private
|
|
137
136
|
*/
|
|
138
|
-
export function createExpression(expression: unknown, propertySpec?: StylePropertySpecification | null): Result<StyleExpression, Array<
|
|
137
|
+
export function createExpression(expression: unknown, propertySpec?: StylePropertySpecification | null): Result<StyleExpression, Array<ExpressionParsingError>> {
|
|
139
138
|
const parser = new ParsingContext(definitions, [], propertySpec ? getExpectedType(propertySpec) : undefined);
|
|
140
139
|
|
|
141
140
|
// For string-valued properties, coerce to string at the top level rather than asserting.
|
|
@@ -143,7 +142,6 @@ export function createExpression(expression: unknown, propertySpec?: StyleProper
|
|
|
143
142
|
propertySpec && propertySpec.type === 'string' ? {typeAnnotation: 'coerce'} : undefined);
|
|
144
143
|
|
|
145
144
|
if (!parsed) {
|
|
146
|
-
assert(parser.errors.length > 0);
|
|
147
145
|
return error(parser.errors);
|
|
148
146
|
}
|
|
149
147
|
|
|
@@ -287,7 +285,7 @@ export type CompositeExpression = {
|
|
|
287
285
|
|
|
288
286
|
export type StylePropertyExpression = ConstantExpression | SourceExpression | CameraExpression | CompositeExpression;
|
|
289
287
|
|
|
290
|
-
export function createPropertyExpression(expressionInput: unknown, propertySpec: StylePropertySpecification): Result<StylePropertyExpression, Array<
|
|
288
|
+
export function createPropertyExpression(expressionInput: unknown, propertySpec: StylePropertySpecification): Result<StylePropertyExpression, Array<ExpressionParsingError>> {
|
|
291
289
|
const expression = createExpression(expressionInput, propertySpec);
|
|
292
290
|
if (expression.result === 'error') {
|
|
293
291
|
return expression;
|
|
@@ -297,21 +295,21 @@ export function createPropertyExpression(expressionInput: unknown, propertySpec:
|
|
|
297
295
|
|
|
298
296
|
const isFeatureConstant = isConstant.isFeatureConstant(parsed);
|
|
299
297
|
if (!isFeatureConstant && !supportsPropertyExpression(propertySpec)) {
|
|
300
|
-
return error([new
|
|
298
|
+
return error([new ExpressionParsingError('', 'data expressions not supported')]);
|
|
301
299
|
}
|
|
302
300
|
|
|
303
301
|
const isZoomConstant = isConstant.isGlobalPropertyConstant(parsed, ['zoom']);
|
|
304
302
|
if (!isZoomConstant && !supportsZoomExpression(propertySpec)) {
|
|
305
|
-
return error([new
|
|
303
|
+
return error([new ExpressionParsingError('', 'zoom expressions not supported')]);
|
|
306
304
|
}
|
|
307
305
|
|
|
308
306
|
const zoomCurve = findZoomCurve(parsed);
|
|
309
307
|
if (!zoomCurve && !isZoomConstant) {
|
|
310
|
-
return error([new
|
|
311
|
-
} else if (zoomCurve instanceof
|
|
308
|
+
return error([new ExpressionParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.')]);
|
|
309
|
+
} else if (zoomCurve instanceof ExpressionParsingError) {
|
|
312
310
|
return error([zoomCurve]);
|
|
313
311
|
} else if (zoomCurve instanceof Interpolate && !supportsInterpolation(propertySpec)) {
|
|
314
|
-
return error([new
|
|
312
|
+
return error([new ExpressionParsingError('', '"interpolate" expressions cannot be used with this property')]);
|
|
315
313
|
}
|
|
316
314
|
|
|
317
315
|
if (!zoomCurve) {
|
|
@@ -394,7 +392,7 @@ export function normalizePropertyExpression<T>(
|
|
|
394
392
|
// Zoom-dependent expressions may only use ["zoom"] as the input to a top-level "step" or "interpolate"
|
|
395
393
|
// expression (collectively referred to as a "curve"). The curve may be wrapped in one or more "let" or
|
|
396
394
|
// "coalesce" expressions.
|
|
397
|
-
function findZoomCurve(expression: Expression): Step | Interpolate |
|
|
395
|
+
function findZoomCurve(expression: Expression): Step | Interpolate | ExpressionParsingError | null {
|
|
398
396
|
let result = null;
|
|
399
397
|
if (expression instanceof Let) {
|
|
400
398
|
result = findZoomCurve(expression.result);
|
|
@@ -414,18 +412,18 @@ function findZoomCurve(expression: Expression): Step | Interpolate | ParsingErro
|
|
|
414
412
|
result = expression;
|
|
415
413
|
}
|
|
416
414
|
|
|
417
|
-
if (result instanceof
|
|
415
|
+
if (result instanceof ExpressionParsingError) {
|
|
418
416
|
return result;
|
|
419
417
|
}
|
|
420
418
|
|
|
421
419
|
expression.eachChild((child) => {
|
|
422
420
|
const childResult = findZoomCurve(child);
|
|
423
|
-
if (childResult instanceof
|
|
421
|
+
if (childResult instanceof ExpressionParsingError) {
|
|
424
422
|
result = childResult;
|
|
425
423
|
} else if (!result && childResult) {
|
|
426
|
-
result = new
|
|
424
|
+
result = new ExpressionParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.');
|
|
427
425
|
} else if (result && childResult && result !== childResult) {
|
|
428
|
-
result = new
|
|
426
|
+
result = new ExpressionParsingError('', 'Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.');
|
|
429
427
|
}
|
|
430
428
|
});
|
|
431
429
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Scope from './scope';
|
|
2
2
|
import {checkSubtype} from './types';
|
|
3
|
-
import
|
|
3
|
+
import ExpressionParsingError from './parsing_error';
|
|
4
4
|
import Literal from './definitions/literal';
|
|
5
5
|
import Assertion from './definitions/assertion';
|
|
6
6
|
import Coercion from './definitions/coercion';
|
|
@@ -23,7 +23,7 @@ class ParsingContext {
|
|
|
23
23
|
path: Array<number>;
|
|
24
24
|
key: string;
|
|
25
25
|
scope: Scope;
|
|
26
|
-
errors: Array<
|
|
26
|
+
errors: Array<ExpressionParsingError>;
|
|
27
27
|
|
|
28
28
|
// The expected type of this expression. Provided only to allow Expression
|
|
29
29
|
// implementations to infer argument types: Expression#parse() need not
|
|
@@ -36,7 +36,7 @@ class ParsingContext {
|
|
|
36
36
|
path: Array<number> = [],
|
|
37
37
|
expectedType?: Type | null,
|
|
38
38
|
scope: Scope = new Scope(),
|
|
39
|
-
errors: Array<
|
|
39
|
+
errors: Array<ExpressionParsingError> = []
|
|
40
40
|
) {
|
|
41
41
|
this.registry = registry;
|
|
42
42
|
this.path = path;
|
|
@@ -183,7 +183,7 @@ class ParsingContext {
|
|
|
183
183
|
*/
|
|
184
184
|
error(error: string, ...keys: Array<number>) {
|
|
185
185
|
const key = `${this.key}${keys.map(k => `[${k}]`).join('')}`;
|
|
186
|
-
this.errors.push(new
|
|
186
|
+
this.errors.push(new ExpressionParsingError(key, error));
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class ExpressionParsingError extends Error {
|
|
2
2
|
key: string;
|
|
3
3
|
message: string;
|
|
4
4
|
constructor(key: string, message: string) {
|
|
@@ -8,4 +8,4 @@ class ParsingError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default
|
|
11
|
+
export default ExpressionParsingError;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
1
|
|
|
3
2
|
import Color from '../util/color';
|
|
4
3
|
import Collator from './types/collator';
|
|
@@ -107,7 +106,6 @@ export function typeOf(value: Value): Type {
|
|
|
107
106
|
|
|
108
107
|
return array(itemType || ValueType, length);
|
|
109
108
|
} else {
|
|
110
|
-
assert(typeof value === 'object');
|
|
111
109
|
return ObjectType;
|
|
112
110
|
}
|
|
113
111
|
}
|
|
@@ -5,11 +5,11 @@ import Point from '@mapbox/point-geometry';
|
|
|
5
5
|
import MercatorCoordinate from '../../geo/mercator_coordinate';
|
|
6
6
|
import EXTENT from '../../data/extent';
|
|
7
7
|
import {CanonicalTileID} from '../../source/tile_id';
|
|
8
|
-
import {ExpressionFilterSpecification, FilterSpecification} from '../types.g';
|
|
8
|
+
import {ExpressionFilterSpecification, ExpressionInputType, ExpressionSpecification, FilterSpecification} from '../types.g';
|
|
9
9
|
import {Feature} from '../expression';
|
|
10
10
|
|
|
11
11
|
describe('filter', () => {
|
|
12
|
-
test('
|
|
12
|
+
test('expressions transpilation test', () => {
|
|
13
13
|
function compileTimeCheck(_: ExpressionFilterSpecification) {
|
|
14
14
|
expect(true).toBeTruthy();
|
|
15
15
|
}
|
|
@@ -36,6 +36,43 @@ describe('filter', () => {
|
|
|
36
36
|
compileTimeCheck(['match', ['get', 'TYPE'], ['TARGETPOINT:HOSPITAL'], true, false]);
|
|
37
37
|
compileTimeCheck(['match', ['get', 'TYPE'], ['ADIZ', 'AMA', 'AWY', 'CLASS', 'NO-FIR', 'OCA', 'OTA', 'P', 'RAS', 'RCA', 'UTA', 'UTA-P'], true, false]);
|
|
38
38
|
compileTimeCheck(['==', ['get', 'MILITARYAIRPORT'], 1]);
|
|
39
|
+
compileTimeCheck(['interpolate', ['linear'], ['line-progress'], 0, 10, 0.5, 100, 1, 1000]); // number output
|
|
40
|
+
compileTimeCheck(['interpolate', ['linear'], ['line-progress'], 0, 'red', 0.5, 'green', 1, 'blue']); // color output
|
|
41
|
+
compileTimeCheck(['interpolate', ['linear'], ['line-progress'], 0, [10, 20, 30], 0.5, [20, 30, 40], 1, [30, 40, 80]]); // number array output!
|
|
42
|
+
compileTimeCheck(['interpolate-hcl', ['linear'], ['line-progress'], 0, 'red', 0.5, 'green', 1, 'blue']);
|
|
43
|
+
compileTimeCheck(['interpolate-lab', ['linear'], ['line-progress'], 0, 'red', 0.5, 'green', 1, 'blue']);
|
|
44
|
+
compileTimeCheck(['step', ['get', 'point_count'], '#df2d43', 50, '#df2d43', 200, '#df2d43']);
|
|
45
|
+
compileTimeCheck(['step', ['get', 'point_count'], 20, 50, 30, 200, 40]);
|
|
46
|
+
compileTimeCheck(['step', ['get', 'point_count'], 0.6, 50, 0.7, 200, 0.8]);
|
|
47
|
+
|
|
48
|
+
// checks, where parts of the expression are injected from constants
|
|
49
|
+
// as in most cases the styling is read from JSON, these are rather optional tests.
|
|
50
|
+
// due to typescript inferring rather broad types, this is only possible in few places without specifying a type for the constant.
|
|
51
|
+
const colorStops = [0, 'red', 0.5, 'green', 1, 'blue'];
|
|
52
|
+
compileTimeCheck([
|
|
53
|
+
'interpolate',
|
|
54
|
+
['linear'],
|
|
55
|
+
['line-progress'],
|
|
56
|
+
...colorStops
|
|
57
|
+
]);
|
|
58
|
+
compileTimeCheck([
|
|
59
|
+
'interpolate-hcl',
|
|
60
|
+
['linear'],
|
|
61
|
+
['line-progress'],
|
|
62
|
+
...colorStops
|
|
63
|
+
]);
|
|
64
|
+
compileTimeCheck([
|
|
65
|
+
'interpolate-lab',
|
|
66
|
+
['linear'],
|
|
67
|
+
['line-progress'],
|
|
68
|
+
...colorStops
|
|
69
|
+
]);
|
|
70
|
+
const [firstOutput, ...steps] = ['#df2d43', 50, '#df2d43', 200, '#df2d43'];
|
|
71
|
+
compileTimeCheck(['step', ['get', 'point_count'], firstOutput, ...steps]);
|
|
72
|
+
const strings = ['first', 'second', 'third'];
|
|
73
|
+
compileTimeCheck(['concat', ...strings]);
|
|
74
|
+
const values: (ExpressionInputType | ExpressionSpecification)[] = [['get', 'name'], ['get', 'code'], 'NONE']; // type is necessary!
|
|
75
|
+
compileTimeCheck(['coalesce', ...values]);
|
|
39
76
|
});
|
|
40
77
|
|
|
41
78
|
test('expression, zoom', () => {
|