@loaders.gl/worker-utils 4.4.0-alpha.2 → 4.4.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 (73) hide show
  1. package/dist/index.cjs +58 -138
  2. package/dist/index.cjs.map +4 -4
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -1
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/async-queue/async-queue.js +1 -0
  8. package/dist/lib/async-queue/async-queue.js.map +1 -0
  9. package/dist/lib/env-utils/assert.js +1 -0
  10. package/dist/lib/env-utils/assert.js.map +1 -0
  11. package/dist/lib/env-utils/globals.js +1 -0
  12. package/dist/lib/env-utils/globals.js.map +1 -0
  13. package/dist/lib/env-utils/version.d.ts.map +1 -1
  14. package/dist/lib/env-utils/version.js +5 -2
  15. package/dist/lib/env-utils/version.js.map +1 -0
  16. package/dist/lib/library-utils/library-utils.d.ts +19 -2
  17. package/dist/lib/library-utils/library-utils.d.ts.map +1 -1
  18. package/dist/lib/library-utils/library-utils.js +72 -30
  19. package/dist/lib/library-utils/library-utils.js.map +1 -0
  20. package/dist/lib/node/worker_threads-browser.js +1 -0
  21. package/dist/lib/node/worker_threads-browser.js.map +1 -0
  22. package/dist/lib/node/worker_threads.js +1 -0
  23. package/dist/lib/node/worker_threads.js.map +1 -0
  24. package/dist/lib/npm-tag.js +1 -0
  25. package/dist/lib/npm-tag.js.map +1 -0
  26. package/dist/lib/process-utils/child-process-proxy.browser.d.ts +8 -0
  27. package/dist/lib/process-utils/child-process-proxy.browser.d.ts.map +1 -0
  28. package/dist/lib/process-utils/child-process-proxy.browser.js +18 -0
  29. package/dist/lib/process-utils/child-process-proxy.browser.js.map +1 -0
  30. package/dist/lib/process-utils/child-process-proxy.d.ts +3 -2
  31. package/dist/lib/process-utils/child-process-proxy.d.ts.map +1 -1
  32. package/dist/lib/process-utils/child-process-proxy.js +12 -7
  33. package/dist/lib/process-utils/child-process-proxy.js.map +1 -0
  34. package/dist/lib/process-utils/process-utils.js +1 -0
  35. package/dist/lib/process-utils/process-utils.js.map +1 -0
  36. package/dist/lib/worker-api/create-worker.js +1 -0
  37. package/dist/lib/worker-api/create-worker.js.map +1 -0
  38. package/dist/lib/worker-api/get-worker-url.d.ts.map +1 -1
  39. package/dist/lib/worker-api/get-worker-url.js +3 -1
  40. package/dist/lib/worker-api/get-worker-url.js.map +1 -0
  41. package/dist/lib/worker-api/process-on-worker.js +1 -0
  42. package/dist/lib/worker-api/process-on-worker.js.map +1 -0
  43. package/dist/lib/worker-api/validate-worker-version.js +1 -0
  44. package/dist/lib/worker-api/validate-worker-version.js.map +1 -0
  45. package/dist/lib/worker-farm/worker-body.js +1 -0
  46. package/dist/lib/worker-farm/worker-body.js.map +1 -0
  47. package/dist/lib/worker-farm/worker-farm.js +1 -0
  48. package/dist/lib/worker-farm/worker-farm.js.map +1 -0
  49. package/dist/lib/worker-farm/worker-job.js +1 -0
  50. package/dist/lib/worker-farm/worker-job.js.map +1 -0
  51. package/dist/lib/worker-farm/worker-pool.js +1 -0
  52. package/dist/lib/worker-farm/worker-pool.js.map +1 -0
  53. package/dist/lib/worker-farm/worker-thread.d.ts.map +1 -1
  54. package/dist/lib/worker-farm/worker-thread.js +4 -2
  55. package/dist/lib/worker-farm/worker-thread.js.map +1 -0
  56. package/dist/lib/worker-utils/get-loadable-worker-url.js +1 -0
  57. package/dist/lib/worker-utils/get-loadable-worker-url.js.map +1 -0
  58. package/dist/lib/worker-utils/get-transfer-list.js +1 -0
  59. package/dist/lib/worker-utils/get-transfer-list.js.map +1 -0
  60. package/dist/lib/worker-utils/remove-nontransferable-options.js +1 -0
  61. package/dist/lib/worker-utils/remove-nontransferable-options.js.map +1 -0
  62. package/dist/types.js +1 -0
  63. package/dist/types.js.map +1 -0
  64. package/dist/workers/null-worker.js +1 -0
  65. package/dist/workers/null-worker.js.map +1 -0
  66. package/package.json +10 -6
  67. package/src/index.ts +6 -1
  68. package/src/lib/env-utils/version.ts +4 -1
  69. package/src/lib/library-utils/library-utils.ts +95 -34
  70. package/src/lib/process-utils/child-process-proxy.browser.ts +23 -0
  71. package/src/lib/process-utils/child-process-proxy.ts +23 -9
  72. package/src/lib/worker-api/get-worker-url.ts +2 -1
  73. package/src/lib/worker-farm/worker-thread.ts +4 -3
package/src/index.ts CHANGED
@@ -40,7 +40,12 @@ export {validateWorkerVersion} from './lib/worker-api/validate-worker-version';
40
40
  export {getTransferList, getTransferListForWriter} from './lib/worker-utils/get-transfer-list';
41
41
 
42
42
  // LIBRARY UTILS
43
- export {getLibraryUrl, loadLibrary} from './lib/library-utils/library-utils';
43
+ export {
44
+ extractLoadLibraryOptions,
45
+ getLibraryUrl,
46
+ loadLibrary,
47
+ type LoadLibraryOptions
48
+ } from './lib/library-utils/library-utils';
44
49
 
45
50
  // PARSER UTILS
46
51
  export {default as AsyncQueue} from './lib/async-queue/async-queue';
@@ -7,16 +7,19 @@ import {NPM_TAG} from '../npm-tag';
7
7
  // Version constant cannot be imported, it needs to correspond to the build version of **this** module.
8
8
  declare let __VERSION__: string;
9
9
 
10
+ let warningIssued = false;
11
+
10
12
  function getVersion() {
11
13
  if (!globalThis._loadersgl_?.version) {
12
14
  globalThis._loadersgl_ = globalThis._loadersgl_ || {};
13
15
  // __VERSION__ is injected by babel-plugin-version-inline
14
- if (typeof __VERSION__ === 'undefined') {
16
+ if (typeof __VERSION__ === 'undefined' && !warningIssued) {
15
17
  // eslint-disable-next-line
16
18
  console.warn(
17
19
  'loaders.gl: The __VERSION__ variable is not injected using babel plugin. Latest unstable workers would be fetched from the CDN.'
18
20
  );
19
21
  globalThis._loadersgl_.version = NPM_TAG;
22
+ warningIssued = true;
20
23
  } else {
21
24
  globalThis._loadersgl_.version = __VERSION__;
22
25
  }
@@ -7,8 +7,40 @@ import {isBrowser, isWorker} from '../env-utils/globals';
7
7
  import {assert} from '../env-utils/assert';
8
8
  import {VERSION} from '../env-utils/version';
9
9
 
10
+ export type LoadLibraryOptions<ModulesT extends Record<string, any> = Record<string, any>> = {
11
+ useLocalLibraries?: boolean;
12
+ CDN?: string | null;
13
+ modules?: ModulesT;
14
+ // Core must not be supplied
15
+ core?: never;
16
+ };
17
+
18
+ type ExtractableLoadLibraryOptions<ModulesT extends Record<string, any> = Record<string, any>> = {
19
+ useLocalLibraries?: boolean;
20
+ CDN?: string | null;
21
+ modules?: ModulesT;
22
+ core?: {
23
+ useLocalLibraries?: boolean;
24
+ CDN?: string | null;
25
+ } | null;
26
+ };
27
+
10
28
  const loadLibraryPromises: Record<string, Promise<any>> = {}; // promises
11
29
 
30
+ export function extractLoadLibraryOptions<
31
+ ModulesT extends Record<string, any> = Record<string, any>
32
+ >(options: ExtractableLoadLibraryOptions<ModulesT> = {}): LoadLibraryOptions<ModulesT> {
33
+ const useLocalLibraries = options.useLocalLibraries ?? options.core?.useLocalLibraries;
34
+ const CDN = options.CDN ?? options.core?.CDN;
35
+ const modules = options.modules;
36
+
37
+ return {
38
+ ...(useLocalLibraries !== undefined ? {useLocalLibraries} : {}),
39
+ ...(CDN !== undefined ? {CDN} : {}),
40
+ ...(modules !== undefined ? {modules} : {})
41
+ };
42
+ }
43
+
12
44
  /**
13
45
  * Dynamically loads a library ("module")
14
46
  *
@@ -27,7 +59,7 @@ const loadLibraryPromises: Record<string, Promise<any>> = {}; // promises
27
59
  export async function loadLibrary(
28
60
  libraryUrl: string,
29
61
  moduleName: string | null = null,
30
- options: object = {},
62
+ options: LoadLibraryOptions = {},
31
63
  libraryName: string | null = null
32
64
  ): Promise<any> {
33
65
  if (moduleName) {
@@ -45,9 +77,13 @@ export async function loadLibrary(
45
77
  export function getLibraryUrl(
46
78
  library: string,
47
79
  moduleName?: string,
48
- options: any = {},
80
+ options: LoadLibraryOptions = {},
49
81
  libraryName: string | null = null
50
82
  ): string {
83
+ if (options?.core) {
84
+ throw new Error('loadLibrary: options.core must be pre-normalized');
85
+ }
86
+
51
87
  // Check if already a URL
52
88
  if (!options.useLocalLibraries && library.startsWith('http')) {
53
89
  return library;
@@ -94,10 +130,21 @@ async function loadLibraryFromFile(libraryUrl: string): Promise<any> {
94
130
  // } catch (error) {
95
131
  // console.error(error);
96
132
  // }
133
+ const {requireFromFile} = globalThis.loaders || {};
97
134
  try {
98
- const {requireFromFile} = globalThis.loaders || {};
99
- return await requireFromFile?.(libraryUrl);
135
+ const result = await requireFromFile?.(libraryUrl);
136
+ if (result || !libraryUrl.includes('/dist/libs/')) {
137
+ return result;
138
+ }
139
+ return await requireFromFile?.(libraryUrl.replace('/dist/libs/', '/src/libs/'));
100
140
  } catch (error) {
141
+ if (libraryUrl.includes('/dist/libs/')) {
142
+ try {
143
+ return await requireFromFile?.(libraryUrl.replace('/dist/libs/', '/src/libs/'));
144
+ } catch {
145
+ // ignore
146
+ }
147
+ }
101
148
  console.error(error); // eslint-disable-line no-console
102
149
  return null;
103
150
  }
@@ -114,19 +161,6 @@ async function loadLibraryFromFile(libraryUrl: string): Promise<any> {
114
161
  return loadLibraryFromString(scriptSource, libraryUrl);
115
162
  }
116
163
 
117
- /*
118
- async function loadScriptFromFile(libraryUrl) {
119
- const script = document.createElement('script');
120
- script.src = libraryUrl;
121
- return await new Promise((resolve, reject) => {
122
- script.onload = data => {
123
- resolve(data);
124
- };
125
- script.onerror = reject;
126
- });
127
- }
128
- */
129
-
130
164
  // TODO - Needs security audit...
131
165
  // - Raw eval call
132
166
  // - Potentially bypasses CORS
@@ -158,28 +192,20 @@ function loadLibraryFromString(scriptSource: string, id: string): null | any {
158
192
  return null;
159
193
  }
160
194
 
161
- // TODO - technique for module injection into worker, from THREE.DracoLoader...
162
- /*
163
- function combineWorkerWithLibrary(worker, jsContent) {
164
- var fn = wWorker.toString();
165
- var body = [
166
- '// injected',
167
- jsContent,
168
- '',
169
- '// worker',
170
- fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
171
- ].join('\n');
172
- this.workerSourceURL = URL.createObjectURL(new Blob([body]));
173
- }
174
- */
175
-
176
195
  async function loadAsArrayBuffer(url: string): Promise<ArrayBuffer> {
177
196
  const {readFileAsArrayBuffer} = globalThis.loaders || {};
178
197
  if (isBrowser || !readFileAsArrayBuffer || url.startsWith('http')) {
179
198
  const response = await fetch(url);
180
199
  return await response.arrayBuffer();
181
200
  }
182
- return await readFileAsArrayBuffer(url);
201
+ try {
202
+ return await readFileAsArrayBuffer(url);
203
+ } catch {
204
+ if (url.includes('/dist/libs/')) {
205
+ return await readFileAsArrayBuffer(url.replace('/dist/libs/', '/src/libs/'));
206
+ }
207
+ throw new Error(`Failed to load ArrayBuffer from ${url}`);
208
+ }
183
209
  }
184
210
 
185
211
  /**
@@ -193,5 +219,40 @@ async function loadAsText(url: string): Promise<string> {
193
219
  const response = await fetch(url);
194
220
  return await response.text();
195
221
  }
196
- return await readFileAsText(url);
222
+ try {
223
+ return await readFileAsText(url);
224
+ } catch {
225
+ if (url.includes('/dist/libs/')) {
226
+ return await readFileAsText(url.replace('/dist/libs/', '/src/libs/'));
227
+ }
228
+ throw new Error(`Failed to load text from ${url}`);
229
+ }
230
+ }
231
+
232
+ /*
233
+ async function loadScriptFromFile(libraryUrl) {
234
+ const script = document.createElement('script');
235
+ script.src = libraryUrl;
236
+ return await new Promise((resolve, reject) => {
237
+ script.onload = data => {
238
+ resolve(data);
239
+ };
240
+ script.onerror = reject;
241
+ });
197
242
  }
243
+ */
244
+
245
+ // TODO - technique for module injection into worker, from THREE.DracoLoader...
246
+ /*
247
+ function combineWorkerWithLibrary(worker, jsContent) {
248
+ var fn = wWorker.toString();
249
+ var body = [
250
+ '// injected',
251
+ jsContent,
252
+ '',
253
+ '// worker',
254
+ fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
255
+ ].join('\n');
256
+ this.workerSourceURL = URL.createObjectURL(new Blob([body]));
257
+ }
258
+ */
@@ -0,0 +1,23 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import type {ChildProcessProxyProps} from './child-process-proxy';
6
+
7
+ export default class ChildProcessProxy {
8
+ constructor() {
9
+ throw new Error('ChildProcessProxy is not available in browser environments');
10
+ }
11
+
12
+ async start(props?: ChildProcessProxyProps): Promise<object> {
13
+ return await Promise.resolve({});
14
+ }
15
+
16
+ async stop(): Promise<void> {
17
+ return await Promise.resolve();
18
+ }
19
+
20
+ async exit(): Promise<void> {
21
+ return await Promise.resolve();
22
+ }
23
+ }
@@ -3,12 +3,19 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  /* eslint-disable no-console */
6
- // Avoid using named imports for Node builtins to help with "empty" resolution
7
- // for bundlers targeting browser environments. Access imports & types
8
- // through the `ChildProcess` object (e.g. `ChildProcess.spawn`, `ChildProcess.ChildProcess`).
9
- import * as ChildProcess from 'child_process';
10
6
  import {getAvailablePort} from './process-utils';
11
7
 
8
+ type NodeChildProcess = import('child_process').ChildProcess;
9
+ type SpawnOptions = import('child_process').SpawnOptions;
10
+
11
+ async function getChildProcessModule(): Promise<typeof import('child_process')> {
12
+ if (typeof process === 'undefined' || !process.versions?.node) {
13
+ throw new Error('ChildProcessProxy is only available in Node.js environments');
14
+ }
15
+
16
+ return await import('child_process');
17
+ }
18
+
12
19
  export type ChildProcessProxyProps = {
13
20
  command: string;
14
21
  arguments: string[];
@@ -22,7 +29,7 @@ export type ChildProcessProxyProps = {
22
29
  /** wait: 0 - infinity */
23
30
  wait?: number;
24
31
  /** Options passed on to Node'.js `spawn` */
25
- spawn?: ChildProcess.SpawnOptions;
32
+ spawn?: SpawnOptions;
26
33
  /** Should proceed if stderr stream recieved data */
27
34
  ignoreStderr?: boolean;
28
35
  /** Callback when the */
@@ -48,7 +55,7 @@ const DEFAULT_PROPS: ChildProcessProxyProps = {
48
55
  export default class ChildProcessProxy {
49
56
  id: string;
50
57
  props: ChildProcessProxyProps = {...DEFAULT_PROPS};
51
- private childProcess: ChildProcess.ChildProcess | null = null;
58
+ private childProcess: NodeChildProcess | null = null;
52
59
  private port: number = 0;
53
60
  private successTimer?: any; // NodeJS.Timeout;
54
61
 
@@ -62,6 +69,8 @@ export default class ChildProcessProxy {
62
69
  props = {...DEFAULT_PROPS, ...props};
63
70
  this.props = props;
64
71
 
72
+ const childProcessModule = await getChildProcessModule();
73
+
65
74
  const args = [...props.arguments];
66
75
 
67
76
  // If portArg is set, we can look up an available port
@@ -83,13 +92,18 @@ export default class ChildProcessProxy {
83
92
  });
84
93
 
85
94
  console.log(`Spawning ${props.command} ${props.arguments.join(' ')}`);
86
- const childProcess = ChildProcess.spawn(props.command, args, props.spawn);
95
+ const spawnOptions: SpawnOptions = props.spawn || {};
96
+ const childProcess: NodeChildProcess = childProcessModule.spawn(
97
+ props.command,
98
+ args,
99
+ spawnOptions
100
+ );
87
101
  this.childProcess = childProcess;
88
102
 
89
- childProcess.stdout.on('data', (data) => {
103
+ childProcess.stdout?.on('data', (data) => {
90
104
  console.log(data.toString());
91
105
  });
92
- childProcess.stderr.on('data', (data) => {
106
+ childProcess.stderr?.on('data', (data) => {
93
107
  console.log(`Child process wrote to stderr: "${data}".`);
94
108
  if (!props.ignoreStderr) {
95
109
  this._clearTimeout();
@@ -46,7 +46,8 @@ export function getWorkerURL(worker: WorkerObject, options: WorkerOptions = {}):
46
46
 
47
47
  // If URL is test, generate local loaders.gl url
48
48
  // @ts-ignore _workerType
49
- if (options._workerType === 'test') {
49
+ const workerType = (options as any)._workerType || (options as any)?.core?._workerType;
50
+ if (workerType === 'test') {
50
51
  if (isBrowser) {
51
52
  url = `modules/${worker.module}/dist/${workerFile}`;
52
53
  } else {
@@ -134,8 +134,10 @@ export default class WorkerThread {
134
134
  // Make sure relative URLs start with './'
135
135
  const absolute = this.url.includes(':/') || this.url.startsWith('/');
136
136
  const url = absolute ? this.url : `./${this.url}`;
137
+ const type = this.url.endsWith('.ts') || this.url.endsWith('.mjs') ? 'module' : 'commonjs';
137
138
  // console.log('Starting work from', url);
138
- worker = new NodeWorker(url, {eval: false});
139
+ // @ts-expect-error type is not known
140
+ worker = new NodeWorker(url, {eval: false, type});
139
141
  } else if (this.source) {
140
142
  worker = new NodeWorker(this.source, {eval: true});
141
143
  } else {
@@ -146,8 +148,7 @@ export default class WorkerThread {
146
148
  this.onMessage(data);
147
149
  });
148
150
  worker.on('error', (error) => {
149
- // console.error('error', error);
150
- this.onError(error);
151
+ this.onError(error as Error);
151
152
  });
152
153
  worker.on('exit', (code) => {
153
154
  // console.error('exit', code);