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

visgl / loaders.gl / 24369398061

13 Apr 2026 10:07PM UTC coverage: 55.756% (+0.004%) from 55.752%
24369398061

push

github

web-flow
chore: Warn if core is imported by loader module (#3379)

9478 of 18401 branches covered (51.51%)

Branch coverage included in aggregate %.

85 of 136 new or added lines in 33 files covered. (62.5%)

4 existing lines in 4 files now uncovered.

19703 of 33936 relevant lines covered (58.06%)

4979.77 hits per line

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

1.52
/modules/loader-utils/src/lib/worker-loader-utils/create-loader-worker.ts
1
/* eslint-disable no-restricted-globals */
2
import type {CoreAPI} from '../sources/data-source';
3
import type {LoaderWithParser, LoaderOptions, LoaderContext} from '../../loader-types';
4
import {WorkerBody} from '@loaders.gl/worker-utils';
5
// import {validateLoaderVersion} from './validate-loader-version';
6

7
let requestId = 0;
403✔
8

9
/**
10
 * Set up a WebWorkerGlobalScope to talk with the main thread
11
 * @param loader
12
 */
13
export async function createLoaderWorker(loader: LoaderWithParser) {
14
  // Check that we are actually in a worker thread
15
  if (!(await WorkerBody.inWorkerThread())) {
×
16
    return;
×
17
  }
18

19
  WorkerBody.onmessage = async (type, payload) => {
×
20
    switch (type) {
×
21
      case 'process':
22
        try {
×
23
          // validateLoaderVersion(loader, data.source.split('@')[1]);
24

25
          const {input, options = {}, context = {}} = payload;
×
26

27
          const result = await parseData({
×
28
            loader,
29
            arrayBuffer: input,
30
            options,
31
            // @ts-expect-error fetch missing
32
            context: {
33
              ...context,
34
              coreApi: createWorkerCoreApi(),
35
              _parse: parseOnMainThread
36
            }
37
          });
38
          WorkerBody.postMessage('done', {result});
×
39
        } catch (error) {
40
          const message = error instanceof Error ? error.message : '';
×
41
          WorkerBody.postMessage('error', {error: message});
×
42
        }
43
        break;
×
44
      default:
45
    }
46
  };
47
}
48

49
function createWorkerCoreApi(): CoreAPI {
NEW
50
  const unavailable = (methodName: keyof CoreAPI) => () => {
×
NEW
51
    throw new Error(`context.coreApi.${methodName} is unavailable inside worker loaders.`);
×
52
  };
53

NEW
54
  return {
×
NEW
55
    fetchFile: async urlOrData => await fetch(urlOrData as RequestInfo | URL),
×
56
    parseSync: unavailable('parseSync'),
57
    parse: unavailable('parse'),
58
    parseInBatches: unavailable('parseInBatches'),
59
    load: unavailable('load'),
60
    loadInBatches: unavailable('loadInBatches')
61
  };
62
}
63

64
function parseOnMainThread(
65
  arrayBuffer: ArrayBuffer,
66
  loader: any,
67
  options?: LoaderOptions,
68
  context?: LoaderContext
69
): Promise<void> {
70
  return new Promise((resolve, reject) => {
×
71
    const id = requestId++;
×
72

73
    /**
74
     */
75
    const onMessage = (type, payload) => {
×
76
      if (payload.id !== id) {
×
77
        // not ours
78
        return;
×
79
      }
80

81
      switch (type) {
×
82
        case 'done':
83
          WorkerBody.removeEventListener(onMessage);
×
84
          resolve(payload.result);
×
85
          break;
×
86

87
        case 'error':
88
          WorkerBody.removeEventListener(onMessage);
×
89
          reject(payload.error);
×
90
          break;
×
91

92
        default:
93
        // ignore
94
      }
95
    };
96

97
    WorkerBody.addEventListener(onMessage);
×
98

99
    // Ask the main thread to decode data
100
    const payload = {id, input: arrayBuffer, options};
×
101
    WorkerBody.postMessage('process', payload);
×
102
  });
103
}
104

105
// TODO - Support byteOffset and byteLength (enabling parsing of embedded binaries without copies)
106
// TODO - Why not support async loader.parse* funcs here?
107
// TODO - Why not reuse a common function instead of reimplementing loader.parse* selection logic? Keeping loader small?
108
// TODO - Lack of appropriate parser functions can be detected when we create worker, no need to wait until parse
109
async function parseData({
110
  loader,
111
  arrayBuffer,
112
  options,
113
  context
114
}: {
115
  loader: LoaderWithParser;
116
  arrayBuffer: ArrayBuffer;
117
  options: LoaderOptions;
118
  context: LoaderContext;
119
}) {
120
  let data;
121
  let parser;
122
  if (loader.parseSync || loader.parse) {
×
123
    data = arrayBuffer;
×
124
    parser = loader.parseSync || loader.parse;
×
125
  } else if (loader.parseTextSync) {
×
126
    const textDecoder = new TextDecoder();
×
127
    data = textDecoder.decode(arrayBuffer);
×
128
    parser = loader.parseTextSync;
×
129
  } else {
130
    throw new Error(`Could not load data with ${loader.name} loader`);
×
131
  }
132

133
  // TODO - proper merge in of loader options...
134
  options = {
×
135
    ...options,
136
    modules: (loader && loader.options && loader.options.modules) || {},
×
137
    core: {
138
      ...options.core,
139
      worker: false
140
    }
141
  };
142

143
  return await parser(data, {...options}, context, loader);
×
144
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc