@loaders.gl/loader-utils 4.4.0-alpha.1 → 4.4.0-alpha.9

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 (160) hide show
  1. package/README.md +8 -0
  2. package/dist/format-types.js +1 -0
  3. package/dist/format-types.js.map +1 -0
  4. package/dist/index.cjs +165 -287
  5. package/dist/index.cjs.map +4 -4
  6. package/dist/index.d.ts +6 -9
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +4 -6
  9. package/dist/index.js.map +1 -0
  10. package/dist/json-loader.js +2 -1
  11. package/dist/json-loader.js.map +1 -0
  12. package/dist/lib/binary-utils/array-buffer-utils.d.ts +2 -2
  13. package/dist/lib/binary-utils/array-buffer-utils.d.ts.map +1 -1
  14. package/dist/lib/binary-utils/array-buffer-utils.js +1 -0
  15. package/dist/lib/binary-utils/array-buffer-utils.js.map +1 -0
  16. package/dist/lib/binary-utils/dataview-copy-utils.js +1 -0
  17. package/dist/lib/binary-utils/dataview-copy-utils.js.map +1 -0
  18. package/dist/lib/binary-utils/get-first-characters.d.ts +1 -1
  19. package/dist/lib/binary-utils/get-first-characters.d.ts.map +1 -1
  20. package/dist/lib/binary-utils/get-first-characters.js +1 -0
  21. package/dist/lib/binary-utils/get-first-characters.js.map +1 -0
  22. package/dist/lib/binary-utils/memory-conversion-utils.d.ts +10 -4
  23. package/dist/lib/binary-utils/memory-conversion-utils.d.ts.map +1 -1
  24. package/dist/lib/binary-utils/memory-conversion-utils.js +40 -4
  25. package/dist/lib/binary-utils/memory-conversion-utils.js.map +1 -0
  26. package/dist/lib/binary-utils/memory-copy-utils.js +1 -0
  27. package/dist/lib/binary-utils/memory-copy-utils.js.map +1 -0
  28. package/dist/lib/env-utils/assert.js +1 -0
  29. package/dist/lib/env-utils/assert.js.map +1 -0
  30. package/dist/lib/env-utils/globals.js +1 -0
  31. package/dist/lib/env-utils/globals.js.map +1 -0
  32. package/dist/lib/file-provider/data-view-file.d.ts.map +1 -1
  33. package/dist/lib/file-provider/data-view-file.js +3 -1
  34. package/dist/lib/file-provider/data-view-file.js.map +1 -0
  35. package/dist/lib/file-provider/file-handle-file.js +1 -0
  36. package/dist/lib/file-provider/file-handle-file.js.map +1 -0
  37. package/dist/lib/file-provider/file-provider-interface.js +1 -0
  38. package/dist/lib/file-provider/file-provider-interface.js.map +1 -0
  39. package/dist/lib/file-provider/file-provider.js +1 -0
  40. package/dist/lib/file-provider/file-provider.js.map +1 -0
  41. package/dist/lib/files/blob-file.js +1 -0
  42. package/dist/lib/files/blob-file.js.map +1 -0
  43. package/dist/lib/files/file.js +1 -0
  44. package/dist/lib/files/file.js.map +1 -0
  45. package/dist/lib/files/http-file.js +1 -0
  46. package/dist/lib/files/http-file.js.map +1 -0
  47. package/dist/lib/files/node-file-facade.js +1 -0
  48. package/dist/lib/files/node-file-facade.js.map +1 -0
  49. package/dist/lib/files/sources.js +1 -0
  50. package/dist/lib/files/sources.js.map +1 -0
  51. package/dist/lib/filesystems/filesystem.js +1 -0
  52. package/dist/lib/filesystems/filesystem.js.map +1 -0
  53. package/dist/lib/filesystems/node-filesystem-facade.js +1 -0
  54. package/dist/lib/filesystems/node-filesystem-facade.js.map +1 -0
  55. package/dist/lib/iterators/async-iteration.d.ts +14 -14
  56. package/dist/lib/iterators/async-iteration.d.ts.map +1 -1
  57. package/dist/lib/iterators/async-iteration.js +68 -16
  58. package/dist/lib/iterators/async-iteration.js.map +1 -0
  59. package/dist/lib/iterators/text-iterators.js +2 -1
  60. package/dist/lib/iterators/text-iterators.js.map +1 -0
  61. package/dist/lib/javascript-utils/is-type.d.ts +59 -0
  62. package/dist/lib/javascript-utils/is-type.d.ts.map +1 -0
  63. package/dist/lib/javascript-utils/is-type.js +68 -0
  64. package/dist/lib/javascript-utils/is-type.js.map +1 -0
  65. package/dist/lib/log-utils/log.js +2 -1
  66. package/dist/lib/log-utils/log.js.map +1 -0
  67. package/dist/lib/module-utils/js-module-utils.js +1 -0
  68. package/dist/lib/module-utils/js-module-utils.js.map +1 -0
  69. package/dist/lib/node/buffer.browser.js +1 -0
  70. package/dist/lib/node/buffer.browser.js.map +1 -0
  71. package/dist/lib/node/buffer.js +1 -0
  72. package/dist/lib/node/buffer.js.map +1 -0
  73. package/dist/lib/node/fs.browser.js +1 -0
  74. package/dist/lib/node/fs.browser.js.map +1 -0
  75. package/dist/lib/node/promisify.js +1 -0
  76. package/dist/lib/node/promisify.js.map +1 -0
  77. package/dist/lib/node/stream.browser.js +1 -0
  78. package/dist/lib/node/stream.browser.js.map +1 -0
  79. package/dist/lib/node/stream.js +1 -0
  80. package/dist/lib/node/stream.js.map +1 -0
  81. package/dist/lib/option-utils/merge-options.js +1 -0
  82. package/dist/lib/option-utils/merge-options.js.map +1 -0
  83. package/dist/lib/parser-utils/parse-json.js +1 -0
  84. package/dist/lib/parser-utils/parse-json.js.map +1 -0
  85. package/dist/lib/path-utils/file-aliases.js +1 -0
  86. package/dist/lib/path-utils/file-aliases.js.map +1 -0
  87. package/dist/lib/path-utils/get-cwd.js +1 -0
  88. package/dist/lib/path-utils/get-cwd.js.map +1 -0
  89. package/dist/lib/path-utils/path.js +2 -1
  90. package/dist/lib/path-utils/path.js.map +1 -0
  91. package/dist/lib/request-utils/request-scheduler.d.ts +4 -0
  92. package/dist/lib/request-utils/request-scheduler.d.ts.map +1 -1
  93. package/dist/lib/request-utils/request-scheduler.js +15 -0
  94. package/dist/lib/request-utils/request-scheduler.js.map +1 -0
  95. package/dist/lib/sources/data-source.d.ts +4 -4
  96. package/dist/lib/sources/data-source.d.ts.map +1 -1
  97. package/dist/lib/sources/data-source.js +2 -1
  98. package/dist/lib/sources/data-source.js.map +1 -0
  99. package/dist/lib/sources/image-source.js +1 -0
  100. package/dist/lib/sources/image-source.js.map +1 -0
  101. package/dist/lib/sources/image-tile-source.js +1 -0
  102. package/dist/lib/sources/image-tile-source.js.map +1 -0
  103. package/dist/lib/sources/tile-source-adapter.js +1 -0
  104. package/dist/lib/sources/tile-source-adapter.js.map +1 -0
  105. package/dist/lib/sources/tile-source.js +1 -0
  106. package/dist/lib/sources/tile-source.js.map +1 -0
  107. package/dist/lib/sources/utils/image-type.js +1 -0
  108. package/dist/lib/sources/utils/image-type.js.map +1 -0
  109. package/dist/lib/sources/utils/utils.js +2 -1
  110. package/dist/lib/sources/utils/utils.js.map +1 -0
  111. package/dist/lib/sources/vector-source.js +1 -0
  112. package/dist/lib/sources/vector-source.js.map +1 -0
  113. package/dist/lib/sources/vector-tile-source.js +1 -0
  114. package/dist/lib/sources/vector-tile-source.js.map +1 -0
  115. package/dist/lib/worker-loader-utils/create-loader-worker.js +5 -1
  116. package/dist/lib/worker-loader-utils/create-loader-worker.js.map +1 -0
  117. package/dist/lib/worker-loader-utils/encode-with-worker.d.ts +1 -1
  118. package/dist/lib/worker-loader-utils/encode-with-worker.d.ts.map +1 -1
  119. package/dist/lib/worker-loader-utils/encode-with-worker.js +5 -2
  120. package/dist/lib/worker-loader-utils/encode-with-worker.js.map +1 -0
  121. package/dist/lib/worker-loader-utils/parse-with-worker.d.ts +1 -1
  122. package/dist/lib/worker-loader-utils/parse-with-worker.d.ts.map +1 -1
  123. package/dist/lib/worker-loader-utils/parse-with-worker.js +6 -3
  124. package/dist/lib/worker-loader-utils/parse-with-worker.js.map +1 -0
  125. package/dist/loader-types.d.ts +91 -67
  126. package/dist/loader-types.d.ts.map +1 -1
  127. package/dist/loader-types.js +1 -0
  128. package/dist/loader-types.js.map +1 -0
  129. package/dist/source-types.js +1 -0
  130. package/dist/source-types.js.map +1 -0
  131. package/dist/types.d.ts +9 -4
  132. package/dist/types.d.ts.map +1 -1
  133. package/dist/types.js +1 -0
  134. package/dist/types.js.map +1 -0
  135. package/dist/workers/json-worker.js +1 -0
  136. package/dist/workers/json-worker.js.map +1 -0
  137. package/dist/writer-types.d.ts +14 -7
  138. package/dist/writer-types.d.ts.map +1 -1
  139. package/dist/writer-types.js +1 -0
  140. package/dist/writer-types.js.map +1 -0
  141. package/package.json +4 -4
  142. package/src/index.ts +36 -9
  143. package/src/lib/binary-utils/array-buffer-utils.ts +3 -3
  144. package/src/lib/binary-utils/get-first-characters.ts +1 -1
  145. package/src/lib/binary-utils/memory-conversion-utils.ts +58 -8
  146. package/src/lib/file-provider/data-view-file.ts +6 -1
  147. package/src/lib/iterators/async-iteration.ts +94 -19
  148. package/src/lib/iterators/text-iterators.ts +1 -1
  149. package/src/lib/javascript-utils/is-type.ts +130 -0
  150. package/src/lib/node/buffer.ts +1 -1
  151. package/src/lib/path-utils/path.ts +1 -1
  152. package/src/lib/request-utils/request-scheduler.ts +15 -0
  153. package/src/lib/sources/data-source.ts +5 -5
  154. package/src/lib/sources/utils/utils.ts +1 -1
  155. package/src/lib/worker-loader-utils/create-loader-worker.ts +4 -1
  156. package/src/lib/worker-loader-utils/encode-with-worker.ts +5 -2
  157. package/src/lib/worker-loader-utils/parse-with-worker.ts +5 -3
  158. package/src/loader-types.ts +115 -84
  159. package/src/types.ts +17 -9
  160. package/src/writer-types.ts +15 -8
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export type {
9
9
  DataType,
10
10
  SyncDataType,
11
11
  BatchableDataType,
12
+ TransformBatches,
12
13
  // numeric array types
13
14
  TypedArray,
14
15
  BigTypedArray,
@@ -30,6 +31,7 @@ export type {
30
31
  Loader,
31
32
  LoaderWithParser,
32
33
  LoaderContext,
34
+ StrictLoaderOptions,
33
35
  LoaderOptions,
34
36
  LoaderOptionsType,
35
37
  LoaderReturnType,
@@ -66,6 +68,27 @@ export {
66
68
 
67
69
  export {log} from './lib/log-utils/log';
68
70
 
71
+ export type {ReadableStreamType} from './lib/javascript-utils/is-type';
72
+ export {
73
+ isObject,
74
+ isPureObject,
75
+ isArrayBuffer,
76
+ isArrayBufferLike,
77
+ isPromise,
78
+ isIterable,
79
+ isAsyncIterable,
80
+ isIterator,
81
+ isResponse,
82
+ isFile,
83
+ isBlob,
84
+ isWritableDOMStream,
85
+ isReadableDOMStream,
86
+ isWritableNodeStream,
87
+ isReadableNodeStream,
88
+ isReadableStream,
89
+ isWritableStream
90
+ } from './lib/javascript-utils/is-type';
91
+
69
92
  // Options and modules
70
93
  export type {RequiredOptions} from './lib/option-utils/merge-options';
71
94
  export {mergeOptions, getRequiredOptions} from './lib/option-utils/merge-options';
@@ -107,7 +130,11 @@ export {
107
130
  makeLineIterator,
108
131
  makeNumberedLineIterator
109
132
  } from './lib/iterators/text-iterators';
110
- export {forEach, concatenateArrayBuffersAsync} from './lib/iterators/async-iteration';
133
+ export {
134
+ forEach,
135
+ concatenateArrayBuffersAsync,
136
+ toArrayBufferIterator
137
+ } from './lib/iterators/async-iteration';
111
138
 
112
139
  // REQUEST UTILS
113
140
  export {default as RequestScheduler} from './lib/request-utils/request-scheduler';
@@ -124,7 +151,14 @@ export {JSONLoader} from './json-loader';
124
151
  // Node.js emulation (can be used in browser)
125
152
 
126
153
  // Avoid direct use of `Buffer` which pulls in 50KB polyfill
127
- export {isBuffer, toBuffer, toArrayBuffer} from './lib/binary-utils/memory-conversion-utils';
154
+ export {
155
+ isBuffer,
156
+ toBuffer,
157
+ toArrayBuffer,
158
+ toArrayBufferView,
159
+ copyToArrayBuffer,
160
+ ensureArrayBuffer
161
+ } from './lib/binary-utils/memory-conversion-utils';
128
162
 
129
163
  // Note.js wrappers (can be safely imported, but not used in browser)
130
164
 
@@ -149,13 +183,6 @@ export {NodeFileFacade as NodeFile} from './lib/files/node-file-facade';
149
183
  export type {FileSystem, RandomAccessFileSystem} from './lib/filesystems/filesystem';
150
184
  export {NodeFileSystemFacade as NodeFilesystem} from './lib/filesystems/node-filesystem-facade';
151
185
 
152
- // TODO - replace with ReadableFile
153
- export type {FileProviderInterface} from './lib/file-provider/file-provider-interface';
154
- export {isFileProvider} from './lib/file-provider/file-provider-interface';
155
- export {FileProvider} from './lib/file-provider/file-provider';
156
- export {FileHandleFile} from './lib/file-provider/file-handle-file';
157
- export {DataViewFile} from './lib/file-provider/data-view-file';
158
-
159
186
  // EXPERIMENTAL: DATA SOURCES
160
187
  export type {Source, SourceArrayOptionsType, SourceArrayDataSourceType} from './source-types';
161
188
 
@@ -7,8 +7,8 @@ import {TypedArray} from '../../types';
7
7
  * @param byteLength
8
8
  */
9
9
  export function compareArrayBuffers(
10
- arrayBuffer1: ArrayBuffer,
11
- arrayBuffer2: ArrayBuffer,
10
+ arrayBuffer1: ArrayBufferLike,
11
+ arrayBuffer2: ArrayBufferLike,
12
12
  byteLength?: number
13
13
  ): boolean {
14
14
  byteLength = byteLength || arrayBuffer1.byteLength;
@@ -97,7 +97,7 @@ export function concatenateTypedArrays<T>(...typedArrays: T[]): T {
97
97
  * @param byteLength
98
98
  */
99
99
  export function sliceArrayBuffer(
100
- arrayBuffer: ArrayBuffer,
100
+ arrayBuffer: ArrayBufferLike,
101
101
  byteOffset: number,
102
102
  byteLength?: number
103
103
  ): ArrayBuffer {
@@ -30,7 +30,7 @@ export function getFirstCharacters(data: string | ArrayBuffer, length: number =
30
30
  * @returns
31
31
  */
32
32
  export function getMagicString(
33
- arrayBuffer: ArrayBuffer,
33
+ arrayBuffer: ArrayBufferLike,
34
34
  byteOffset: number,
35
35
  length: number
36
36
  ): string {
@@ -2,12 +2,13 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
+ import {isSharedArrayBuffer} from '../javascript-utils/is-type';
5
6
  import * as node from '../node/buffer';
6
7
 
7
8
  /**
8
9
  * Check for Node.js `Buffer` (without triggering bundler to include Buffer polyfill on browser)
9
10
  */
10
- export function isBuffer(value: any): boolean {
11
+ export function isBuffer(value: any): value is Buffer {
11
12
  return value && typeof value === 'object' && value.isBuffer;
12
13
  }
13
14
 
@@ -15,14 +16,16 @@ export function isBuffer(value: any): boolean {
15
16
  * Converts to Node.js `Buffer` (without triggering bundler to include Buffer polyfill on browser)
16
17
  * @todo better data type
17
18
  */
18
- export function toBuffer(data: any): Buffer {
19
- return node.toBuffer ? node.toBuffer(data) : data;
19
+ export function toBuffer(data: unknown): Buffer {
20
+ return node.toBuffer ? node.toBuffer(data as any) : (data as Buffer);
20
21
  }
21
22
 
22
23
  /**
23
- * Convert an object to an array buffer
24
+ * Convert an object to an array buffer. Handles SharedArrayBuffers.
24
25
  */
25
- export function toArrayBuffer(data: unknown): ArrayBuffer {
26
+ export function toArrayBuffer(
27
+ data: Buffer | ArrayBufferLike | ArrayBufferView | string | Blob
28
+ ): ArrayBuffer {
26
29
  // Note: Should be called first, Buffers can trigger other detections below
27
30
  if (isBuffer(data)) {
28
31
  return node.toArrayBuffer(data);
@@ -32,12 +35,18 @@ export function toArrayBuffer(data: unknown): ArrayBuffer {
32
35
  return data;
33
36
  }
34
37
 
35
- // Careful - Node Buffers look like Uint8Arrays (keep after isBuffer)
38
+ if (isSharedArrayBuffer(data)) {
39
+ return copyToArrayBuffer(data);
40
+ }
41
+
42
+ // Node Buffers look like Uint8Arrays (Check isBuffer first)
36
43
  if (ArrayBuffer.isView(data)) {
44
+ // TODO - ArrayBufferLike type mess
45
+ const buffer = data.buffer as ArrayBuffer;
37
46
  if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
38
- return data.buffer;
47
+ return buffer;
39
48
  }
40
- return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
49
+ return buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
41
50
  }
42
51
 
43
52
  if (typeof data === 'string') {
@@ -53,3 +62,44 @@ export function toArrayBuffer(data: unknown): ArrayBuffer {
53
62
 
54
63
  throw new Error('toArrayBuffer');
55
64
  }
65
+
66
+ /** Ensure that SharedArrayBuffers are copied into ArrayBuffers */
67
+ export function ensureArrayBuffer(bufferSource: ArrayBufferLike | ArrayBufferView): ArrayBuffer {
68
+ if (bufferSource instanceof ArrayBuffer) {
69
+ return bufferSource;
70
+ }
71
+
72
+ if (isSharedArrayBuffer(bufferSource)) {
73
+ return copyToArrayBuffer(bufferSource);
74
+ }
75
+
76
+ const {buffer, byteOffset, byteLength} = bufferSource;
77
+ if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) {
78
+ return buffer;
79
+ }
80
+ return copyToArrayBuffer(buffer, byteOffset, byteLength);
81
+ }
82
+
83
+ /** Copies an ArrayBuffer or a section of an ArrayBuffer to a new ArrayBuffer, handles SharedArrayBuffers */
84
+ export function copyToArrayBuffer(
85
+ buffer: ArrayBufferLike,
86
+ byteOffset = 0,
87
+ byteLength = buffer.byteLength - byteOffset
88
+ ): ArrayBuffer {
89
+ const view = new Uint8Array(buffer, byteOffset, byteLength);
90
+ const copy = new Uint8Array(view.length);
91
+ copy.set(view);
92
+ return copy.buffer;
93
+ }
94
+
95
+ /** Convert an object to an ArrayBufferView, handles SharedArrayBuffers */
96
+ export function toArrayBufferView(
97
+ data: ArrayBufferLike | ArrayBufferView
98
+ ): ArrayBuffer | ArrayBufferView {
99
+ if (ArrayBuffer.isView(data)) {
100
+ return data;
101
+ }
102
+
103
+ // Create a view to support ArrayBufferLike sources such as SharedArrayBuffer
104
+ return new Uint8Array(data);
105
+ }
@@ -1,4 +1,5 @@
1
1
  import {FileProviderInterface} from './file-provider-interface';
2
+ import {copyToArrayBuffer} from '../binary-utils/memory-conversion-utils';
2
3
 
3
4
  /**
4
5
  * Checks if bigint can be converted to number and convert it if possible
@@ -64,7 +65,11 @@ export class DataViewFile implements FileProviderInterface {
64
65
  * @param endOffset The offset, in bytes, from the start of the file where to end reading the data.
65
66
  */
66
67
  async slice(startOffset: bigint, endOffset: bigint): Promise<ArrayBuffer> {
67
- return this.file.buffer.slice(toNumber(startOffset), toNumber(endOffset));
68
+ return copyToArrayBuffer(
69
+ this.file.buffer,
70
+ toNumber(startOffset + BigInt(this.file.byteOffset)),
71
+ toNumber(endOffset - startOffset)
72
+ );
68
73
  }
69
74
 
70
75
  /** the length (in bytes) of the data. */
@@ -3,23 +3,22 @@ import {concatenateArrayBuffers} from '../binary-utils/array-buffer-utils';
3
3
  // GENERAL UTILITIES
4
4
 
5
5
  /**
6
- * Iterate over async iterator, without resetting iterator if end is not reached
7
- * - forEach intentionally does not reset iterator if exiting loop prematurely
8
- * so that iteration can continue in a second loop
9
- * - It is recommended to use a standard for-await as last loop to ensure
10
- * iterator gets properly reset
11
- *
12
- * TODO - optimize using sync iteration if argument is an Iterable?
13
- *
14
- * @param iterator
15
- * @param visitor
6
+ * Iterates over an {@link AsyncIterable} or {@link Iterable}, invoking `visitor` for each yielded
7
+ * value without rewinding the iterator when exiting early. This enables the caller to continue
8
+ * iterating in another loop after `visitor` signals cancellation.
16
9
  */
17
- export async function forEach(iterator, visitor) {
10
+ export async function forEach<TValue>(
11
+ iterable: AsyncIterable<TValue> | Iterable<TValue> | AsyncIterator<TValue>,
12
+ visitor: (value: TValue) => any
13
+ ) {
14
+ const iterator = toAsyncIterator(iterable);
18
15
  // eslint-disable-next-line
19
16
  while (true) {
20
17
  const {done, value} = await iterator.next();
21
18
  if (done) {
22
- iterator.return();
19
+ if (iterator.return) {
20
+ iterator.return();
21
+ }
23
22
  return;
24
23
  }
25
24
  const cancel = visitor(value);
@@ -29,19 +28,19 @@ export async function forEach(iterator, visitor) {
29
28
  }
30
29
  }
31
30
 
32
- // Breaking big data into iterable chunks, concatenating iterable chunks into big data objects
33
-
34
31
  /**
35
- * Concatenates all data chunks yielded by an (async) iterator
36
- * This function can e.g. be used to enable atomic parsers to work on (async) iterator inputs
32
+ * Concatenates all binary chunks yielded by an async or sync iterator.
33
+ * Supports `ArrayBuffer`, typed array views, and `ArrayBufferLike` sources (e.g. `SharedArrayBuffer`).
34
+ * This allows atomic parsers to operate on iterator inputs by materializing them into a single buffer.
37
35
  */
38
-
39
36
  export async function concatenateArrayBuffersAsync(
40
- asyncIterator: AsyncIterable<ArrayBuffer> | Iterable<ArrayBuffer>
37
+ asyncIterator:
38
+ | AsyncIterable<ArrayBufferLike | ArrayBufferView>
39
+ | Iterable<ArrayBufferLike | ArrayBufferView>
41
40
  ): Promise<ArrayBuffer> {
42
41
  const arrayBuffers: ArrayBuffer[] = [];
43
42
  for await (const chunk of asyncIterator) {
44
- arrayBuffers.push(chunk);
43
+ arrayBuffers.push(copyToArrayBuffer(chunk));
45
44
  }
46
45
  return concatenateArrayBuffers(...arrayBuffers);
47
46
  }
@@ -55,3 +54,79 @@ export async function concatenateStringsAsync(
55
54
  }
56
55
  return strings.join('');
57
56
  }
57
+
58
+ /**
59
+ * Normalizes binary chunk iterators to yield `ArrayBuffer` instances.
60
+ * Accepts `ArrayBuffer`, `ArrayBufferView`, and `ArrayBufferLike` sources
61
+ * (e.g. `SharedArrayBuffer`) and returns a copied `ArrayBuffer` for each chunk.
62
+ */
63
+ export async function* toArrayBufferIterator(
64
+ asyncIterator:
65
+ | AsyncIterable<ArrayBufferLike | ArrayBufferView>
66
+ | Iterable<ArrayBufferLike | ArrayBufferView>
67
+ ): AsyncIterable<ArrayBuffer> {
68
+ for await (const chunk of asyncIterator) {
69
+ yield copyToArrayBuffer(chunk);
70
+ }
71
+ }
72
+
73
+ function copyToArrayBuffer(chunk: ArrayBufferLike | ArrayBufferView | ArrayBuffer): ArrayBuffer {
74
+ if (chunk instanceof ArrayBuffer) {
75
+ return chunk;
76
+ }
77
+
78
+ if (ArrayBuffer.isView(chunk)) {
79
+ const {buffer, byteOffset, byteLength} = chunk;
80
+ return copyFromBuffer(buffer, byteOffset, byteLength);
81
+ }
82
+
83
+ return copyFromBuffer(chunk as ArrayBufferLike);
84
+ }
85
+
86
+ function copyFromBuffer(
87
+ buffer: ArrayBufferLike,
88
+ byteOffset = 0,
89
+ byteLength = buffer.byteLength - byteOffset
90
+ ): ArrayBuffer {
91
+ const view = new Uint8Array(buffer, byteOffset, byteLength);
92
+ const copy = new Uint8Array(view.length);
93
+ copy.set(view);
94
+ return copy.buffer;
95
+ }
96
+
97
+ function toAsyncIterator<TValue>(
98
+ iterable: AsyncIterable<TValue> | Iterable<TValue> | AsyncIterator<TValue>
99
+ ): AsyncIterator<TValue> {
100
+ if (typeof iterable[Symbol.asyncIterator] === 'function') {
101
+ return iterable[Symbol.asyncIterator]();
102
+ }
103
+
104
+ if (typeof iterable[Symbol.iterator] === 'function') {
105
+ const iterator = iterable[Symbol.iterator]();
106
+ return iteratorToAsyncIterator(iterator);
107
+ }
108
+
109
+ return iterable as AsyncIterator<TValue>;
110
+ }
111
+
112
+ function iteratorToAsyncIterator<T>(iterator: Iterator<T>): AsyncIterator<T> {
113
+ return {
114
+ next(value?: any) {
115
+ return Promise.resolve(iterator.next(value));
116
+ },
117
+
118
+ return(value?: any) {
119
+ if (typeof iterator.return === 'function') {
120
+ return Promise.resolve(iterator.return(value));
121
+ }
122
+ return Promise.resolve({done: true, value});
123
+ },
124
+
125
+ throw(error?: any) {
126
+ if (typeof iterator.throw === 'function') {
127
+ return Promise.resolve(iterator.throw(error));
128
+ }
129
+ return Promise.reject(error);
130
+ }
131
+ };
132
+ }
@@ -23,7 +23,7 @@ export async function* makeTextEncoderIterator(
23
23
  ): AsyncIterable<ArrayBuffer> {
24
24
  const textEncoder = new TextEncoder();
25
25
  for await (const text of textIterator) {
26
- yield typeof text === 'string' ? textEncoder.encode(text) : text;
26
+ yield typeof text === 'string' ? textEncoder.encode(text).buffer : text;
27
27
  }
28
28
  }
29
29
 
@@ -0,0 +1,130 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ /* eslint-disable @typescript-eslint/unbound-method */
6
+
7
+ import type {Readable} from 'stream';
8
+
9
+ /** Minimal shape for Node.js Buffer-like values */
10
+ type NodeBufferLike = {buffer: ArrayBufferLike; isBuffer: true};
11
+
12
+ /** Minimal shape for Node.js writable streams */
13
+ type NodeWritableStream = {
14
+ end: (...args: unknown[]) => unknown;
15
+ write: (...args: unknown[]) => unknown;
16
+ writable: boolean;
17
+ };
18
+
19
+ /** Minimal shape for WritableStream-like DOM implementations */
20
+ type WritableDOMStreamLike = WritableStream | {abort: () => unknown; getWriter: () => unknown};
21
+
22
+ /** A DOM or Node readable stream */
23
+ export type ReadableStreamType = ReadableStream | Readable;
24
+
25
+ /** Checks whether a value is a boolean */
26
+ const isBoolean = (value: unknown): value is boolean => typeof value === 'boolean';
27
+
28
+ /** Checks whether a value is a function */
29
+ const isFunction = (value: unknown): value is (...args: unknown[]) => unknown =>
30
+ typeof value === 'function';
31
+
32
+ /** Checks whether a value is a non-null object */
33
+ export const isObject = (value: unknown): value is object =>
34
+ value !== null && typeof value === 'object';
35
+
36
+ /** Checks whether a value is a plain object (created by the Object constructor) */
37
+ export const isPureObject = (value: unknown): value is Record<string, unknown> =>
38
+ isObject(value) && value.constructor === {}.constructor;
39
+
40
+ /** Checks whether a value is an ArrayBuffer */
41
+ export const isArrayBuffer = (value: unknown): value is ArrayBuffer =>
42
+ typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer;
43
+
44
+ /** Checks whether a value is an ArrayBuffer */
45
+ export const isSharedArrayBuffer = (value: unknown): value is SharedArrayBuffer =>
46
+ typeof SharedArrayBuffer !== 'undefined' && value instanceof SharedArrayBuffer;
47
+
48
+ /** Checks whether a value is ArrayBuffer-like */
49
+ export const isArrayBufferLike = (value: unknown): value is ArrayBufferLike =>
50
+ isObject(value) &&
51
+ typeof (value as ArrayBufferLike).byteLength === 'number' &&
52
+ typeof (value as ArrayBufferLike).slice === 'function';
53
+
54
+ /** Checks whether a value behaves like a promise */
55
+ export const isPromise = (value: unknown): value is Promise<unknown> =>
56
+ isObject(value) && 'then' in value && isFunction((value as {then: unknown}).then);
57
+
58
+ /** Checks whether a value implements the iterable protocol */
59
+ export const isIterable = (value: unknown): value is Iterable<unknown> =>
60
+ Boolean(value) && isFunction((value as Iterable<unknown>)[Symbol.iterator]);
61
+
62
+ /** Checks whether a value implements the async iterable protocol */
63
+ export const isAsyncIterable = (value: unknown): value is AsyncIterable<unknown> =>
64
+ Boolean(value) && isFunction((value as AsyncIterable<unknown>)[Symbol.asyncIterator]);
65
+
66
+ /** Checks whether a value is an iterator (has a next function) */
67
+ export const isIterator = (value: unknown): value is Iterator<unknown> =>
68
+ Boolean(value) && isFunction((value as Iterator<unknown>).next);
69
+
70
+ /** Checks whether a value is a fetch Response or a duck-typed equivalent */
71
+ export const isResponse = (value: unknown): value is Response =>
72
+ (typeof Response !== 'undefined' && value instanceof Response) ||
73
+ (isObject(value) &&
74
+ isFunction((value as {arrayBuffer?: unknown}).arrayBuffer) &&
75
+ isFunction((value as {text?: unknown}).text) &&
76
+ isFunction((value as {json?: unknown}).json));
77
+
78
+ /** Checks whether a value is a File */
79
+ export const isFile = (value: unknown): value is File =>
80
+ typeof File !== 'undefined' && value instanceof File;
81
+
82
+ /** Checks whether a value is a Blob */
83
+ export const isBlob = (value: unknown): value is Blob =>
84
+ typeof Blob !== 'undefined' && value instanceof Blob;
85
+
86
+ /** Checks for Node.js Buffers without triggering bundlers to include the Buffer polyfill */
87
+ export const isBuffer = (value: unknown): value is NodeBufferLike =>
88
+ Boolean(
89
+ value &&
90
+ typeof value === 'object' &&
91
+ (value as Partial<NodeBufferLike>).isBuffer &&
92
+ 'buffer' in (value as NodeBufferLike)
93
+ );
94
+
95
+ /** Checks whether a value looks like a DOM WritableStream */
96
+ export const isWritableDOMStream = (value: unknown): value is WritableDOMStreamLike =>
97
+ isObject(value) &&
98
+ isFunction((value as WritableDOMStreamLike).abort) &&
99
+ isFunction((value as WritableDOMStreamLike).getWriter);
100
+
101
+ /** Checks whether a value looks like a DOM ReadableStream */
102
+ export const isReadableDOMStream = (value: unknown): value is ReadableStream =>
103
+ (typeof ReadableStream !== 'undefined' && value instanceof ReadableStream) ||
104
+ (isObject(value) &&
105
+ isFunction((value as ReadableStream).tee) &&
106
+ isFunction((value as ReadableStream).cancel) &&
107
+ isFunction((value as ReadableStream).getReader));
108
+ // Not implemented in Firefox: && isFunction(x.pipeTo)
109
+
110
+ /** Checks whether a value looks like a Node.js writable stream */
111
+ export const isWritableNodeStream = (value: unknown): value is NodeWritableStream =>
112
+ isObject(value) &&
113
+ isFunction((value as NodeWritableStream).end) &&
114
+ isFunction((value as NodeWritableStream).write) &&
115
+ isBoolean((value as NodeWritableStream).writable);
116
+
117
+ /** Checks whether a value looks like a Node.js readable stream */
118
+ export const isReadableNodeStream = (value: unknown): value is Readable =>
119
+ isObject(value) &&
120
+ isFunction((value as Readable).read) &&
121
+ isFunction((value as Readable).pipe) &&
122
+ isBoolean((value as Readable).readable);
123
+
124
+ /** Checks whether a value is any readable stream (DOM or Node.js) */
125
+ export const isReadableStream = (value: unknown): value is ReadableStreamType =>
126
+ isReadableDOMStream(value) || isReadableNodeStream(value);
127
+
128
+ /** Checks whether a value is any writable stream (DOM or Node.js) */
129
+ export const isWritableStream = (value: unknown): value is WritableStream | NodeWritableStream =>
130
+ isWritableDOMStream(value) || isWritableNodeStream(value);
@@ -28,7 +28,7 @@ export function toBuffer(binaryData: ArrayBuffer | Buffer): Buffer {
28
28
  }
29
29
 
30
30
  if (ArrayBuffer.isView(binaryData)) {
31
- binaryData = binaryData.buffer;
31
+ binaryData = binaryData.buffer as ArrayBuffer;
32
32
  }
33
33
 
34
34
  // TODO - move to loaders.gl/polyfills
@@ -8,7 +8,7 @@ import {getCWD} from './get-cwd';
8
8
  */
9
9
  export function filename(url: string): string {
10
10
  const slashIndex = url ? url.lastIndexOf('/') : -1;
11
- return slashIndex >= 0 ? url.substr(slashIndex + 1) : '';
11
+ return slashIndex >= 0 ? url.substr(slashIndex + 1) : url;
12
12
  }
13
13
 
14
14
  /**
@@ -68,6 +68,21 @@ export default class RequestScheduler {
68
68
  this.stats.get(STAT_ACTIVE_REQUESTS_EVER);
69
69
  }
70
70
 
71
+ /**
72
+ * Update scheduler props. Preserves active and queued requests.
73
+ */
74
+ setProps(props: Omit<RequestSchedulerProps, 'id'>): void {
75
+ if (props.throttleRequests !== undefined) {
76
+ this.props.throttleRequests = props.throttleRequests;
77
+ }
78
+ if (props.maxRequests !== undefined) {
79
+ this.props.maxRequests = props.maxRequests;
80
+ }
81
+ if (props.debounceTime !== undefined) {
82
+ this.props.debounceTime = props.debounceTime;
83
+ }
84
+ }
85
+
71
86
  /**
72
87
  * Called by an application that wants to issue a request, without having it deeply queued by the browser
73
88
  *
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {LoaderOptions, Loader} from '../../loader-types';
5
+ import type {Loader, StrictLoaderOptions} from '../../loader-types';
6
6
  import type {RequiredOptions} from '../option-utils/merge-options';
7
7
  import {mergeOptions} from '../option-utils/merge-options';
8
8
  import {resolvePath} from '../path-utils/file-aliases';
@@ -15,7 +15,7 @@ export type DataSourceOptions = Partial<{
15
15
  /** Any dataset attributions (in case underlying metadata does not include attributions) */
16
16
  attributions?: string[];
17
17
  /** LoaderOptions provide an option to override `fetch`. Will also be passed to any sub loaders */
18
- loadOptions?: LoaderOptions;
18
+ loadOptions?: StrictLoaderOptions;
19
19
  /** Make additional loaders available to the data source */
20
20
  loaders?: Loader[];
21
21
  };
@@ -39,7 +39,7 @@ export abstract class DataSource<DataT, OptionsT extends DataSourceOptions> {
39
39
  readonly url: string;
40
40
 
41
41
  /** The actual load options, if calling a loaders.gl loader */
42
- loadOptions: LoaderOptions;
42
+ loadOptions: StrictLoaderOptions;
43
43
  /** A resolved fetch function extracted from loadOptions prop */
44
44
  fetch: (url: string, options?: RequestInit) => Promise<Response>;
45
45
  _needsRefresh: boolean = true;
@@ -93,8 +93,8 @@ export abstract class DataSource<DataT, OptionsT extends DataSourceOptions> {
93
93
  * @param options
94
94
  * @param context
95
95
  */
96
- export function getFetchFunction(options?: LoaderOptions) {
97
- const fetchFunction = options?.fetch;
96
+ export function getFetchFunction(options?: StrictLoaderOptions) {
97
+ const fetchFunction = options?.core?.fetch;
98
98
 
99
99
  // options.fetch can be a function
100
100
  if (fetchFunction && typeof fetchFunction === 'function') {
@@ -12,7 +12,7 @@ import type {LoaderOptions} from '@loaders.gl/loader-utils';
12
12
  * @param context
13
13
  */
14
14
  export function getFetchFunction(options?: LoaderOptions) {
15
- const fetchFunction = options?.fetch;
15
+ const fetchFunction = options?.core?.fetch;
16
16
 
17
17
  // options.fetch can be a function
18
18
  if (fetchFunction && typeof fetchFunction === 'function') {
@@ -117,7 +117,10 @@ async function parseData({
117
117
  options = {
118
118
  ...options,
119
119
  modules: (loader && loader.options && loader.options.modules) || {},
120
- worker: false
120
+ core: {
121
+ ...options.core,
122
+ worker: false
123
+ }
121
124
  };
122
125
 
123
126
  return await parser(data, {...options}, context, loader);
@@ -12,10 +12,13 @@ export function canEncodeWithWorker(writer: Writer, options?: WriterOptions) {
12
12
  return false;
13
13
  }
14
14
 
15
+ const nodeWorkers = options?._nodeWorkers ?? options?.core?._nodeWorkers;
16
+ const useWorkers = options?.worker ?? options?.core?.worker;
17
+
15
18
  // Node workers are still experimental
16
- if (!isBrowser && !options?._nodeWorkers) {
19
+ if (!isBrowser && !nodeWorkers) {
17
20
  return false;
18
21
  }
19
22
 
20
- return writer.worker && options?.worker;
23
+ return Boolean(writer.worker && useWorkers);
21
24
  }
@@ -19,11 +19,13 @@ export function canParseWithWorker(loader: Loader, options?: LoaderOptions) {
19
19
  }
20
20
 
21
21
  // Node workers are still experimental
22
- if (!isBrowser && !options?._nodeWorkers) {
22
+ const nodeWorkers = options?._nodeWorkers ?? options?.core?._nodeWorkers;
23
+ if (!isBrowser && !nodeWorkers) {
23
24
  return false;
24
25
  }
25
26
 
26
- return loader.worker && options?.worker;
27
+ const useWorkers = options?.worker ?? options?.core?.worker;
28
+ return Boolean(loader.worker && useWorkers);
27
29
  }
28
30
 
29
31
  /**
@@ -40,7 +42,7 @@ export async function parseWithWorker(
40
42
  const name = loader.id; // TODO
41
43
  const url = getWorkerURL(loader, options);
42
44
 
43
- const workerFarm = WorkerFarm.getWorkerFarm(options);
45
+ const workerFarm = WorkerFarm.getWorkerFarm(options?.core);
44
46
  const workerPool = workerFarm.getWorkerPool({name, url});
45
47
 
46
48
  // options.log object contains functions which cannot be transferred