@mapwhit/tilerenderer 0.47.1 → 0.48.0

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 (76) hide show
  1. package/build/min/package.json +1 -1
  2. package/package.json +1 -2
  3. package/src/data/array_types.js +1 -1
  4. package/src/data/bucket/circle_bucket.js +1 -1
  5. package/src/data/bucket/fill_bucket.js +1 -1
  6. package/src/data/bucket/fill_extrusion_bucket.js +1 -1
  7. package/src/data/bucket/heatmap_bucket.js +1 -1
  8. package/src/data/bucket/line_bucket.js +1 -1
  9. package/src/data/bucket/symbol_bucket.js +26 -12
  10. package/src/data/dem_data.js +1 -1
  11. package/src/data/feature_index.js +43 -82
  12. package/src/data/program_configuration.js +19 -11
  13. package/src/data/segment.js +2 -2
  14. package/src/geo/transform.js +4 -2
  15. package/src/gl/color_mode.js +6 -6
  16. package/src/index.js +3 -1
  17. package/src/render/glyph_atlas.js +1 -1
  18. package/src/render/glyph_manager.js +43 -48
  19. package/src/render/image_atlas.js +1 -1
  20. package/src/render/image_manager.js +9 -37
  21. package/src/source/geojson_source.js +49 -93
  22. package/src/source/geojson_worker_source.js +33 -134
  23. package/src/source/image_source.js +9 -14
  24. package/src/source/load_tilejson.js +27 -34
  25. package/src/source/raster_dem_tile_source.js +27 -40
  26. package/src/source/raster_tile_source.js +53 -62
  27. package/src/source/rtl_text_plugin.js +3 -1
  28. package/src/source/source_cache.js +23 -21
  29. package/src/source/source_state.js +17 -26
  30. package/src/source/tile.js +6 -5
  31. package/src/source/tile_id.js +1 -1
  32. package/src/source/vector_tile_source.js +56 -73
  33. package/src/source/vector_tile_worker_source.js +20 -85
  34. package/src/source/worker.js +37 -103
  35. package/src/source/worker_tile.js +39 -84
  36. package/src/style/load_sprite.js +14 -17
  37. package/src/style/properties.js +1 -1
  38. package/src/style/style.js +22 -37
  39. package/src/style/style_layer/symbol_style_layer_properties.js +1 -1
  40. package/src/style/style_layer_index.js +17 -23
  41. package/src/style-spec/expression/compound_expression.js +30 -16
  42. package/src/style-spec/expression/definitions/coercion.js +13 -0
  43. package/src/style-spec/expression/definitions/comparison.js +193 -0
  44. package/src/style-spec/expression/definitions/formatted.js +123 -0
  45. package/src/style-spec/expression/definitions/index.js +10 -60
  46. package/src/style-spec/expression/definitions/interpolate.js +17 -7
  47. package/src/style-spec/expression/definitions/literal.js +5 -0
  48. package/src/style-spec/expression/parsing_context.js +4 -0
  49. package/src/style-spec/expression/types.js +12 -1
  50. package/src/style-spec/feature_filter/index.js +1 -1
  51. package/src/style-spec/reference/v8.json +120 -49
  52. package/src/symbol/anchor.js +1 -1
  53. package/src/symbol/collision_index.js +23 -16
  54. package/src/symbol/get_anchors.js +11 -22
  55. package/src/symbol/grid_index.js +176 -182
  56. package/src/symbol/mergelines.js +51 -48
  57. package/src/symbol/opacity_state.js +1 -1
  58. package/src/symbol/placement.js +8 -2
  59. package/src/symbol/quads.js +7 -6
  60. package/src/symbol/shaping.js +185 -40
  61. package/src/symbol/symbol_layout.js +9 -6
  62. package/src/symbol/transform_text.js +12 -1
  63. package/src/ui/camera.js +82 -85
  64. package/src/ui/map.js +13 -57
  65. package/src/util/actor.js +46 -42
  66. package/src/util/browser.js +6 -0
  67. package/src/util/dictionary_coder.js +13 -21
  68. package/src/util/dispatcher.js +14 -17
  69. package/src/util/image.js +1 -1
  70. package/src/util/loader/image.js +11 -11
  71. package/src/util/polyfill.js +16 -0
  72. package/src/util/task_queue.js +39 -43
  73. package/src/util/transfer_registry.js +167 -0
  74. package/src/util/web_worker_transfer.js +5 -190
  75. package/src/source/raster_dem_tile_worker_source.js +0 -26
  76. package/src/style-spec/expression/definitions/equals.js +0 -93
@@ -1,19 +1,18 @@
1
- const vt = require('@mapbox/vector-tile');
1
+ const { VectorTile } = require('@mapbox/vector-tile');
2
2
  const Protobuf = require('@mapwhit/pbf');
3
3
  const WorkerTile = require('./worker_tile');
4
4
 
5
- function loadVectorTile(params, callback) {
5
+ function loadVectorTile(params) {
6
6
  if (!params.response) {
7
- return callback(new Error('no tile data'));
7
+ throw new Error('no tile data');
8
8
  }
9
9
  const { data } = params.response;
10
10
  if (!data) {
11
- return callback();
11
+ return;
12
12
  }
13
- callback(null, {
14
- vectorTile: new vt.VectorTile(new Protobuf(data)),
15
- rawData: data
16
- });
13
+ return {
14
+ vectorTile: new VectorTile(new Protobuf(data))
15
+ };
17
16
  }
18
17
 
19
18
  /**
@@ -32,11 +31,10 @@ class VectorTileWorkerSource {
32
31
  * {@link VectorTileWorkerSource#loadTile}. The default implementation simply
33
32
  * loads the pbf at `params.url`.
34
33
  */
35
- constructor(actor, layerIndex, loadVectorData) {
34
+ constructor(actor, layerIndex, loadVectorData = loadVectorTile) {
36
35
  this.actor = actor;
37
36
  this.layerIndex = layerIndex;
38
- this.loadVectorData = loadVectorData || loadVectorTile.bind(this);
39
- this.loaded = {};
37
+ this.loadVectorData = loadVectorData;
40
38
  }
41
39
 
42
40
  /**
@@ -44,83 +42,20 @@ class VectorTileWorkerSource {
44
42
  * {@link VectorTileWorkerSource#loadVectorData} (which by default expects
45
43
  * a `params.url` property) for fetching and producing a VectorTile object.
46
44
  */
47
- loadTile(params, callback) {
48
- const uid = params.uid;
49
-
50
- const workerTile = new WorkerTile(params);
51
- this.loadVectorData(params, (err, response) => {
52
- if (err || !response) {
53
- return callback(err);
54
- }
55
-
56
- const rawTileData = response.rawData;
57
- workerTile.vectorTile = response.vectorTile;
58
- workerTile.parse(response.vectorTile, this.layerIndex, this.actor, (err, result) => {
59
- if (err || !result) return callback(err);
60
-
61
- // Transferring a copy of rawTileData because the worker needs to retain its copy.
62
- callback(null, Object.assign({ rawTileData: rawTileData.slice(0) }, result));
63
- });
64
-
65
- this.loaded = this.loaded || {};
66
- this.loaded[uid] = workerTile;
67
- });
68
- }
69
-
70
- /**
71
- * Implements {@link WorkerSource#reloadTile}.
72
- */
73
- reloadTile(params, callback) {
74
- const loaded = this.loaded;
75
- const uid = params.uid;
76
- const vtSource = this;
77
- if (loaded?.[uid]) {
78
- const workerTile = loaded[uid];
79
- workerTile.showCollisionBoxes = params.showCollisionBoxes;
80
-
81
- const done = (err, data) => {
82
- const reloadCallback = workerTile.reloadCallback;
83
- if (reloadCallback) {
84
- delete workerTile.reloadCallback;
85
- workerTile.parse(workerTile.vectorTile, vtSource.layerIndex, vtSource.actor, reloadCallback);
86
- }
87
- callback(err, data);
88
- };
89
-
90
- if (workerTile.status === 'parsing') {
91
- workerTile.reloadCallback = done;
92
- } else if (workerTile.status === 'done') {
93
- workerTile.parse(workerTile.vectorTile, this.layerIndex, this.actor, done);
94
- }
45
+ async loadTile(params) {
46
+ const response = this.loadVectorData(params);
47
+ if (!response) {
48
+ return;
95
49
  }
96
- }
97
-
98
- /**
99
- * Implements {@link WorkerSource#abortTile}.
100
- *
101
- * @param params
102
- * @param params.uid The UID for this tile.
103
- */
104
- abortTile(params, callback) {
105
- callback();
106
- }
107
-
108
- /**
109
- * Implements {@link WorkerSource#removeTile}.
110
- *
111
- * @param params
112
- * @param params.uid The UID for this tile.
113
- */
114
- removeTile(params, callback) {
115
- const loaded = this.loaded;
116
- const uid = params.uid;
117
- if (loaded?.[uid]) {
118
- delete loaded[uid];
50
+ const { vectorTile, rawData } = response;
51
+ const workerTile = new WorkerTile(params);
52
+ workerTile.vectorTile = vectorTile;
53
+ const result = await workerTile.parse(vectorTile, this.layerIndex, this.actor);
54
+ if (rawData) {
55
+ result.rawTileData = rawData;
119
56
  }
120
- callback();
57
+ return result;
121
58
  }
122
-
123
- updateConfig() {}
124
59
  }
125
60
 
126
61
  module.exports = VectorTileWorkerSource;
@@ -1,20 +1,20 @@
1
+ require('../util/polyfill');
2
+
1
3
  const Actor = require('../util/actor');
2
4
 
3
5
  const StyleLayerIndex = require('../style/style_layer_index');
4
6
  const VectorTileWorkerSource = require('./vector_tile_worker_source');
5
- const RasterDEMTileWorkerSource = require('./raster_dem_tile_worker_source');
6
7
  const GeoJSONWorkerSource = require('./geojson_worker_source');
7
8
  const assert = require('assert');
8
9
  const { plugin: globalRTLTextPlugin } = require('./rtl_text_plugin');
10
+ const DEMData = require('../data/dem_data');
9
11
 
10
- /**
11
- * @private
12
- */
13
12
  class Worker {
14
13
  constructor(self) {
15
14
  this.self = self;
16
15
  this.actor = new Actor(self, this);
17
16
 
17
+ this.actors = {};
18
18
  this.layerIndexes = {};
19
19
 
20
20
  this.workerSourceTypes = {
@@ -24,7 +24,6 @@ class Worker {
24
24
 
25
25
  // [mapId][sourceType][sourceName] => worker source instance
26
26
  this.workerSources = {};
27
- this.demWorkerSources = {};
28
27
 
29
28
  this.self.registerWorkerSource = (name, WorkerSource) => {
30
29
  if (this.workerSourceTypes[name]) {
@@ -39,134 +38,69 @@ class Worker {
39
38
  }
40
39
  globalRTLTextPlugin['applyArabicShaping'] = rtlTextPlugin.applyArabicShaping;
41
40
  globalRTLTextPlugin['processBidirectionalText'] = rtlTextPlugin.processBidirectionalText;
41
+ globalRTLTextPlugin['processStyledBidirectionalText'] = rtlTextPlugin.processStyledBidirectionalText;
42
42
  };
43
43
  }
44
44
 
45
- setLayers(mapId, layers, callback) {
45
+ setLayers(mapId, layers) {
46
46
  this.getLayerIndex(mapId).replace(layers);
47
- callback();
48
47
  }
49
48
 
50
- updateLayers(mapId, params, callback) {
49
+ updateLayers(mapId, params) {
51
50
  this.getLayerIndex(mapId).update(params.layers, params.removedIds);
52
- callback();
53
51
  }
54
52
 
55
- loadTile(mapId, params, callback) {
53
+ loadTile(mapId, params) {
56
54
  assert(params.type);
57
- this.getWorkerSource(mapId, params.type, params.source).loadTile(params, callback);
55
+ return this.getWorkerSource(mapId, params.type, params.source).loadTile(params);
58
56
  }
59
57
 
60
- loadDEMTile(mapId, params, callback) {
61
- this.getDEMWorkerSource(mapId, params.source).loadTile(params, callback);
58
+ loadDEMTile(mapId, params) {
59
+ const { uid, rawImageData, encoding } = params;
60
+ return new DEMData(uid, rawImageData, encoding);
62
61
  }
63
62
 
64
- reloadTile(mapId, params, callback) {
65
- assert(params.type);
66
- this.getWorkerSource(mapId, params.type, params.source).reloadTile(params, callback);
67
- }
63
+ removeSource(mapId, params) {
64
+ const { type, source } = params;
65
+ assert(type);
66
+ assert(source);
68
67
 
69
- abortTile(mapId, params, callback) {
70
- assert(params.type);
71
- this.getWorkerSource(mapId, params.type, params.source).abortTile(params, callback);
72
- }
73
-
74
- removeTile(mapId, params, callback) {
75
- assert(params.type);
76
- this.getWorkerSource(mapId, params.type, params.source).removeTile(params, callback);
77
- }
78
-
79
- removeDEMTile(mapId, params) {
80
- this.getDEMWorkerSource(mapId, params.source).removeTile(params);
81
- }
82
-
83
- removeSource(mapId, params, callback) {
84
- assert(params.type);
85
- assert(params.source);
86
-
87
- if (
88
- !this.workerSources[mapId] ||
89
- !this.workerSources[mapId][params.type] ||
90
- !this.workerSources[mapId][params.type][params.source]
91
- ) {
92
- return;
93
- }
94
-
95
- const worker = this.workerSources[mapId][params.type][params.source];
96
- delete this.workerSources[mapId][params.type][params.source];
97
-
98
- if (worker.removeSource !== undefined) {
99
- worker.removeSource(params, callback);
100
- } else {
101
- callback();
102
- }
103
- }
104
-
105
- /**
106
- * Load a {@link WorkerSource} script at params.url. The script is run
107
- * (using importScripts) with `registerWorkerSource` in scope, which is a
108
- * function taking `(name, workerSourceObject)`.
109
- * @private
110
- */
111
- loadWorkerSource(map, params, callback) {
112
- try {
113
- this.self.importScripts(params.url);
114
- callback();
115
- } catch (e) {
116
- callback(e.toString());
68
+ const worker = this.workerSources?.[mapId]?.[type]?.[source];
69
+ if (worker) {
70
+ delete this.workerSources[mapId][type][source];
71
+ worker.removeSource?.(params);
117
72
  }
118
73
  }
119
74
 
120
- loadRTLTextPlugin(map, pluginURL, callback) {
121
- try {
75
+ loadRTLTextPlugin(map, pluginURL) {
76
+ if (!globalRTLTextPlugin.isLoaded()) {
77
+ this.self.importScripts(pluginURL);
122
78
  if (!globalRTLTextPlugin.isLoaded()) {
123
- this.self.importScripts(pluginURL);
124
- callback(
125
- globalRTLTextPlugin.isLoaded()
126
- ? null
127
- : new Error(`RTL Text Plugin failed to import scripts from ${pluginURL}`)
128
- );
79
+ throw new Error(`RTL Text Plugin failed to import scripts from ${pluginURL}`);
129
80
  }
130
- } catch (e) {
131
- callback(e.toString());
132
81
  }
133
82
  }
134
83
 
135
84
  getLayerIndex(mapId) {
136
- let layerIndexes = this.layerIndexes[mapId];
137
- if (!layerIndexes) {
138
- layerIndexes = this.layerIndexes[mapId] = new StyleLayerIndex();
139
- }
140
- return layerIndexes;
85
+ return (this.layerIndexes[mapId] ??= new StyleLayerIndex());
141
86
  }
142
87
 
143
- getWorkerSource(mapId, type, source) {
144
- if (!this.workerSources[mapId]) this.workerSources[mapId] = {};
145
- if (!this.workerSources[mapId][type]) this.workerSources[mapId][type] = {};
146
-
147
- if (!this.workerSources[mapId][type][source]) {
148
- // use a wrapped actor so that we can attach a target mapId param
149
- // to any messages invoked by the WorkerSource
150
- const actor = {
151
- send: (type, data, callback) => {
152
- this.actor.send(type, data, callback, mapId);
153
- }
154
- };
155
-
156
- this.workerSources[mapId][type][source] = new this.workerSourceTypes[type](actor, this.getLayerIndex(mapId));
157
- }
158
-
159
- return this.workerSources[mapId][type][source];
88
+ getActor(mapId) {
89
+ return (this.actors[mapId] ??= {
90
+ send: (type, data) => this.actor.send(type, data, mapId)
91
+ });
160
92
  }
161
93
 
162
- getDEMWorkerSource(mapId, source) {
163
- if (!this.demWorkerSources[mapId]) this.demWorkerSources[mapId] = {};
94
+ getWorkerSource(mapId, type, source) {
95
+ this.workerSources[mapId] ??= {};
96
+ this.workerSources[mapId][type] ??= {};
164
97
 
165
- if (!this.demWorkerSources[mapId][source]) {
166
- this.demWorkerSources[mapId][source] = new RasterDEMTileWorkerSource();
167
- }
98
+ return (this.workerSources[mapId][type][source] ??= this.createWorkerSource(type, mapId));
99
+ }
168
100
 
169
- return this.demWorkerSources[mapId][source];
101
+ createWorkerSource(type, mapId) {
102
+ const WorkerSource = this.workerSourceTypes[type];
103
+ return new WorkerSource(this.getActor(mapId), this.getLayerIndex(mapId));
170
104
  }
171
105
  }
172
106
 
@@ -2,7 +2,7 @@ const FeatureIndex = require('../data/feature_index');
2
2
 
3
3
  const { performSymbolLayout } = require('../symbol/symbol_layout');
4
4
  const { CollisionBoxArray } = require('../data/array_types');
5
- const DictionaryCoder = require('../util/dictionary_coder');
5
+ const dictionaryCoder = require('../util/dictionary_coder');
6
6
  const SymbolBucket = require('../data/bucket/symbol_bucket');
7
7
  const LineBucket = require('../data/bucket/line_bucket');
8
8
  const FillBucket = require('../data/bucket/fill_bucket');
@@ -33,12 +33,12 @@ class WorkerTile {
33
33
  this.showCollisionBoxes = params.showCollisionBoxes;
34
34
  }
35
35
 
36
- parse(data, layerIndex, actor, callback) {
36
+ async parse(data, layerIndex, actor) {
37
37
  this.status = 'parsing';
38
38
  this.data = data;
39
39
 
40
40
  this.collisionBoxArray = new CollisionBoxArray();
41
- const sourceLayerCoder = new DictionaryCoder(Object.keys(data.layers).sort());
41
+ const sourceLayerCoder = dictionaryCoder(Object.keys(data.layers));
42
42
 
43
43
  const featureIndex = new FeatureIndex(this.tileID);
44
44
  featureIndex.bucketLayerIDs = [];
@@ -99,92 +99,47 @@ class WorkerTile {
99
99
  }
100
100
  }
101
101
 
102
- let error;
103
- let glyphMap;
104
- let iconMap;
105
- let patternMap;
106
-
107
102
  const stacks = mapObject(options.glyphDependencies, glyphs => Object.keys(glyphs).map(Number));
108
- if (Object.keys(stacks).length) {
109
- actor.send('getGlyphs', { uid: this.uid, stacks }, (err, result) => {
110
- if (!error) {
111
- error = err;
112
- glyphMap = result;
113
- maybePrepare.call(this);
114
- }
115
- });
116
- } else {
117
- glyphMap = {};
118
- }
119
-
120
103
  const icons = Object.keys(options.iconDependencies);
121
- if (icons.length) {
122
- actor.send('getImages', { icons }, (err, result) => {
123
- if (!error) {
124
- error = err;
125
- iconMap = result;
126
- maybePrepare.call(this);
127
- }
128
- });
129
- } else {
130
- iconMap = {};
131
- }
132
-
133
104
  const patterns = Object.keys(options.patternDependencies);
134
- if (patterns.length) {
135
- actor.send('getImages', { icons: patterns }, (err, result) => {
136
- if (!error) {
137
- error = err;
138
- patternMap = result;
139
- maybePrepare.call(this);
140
- }
141
- });
142
- } else {
143
- patternMap = {};
144
- }
145
-
146
- maybePrepare.call(this);
147
-
148
- function maybePrepare() {
149
- if (error) {
150
- return callback(error);
151
- }
152
- if (glyphMap && iconMap && patternMap) {
153
- const glyphAtlas = new GlyphAtlas(glyphMap);
154
- const imageAtlas = new ImageAtlas(iconMap, patternMap);
155
-
156
- for (const key in buckets) {
157
- const bucket = buckets[key];
158
- if (bucket instanceof SymbolBucket) {
159
- recalculateLayers(bucket.layers, this.zoom);
160
- performSymbolLayout(
161
- bucket,
162
- glyphMap,
163
- glyphAtlas.positions,
164
- iconMap,
165
- imageAtlas.iconPositions,
166
- this.showCollisionBoxes
167
- );
168
- } else if (
169
- bucket.hasPattern &&
170
- (bucket instanceof LineBucket || bucket instanceof FillBucket || bucket instanceof FillExtrusionBucket)
171
- ) {
172
- recalculateLayers(bucket.layers, this.zoom);
173
- bucket.addFeatures(options, imageAtlas.patternPositions);
174
- }
175
- }
176
-
177
- this.status = 'done';
178
-
179
- callback(null, {
180
- buckets: values(buckets).filter(b => !b.isEmpty()),
181
- featureIndex,
182
- collisionBoxArray: this.collisionBoxArray,
183
- glyphAtlasImage: glyphAtlas.image,
184
- imageAtlas
185
- });
105
+ const tasks = [
106
+ Object.keys(stacks).length ? actor.send('getGlyphs', { uid: this.uid, stacks }) : {},
107
+ icons.length ? actor.send('getImages', { icons }) : {},
108
+ patterns.length ? actor.send('getImages', { icons: patterns }) : {}
109
+ ];
110
+ const [glyphMap, iconMap, patternMap] = await Promise.all(tasks);
111
+ const glyphAtlas = new GlyphAtlas(glyphMap);
112
+ const imageAtlas = new ImageAtlas(iconMap, patternMap);
113
+
114
+ for (const key in buckets) {
115
+ const bucket = buckets[key];
116
+ if (bucket instanceof SymbolBucket) {
117
+ recalculateLayers(bucket.layers, this.zoom);
118
+ performSymbolLayout(
119
+ bucket,
120
+ glyphMap,
121
+ glyphAtlas.positions,
122
+ iconMap,
123
+ imageAtlas.iconPositions,
124
+ this.showCollisionBoxes
125
+ );
126
+ } else if (
127
+ bucket.hasPattern &&
128
+ (bucket instanceof LineBucket || bucket instanceof FillBucket || bucket instanceof FillExtrusionBucket)
129
+ ) {
130
+ recalculateLayers(bucket.layers, this.zoom);
131
+ bucket.addFeatures(options, imageAtlas.patternPositions);
186
132
  }
187
133
  }
134
+
135
+ this.status = 'done';
136
+ return {
137
+ buckets: values(buckets).filter(b => !b.isEmpty()),
138
+ featureIndex,
139
+ collisionBoxArray: this.collisionBoxArray,
140
+ glyphAtlasImage: glyphAtlas.image,
141
+ imageAtlas
142
+ };
188
143
  }
189
144
  }
190
145
 
@@ -4,23 +4,20 @@ const loadImage = require('../util/loader/image');
4
4
 
5
5
  module.exports = loadSprite;
6
6
 
7
- function loadSprite(sprite, callback) {
8
- loadImage(sprite.image, (error, image) => {
9
- const { json } = sprite;
10
- if (error) {
11
- callback(error);
12
- } else if (json && image) {
13
- const imageData = browser.getImageData(image);
14
- const result = {};
7
+ async function loadSprite(sprite) {
8
+ const image = await loadImage(sprite.image);
9
+ const { json } = sprite;
10
+ if (json && image) {
11
+ const imageData = browser.getImageData(image);
12
+ const result = {};
15
13
 
16
- for (const id in json) {
17
- const { width, height, x, y, sdf, pixelRatio } = json[id];
18
- const data = new RGBAImage({ width, height });
19
- RGBAImage.copy(imageData, data, { x, y }, { x: 0, y: 0 }, { width, height });
20
- result[id] = { data, pixelRatio, sdf };
21
- }
22
-
23
- callback(null, result);
14
+ for (const id in json) {
15
+ const { width, height, x, y, sdf, pixelRatio } = json[id];
16
+ const data = new RGBAImage({ width, height });
17
+ RGBAImage.copy(imageData, data, { x, y }, { x: 0, y: 0 }, { width, height });
18
+ result[id] = { data, pixelRatio, sdf };
24
19
  }
25
- });
20
+
21
+ return result;
22
+ }
26
23
  }
@@ -4,7 +4,7 @@ const { clone } = require('../util/object');
4
4
  const { easeCubicInOut } = require('../util/util');
5
5
  const interpolate = require('../style-spec/util/interpolate');
6
6
  const { normalizePropertyExpression } = require('../style-spec/expression');
7
- const { register } = require('../util/web_worker_transfer');
7
+ const { register } = require('../util/transfer_registry');
8
8
  const EvaluationParameters = require('./evaluation_parameters');
9
9
 
10
10
  /**
@@ -46,7 +46,9 @@ class Style extends Evented {
46
46
 
47
47
  const self = this;
48
48
  this._rtlTextPluginCallback = Style.registerForPluginAvailability(args => {
49
- self.dispatcher.broadcast('loadRTLTextPlugin', args.pluginURL, args.completionCallback);
49
+ self.dispatcher
50
+ .broadcast('loadRTLTextPlugin', args.pluginURL)
51
+ .then(_ => args.completionCallback(), args.completionCallback);
50
52
  for (const id in self.sourceCaches) {
51
53
  self.sourceCaches[id].reload(); // Should be a no-op if the plugin loads before any tiles load
52
54
  }
@@ -93,20 +95,20 @@ class Style extends Evented {
93
95
  }
94
96
 
95
97
  if (json.sprite) {
96
- loadSprite(json.sprite, (err, images) => {
97
- if (err) {
98
- this.fire(new ErrorEvent(err));
99
- } else if (images) {
100
- for (const id in images) {
101
- this.imageManager.addImage(id, images[id]);
98
+ loadSprite(json.sprite)
99
+ .then(images => {
100
+ if (images) {
101
+ for (const id in images) {
102
+ this.imageManager.addImage(id, images[id]);
103
+ }
102
104
  }
103
- }
104
105
 
105
- this.imageManager.setLoaded(true);
106
- this.fire(new Event('data', { dataType: 'style' }));
107
- });
106
+ this.imageManager.setLoaded();
107
+ this.fire(new Event('data', { dataType: 'style' }));
108
+ })
109
+ .catch(err => this.fire(new ErrorEvent(err)));
108
110
  } else {
109
- this.imageManager.setLoaded(true);
111
+ this.imageManager.setLoaded();
110
112
  }
111
113
 
112
114
  this.glyphManager.setGlyphsLoader(json.glyphs);
@@ -631,6 +633,10 @@ class Style extends Evented {
631
633
  this.fire(new ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
632
634
  return;
633
635
  }
636
+ if (feature.id == null || feature.id === '') {
637
+ this.fire(new ErrorEvent(new Error('The feature id parameter must be provided.')));
638
+ return;
639
+ }
634
640
 
635
641
  sourceCache.setFeatureState(sourceLayer, feature.id, state);
636
642
  }
@@ -765,27 +771,6 @@ class Style extends Evented {
765
771
  return sourceCache ? querySourceFeatures(sourceCache, params) : [];
766
772
  }
767
773
 
768
- addSourceType(name, SourceType, callback) {
769
- if (Style.getSourceType(name)) {
770
- return callback(new Error(`A source type called "${name}" already exists.`));
771
- }
772
-
773
- Style.setSourceType(name, SourceType);
774
-
775
- if (!SourceType.workerSourceURL) {
776
- return callback(null, null);
777
- }
778
-
779
- this.dispatcher.broadcast(
780
- 'loadWorkerSource',
781
- {
782
- name: name,
783
- url: SourceType.workerSourceURL
784
- },
785
- callback
786
- );
787
- }
788
-
789
774
  getLight() {
790
775
  return this.light.getLight();
791
776
  }
@@ -939,12 +924,12 @@ class Style extends Evented {
939
924
 
940
925
  // Callbacks from web workers
941
926
 
942
- getImages(mapId, params, callback) {
943
- this.imageManager.getImages(params.icons, callback);
927
+ getImages(_mapId, { icons }) {
928
+ return this.imageManager.getImages(icons);
944
929
  }
945
930
 
946
- getGlyphs(mapId, params, callback) {
947
- return this.glyphManager.getGlyphs(params.stacks, callback);
931
+ getGlyphs(_mapId, { stacks }) {
932
+ return this.glyphManager.getGlyphs(stacks);
948
933
  }
949
934
  }
950
935
 
@@ -106,7 +106,7 @@ const layout = new Properties({
106
106
  expression: { parameters: ['zoom'] }
107
107
  }),
108
108
  'text-field': new DataDrivenProperty({
109
- type: 'string',
109
+ type: 'formatted',
110
110
  default: '',
111
111
  tokens: true,
112
112
  expression: { parameters: ['zoom', 'feature'] }