@xylabs/threads 4.7.1 → 4.7.2

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 (231) hide show
  1. package/dist/browser/master/implementation.browser.mjs +89 -0
  2. package/dist/browser/master/implementation.browser.mjs.map +1 -0
  3. package/dist/browser/worker/worker.browser.mjs +291 -0
  4. package/dist/browser/worker/worker.browser.mjs.map +1 -0
  5. package/dist/neutral/index.mjs +1022 -0
  6. package/dist/neutral/index.mjs.map +1 -0
  7. package/dist/neutral/master/implementation.mjs +264 -0
  8. package/dist/neutral/master/implementation.mjs.map +1 -0
  9. package/dist/neutral/master/index.mjs +988 -0
  10. package/dist/neutral/master/index.mjs.map +1 -0
  11. package/dist/neutral/master/pool.mjs +579 -0
  12. package/dist/neutral/master/pool.mjs.map +1 -0
  13. package/dist/neutral/master/register.mjs +272 -0
  14. package/dist/neutral/master/register.mjs.map +1 -0
  15. package/dist/neutral/master/spawn.mjs +412 -0
  16. package/dist/neutral/master/spawn.mjs.map +1 -0
  17. package/dist/neutral/master/thread.mjs +29 -0
  18. package/dist/neutral/master/thread.mjs.map +1 -0
  19. package/dist/neutral/observable-promise.mjs +132 -0
  20. package/dist/neutral/observable-promise.mjs.map +1 -0
  21. package/dist/neutral/observable.mjs +31 -0
  22. package/dist/neutral/observable.mjs.map +1 -0
  23. package/dist/node/master/implementation.node.mjs +154 -0
  24. package/dist/node/master/implementation.node.mjs.map +1 -0
  25. package/dist/node/worker/worker.node.mjs +304 -0
  26. package/dist/node/worker/worker.node.mjs.map +1 -0
  27. package/dist/{common.d.ts → types/common.d.ts} +5 -1
  28. package/dist/types/common.d.ts.map +1 -0
  29. package/dist/types/index.d.ts +9 -0
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/dist/{master → types/master}/get-bundle-url.browser.d.ts +1 -0
  32. package/dist/types/master/get-bundle-url.browser.d.ts.map +1 -0
  33. package/dist/{master → types/master}/implementation.browser.d.ts +2 -1
  34. package/dist/types/master/implementation.browser.d.ts.map +1 -0
  35. package/dist/{master → types/master}/implementation.d.ts +4 -1
  36. package/dist/types/master/implementation.d.ts.map +1 -0
  37. package/dist/{master → types/master}/implementation.node.d.ts +2 -1
  38. package/dist/types/master/implementation.node.d.ts.map +1 -0
  39. package/dist/types/master/index.d.ts +13 -0
  40. package/dist/types/master/index.d.ts.map +1 -0
  41. package/dist/{master → types/master}/invocation-proxy.d.ts +2 -1
  42. package/dist/types/master/invocation-proxy.d.ts.map +1 -0
  43. package/dist/{master → types/master}/pool-types.d.ts +16 -1
  44. package/dist/types/master/pool-types.d.ts.map +1 -0
  45. package/dist/types/master/pool.d.ts +93 -0
  46. package/dist/types/master/pool.d.ts.map +1 -0
  47. package/dist/types/master/register.d.ts +2 -0
  48. package/dist/types/master/register.d.ts.map +1 -0
  49. package/dist/{master → types/master}/spawn.d.ts +12 -2
  50. package/dist/types/master/spawn.d.ts.map +1 -0
  51. package/dist/types/master/thread.d.ts +13 -0
  52. package/dist/types/master/thread.d.ts.map +1 -0
  53. package/dist/{observable-promise.d.ts → types/observable-promise.d.ts} +14 -0
  54. package/dist/types/observable-promise.d.ts.map +1 -0
  55. package/dist/types/observable.d.ts +21 -0
  56. package/dist/types/observable.d.ts.map +1 -0
  57. package/dist/{ponyfills.d.ts → types/ponyfills.d.ts} +1 -0
  58. package/dist/types/ponyfills.d.ts.map +1 -0
  59. package/dist/types/promise.d.ts +6 -0
  60. package/dist/types/promise.d.ts.map +1 -0
  61. package/dist/{serializers.d.ts → types/serializers.d.ts} +1 -0
  62. package/dist/types/serializers.d.ts.map +1 -0
  63. package/dist/{symbols.d.ts → types/symbols.d.ts} +1 -0
  64. package/dist/types/symbols.d.ts.map +1 -0
  65. package/{src/transferable.ts → dist/types/transferable.d.ts} +8 -33
  66. package/dist/types/transferable.d.ts.map +1 -0
  67. package/dist/types/{master.d.ts → types/master.d.ts} +17 -3
  68. package/dist/types/types/master.d.ts.map +1 -0
  69. package/dist/types/{messages.d.ts → types/messages.d.ts} +1 -0
  70. package/dist/types/types/messages.d.ts.map +1 -0
  71. package/dist/types/{worker.d.ts → types/worker.d.ts} +1 -0
  72. package/dist/types/types/worker.d.ts.map +1 -0
  73. package/dist/types/worker/WorkerGlobalScope.d.ts +6 -0
  74. package/dist/types/worker/WorkerGlobalScope.d.ts.map +1 -0
  75. package/dist/types/worker/expose.d.ts +4 -0
  76. package/dist/types/worker/expose.d.ts.map +1 -0
  77. package/dist/types/worker/worker.browser.d.ts +14 -0
  78. package/dist/types/worker/worker.browser.d.ts.map +1 -0
  79. package/dist/types/worker/worker.node.d.ts +25 -0
  80. package/dist/types/worker/worker.node.d.ts.map +1 -0
  81. package/package.json +51 -92
  82. package/dist/common.js +0 -16
  83. package/dist/esm/common.js +0 -16
  84. package/dist/esm/index.js +0 -26
  85. package/dist/esm/master/get-bundle-url.browser.js +0 -25
  86. package/dist/esm/master/implementation.browser.js +0 -65
  87. package/dist/esm/master/implementation.js +0 -43
  88. package/dist/esm/master/implementation.node.js +0 -205
  89. package/dist/esm/master/index.js +0 -14
  90. package/dist/esm/master/invocation-proxy.js +0 -121
  91. package/dist/esm/master/pool-types.js +0 -14
  92. package/dist/esm/master/pool.js +0 -262
  93. package/dist/esm/master/register.js +0 -11
  94. package/dist/esm/master/spawn.js +0 -114
  95. package/dist/esm/master/thread.js +0 -18
  96. package/dist/esm/observable-promise.js +0 -132
  97. package/dist/esm/observable.js +0 -33
  98. package/dist/esm/ponyfills.js +0 -20
  99. package/dist/esm/promise.js +0 -23
  100. package/dist/esm/serializers.js +0 -41
  101. package/dist/esm/symbols.js +0 -8
  102. package/dist/esm/transferable.js +0 -25
  103. package/dist/esm/types/master.js +0 -9
  104. package/dist/esm/types/messages.js +0 -16
  105. package/dist/esm/types/worker.js +0 -2
  106. package/dist/esm/worker/bundle-entry.js +0 -26
  107. package/dist/esm/worker/implementation.browser.js +0 -24
  108. package/dist/esm/worker/implementation.js +0 -19
  109. package/dist/esm/worker/implementation.tiny-worker.js +0 -37
  110. package/dist/esm/worker/implementation.worker_threads.js +0 -41
  111. package/dist/esm/worker/index.js +0 -174
  112. package/dist/esm/worker_threads.js +0 -13
  113. package/dist/index.d.ts +0 -7
  114. package/dist/index.js +0 -26
  115. package/dist/master/get-bundle-url.browser.js +0 -25
  116. package/dist/master/implementation.browser.js +0 -65
  117. package/dist/master/implementation.js +0 -43
  118. package/dist/master/implementation.node.js +0 -205
  119. package/dist/master/index.d.ts +0 -10
  120. package/dist/master/index.js +0 -14
  121. package/dist/master/invocation-proxy.js +0 -121
  122. package/dist/master/pool-types.js +0 -14
  123. package/dist/master/pool.d.ts +0 -50
  124. package/dist/master/pool.js +0 -262
  125. package/dist/master/register.d.ts +0 -1
  126. package/dist/master/register.js +0 -11
  127. package/dist/master/spawn.js +0 -114
  128. package/dist/master/thread.d.ts +0 -8
  129. package/dist/master/thread.js +0 -18
  130. package/dist/observable-promise.js +0 -132
  131. package/dist/observable.d.ts +0 -11
  132. package/dist/observable.js +0 -33
  133. package/dist/ponyfills.js +0 -20
  134. package/dist/promise.d.ts +0 -1
  135. package/dist/promise.js +0 -23
  136. package/dist/serializers.js +0 -41
  137. package/dist/symbols.js +0 -8
  138. package/dist/transferable.d.ts +0 -9
  139. package/dist/transferable.js +0 -25
  140. package/dist/types/master.js +0 -9
  141. package/dist/types/messages.js +0 -16
  142. package/dist/types/worker.js +0 -2
  143. package/dist/worker/bundle-entry.d.ts +0 -1
  144. package/dist/worker/bundle-entry.js +0 -26
  145. package/dist/worker/implementation.browser.d.ts +0 -6
  146. package/dist/worker/implementation.browser.js +0 -24
  147. package/dist/worker/implementation.d.ts +0 -3
  148. package/dist/worker/implementation.js +0 -19
  149. package/dist/worker/implementation.tiny-worker.d.ts +0 -6
  150. package/dist/worker/implementation.tiny-worker.js +0 -37
  151. package/dist/worker/implementation.worker_threads.d.ts +0 -8
  152. package/dist/worker/implementation.worker_threads.js +0 -41
  153. package/dist/worker/index.d.ts +0 -5
  154. package/dist/worker/index.js +0 -174
  155. package/dist/worker_threads.d.ts +0 -8
  156. package/dist/worker_threads.js +0 -13
  157. package/eslint.config.mjs +0 -35
  158. package/index.mjs +0 -10
  159. package/observable.d.ts +0 -2
  160. package/observable.js +0 -2
  161. package/observable.mjs +0 -4
  162. package/register.d.ts +0 -2
  163. package/register.js +0 -2
  164. package/register.mjs +0 -1
  165. package/rollup.config.js +0 -16
  166. package/src/common.ts +0 -19
  167. package/src/index.ts +0 -10
  168. package/src/master/get-bundle-url.browser.ts +0 -31
  169. package/src/master/implementation.browser.ts +0 -82
  170. package/src/master/implementation.node.ts +0 -285
  171. package/src/master/implementation.ts +0 -21
  172. package/src/master/index.ts +0 -19
  173. package/src/master/invocation-proxy.ts +0 -151
  174. package/src/master/pool-types.ts +0 -83
  175. package/src/master/pool.ts +0 -399
  176. package/src/master/register.ts +0 -10
  177. package/src/master/spawn.ts +0 -172
  178. package/src/master/thread.ts +0 -29
  179. package/src/observable-promise.ts +0 -183
  180. package/src/observable.ts +0 -44
  181. package/src/ponyfills.ts +0 -31
  182. package/src/promise.ts +0 -26
  183. package/src/serializers.ts +0 -68
  184. package/src/symbols.ts +0 -5
  185. package/src/types/master.ts +0 -132
  186. package/src/types/messages.ts +0 -72
  187. package/src/types/worker.ts +0 -14
  188. package/src/worker/bundle-entry.ts +0 -10
  189. package/src/worker/implementation.browser.ts +0 -40
  190. package/src/worker/implementation.tiny-worker.ts +0 -55
  191. package/src/worker/implementation.ts +0 -23
  192. package/src/worker/implementation.worker_threads.ts +0 -50
  193. package/src/worker/index.ts +0 -230
  194. package/src/worker_threads.ts +0 -27
  195. package/test/lib/index.ts +0 -1
  196. package/test/lib/serialization.ts +0 -38
  197. package/test/observable-promise.test.ts +0 -205
  198. package/test/observable.test.ts +0 -87
  199. package/test/pool.test.ts +0 -183
  200. package/test/serialization.test.ts +0 -23
  201. package/test/spawn.chromium.mocha.ts +0 -53
  202. package/test/spawn.test.ts +0 -87
  203. package/test/streaming.test.ts +0 -29
  204. package/test/transferables.test.ts +0 -71
  205. package/test/workers/arraybuffer-xor.ts +0 -10
  206. package/test/workers/count-to-five.ts +0 -12
  207. package/test/workers/counter.ts +0 -19
  208. package/test/workers/faulty-function.ts +0 -5
  209. package/test/workers/hello-world.ts +0 -5
  210. package/test/workers/increment.ts +0 -8
  211. package/test/workers/minmax.ts +0 -25
  212. package/test/workers/serialization.ts +0 -13
  213. package/test/workers/top-level-throw.ts +0 -1
  214. package/test-tooling/rollup/app.js +0 -21
  215. package/test-tooling/rollup/rollup.config.ts +0 -14
  216. package/test-tooling/rollup/worker.js +0 -7
  217. package/test-tooling/tsconfig/minimal.ts +0 -12
  218. package/test-tooling/webpack/addition-worker.ts +0 -9
  219. package/test-tooling/webpack/app-with-inlined-worker.ts +0 -28
  220. package/test-tooling/webpack/app.ts +0 -61
  221. package/test-tooling/webpack/pool-worker.ts +0 -5
  222. package/test-tooling/webpack/raw-loader.d.ts +0 -4
  223. package/test-tooling/webpack/webpack.chromium.mocha.ts +0 -21
  224. package/test-tooling/webpack/webpack.node.config.js +0 -29
  225. package/test-tooling/webpack/webpack.web.config.js +0 -28
  226. package/types/is-observable.d.ts +0 -7
  227. package/types/tiny-worker.d.ts +0 -4
  228. package/types/webworker.d.ts +0 -9
  229. package/worker.d.ts +0 -2
  230. package/worker.js +0 -2
  231. package/worker.mjs +0 -6
@@ -1,31 +0,0 @@
1
- // Source: <https://github.com/parcel-bundler/parcel/blob/master/packages/core/parcel-bundler/src/builtins/bundle-url.js>
2
-
3
- let bundleURL: string | undefined
4
-
5
- function getBundleURLCached(): string {
6
- if (!bundleURL) {
7
- bundleURL = getBundleURL()
8
- }
9
-
10
- return bundleURL
11
- }
12
-
13
- function getBundleURL(): string {
14
- // Attempt to find the URL of the current script and use that as the base URL
15
- try {
16
- throw new Error('getBundleURL failed')
17
- } catch (err) {
18
- const matches = ('' + err.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\/\/[^\n)]+/g)
19
- if (matches) {
20
- return getBaseURL(matches[0])
21
- }
22
- }
23
-
24
- return '/'
25
- }
26
-
27
- function getBaseURL(url: string): string {
28
- return ('' + url).replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\/\/.+)?\/[^/]+(?:\?.*)?$/, '$1') + '/'
29
- }
30
-
31
- export { getBundleURLCached as getBundleURL }
@@ -1,82 +0,0 @@
1
- /* eslint-disable @stylistic/max-len */
2
- /* eslint-disable import-x/no-internal-modules */
3
- // tslint:disable max-classes-per-file
4
-
5
- import type { ImplementationExport, ThreadsWorkerOptions } from '../types/master'
6
- import { getBundleURL } from './get-bundle-url.browser'
7
-
8
- export const defaultPoolSize = typeof navigator !== 'undefined' && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4
9
-
10
- const isAbsoluteURL = (value: string) => /^[A-Za-z][\d+.A-Za-z\-]*:/.test(value)
11
-
12
- function createSourceBlobURL(code: string): string {
13
- const blob = new Blob([code], { type: 'application/javascript' })
14
- return URL.createObjectURL(blob)
15
- }
16
-
17
- function selectWorkerImplementation(): ImplementationExport {
18
- if (typeof Worker === 'undefined') {
19
- // Might happen on Safari, for instance
20
- // The idea is to only fail if the constructor is actually used
21
- return class NoWebWorker {
22
- constructor() {
23
- throw new Error(
24
- "No web worker implementation available. You might have tried to spawn a worker within a worker in a browser that doesn't support workers in workers.",
25
- )
26
- }
27
- } as unknown as ImplementationExport
28
- }
29
-
30
- class WebWorker extends Worker {
31
- constructor(url: string | URL, options?: ThreadsWorkerOptions) {
32
- if (typeof url === 'string' && options && options._baseURL) {
33
- url = new URL(url, options._baseURL)
34
- } else if (typeof url === 'string' && !isAbsoluteURL(url) && /^file:\/\//i.test(getBundleURL())) {
35
- url = new URL(url, getBundleURL().replace(/\/[^/]+$/, '/'))
36
- if (options?.CORSWorkaround ?? true) {
37
- url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`)
38
- }
39
- }
40
- if (
41
- typeof url === 'string'
42
- && isAbsoluteURL(url) // Create source code blob loading JS file via `importScripts()`
43
- // to circumvent worker CORS restrictions
44
- && (options?.CORSWorkaround ?? true)
45
- ) {
46
- url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`)
47
- }
48
- super(url, options)
49
- }
50
- }
51
-
52
- class BlobWorker extends WebWorker {
53
- constructor(blob: Blob, options?: ThreadsWorkerOptions) {
54
- const url = globalThis.URL.createObjectURL(blob)
55
- super(url, options)
56
- }
57
-
58
- static fromText(source: string, options?: ThreadsWorkerOptions): WebWorker {
59
- const blob = new globalThis.Blob([source], { type: 'text/javascript' })
60
- return new BlobWorker(blob, options)
61
- }
62
- }
63
-
64
- return {
65
- blob: BlobWorker,
66
- default: WebWorker,
67
- }
68
- }
69
-
70
- let implementation: ImplementationExport
71
-
72
- export function getWorkerImplementation(): ImplementationExport {
73
- if (!implementation) {
74
- implementation = selectWorkerImplementation()
75
- }
76
- return implementation
77
- }
78
-
79
- export function isWorkerRuntime() {
80
- const isWindowContext = typeof globalThis !== 'undefined' && typeof Window !== 'undefined' && globalThis instanceof Window
81
- return typeof globalThis !== 'undefined' && self['postMessage'] && !isWindowContext ? true : false
82
- }
@@ -1,285 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-require-imports */
2
- /* eslint-disable import-x/no-internal-modules */
3
- /* eslint-disable unicorn/no-process-exit */
4
- /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
5
- /* eslint-disable unicorn/prefer-regexp-test */
6
-
7
- /* eslint-disable unicorn/prefer-add-event-listener */
8
- /* eslint-disable unicorn/prefer-event-target */
9
- /* eslint-disable @typescript-eslint/no-explicit-any */
10
- /* eslint-disable unicorn/text-encoding-identifier-case */
11
- /// <reference lib="dom" />
12
-
13
- import { EventEmitter } from 'node:events'
14
- import { cpus } from 'node:os'
15
- import path from 'node:path'
16
- import { fileURLToPath } from 'node:url'
17
-
18
- import type { CallSite } from 'callsites-3-1-0'
19
- import getCallsites from 'callsites-3-1-0'
20
-
21
- import type {
22
- ImplementationExport, ThreadsWorkerOptions, WorkerImplementation,
23
- } from '../types/master'
24
-
25
- interface WorkerGlobalScope {
26
- addEventListener(eventName: string, listener: (event: Event) => void): void
27
- postMessage(message: any, transferables?: any[]): void
28
- removeEventListener(eventName: string, listener: (event: Event) => void): void
29
- }
30
-
31
- declare const __non_webpack_require__: typeof require
32
- declare const self: WorkerGlobalScope
33
-
34
- type WorkerEventName = 'error' | 'message'
35
-
36
- let tsNodeAvailable: boolean | undefined
37
-
38
- export const defaultPoolSize = cpus().length
39
-
40
- function detectTsNode() {
41
- if (typeof __non_webpack_require__ === 'function') {
42
- // Webpack build: => No ts-node required or possible
43
- return false
44
- }
45
- if (tsNodeAvailable) {
46
- return tsNodeAvailable
47
- }
48
-
49
- try {
50
- eval('require').resolve('ts-node')
51
- tsNodeAvailable = true
52
- } catch (error) {
53
- if (error && error.code === 'MODULE_NOT_FOUND') {
54
- tsNodeAvailable = false
55
- } else {
56
- // Re-throw
57
- throw error
58
- }
59
- }
60
- return tsNodeAvailable
61
- }
62
-
63
- function createTsNodeModule(scriptPath: string) {
64
- return `
65
- require("ts-node/register/transpile-only");
66
- require(${JSON.stringify(scriptPath)});
67
- `
68
- }
69
-
70
- function rebaseScriptPath(scriptPath: string, ignoreRegex: RegExp) {
71
- const parentCallSite = getCallsites().find((callsite: CallSite) => {
72
- const filename = callsite.getFileName()
73
- return Boolean(
74
- filename && !filename.match(ignoreRegex) && !/[/\\]master[/\\]implementation/.test(filename) && !/^internal\/process/.test(filename),
75
- )
76
- })
77
-
78
- const rawCallerPath = parentCallSite ? parentCallSite.getFileName() : null
79
- let callerPath = rawCallerPath ? rawCallerPath : null
80
- if (callerPath && callerPath.startsWith('file:')) {
81
- callerPath = fileURLToPath(callerPath)
82
- }
83
- return callerPath ? path.join(path.dirname(callerPath), scriptPath) : scriptPath
84
- }
85
-
86
- function resolveScriptPath(scriptPath: string, baseURL?: string | undefined) {
87
- const makeRelative = (filePath: string) => {
88
- // eval() hack is also webpack-related
89
- return path.isAbsolute(filePath) ? filePath : path.join(baseURL || eval('__dirname'), filePath)
90
- }
91
-
92
- return typeof __non_webpack_require__ === 'function'
93
- ? __non_webpack_require__.resolve(makeRelative(scriptPath))
94
- : eval('require').resolve(makeRelative(rebaseScriptPath(scriptPath, /[/\\]worker_threads[/\\]/)))
95
- }
96
-
97
- function initWorkerThreadsWorker(): ImplementationExport {
98
- // Webpack hack
99
- const NativeWorker
100
- = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__('worker_threads').Worker : eval('require')('worker_threads').Worker
101
-
102
- let allWorkers: Array<typeof NativeWorker> = []
103
-
104
- class Worker extends NativeWorker {
105
- private mappedEventListeners: WeakMap<EventListener, EventListener>
106
-
107
- constructor(scriptPath: string, options?: ThreadsWorkerOptions & { fromSource: boolean }) {
108
- const resolvedScriptPath = options && options.fromSource ? null : resolveScriptPath(scriptPath, (options || {})._baseURL)
109
-
110
- if (!resolvedScriptPath) {
111
- // `options.fromSource` is true
112
- const sourceCode = scriptPath
113
- super(sourceCode, { ...options, eval: true })
114
- } else if (/\.tsx?$/i.test(resolvedScriptPath) && detectTsNode()) {
115
- super(createTsNodeModule(resolvedScriptPath), { ...options, eval: true })
116
- } else if (/\.asar[/\\]/.test(resolvedScriptPath)) {
117
- // See <https://github.com/andywer/threads-plugin/issues/17>
118
- super(resolvedScriptPath.replace(/\.asar([/\\])/, '.asar.unpacked$1'), options)
119
- } else {
120
- super(resolvedScriptPath, options)
121
- }
122
-
123
- this.mappedEventListeners = new WeakMap()
124
- allWorkers.push(this)
125
- }
126
-
127
- addEventListener(eventName: string, rawListener: EventListener) {
128
- const listener = (message: any) => {
129
- rawListener({ data: message } as any)
130
- }
131
- this.mappedEventListeners.set(rawListener, listener)
132
- this.on(eventName, listener)
133
- }
134
-
135
- removeEventListener(eventName: string, rawListener: EventListener) {
136
- const listener = this.mappedEventListeners.get(rawListener) || rawListener
137
- this.off(eventName, listener)
138
- }
139
- }
140
-
141
- const terminateWorkersAndMaster = () => {
142
- // we should terminate all workers and then gracefully shutdown self process
143
- Promise.all(allWorkers.map(worker => worker.terminate())).then(
144
- () => process.exit(0),
145
- () => process.exit(1),
146
- )
147
- allWorkers = []
148
- }
149
-
150
- // Take care to not leave orphaned processes behind. See #147.
151
- process.on('SIGINT', () => terminateWorkersAndMaster())
152
- process.on('SIGTERM', () => terminateWorkersAndMaster())
153
-
154
- class BlobWorker extends Worker {
155
- constructor(blob: Uint8Array, options?: ThreadsWorkerOptions) {
156
- super(Buffer.from(blob).toString('utf-8'), { ...options, fromSource: true })
157
- }
158
-
159
- static fromText(source: string, options?: ThreadsWorkerOptions): WorkerImplementation {
160
- return new Worker(source, { ...options, fromSource: true }) as any
161
- }
162
- }
163
-
164
- return {
165
- blob: BlobWorker as any,
166
- default: Worker as any,
167
- }
168
- }
169
-
170
- function initTinyWorker(): ImplementationExport {
171
- const TinyWorker = require('tiny-worker')
172
-
173
- let allWorkers: Array<typeof TinyWorker> = []
174
-
175
- class Worker extends TinyWorker {
176
- private emitter: EventEmitter
177
-
178
- constructor(scriptPath: string, options?: ThreadsWorkerOptions & { fromSource?: boolean }) {
179
- // Need to apply a work-around for Windows or it will choke upon the absolute path
180
- // (`Error [ERR_INVALID_PROTOCOL]: Protocol 'c:' not supported`)
181
- const resolvedScriptPath
182
- = options && options.fromSource
183
- ? null
184
- : process.platform === 'win32'
185
- ? `file:///${resolveScriptPath(scriptPath).replaceAll('\\', '/')}`
186
- : resolveScriptPath(scriptPath)
187
-
188
- if (!resolvedScriptPath) {
189
- // `options.fromSource` is true
190
- const sourceCode = scriptPath
191
- super(new Function(sourceCode), [], { esm: true })
192
- } else if (/\.tsx?$/i.test(resolvedScriptPath) && detectTsNode()) {
193
- super(new Function(createTsNodeModule(resolveScriptPath(scriptPath))), [], { esm: true })
194
- } else if (/\.asar[/\\]/.test(resolvedScriptPath)) {
195
- // See <https://github.com/andywer/threads-plugin/issues/17>
196
- super(resolvedScriptPath.replace(/\.asar([/\\])/, '.asar.unpacked$1'), [], { esm: true })
197
- } else {
198
- super(resolvedScriptPath, [], { esm: true })
199
- }
200
-
201
- allWorkers.push(this)
202
-
203
- this.emitter = new EventEmitter()
204
- this.onerror = (error: Error) => this.emitter.emit('error', error)
205
- this.onmessage = (message: MessageEvent) => this.emitter.emit('message', message)
206
- }
207
-
208
- addEventListener(eventName: WorkerEventName, listener: EventListener) {
209
- this.emitter.addListener(eventName, listener)
210
- }
211
-
212
- removeEventListener(eventName: WorkerEventName, listener: EventListener) {
213
- this.emitter.removeListener(eventName, listener)
214
- }
215
-
216
- terminate() {
217
- allWorkers = allWorkers.filter(worker => worker !== this)
218
- return super.terminate()
219
- }
220
- }
221
-
222
- const terminateWorkersAndMaster = () => {
223
- // we should terminate all workers and then gracefully shutdown self process
224
- Promise.all(allWorkers.map(worker => worker.terminate())).then(
225
- () => process.exit(0),
226
- () => process.exit(1),
227
- )
228
- allWorkers = []
229
- }
230
-
231
- // Take care to not leave orphaned processes behind
232
- // See <https://github.com/avoidwork/tiny-worker#faq>
233
- process.on('SIGINT', () => terminateWorkersAndMaster())
234
- process.on('SIGTERM', () => terminateWorkersAndMaster())
235
-
236
- class BlobWorker extends Worker {
237
- constructor(blob: Uint8Array, options?: ThreadsWorkerOptions) {
238
- super(Buffer.from(blob).toString('utf-8'), { ...options, fromSource: true })
239
- }
240
-
241
- static fromText(source: string, options?: ThreadsWorkerOptions): WorkerImplementation {
242
- return new Worker(source, { ...options, fromSource: true }) as any
243
- }
244
- }
245
-
246
- return {
247
- blob: BlobWorker as any,
248
- default: Worker as any,
249
- }
250
- }
251
-
252
- let implementation: ImplementationExport
253
- let isTinyWorker: boolean
254
-
255
- function selectWorkerImplementation(): ImplementationExport {
256
- try {
257
- isTinyWorker = false
258
- return initWorkerThreadsWorker()
259
- } catch {
260
- // tslint:disable-next-line no-console
261
- console.debug('Node worker_threads not available. Trying to fall back to tiny-worker polyfill...')
262
- isTinyWorker = true
263
- return initTinyWorker()
264
- }
265
- }
266
-
267
- export function getWorkerImplementation(): ImplementationExport {
268
- if (!implementation) {
269
- implementation = selectWorkerImplementation()
270
- }
271
- return implementation
272
- }
273
-
274
- export function isWorkerRuntime() {
275
- if (isTinyWorker) {
276
- return self !== undefined && self['postMessage'] ? true : false
277
- } else {
278
- // Webpack hack
279
- const isMainThread
280
- = typeof __non_webpack_require__ === 'function'
281
- ? __non_webpack_require__('worker_threads').isMainThread
282
- : eval('require')('worker_threads').isMainThread
283
- return !isMainThread
284
- }
285
- }
@@ -1,21 +0,0 @@
1
- /*
2
- * This file is only a stub to make './implementation' resolve to the right module.
3
- */
4
-
5
- // We alias `src/master/implementation` to `src/master/implementation.browser` for web
6
- // browsers already in the package.json, so if get here, it's safe to pass-through the
7
- // node implementation
8
-
9
- import * as BrowserImplementation from './implementation.browser'
10
- import * as NodeImplementation from './implementation.node'
11
-
12
- const runningInNode = typeof process !== 'undefined' && (process.arch as string) !== 'browser' && 'pid' in process
13
- const implementation = runningInNode ? NodeImplementation : BrowserImplementation
14
-
15
- /** Default size of pools. Depending on the platform the value might vary from device to device. */
16
- export const defaultPoolSize = implementation.defaultPoolSize
17
-
18
- export const getWorkerImplementation = implementation.getWorkerImplementation
19
-
20
- /** Returns `true` if this code is currently running in a worker. */
21
- export const isWorkerRuntime = implementation.isWorkerRuntime
@@ -1,19 +0,0 @@
1
- /* eslint-disable import-x/no-internal-modules */
2
- import type { BlobWorker as BlobWorkerClass, Worker as WorkerType } from '../types/master'
3
- import { getWorkerImplementation } from './implementation'
4
-
5
- export { FunctionThread, ModuleThread } from '../types/master'
6
- export { Pool } from './pool'
7
- export { spawn } from './spawn'
8
- export { Thread } from './thread'
9
-
10
- export type BlobWorker = typeof BlobWorkerClass
11
- export type Worker = WorkerType
12
-
13
- /** Separate class to spawn workers from source code blobs or strings. */
14
- export const BlobWorker = getWorkerImplementation().blob
15
-
16
- /** Worker implementation. Either web worker or a node.js Worker class. */
17
- export const Worker = getWorkerImplementation().default
18
-
19
- export { isWorkerRuntime } from './implementation'
@@ -1,151 +0,0 @@
1
- /* eslint-disable import-x/no-internal-modules */
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- /*
4
- * This source file contains the code for proxying calls in the master thread to calls in the workers
5
- * by `.postMessage()`-ing.
6
- *
7
- * Keep in mind that this code can make or break the program's performance! Need to optimize more…
8
- */
9
-
10
- import DebugLogger from 'debug'
11
- import { multicast, Observable } from 'observable-fns'
12
-
13
- import { deserialize, serialize } from '../common'
14
- import { ObservablePromise } from '../observable-promise'
15
- import { isTransferDescriptor } from '../transferable'
16
- import type {
17
- ModuleMethods, ModuleProxy, ProxyableFunction, Worker as WorkerType,
18
- } from '../types/master'
19
- import type {
20
- MasterJobCancelMessage,
21
- MasterJobRunMessage,
22
- WorkerJobErrorMessage,
23
- WorkerJobResultMessage,
24
- WorkerJobStartMessage,
25
- } from '../types/messages'
26
- import {
27
- MasterMessageType,
28
- WorkerMessageType,
29
- } from '../types/messages'
30
-
31
- const debugMessages = DebugLogger('threads:master:messages')
32
-
33
- let nextJobUID = 1
34
-
35
- const dedupe = <T>(array: T[]): T[] => [...new Set(array)]
36
-
37
- const isJobErrorMessage = (data: any): data is WorkerJobErrorMessage => data && data.type === WorkerMessageType.error
38
- const isJobResultMessage = (data: any): data is WorkerJobResultMessage => data && data.type === WorkerMessageType.result
39
- const isJobStartMessage = (data: any): data is WorkerJobStartMessage => data && data.type === WorkerMessageType.running
40
-
41
- function createObservableForJob<ResultType>(worker: WorkerType, jobUID: number): Observable<ResultType> {
42
- return new Observable((observer) => {
43
- let asyncType: 'observable' | 'promise' | undefined
44
-
45
- const messageHandler = ((event: MessageEvent) => {
46
- debugMessages('Message from worker:', event.data)
47
- if (!event.data || event.data.uid !== jobUID) return
48
-
49
- if (isJobStartMessage(event.data)) {
50
- asyncType = event.data.resultType
51
- } else if (isJobResultMessage(event.data)) {
52
- if (asyncType === 'promise') {
53
- if (event.data.payload !== undefined) {
54
- observer.next(deserialize(event.data.payload))
55
- }
56
- observer.complete()
57
- worker.removeEventListener('message', messageHandler)
58
- } else {
59
- if (event.data.payload) {
60
- observer.next(deserialize(event.data.payload))
61
- }
62
- if (event.data.complete) {
63
- observer.complete()
64
- worker.removeEventListener('message', messageHandler)
65
- }
66
- }
67
- } else if (isJobErrorMessage(event.data)) {
68
- const error = deserialize(event.data.error as any)
69
- if (asyncType === 'promise' || !asyncType) {
70
- observer.error(error)
71
- } else {
72
- observer.error(error)
73
- }
74
- worker.removeEventListener('message', messageHandler)
75
- }
76
- }) as EventListener
77
-
78
- worker.addEventListener('message', messageHandler)
79
-
80
- return () => {
81
- if (asyncType === 'observable' || !asyncType) {
82
- const cancelMessage: MasterJobCancelMessage = {
83
- type: MasterMessageType.cancel,
84
- uid: jobUID,
85
- }
86
- worker.postMessage(cancelMessage)
87
- }
88
- worker.removeEventListener('message', messageHandler)
89
- }
90
- })
91
- }
92
-
93
- function prepareArguments(rawArgs: any[]): { args: any[]; transferables: Transferable[] } {
94
- if (rawArgs.length === 0) {
95
- // Exit early if possible
96
- return {
97
- args: [],
98
- transferables: [],
99
- }
100
- }
101
-
102
- const args: any[] = []
103
- const transferables: Transferable[] = []
104
-
105
- for (const arg of rawArgs) {
106
- if (isTransferDescriptor(arg)) {
107
- args.push(serialize(arg.send))
108
- transferables.push(...arg.transferables)
109
- } else {
110
- args.push(serialize(arg))
111
- }
112
- }
113
-
114
- return {
115
- args,
116
- transferables: transferables.length === 0 ? transferables : dedupe(transferables),
117
- }
118
- }
119
-
120
- export function createProxyFunction<Args extends any[], ReturnType>(worker: WorkerType, method?: string) {
121
- return ((...rawArgs: Args) => {
122
- const uid = nextJobUID++
123
- const { args, transferables } = prepareArguments(rawArgs)
124
- const runMessage: MasterJobRunMessage = {
125
- args,
126
- method,
127
- type: MasterMessageType.run,
128
- uid,
129
- }
130
-
131
- debugMessages('Sending command to run function to worker:', runMessage)
132
-
133
- try {
134
- worker.postMessage(runMessage, transferables)
135
- } catch (error) {
136
- return ObservablePromise.from(Promise.reject(error))
137
- }
138
-
139
- return ObservablePromise.from(multicast(createObservableForJob<ReturnType>(worker, uid)))
140
- }) as any as ProxyableFunction<Args, ReturnType>
141
- }
142
-
143
- export function createProxyModule<Methods extends ModuleMethods>(worker: WorkerType, methodNames: string[]): ModuleProxy<Methods> {
144
- const proxy: any = {}
145
-
146
- for (const methodName of methodNames) {
147
- proxy[methodName] = createProxyFunction(worker, methodName)
148
- }
149
-
150
- return proxy
151
- }
@@ -1,83 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /* eslint-disable @typescript-eslint/member-ordering */
3
- import type { Thread } from './thread'
4
-
5
- /** Pool event type. Specifies the type of each `PoolEvent`. */
6
- export enum PoolEventType {
7
- initialized = 'initialized',
8
- taskCanceled = 'taskCanceled',
9
- taskCompleted = 'taskCompleted',
10
- taskFailed = 'taskFailed',
11
- taskQueued = 'taskQueued',
12
- taskQueueDrained = 'taskQueueDrained',
13
- taskStart = 'taskStart',
14
- terminated = 'terminated',
15
- }
16
-
17
- export type TaskRunFunction<ThreadType extends Thread, Return> = (worker: ThreadType) => Promise<Return>
18
-
19
- /** Pool event. Subscribe to those events using `pool.events()`. Useful for debugging. */
20
- export type PoolEvent<ThreadType extends Thread> =
21
- | {
22
- type: PoolEventType.initialized
23
- size: number
24
- }
25
- | {
26
- type: PoolEventType.taskQueued
27
- taskID: number
28
- }
29
- | {
30
- type: PoolEventType.taskQueueDrained
31
- }
32
- | {
33
- type: PoolEventType.taskStart
34
- taskID: number
35
- workerID: number
36
- }
37
- | {
38
- type: PoolEventType.taskCompleted
39
- returnValue: any
40
- taskID: number
41
- workerID: number
42
- }
43
- | {
44
- type: PoolEventType.taskFailed
45
- error: Error
46
- taskID: number
47
- workerID: number
48
- }
49
- | {
50
- type: PoolEventType.taskCanceled
51
- taskID: number
52
- }
53
- | {
54
- type: PoolEventType.terminated
55
- remainingQueue: Array<QueuedTask<ThreadType, any>>
56
- }
57
-
58
- export interface WorkerDescriptor<ThreadType extends Thread> {
59
- init: Promise<ThreadType>
60
- runningTasks: Array<Promise<any>>
61
- }
62
-
63
- /**
64
- * Task that has been `pool.queued()`-ed.
65
- */
66
- export interface QueuedTask<ThreadType extends Thread, Return> {
67
- /** @private */
68
- id: number
69
-
70
- /** @private */
71
- run: TaskRunFunction<ThreadType, Return>
72
-
73
- /**
74
- * Queued tasks can be cancelled until the pool starts running them on a worker thread.
75
- */
76
- cancel(): void
77
-
78
- /**
79
- * `QueuedTask` is thenable, so you can `await` it.
80
- * Resolves when the task has successfully been executed. Rejects if the task fails.
81
- */
82
- then: Promise<Return>['then']
83
- }