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.
Files changed (78) hide show
  1. package/build/generate-query-test-fixtures.ts +3 -2
  2. package/build/generate-struct-arrays.ts +0 -2
  3. package/build/generate-style-spec.ts +12 -17
  4. package/build/generate-typings.ts +11 -1
  5. package/build/rollup_plugins.ts +0 -4
  6. package/dist/maplibre-gl-csp-worker.js +1 -1
  7. package/dist/maplibre-gl-csp.js +1 -1
  8. package/dist/maplibre-gl-dev.js +376 -1402
  9. package/dist/maplibre-gl.d.ts +13 -16
  10. package/dist/maplibre-gl.js +4 -4
  11. package/dist/style-spec/index.d.ts +1768 -0
  12. package/package.json +14 -16
  13. package/src/data/array_types.g.ts +0 -5
  14. package/src/data/bucket/fill_bucket.ts +0 -2
  15. package/src/data/bucket/fill_extrusion_bucket.ts +0 -2
  16. package/src/data/bucket/symbol_bucket.test.ts +30 -19
  17. package/src/data/feature_position_map.ts +1 -2
  18. package/src/gl/framebuffer.ts +3 -2
  19. package/src/gl/index_buffer.ts +1 -2
  20. package/src/gl/vertex_buffer.ts +1 -2
  21. package/src/index.test.ts +9 -0
  22. package/src/index.ts +12 -4
  23. package/src/render/image_manager.ts +5 -7
  24. package/src/render/program/pattern.ts +0 -2
  25. package/src/render/program.ts +12 -9
  26. package/src/render/vertex_array_object.ts +1 -3
  27. package/src/source/geojson_worker_source.ts +0 -4
  28. package/src/source/query_features.ts +0 -3
  29. package/src/source/rtl_text_plugin.ts +3 -4
  30. package/src/source/source_cache.ts +0 -2
  31. package/src/source/tile_id.ts +8 -8
  32. package/src/source/worker.ts +0 -7
  33. package/src/source/worker_tile.ts +12 -3
  34. package/src/style/format_section_override.ts +1 -2
  35. package/src/style/properties.ts +1 -3
  36. package/src/style/style.ts +5 -5
  37. package/src/style/style_layer/custom_style_layer.ts +1 -2
  38. package/src/style/style_layer/symbol_style_layer.ts +1 -3
  39. package/src/style-spec/CHANGELOG.md +10 -0
  40. package/src/style-spec/composite.test.ts +7 -8
  41. package/src/style-spec/expression/compound_expression.ts +0 -4
  42. package/src/style-spec/expression/definitions/assertion.ts +2 -4
  43. package/src/style-spec/expression/definitions/case.ts +1 -2
  44. package/src/style-spec/expression/definitions/coalesce.ts +1 -3
  45. package/src/style-spec/expression/definitions/coercion.ts +2 -4
  46. package/src/style-spec/expression/definitions/match.ts +0 -3
  47. package/src/style-spec/expression/index.ts +13 -15
  48. package/src/style-spec/expression/parsing_context.ts +4 -4
  49. package/src/style-spec/expression/parsing_error.ts +2 -2
  50. package/src/style-spec/expression/values.ts +0 -2
  51. package/src/style-spec/feature_filter/feature_filter.test.ts +39 -2
  52. package/src/style-spec/function/convert.ts +1 -3
  53. package/src/style-spec/migrate/v8.test.ts +12 -14
  54. package/src/style-spec/migrate/v9.test.ts +2 -4
  55. package/src/style-spec/migrate.test.ts +6 -8
  56. package/src/style-spec/package.json +2 -1
  57. package/src/style-spec/types.g.ts +12 -17
  58. package/src/symbol/collision_index.ts +0 -3
  59. package/src/symbol/path_interpolator.ts +0 -2
  60. package/src/symbol/placement.ts +14 -9
  61. package/src/symbol/shaping.ts +0 -4
  62. package/src/symbol/symbol_layout.ts +56 -56
  63. package/src/ui/camera.ts +0 -10
  64. package/src/ui/control/geolocate_control.ts +4 -6
  65. package/src/ui/handler/handler_util.ts +1 -2
  66. package/src/ui/handler/scroll_zoom.ts +0 -2
  67. package/src/ui/handler_manager.ts +0 -2
  68. package/src/ui/map.test.ts +11 -0
  69. package/src/ui/map.ts +11 -0
  70. package/src/util/ajax.ts +1 -2
  71. package/src/util/color_ramp.ts +1 -2
  72. package/src/util/dictionary_coder.ts +1 -3
  73. package/src/util/dispatcher.ts +1 -4
  74. package/src/util/dom.ts +0 -3
  75. package/src/util/image.ts +1 -3
  76. package/src/util/struct_array.ts +0 -5
  77. package/src/util/task_queue.ts +1 -3
  78. package/src/util/web_worker_transfer.ts +5 -6
@@ -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
- assert(z >= 0 && z <= 25);
18
- assert(x >= 0 && x < Math.pow(2, z));
19
- assert(y >= 0 && y < Math.pow(2, z));
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
- assert(overscaledZ >= z);
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
- assert(targetZ <= this.overscaledZ);
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
- assert(targetZ <= this.overscaledZ);
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);
@@ -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
- assert(layer.source === this.source);
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(bucket, glyphMap, glyphAtlas.positions, iconMap, imageAtlas.iconPositions, this.showCollisionBoxes, this.tileID.canonical);
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
- assert(defaultValue.property.overrides !== undefined);
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
  }
@@ -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
- assert(!value.isDataDriven());
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)),
@@ -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
- assert(action === 'reload' || action === 'clear');
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
- assert(this.sourceCaches[id] !== undefined, 'There is no source with this ID');
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
- assert(geojsonSource.type === 'geojson');
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
- assert(false, 'Custom layers cannot be serialized');
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
- assert(false); // Should take a different path in FeatureIndex
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
- assert(types[name], name);
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
- assert(false);
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
- assert(outputType);
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
- assert(outputType);
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
- assert(types[name], name);
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 ParsingError from './parsing_error';
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<ParsingError>> {
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<ParsingError>> {
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 ParsingError('', 'data expressions not supported')]);
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 ParsingError('', 'zoom expressions not supported')]);
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 ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.')]);
311
- } else if (zoomCurve instanceof ParsingError) {
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 ParsingError('', '"interpolate" expressions cannot be used with this property')]);
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 | ParsingError | null {
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 ParsingError) {
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 ParsingError) {
421
+ if (childResult instanceof ExpressionParsingError) {
424
422
  result = childResult;
425
423
  } else if (!result && childResult) {
426
- result = new ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.');
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 ParsingError('', 'Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.');
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 ParsingError from './parsing_error';
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<ParsingError>;
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<ParsingError> = []
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 ParsingError(key, error));
186
+ this.errors.push(new ExpressionParsingError(key, error));
187
187
  }
188
188
 
189
189
  /**
@@ -1,4 +1,4 @@
1
- class ParsingError extends Error {
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 ParsingError;
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('exprssions transpilation 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', () => {