maplibre-gl 3.2.0 → 3.2.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "maplibre-gl",
3
3
  "description": "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library",
4
- "version": "3.2.0",
4
+ "version": "3.2.1",
5
5
  "main": "dist/maplibre-gl.js",
6
6
  "style": "dist/maplibre-gl.css",
7
7
  "license": "BSD-3-Clause",
@@ -20,11 +20,12 @@
20
20
  "@mapbox/unitbezier": "^0.0.1",
21
21
  "@mapbox/vector-tile": "^1.3.1",
22
22
  "@mapbox/whoots-js": "^3.1.0",
23
- "@maplibre/maplibre-gl-style-spec": "^19.2.1",
23
+ "@maplibre/maplibre-gl-style-spec": "^19.2.2",
24
24
  "@types/geojson": "^7946.0.10",
25
25
  "@types/mapbox__point-geometry": "^0.1.2",
26
26
  "@types/mapbox__vector-tile": "^1.3.0",
27
27
  "@types/pbf": "^3.0.2",
28
+ "@types/supercluster": "^7.1.0",
28
29
  "earcut": "^2.2.4",
29
30
  "geojson-vt": "^3.2.1",
30
31
  "gl-matrix": "^3.4.3",
@@ -41,7 +42,7 @@
41
42
  "devDependencies": {
42
43
  "@mapbox/mapbox-gl-rtl-text": "^0.2.3",
43
44
  "@mapbox/mvt-fixtures": "^3.10.0",
44
- "@rollup/plugin-commonjs": "^25.0.2",
45
+ "@rollup/plugin-commonjs": "^25.0.3",
45
46
  "@rollup/plugin-json": "^6.0.0",
46
47
  "@rollup/plugin-node-resolve": "^15.1.0",
47
48
  "@rollup/plugin-replace": "^5.0.2",
@@ -53,49 +54,48 @@
53
54
  "@types/d3": "^7.4.0",
54
55
  "@types/diff": "^5.0.3",
55
56
  "@types/earcut": "^2.1.1",
56
- "@types/eslint": "^8.40.2",
57
+ "@types/eslint": "^8.44.0",
57
58
  "@types/gl": "^6.0.2",
58
59
  "@types/glob": "^8.1.0",
59
- "@types/jest": "^29.5.2",
60
+ "@types/jest": "^29.5.3",
60
61
  "@types/jsdom": "^21.1.1",
61
62
  "@types/minimist": "^1.2.2",
62
63
  "@types/murmurhash-js": "^1.0.4",
63
64
  "@types/nise": "^1.4.1",
64
- "@types/node": "^20.3.3",
65
+ "@types/node": "^20.4.4",
65
66
  "@types/offscreencanvas": "^2019.7.0",
66
67
  "@types/pixelmatch": "^5.2.4",
67
68
  "@types/pngjs": "^6.0.1",
68
- "@types/react": "^18.2.14",
69
- "@types/react-dom": "^18.2.6",
69
+ "@types/react": "^18.2.15",
70
+ "@types/react-dom": "^18.2.7",
70
71
  "@types/request": "^2.48.8",
71
72
  "@types/shuffle-seed": "^1.1.0",
72
- "@types/supercluster": "^7.1.0",
73
73
  "@types/window-or-global": "^1.0.4",
74
- "@typescript-eslint/eslint-plugin": "^5.60.1",
75
- "@typescript-eslint/parser": "^5.60.1",
74
+ "@typescript-eslint/eslint-plugin": "^5.61.0",
75
+ "@typescript-eslint/parser": "^5.62.0",
76
76
  "address": "^1.2.2",
77
77
  "benchmark": "^2.1.4",
78
78
  "canvas": "^2.11.2",
79
79
  "cssnano": "^6.0.1",
80
80
  "d3": "^7.8.5",
81
81
  "d3-queue": "^3.0.7",
82
- "devtools-protocol": "^0.0.1165014",
82
+ "devtools-protocol": "^0.0.1170846",
83
83
  "diff": "^5.1.0",
84
84
  "dts-bundle-generator": "^8.0.1",
85
- "eslint": "^8.44.0",
85
+ "eslint": "^8.45.0",
86
86
  "eslint-config-mourner": "^3.0.0",
87
87
  "eslint-plugin-html": "^7.1.0",
88
88
  "eslint-plugin-import": "^2.27.5",
89
- "eslint-plugin-jest": "^27.2.2",
89
+ "eslint-plugin-jest": "^27.2.3",
90
90
  "eslint-plugin-tsdoc": "0.2.17",
91
- "eslint-plugin-react": "^7.32.2",
91
+ "eslint-plugin-react": "^7.33.0",
92
92
  "expect": "^29.5.0",
93
93
  "gl": "^6.0.2",
94
- "glob": "^10.3.1",
94
+ "glob": "^10.3.3",
95
95
  "is-builtin-module": "^3.2.1",
96
- "jest": "^29.5.0",
96
+ "jest": "^29.6.1",
97
97
  "jest-canvas-mock": "^2.5.2",
98
- "jest-environment-jsdom": "^29.5.0",
98
+ "jest-environment-jsdom": "^29.6.1",
99
99
  "jsdom": "^22.1.0",
100
100
  "json-stringify-pretty-compact": "^4.0.0",
101
101
  "minimist": "^1.2.8",
@@ -107,22 +107,22 @@
107
107
  "pdf-merger-js": "^4.3.0",
108
108
  "pixelmatch": "^5.3.0",
109
109
  "pngjs": "^7.0.0",
110
- "postcss": "^8.4.24",
110
+ "postcss": "^8.4.26",
111
111
  "postcss-cli": "^10.1.0",
112
112
  "postcss-inline-svg": "^6.0.0",
113
- "pretty-bytes": "^6.1.0",
114
- "puppeteer": "^20.7.4",
113
+ "pretty-bytes": "^6.1.1",
114
+ "puppeteer": "^20.9.0",
115
115
  "react": "^18.2.0",
116
116
  "react-dom": "^18.2.0",
117
- "rollup": "^3.26.0",
117
+ "rollup": "^3.26.3",
118
118
  "rollup-plugin-sourcemaps": "^0.6.3",
119
119
  "rw": "^1.3.3",
120
- "semver": "^7.5.3",
120
+ "semver": "^7.5.4",
121
121
  "shuffle-seed": "^1.1.6",
122
122
  "source-map-explorer": "^2.5.3",
123
123
  "st": "^3.0.0",
124
- "stylelint": "^15.10.1",
125
- "stylelint-config-standard": "^33.0.0",
124
+ "stylelint": "^15.10.2",
125
+ "stylelint-config-standard": "^34.0.0",
126
126
  "ts-jest": "^29.1.1",
127
127
  "ts-node": "^10.9.1",
128
128
  "tslib": "^2.6.0",
@@ -406,13 +406,16 @@ describe('transform', () => {
406
406
  transform.resize(512, 512);
407
407
 
408
408
  // expect same values because of no elevation change
409
- transform.getElevation = () => 200;
410
- transform.recalculateZoom(null);
409
+ const terrain = {
410
+ getElevationForLngLatZoom: () => 200,
411
+ pointCoordinate: () => null
412
+ };
413
+ transform.recalculateZoom(terrain as any);
411
414
  expect(transform.zoom).toBe(14);
412
415
 
413
416
  // expect new zoom because of elevation change
414
- transform.getElevation = () => 400;
415
- transform.recalculateZoom(null);
417
+ terrain.getElevationForLngLatZoom = () => 400;
418
+ transform.recalculateZoom(terrain as any);
416
419
  expect(transform.zoom).toBe(14.127997275621933);
417
420
  expect(transform.elevation).toBe(400);
418
421
 
@@ -420,8 +423,8 @@ describe('transform', () => {
420
423
  expect(transform._center.lat).toBe(50.00000000000017);
421
424
 
422
425
  // expect new zoom because of elevation change to point below sea level
423
- transform.getElevation = () => -200;
424
- transform.recalculateZoom(null);
426
+ terrain.getElevationForLngLatZoom = () => -200;
427
+ transform.recalculateZoom(terrain as any);
425
428
  expect(transform.zoom).toBe(13.773740316343467);
426
429
  expect(transform.elevation).toBe(-200);
427
430
  });
@@ -458,14 +461,4 @@ describe('transform', () => {
458
461
  expect(top).toBeCloseTo(79.1823898251593, 10);
459
462
  expect(transform.getBounds().getNorthWest().toArray()).toStrictEqual(transform.pointLocation(new Point(0, top)).toArray());
460
463
  });
461
-
462
- test('getElevation with lng less than -180 wraps correctly', () => {
463
- const OVERSCALETILEID_DOES_NOT_THROW = 4;
464
- const terrain = {
465
- getElevation: () => OVERSCALETILEID_DOES_NOT_THROW
466
- } as any as Terrain;
467
- const transform = new Transform(0, 22, 0, 85, true);
468
- expect(transform.getElevation(new LngLat(-183, 40), terrain)).toBe(OVERSCALETILEID_DOES_NOT_THROW);
469
- });
470
-
471
464
  });
@@ -30,7 +30,6 @@ export class Transform {
30
30
  rotationMatrix: mat2;
31
31
  pixelsToGLUnits: [number, number];
32
32
  cameraToCenterDistance: number;
33
- cameraToSeaLevelDistance: number;
34
33
  mercatorMatrix: mat4;
35
34
  projMatrix: mat4;
36
35
  invProjMatrix: mat4;
@@ -40,7 +39,6 @@ export class Transform {
40
39
  pixelMatrixInverse: mat4;
41
40
  glCoordMatrix: mat4;
42
41
  labelPlaneMatrix: mat4;
43
- freezeElevation: boolean;
44
42
  _fov: number;
45
43
  _pitch: number;
46
44
  _zoom: number;
@@ -57,11 +55,11 @@ export class Transform {
57
55
  _constraining: boolean;
58
56
  _posMatrixCache: {[_: string]: mat4};
59
57
  _alignedPosMatrixCache: {[_: string]: mat4};
58
+ _minEleveationForCurrentTile: number;
60
59
 
61
60
  constructor(minZoom?: number, maxZoom?: number, minPitch?: number, maxPitch?: number, renderWorldCopies?: boolean) {
62
61
  this.tileSize = 512; // constant
63
62
  this.maxValidLatitude = 85.051129; // constant
64
- this.freezeElevation = false;
65
63
 
66
64
  this._renderWorldCopies = renderWorldCopies === undefined ? true : !!renderWorldCopies;
67
65
  this._minZoom = minZoom || 0;
@@ -84,6 +82,7 @@ export class Transform {
84
82
  this._edgeInsets = new EdgeInsets();
85
83
  this._posMatrixCache = {};
86
84
  this._alignedPosMatrixCache = {};
85
+ this._minEleveationForCurrentTile = 0;
87
86
  }
88
87
 
89
88
  clone(): Transform {
@@ -99,6 +98,7 @@ export class Transform {
99
98
  this.height = that.height;
100
99
  this._center = that._center;
101
100
  this._elevation = that._elevation;
101
+ this._minEleveationForCurrentTile = that._minEleveationForCurrentTile;
102
102
  this.zoom = that.zoom;
103
103
  this.angle = that.angle;
104
104
  this._fov = that._fov;
@@ -470,30 +470,6 @@ export class Transform {
470
470
 
471
471
  get point(): Point { return this.project(this.center); }
472
472
 
473
- /**
474
- * Updates the center-elevation value unless freezeElevation is activated.
475
- * @param terrain - the terrain
476
- */
477
- updateElevation(terrain?: Terrain) {
478
- if (this.freezeElevation) return;
479
- this.elevation = terrain ? this.getElevation(this._center, terrain) : 0;
480
- }
481
-
482
- /**
483
- * get the elevation from terrain for the current zoomlevel.
484
- * @param lnglat - the location
485
- * @param terrain - the terrain
486
- * @returns elevation in meters
487
- */
488
- getElevation(lnglat: LngLat, terrain: Terrain): number {
489
- const merc = MercatorCoordinate.fromLngLat(lnglat.wrap());
490
- const worldSize = (1 << this.tileZoom) * EXTENT;
491
- const mercX = merc.x * worldSize, mercY = merc.y * worldSize;
492
- const tileX = Math.floor(mercX / EXTENT), tileY = Math.floor(mercY / EXTENT);
493
- const tileID = new OverscaledTileID(this.tileZoom, 0, this.tileZoom, tileX, tileY);
494
- return terrain.getElevation(tileID, mercX % EXTENT, mercY % EXTENT, EXTENT);
495
- }
496
-
497
473
  /**
498
474
  * get the camera position in LngLat and altitudes in meter
499
475
  * @returns An object with lngLat & altitude.
@@ -516,7 +492,7 @@ export class Transform {
516
492
  recalculateZoom(terrain: Terrain) {
517
493
  // find position the camera is looking on
518
494
  const center = this.pointLocation(this.centerPoint, terrain);
519
- const elevation = this.getElevation(center, terrain);
495
+ const elevation = terrain.getElevationForLngLatZoom(center, this.tileZoom);
520
496
  const deltaElevation = this.elevation - elevation;
521
497
  if (!deltaElevation) return;
522
498
 
@@ -557,7 +533,7 @@ export class Transform {
557
533
  */
558
534
  locationPoint(lnglat: LngLat, terrain?: Terrain): Point {
559
535
  return terrain ?
560
- this.coordinatePoint(this.locationCoordinate(lnglat), this.getElevation(lnglat, terrain), this.pixelMatrix3D) :
536
+ this.coordinatePoint(this.locationCoordinate(lnglat), terrain.getElevationForLngLatZoom(lnglat, this.tileZoom), this.pixelMatrix3D) :
561
537
  this.coordinatePoint(this.locationCoordinate(lnglat));
562
538
  }
563
539
 
@@ -827,9 +803,11 @@ export class Transform {
827
803
  this.glCoordMatrix = m;
828
804
 
829
805
  // Calculate the camera to sea-level distance in pixel in respect of terrain
830
- // In case of negative elevation (e.g. the dead see) use the lower plane for calculation
831
- this.cameraToSeaLevelDistance = this.cameraToCenterDistance + this._elevation * this._pixelPerMeter / Math.cos(this._pitch);
832
- const lowestPlane = this._elevation < 0 ? this.cameraToCenterDistance : this.cameraToSeaLevelDistance;
806
+ const cameraToSeaLevelDistance = this.cameraToCenterDistance + this._elevation * this._pixelPerMeter / Math.cos(this._pitch);
807
+ // In case of negative minimum elevation (e.g. the dead see, under the sea maps) use a lower plane for calculation
808
+ const minElevation = Math.min(this.elevation, this._minEleveationForCurrentTile);
809
+ const cameraToLowestPointDistance = cameraToSeaLevelDistance - minElevation * this._pixelPerMeter / Math.cos(this._pitch);
810
+ const lowestPlane = minElevation < 0 ? cameraToLowestPointDistance : cameraToSeaLevelDistance;
833
811
 
834
812
  // Find the distance from the center point [width/2 + offset.x, height/2 + offset.y] to the
835
813
  // center top point [width/2 + offset.x, 0] in Z units, using the law of sines.
@@ -28,7 +28,7 @@ describe('drawFill', () => {
28
28
  const painterMock: Painter = constructMockPainer();
29
29
  const layer: FillStyleLayer = constructMockLayer();
30
30
 
31
- const programMock = new Program(null as any, null as any, null as any, null as any, null as any, null as any, null as any);
31
+ const programMock = new Program(null as any, null as any, null as any, null as any, null as any, null as any);
32
32
  (painterMock.useProgram as jest.Mock).mockReturnValue(programMock);
33
33
 
34
34
  const mockTile = constructMockTile(layer);
@@ -62,7 +62,7 @@ describe('drawSymbol', () => {
62
62
 
63
63
  const tileId = new OverscaledTileID(1, 0, 1, 0, 0);
64
64
  tileId.posMatrix = mat4.create();
65
- const programMock = new Program(null, null, null, null, null, null, null);
65
+ const programMock = new Program(null, null, null, null, null, null);
66
66
  (painterMock.useProgram as jest.Mock).mockReturnValue(programMock);
67
67
  const bucketMock = new SymbolBucket(null);
68
68
  bucketMock.icon = {
@@ -124,7 +124,7 @@ describe('drawSymbol', () => {
124
124
 
125
125
  const tileId = new OverscaledTileID(1, 0, 1, 0, 0);
126
126
  tileId.posMatrix = mat4.create();
127
- const programMock = new Program(null, null, null, null, null, null, null);
127
+ const programMock = new Program(null, null, null, null, null, null);
128
128
  (painterMock.useProgram as jest.Mock).mockReturnValue(programMock);
129
129
  const bucketMock = new SymbolBucket(null);
130
130
  bucketMock.icon = {
@@ -189,7 +189,7 @@ describe('drawSymbol', () => {
189
189
 
190
190
  const tileId = new OverscaledTileID(1, 0, 1, 0, 0);
191
191
  tileId.posMatrix = mat4.create();
192
- const programMock = new Program(null, null, null, null, null, null, null);
192
+ const programMock = new Program(null, null, null, null, null, null);
193
193
  (painterMock.useProgram as jest.Mock).mockReturnValue(programMock);
194
194
  const bucketMock = new SymbolBucket(null);
195
195
  bucketMock.icon = {
@@ -574,7 +574,6 @@ export class Painter {
574
574
  if (!this.cache[key]) {
575
575
  this.cache[key] = new Program(
576
576
  this.context,
577
- name,
578
577
  shaders[name],
579
578
  programConfiguration,
580
579
  programUniforms[name],
@@ -42,7 +42,6 @@ export class Program<Us extends UniformBindings> {
42
42
  failedToCreate: boolean;
43
43
 
44
44
  constructor(context: Context,
45
- name: string,
46
45
  source: {
47
46
  fragmentSource: string;
48
47
  vertexSource: string;
@@ -11,6 +11,7 @@ import type {DEMData} from '../data/dem_data';
11
11
  import {Tile} from '../source/tile';
12
12
  import {Painter} from './painter';
13
13
  import {mat4} from 'gl-matrix';
14
+ import {LngLat} from '../geo/lng_lat';
14
15
 
15
16
  describe('Terrain', () => {
16
17
  test('pointCoordiate should not return null', () => {
@@ -193,4 +194,20 @@ describe('Terrain', () => {
193
194
  expect(mockTerrain.getDEMElevation(null, 0.4, 0.2)).toBeCloseTo(42);
194
195
  });
195
196
 
197
+ test('getElevationForLngLatZoom with lng less than -180 wraps correctly', () => {
198
+ const terrain = new Terrain(null, {} as any, {} as any);
199
+
200
+ const OVERSCALETILEID_DOES_NOT_THROW = 4;
201
+ terrain.getElevation = () => OVERSCALETILEID_DOES_NOT_THROW;
202
+ expect(terrain.getElevationForLngLatZoom(new LngLat(-183, 40), 0)).toBe(OVERSCALETILEID_DOES_NOT_THROW);
203
+ });
204
+
205
+ test('getMinTileElevationForLngLatZoom with lng less than -180 wraps correctly', () => {
206
+ const terrain = new Terrain(null, {} as any, {} as any);
207
+
208
+ const OVERSCALETILEID_DOES_NOT_THROW = 4;
209
+ terrain.getMinMaxElevation = () => ({minElevation: OVERSCALETILEID_DOES_NOT_THROW, maxElevation: 42});
210
+ expect(terrain.getMinTileElevationForLngLatZoom(new LngLat(-183, 40), 0)).toBe(OVERSCALETILEID_DOES_NOT_THROW);
211
+ });
212
+
196
213
  });
@@ -18,7 +18,7 @@ import {TerrainSourceCache} from '../source/terrain_source_cache';
18
18
  import {SourceCache} from '../source/source_cache';
19
19
  import {EXTENT} from '../data/extent';
20
20
  import type {TerrainSpecification} from '@maplibre/maplibre-gl-style-spec';
21
- import {earthRadius} from '../geo/lng_lat';
21
+ import {LngLat, earthRadius} from '../geo/lng_lat';
22
22
 
23
23
  /**
24
24
  * A terrain GPU related object
@@ -180,7 +180,18 @@ export class Terrain {
180
180
  }
181
181
 
182
182
  /**
183
- * get the Elevation for given coordinate in respect of exaggeration.
183
+ * Get the elevation for given {@link LngLat} in respect of exaggeration.
184
+ * @param lnglat - the location
185
+ * @param zoom - the zoom
186
+ * @returns the elevation
187
+ */
188
+ getElevationForLngLatZoom(lnglat: LngLat, zoom: number) {
189
+ const {tileID, mercatorX, mercatorY} = this._getOverscaledTileIDFromLngLatZoom(lnglat, zoom);
190
+ return this.getElevation(tileID, mercatorX % EXTENT, mercatorY % EXTENT, EXTENT);
191
+ }
192
+
193
+ /**
194
+ * Get the elevation for given coordinate in respect of exaggeration.
184
195
  * @param tileID - the tile id
185
196
  * @param x - between 0 .. EXTENT
186
197
  * @param y - between 0 .. EXTENT
@@ -391,6 +402,11 @@ export class Terrain {
391
402
  return 2 * Math.PI * earthRadius / Math.pow(2, zoom) / 5;
392
403
  }
393
404
 
405
+ getMinTileElevationForLngLatZoom(lnglat: LngLat, zoom: number) {
406
+ const {tileID} = this._getOverscaledTileIDFromLngLatZoom(lnglat, zoom);
407
+ return this.getMinMaxElevation(tileID).minElevation ?? 0;
408
+ }
409
+
394
410
  /**
395
411
  * Get the minimum and maximum elevation contained in a tile. This includes any
396
412
  * exaggeration included in the terrain.
@@ -409,4 +425,17 @@ export class Terrain {
409
425
  return minMax;
410
426
  }
411
427
 
428
+ _getOverscaledTileIDFromLngLatZoom(lnglat: LngLat, zoom: number): { tileID: OverscaledTileID; mercatorX: number; mercatorY: number} {
429
+ const mercatorCoordinate = MercatorCoordinate.fromLngLat(lnglat.wrap());
430
+ const worldSize = (1 << zoom) * EXTENT;
431
+ const mercatorX = mercatorCoordinate.x * worldSize;
432
+ const mercatorY = mercatorCoordinate.y * worldSize;
433
+ const tileX = Math.floor(mercatorX / EXTENT), tileY = Math.floor(mercatorY / EXTENT);
434
+ const tileID = new OverscaledTileID(zoom, 0, zoom, tileX, tileY);
435
+ return {
436
+ tileID,
437
+ mercatorX,
438
+ mercatorY
439
+ };
440
+ }
412
441
  }
@@ -150,4 +150,18 @@ describe('RasterTileSource', () => {
150
150
  });
151
151
  server.respond();
152
152
  });
153
+
154
+ it('serializes options', () => {
155
+ const source = createSource({
156
+ tiles: ['http://localhost:2900/raster-dem/{z}/{x}/{y}.png'],
157
+ minzoom: 2,
158
+ maxzoom: 10
159
+ });
160
+ expect(source.serialize()).toStrictEqual({
161
+ type: 'raster-dem',
162
+ tiles: ['http://localhost:2900/raster-dem/{z}/{x}/{y}.png'],
163
+ minzoom: 2,
164
+ maxzoom: 10
165
+ });
166
+ });
153
167
  });
@@ -43,17 +43,6 @@ export class RasterDEMTileSource extends RasterTileSource implements Source {
43
43
  this.encoding = options.encoding || 'mapbox';
44
44
  }
45
45
 
46
- serialize() {
47
- return {
48
- type: 'raster-dem',
49
- url: this.url,
50
- tileSize: this.tileSize,
51
- tiles: this.tiles,
52
- bounds: this.bounds,
53
- encoding: this.encoding
54
- };
55
- }
56
-
57
46
  loadTile(tile: Tile, callback: Callback<void>) {
58
47
  const url = tile.tileID.canonical.url(this.tiles, this.map.getPixelRatio(), this.scheme);
59
48
  tile.request = ImageRequest.getImage(this.map._requestManager.transformRequest(url, ResourceType.Tile), imageLoaded.bind(this), this.map._refreshExpiredTiles);
@@ -170,4 +170,17 @@ describe('RasterTileSource', () => {
170
170
  expect((server.requests.pop() as any).aborted).toBe(true);
171
171
  });
172
172
 
173
+ it('serializes options', () => {
174
+ const source = createSource({
175
+ tiles: ['http://localhost:2900/raster/{z}/{x}/{y}.png'],
176
+ minzoom: 2,
177
+ maxzoom: 10
178
+ });
179
+ expect(source.serialize()).toStrictEqual({
180
+ type: 'raster',
181
+ tiles: ['http://localhost:2900/raster/{z}/{x}/{y}.png'],
182
+ minzoom: 2,
183
+ maxzoom: 10
184
+ });
185
+ });
173
186
  });
@@ -6,7 +6,7 @@ import {VectorTileWorkerSource} from '../source/vector_tile_worker_source';
6
6
  import {StyleLayerIndex} from '../style/style_layer_index';
7
7
  import {fakeServer, FakeServer} from 'nise';
8
8
  import {Actor} from '../util/actor';
9
- import {TileParameters, WorkerTileParameters} from './worker_source';
9
+ import {TileParameters, WorkerTileParameters, WorkerTileResult} from './worker_source';
10
10
  import {WorkerTile} from './worker_tile';
11
11
  import {setPerformance} from '../util/test/util';
12
12
 
@@ -18,7 +18,6 @@ describe('vector tile worker source', () => {
18
18
  global.fetch = null;
19
19
  server = fakeServer.create();
20
20
  setPerformance();
21
-
22
21
  });
23
22
 
24
23
  afterEach(() => {
@@ -87,83 +86,54 @@ describe('vector tile worker source', () => {
87
86
  expect(callback).toHaveBeenCalledTimes(1);
88
87
  });
89
88
 
90
- test('VectorTileWorkerSource#reloadTile queues a reload when parsing is in progress', () => {
91
- const source = new VectorTileWorkerSource(actor, new StyleLayerIndex(), []);
92
- const parse = jest.fn();
93
-
94
- source.loaded = {
95
- '0': {
96
- status: 'done',
97
- vectorTile: {},
98
- parse
99
- } as any as WorkerTile
100
- };
101
-
102
- const callback1 = jest.fn();
103
- const callback2 = jest.fn();
104
- source.reloadTile({uid: 0} as any as WorkerTileParameters, callback1);
105
- expect(parse).toHaveBeenCalledTimes(1);
106
-
107
- source.loaded[0].status = 'parsing';
108
- source.reloadTile({uid: 0} as any as WorkerTileParameters, callback2);
109
- expect(parse).toHaveBeenCalledTimes(1);
110
-
111
- parse.mock.calls[0][4]();
112
- expect(parse).toHaveBeenCalledTimes(2);
113
- expect(callback1).toHaveBeenCalledTimes(1);
114
- expect(callback2).toHaveBeenCalledTimes(0);
115
-
116
- parse.mock.calls[1][4]();
117
- expect(callback1).toHaveBeenCalledTimes(1);
118
- expect(callback2).toHaveBeenCalledTimes(1);
119
- });
120
-
121
- test('VectorTileWorkerSource#reloadTile handles multiple pending reloads', () => {
122
- // https://github.com/mapbox/mapbox-gl-js/issues/6308
123
- const source = new VectorTileWorkerSource(actor, new StyleLayerIndex(), []);
124
- const parse = jest.fn();
89
+ test('VectorTileWorkerSource#loadTile reparses tile if the reloadTile has been called during parsing', (done) => {
90
+ const rawTileData = new Uint8Array([]);
91
+ function loadVectorData(params, callback) {
92
+ return callback(null, {
93
+ vectorTile: new vt.VectorTile(new Protobuf(rawTileData)),
94
+ rawData: rawTileData
95
+ });
96
+ }
125
97
 
126
- source.loaded = {
127
- '0': {
128
- status: 'done',
129
- vectorTile: {},
130
- parse
131
- } as any as WorkerTile
132
- };
98
+ const layerIndex = new StyleLayerIndex([{
99
+ id: 'test',
100
+ source: 'source',
101
+ 'source-layer': 'test',
102
+ type: 'fill'
103
+ }]);
133
104
 
134
- const callback1 = jest.fn();
135
- const callback2 = jest.fn();
136
- const callback3 = jest.fn();
137
- source.reloadTile({uid: 0} as any as WorkerTileParameters, callback1);
138
- expect(parse).toHaveBeenCalledTimes(1);
105
+ const source = new VectorTileWorkerSource(actor, layerIndex, [], loadVectorData);
139
106
 
140
- source.loaded[0].status = 'parsing';
141
- source.reloadTile({uid: 0} as any as WorkerTileParameters, callback2);
142
- expect(parse).toHaveBeenCalledTimes(1);
107
+ const parseWorkerTileMock = jest
108
+ .spyOn(WorkerTile.prototype, 'parse')
109
+ .mockImplementation(function(data, layerIndex, availableImages, actor, callback) {
110
+ this.status = 'parsing';
111
+ window.setTimeout(() => callback(null, {} as WorkerTileResult), 10);
112
+ });
143
113
 
144
- parse.mock.calls[0][4]();
145
- expect(parse).toHaveBeenCalledTimes(2);
146
- expect(callback1).toHaveBeenCalledTimes(1);
147
- expect(callback2).toHaveBeenCalledTimes(0);
148
- expect(callback3).toHaveBeenCalledTimes(0);
149
-
150
- source.reloadTile({uid: 0} as any as WorkerTileParameters, callback3);
151
- expect(parse).toHaveBeenCalledTimes(2);
152
- expect(callback1).toHaveBeenCalledTimes(1);
153
- expect(callback2).toHaveBeenCalledTimes(0);
154
- expect(callback3).toHaveBeenCalledTimes(0);
155
-
156
- parse.mock.calls[1][4]();
157
- expect(parse).toHaveBeenCalledTimes(3);
158
- expect(callback1).toHaveBeenCalledTimes(1);
159
- expect(callback2).toHaveBeenCalledTimes(1);
160
- expect(callback3).toHaveBeenCalledTimes(0);
161
-
162
- parse.mock.calls[2][4]();
163
- expect(callback1).toHaveBeenCalledTimes(1);
164
- expect(callback2).toHaveBeenCalledTimes(1);
165
- expect(callback3).toHaveBeenCalledTimes(1);
114
+ let loadCallbackCalled = false;
115
+ source.loadTile({
116
+ source: 'source',
117
+ uid: 0,
118
+ tileID: {overscaledZ: 0, wrap: 0, canonical: {x: 0, y: 0, z: 0, w: 0}},
119
+ request: {url: 'http://localhost:2900/faketile.pbf'}
120
+ } as any as WorkerTileParameters, (err, res) => {
121
+ expect(err).toBeFalsy();
122
+ expect(res).toBeDefined();
123
+ loadCallbackCalled = true;
124
+ });
166
125
 
126
+ source.reloadTile({
127
+ source: 'source',
128
+ uid: '0',
129
+ tileID: {overscaledZ: 0, wrap: 0, canonical: {x: 0, y: 0, z: 0, w: 0}},
130
+ } as any as WorkerTileParameters, (err, res) => {
131
+ expect(err).toBeFalsy();
132
+ expect(res).toBeDefined();
133
+ expect(parseWorkerTileMock).toHaveBeenCalledTimes(2);
134
+ expect(loadCallbackCalled).toBeTruthy();
135
+ done();
136
+ });
167
137
  });
168
138
 
169
139
  test('VectorTileWorkerSource#reloadTile does not reparse tiles with no vectorTile data but does call callback', () => {