Skip to content

Commit 65bfa1c

Browse files
underootmourner
authored andcommitted
[GLJS-1075] Fix loading of [email protected]+ (internal-2599)
1 parent c8cac7c commit 65bfa1c

File tree

2 files changed

+54
-19
lines changed

2 files changed

+54
-19
lines changed

src/source/rtl_text_plugin.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ import {isWorker} from '../util/util';
66

77
import type {Callback} from '../types/callback';
88

9-
const status = {
9+
export const rtlPluginStatus = {
1010
unavailable: 'unavailable', // Not loaded
1111
deferred: 'deferred', // The plugin URL has been specified, but loading has been deferred
1212
loading: 'loading', // request in-flight
13+
parsing: 'parsing',
14+
parsed: 'parsed',
1315
loaded: 'loaded',
1416
error: 'error'
1517
};
1618

17-
export type PluginStatus = typeof status[keyof typeof status];
19+
export type PluginStatus = typeof rtlPluginStatus[keyof typeof rtlPluginStatus];
1820

1921
export type PluginState = {
2022
pluginStatus: PluginStatus;
@@ -25,14 +27,14 @@ type PluginStateSyncCallback = (state: PluginState) => void;
2527
let _completionCallback = null;
2628

2729
//Variables defining the current state of the plugin
28-
let pluginStatus: PluginStatus = status.unavailable;
30+
let pluginStatus: PluginStatus = rtlPluginStatus.unavailable;
2931
let pluginURL: string | null | undefined = null;
3032

3133
export const triggerPluginCompletionEvent = function (error?: Error | null) {
3234
// NetworkError's are not correctly reflected by the plugin status which prevents reloading plugin
3335
// @ts-expect-error - TS2339 - Property 'indexOf' does not exist on type 'never'.
3436
if (error && typeof error === 'string' && error.indexOf('NetworkError') > -1) {
35-
pluginStatus = status.error;
37+
pluginStatus = rtlPluginStatus.error;
3638
}
3739

3840
if (_completionCallback) {
@@ -63,18 +65,18 @@ export const registerForPluginStateChange = function (callback: PluginStateSyncC
6365
};
6466

6567
export const clearRTLTextPlugin = function () {
66-
pluginStatus = status.unavailable;
68+
pluginStatus = rtlPluginStatus.unavailable;
6769
pluginURL = null;
6870
};
6971

7072
export const setRTLTextPlugin = function (url: string, callback?: Callback<{
7173
err: Error | null | undefined;
7274
}> | null, deferred: boolean = false) {
73-
if (pluginStatus === status.deferred || pluginStatus === status.loading || pluginStatus === status.loaded) {
75+
if (pluginStatus === rtlPluginStatus.deferred || pluginStatus === rtlPluginStatus.loading || pluginStatus === rtlPluginStatus.loaded) {
7476
throw new Error('setRTLTextPlugin cannot be called multiple times.');
7577
}
7678
pluginURL = browser.resolveURL(url);
77-
pluginStatus = status.deferred;
79+
pluginStatus = rtlPluginStatus.deferred;
7880
_completionCallback = callback;
7981
sendPluginStateToWorker();
8082

@@ -85,17 +87,17 @@ export const setRTLTextPlugin = function (url: string, callback?: Callback<{
8587
};
8688

8789
export const downloadRTLTextPlugin = function () {
88-
if (pluginStatus !== status.deferred || !pluginURL) {
90+
if (pluginStatus !== rtlPluginStatus.deferred || !pluginURL) {
8991
throw new Error('rtl-text-plugin cannot be downloaded unless a pluginURL is specified');
9092
}
91-
pluginStatus = status.loading;
93+
pluginStatus = rtlPluginStatus.loading;
9294
sendPluginStateToWorker();
9395
if (pluginURL) {
9496
getArrayBuffer({url: pluginURL}, (error) => {
9597
if (error) {
9698
triggerPluginCompletionEvent(error);
9799
} else {
98-
pluginStatus = status.loaded;
100+
pluginStatus = rtlPluginStatus.loaded;
99101
sendPluginStateToWorker();
100102
}
101103
});
@@ -109,6 +111,7 @@ export type RtlTextPlugin = {
109111
isLoaded: () => boolean;
110112
isLoading: () => boolean;
111113
setState: (state: PluginState) => void;
114+
isParsing: () => boolean;
112115
isParsed: () => boolean;
113116
getPluginURL: () => string | null | undefined;
114117
};
@@ -118,24 +121,27 @@ export const plugin: RtlTextPlugin = {
118121
processBidirectionalText: null,
119122
processStyledBidirectionalText: null,
120123
isLoaded() {
121-
return pluginStatus === status.loaded || // Main Thread: loaded if the completion callback returned successfully
124+
return pluginStatus === rtlPluginStatus.loaded || // Main Thread: loaded if the completion callback returned successfully
122125
plugin.applyArabicShaping != null; // Web-worker: loaded if the plugin functions have been compiled
123126
},
124127
isLoading() { // Main Thread Only: query the loading status, this function does not return the correct value in the worker context.
125-
return pluginStatus === status.loading;
128+
return pluginStatus === rtlPluginStatus.loading;
126129
},
127130
setState(state: PluginState) { // Worker thread only: this tells the worker threads that the plugin is available on the Main thread
128131
assert(isWorker(self), 'Cannot set the state of the rtl-text-plugin when not in the web-worker context');
129132

130133
pluginStatus = state.pluginStatus;
131134
pluginURL = state.pluginURL;
132135
},
136+
isParsing(): boolean {
137+
assert(isWorker(self), 'rtl-text-plugin is only parsed on the worker-threads');
138+
139+
return pluginStatus === rtlPluginStatus.parsing;
140+
},
133141
isParsed(): boolean {
134142
assert(isWorker(self), 'rtl-text-plugin is only parsed on the worker-threads');
135143

136-
return plugin.applyArabicShaping != null &&
137-
plugin.processBidirectionalText != null &&
138-
plugin.processStyledBidirectionalText != null;
144+
return pluginStatus === rtlPluginStatus.parsed;
139145
},
140146
getPluginURL(): string | null | undefined {
141147
assert(isWorker(self), 'rtl-text-plugin url can only be queried from the worker threads');

src/source/worker.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import RasterArrayTileWorkerSource from './raster_array_tile_worker_source';
66
import GeoJSONWorkerSource from './geojson_worker_source';
77
import Tiled3dModelWorkerSource from '../../3d-style/source/tiled_3d_model_worker_source';
88
import assert from 'assert';
9-
import {plugin as globalRTLTextPlugin} from './rtl_text_plugin';
9+
import {plugin as globalRTLTextPlugin, rtlPluginStatus} from './rtl_text_plugin';
1010
import {enforceCacheSizeLimit} from '../util/tile_request_cache';
1111
import {PerformanceUtils} from '../util/performance';
1212
import {Event} from '../util/evented';
@@ -22,6 +22,7 @@ import type {RasterizedImageMap} from '../render/image_manager';
2222
import type {ActorMessage, ActorMessages} from '../util/actor_messages';
2323
import type {WorkerSource, WorkerSourceConstructor} from './worker_source';
2424
import type {StyleModelMap} from '../style/style_mode';
25+
import type {Callback} from '../types/callback';
2526

2627
/**
2728
* Source types that can instantiate a {@link WorkerSource} in {@link MapWorker}.
@@ -62,6 +63,7 @@ export default class MapWorker {
6263
brightness: number | null | undefined;
6364
imageRasterizer: ImageRasterizer;
6465
worldview: string | undefined;
66+
rtlPluginParsingListeners: Array<Callback<boolean>>;
6567

6668
constructor(self: Worker) {
6769
PerformanceUtils.measure('workerEvaluateScript');
@@ -73,6 +75,7 @@ export default class MapWorker {
7375
this.availableModels = {};
7476
this.isSpriteLoaded = {};
7577
this.imageRasterizer = new ImageRasterizer();
78+
this.rtlPluginParsingListeners = [];
7679

7780
this.projections = {};
7881
this.defaultProjection = getProjection({name: 'mercator'});
@@ -100,9 +103,19 @@ export default class MapWorker {
100103
if (globalRTLTextPlugin.isParsed()) {
101104
throw new Error('RTL text plugin already registered.');
102105
}
106+
107+
globalRTLTextPlugin.setState({
108+
pluginStatus: rtlPluginStatus.parsed,
109+
pluginURL: globalRTLTextPlugin.getPluginURL()
110+
});
103111
globalRTLTextPlugin['applyArabicShaping'] = rtlTextPlugin.applyArabicShaping;
104112
globalRTLTextPlugin['processBidirectionalText'] = rtlTextPlugin.processBidirectionalText;
105113
globalRTLTextPlugin['processStyledBidirectionalText'] = rtlTextPlugin.processStyledBidirectionalText;
114+
115+
for (const callback of this.rtlPluginParsingListeners) {
116+
callback(null, true);
117+
}
118+
this.rtlPluginParsingListeners = [];
106119
};
107120
}
108121

@@ -279,18 +292,34 @@ export default class MapWorker {
279292
}
280293

281294
syncRTLPluginState(mapId: number, state: ActorMessages['syncRTLPluginState']['params'], callback: ActorMessages['syncRTLPluginState']['callback']) {
295+
if (globalRTLTextPlugin.isParsed()) {
296+
callback(null, true);
297+
return;
298+
}
299+
if (globalRTLTextPlugin.isParsing()) {
300+
this.rtlPluginParsingListeners.push(callback);
301+
return;
302+
}
282303
try {
283304
globalRTLTextPlugin.setState(state);
284305
const pluginURL = globalRTLTextPlugin.getPluginURL();
285306
if (
286307
globalRTLTextPlugin.isLoaded() &&
287308
!globalRTLTextPlugin.isParsed() &&
309+
!globalRTLTextPlugin.isParsing() &&
288310
pluginURL != null // Not possible when `isLoaded` is true, but keeps flow happy
289311
) {
312+
globalRTLTextPlugin.setState({
313+
pluginStatus: rtlPluginStatus.parsing,
314+
pluginURL: globalRTLTextPlugin.getPluginURL()
315+
});
290316
this.self.importScripts(pluginURL);
291-
const complete = globalRTLTextPlugin.isParsed();
292-
const error = complete ? undefined : new Error(`RTL Text Plugin failed to import scripts from ${pluginURL}`);
293-
callback(error, complete);
317+
318+
if (globalRTLTextPlugin.isParsed()) {
319+
callback(null, true);
320+
} else {
321+
this.rtlPluginParsingListeners.push(callback);
322+
}
294323
}
295324
} catch (e) {
296325
callback(e.toString());

0 commit comments

Comments
 (0)