• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / loaders.gl / 24153816851

08 Apr 2026 07:17PM UTC coverage: 53.247% (-12.1%) from 65.319%
24153816851

push

github

web-flow
chore: Move from tape to vitest (#3351)

8651 of 17291 branches covered (50.03%)

Branch coverage included in aggregate %.

7 of 7 new or added lines in 1 file covered. (100.0%)

2031 existing lines in 296 files now uncovered.

17563 of 31940 relevant lines covered (54.99%)

5279.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.38
/modules/core/src/lib/api/parse.ts
1
// loaders.gl
2
// SPDX-License-Identifier: MIT
3
// Copyright (c) vis.gl contributors
4

5
import type {
6
  Loader,
7
  LoaderContext,
8
  LoaderOptions,
9
  DataType,
10
  LoaderWithParser,
11
  LoaderOptionsType,
12
  LoaderReturnType,
13
  LoaderArrayOptionsType,
14
  LoaderArrayReturnType,
15
  StrictLoaderOptions
16
} from '@loaders.gl/loader-utils';
17
import {
18
  parseWithWorker,
19
  canParseWithWorker,
20
  mergeOptions,
21
  isResponse
22
} from '@loaders.gl/loader-utils';
23
import {assert, validateWorkerVersion} from '@loaders.gl/worker-utils';
24
import {isLoaderObject} from '../loader-utils/normalize-loader';
25
import {normalizeOptions} from '../loader-utils/option-utils';
26
import {getArrayBufferOrStringFromData} from '../loader-utils/get-data';
27
import {getLoaderContext, getLoadersFromContext} from '../loader-utils/loader-context';
28
import {getResourceUrl} from '../utils/resource-utils';
29
import {selectLoader} from './select-loader';
30

31
// type LoaderArrayType<T> = T extends (infer Loader)[] ? LoaderOptionsType<Loader> : T
32

33
/**
34
 * Parses `data` asynchronously using the supplied loader
35
 */
36
export async function parse<
37
  LoaderT extends Loader,
38
  OptionsT extends LoaderOptions = LoaderOptionsType<LoaderT>
39
>(
40
  data: DataType | Promise<DataType>,
41
  loader: LoaderT,
42
  options?: OptionsT,
43
  context?: LoaderContext
44
): Promise<LoaderReturnType<LoaderT>>;
45

46
/**
47
 * Parses `data` asynchronously by matching one of the supplied loader
48
 */
49
export async function parse<
50
  LoaderArrayT extends Loader[],
51
  OptionsT extends LoaderOptions = LoaderArrayOptionsType<LoaderArrayT>
52
>(
53
  data: DataType | Promise<DataType>,
54
  loaders: LoaderArrayT,
55
  options?: OptionsT,
56
  context?: LoaderContext
57
): Promise<LoaderArrayReturnType<LoaderArrayT>>;
58

59
/**
60
 * Parses data asynchronously by matching a pre-registered loader
61
 * @deprecated Loader registration is deprecated, use parse(data, loaders, options) instead
62
 */
63
export async function parse(
64
  data: DataType | Promise<DataType>,
65
  options?: LoaderOptions
66
): Promise<unknown>;
67

68
/**
69
 * Parses `data` using a specified loader
70
 * @param data
71
 * @param loaders
72
 * @param options
73
 * @param context
74
 */
75
// implementation signature
76
export async function parse(
77
  data: DataType | Promise<DataType>,
78
  loaders?: Loader | Loader[] | LoaderOptions,
79
  options?: LoaderOptions,
80
  context?: LoaderContext
81
): Promise<unknown> {
82
  // Signature: parse(data, options, context | url)
83
  // Uses registered loaders
84
  if (loaders && !Array.isArray(loaders) && !isLoaderObject(loaders)) {
996✔
85
    context = undefined; // context not supported in short signature
7✔
86
    options = loaders as LoaderOptions;
7✔
87
    loaders = undefined;
7✔
88
  }
89

90
  data = await data; // Resolve any promise
996✔
91
  options = options || ({} as LoaderOptions); // Could be invalid...
996✔
92

93
  // Extract a url for auto detection
94
  const url = getResourceUrl(data);
996✔
95

96
  // Chooses a loader (and normalizes it)
97
  // Also use any loaders in the context, new loaders take priority
98
  const typedLoaders = loaders as Loader | Loader[] | undefined;
996✔
99
  const candidateLoaders = getLoadersFromContext(typedLoaders, context);
996✔
100
  // todo hacky type cast
101
  const loader = await selectLoader(data as ArrayBuffer, candidateLoaders, options);
996✔
102
  // Note: if no loader was found, if so just return null
103
  if (!loader) {
993!
UNCOV
104
    return null;
×
105
  }
106

107
  // Normalize options
108
  // @ts-expect-error candidateLoaders
109
  const strictOptions = normalizeOptions(options, loader, candidateLoaders, url); // Could be invalid...
993✔
110

111
  // Get a context (if already present, will be unchanged)
112
  context = getLoaderContext(
993✔
113
    // @ts-expect-error
114
    {url, _parse: parse, loaders: candidateLoaders},
115
    strictOptions,
116
    context || null
1,685✔
117
  );
118

119
  return await parseWithLoader(loader, data, strictOptions, context);
996✔
120
}
121

122
// TODO: support progress and abort
123
// TODO - should accept loader.parseAsyncIterator and concatenate.
124
async function parseWithLoader(
125
  loader: Loader,
126
  data,
127
  options: StrictLoaderOptions,
128
  context: LoaderContext
129
): Promise<unknown> {
130
  validateWorkerVersion(loader);
993✔
131

132
  options = mergeOptions(loader.options, options);
993✔
133

134
  if (isResponse(data)) {
993✔
135
    // Serialize to support passing the response to web worker
136
    const {ok, redirected, status, statusText, type, url} = data;
626✔
137
    const headers = Object.fromEntries(data.headers.entries());
626✔
138
    // @ts-expect-error TODO - fix this
139
    context.response = {headers, ok, redirected, status, statusText, type, url};
626✔
140
  }
141

142
  data = await getArrayBufferOrStringFromData(data, loader, options);
993✔
143

144
  const loaderWithParser = loader as LoaderWithParser;
993✔
145

146
  // First check for synchronous text parser, wrap results in promises
147
  if (loaderWithParser.parseTextSync && typeof data === 'string') {
993✔
148
    return loaderWithParser.parseTextSync(data, options, context);
74✔
149
  }
150

151
  // If we have a workerUrl and the loader can parse the given options efficiently in a worker
152
  if (canParseWithWorker(loader, options)) {
919✔
153
    return await parseWithWorker(loader, data, options, context, parse);
99✔
154
  }
155

156
  // Check for asynchronous parser
157
  if (loaderWithParser.parseText && typeof data === 'string') {
820✔
158
    return await loaderWithParser.parseText(data, options, context);
67✔
159
  }
160

161
  if (loaderWithParser.parse) {
753!
162
    return await loaderWithParser.parse(data, options, context);
753✔
163
  }
164

165
  // This should not happen, all sync loaders should also offer `parse` function
166
  assert(!loaderWithParser.parseSync);
×
167

168
  // TBD - If asynchronous parser not available, return null
169
  throw new Error(`${loader.id} loader - no parser found and worker is disabled`);
×
170
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc