@@ -5,7 +5,11 @@ import getCallsites, { CallSite } from "callsites"
55import EventEmitter from "events"
66import { cpus } from 'os'
77import * as path from "path"
8- import { ThreadsWorkerOptions , WorkerImplementation } from "../types/master"
8+ import {
9+ ImplementationExport ,
10+ ThreadsWorkerOptions ,
11+ WorkerImplementation
12+ } from "../types/master"
913
1014interface WorkerGlobalScope {
1115 addEventListener ( eventName : string , listener : ( event : Event ) => void ) : void
@@ -84,7 +88,7 @@ function resolveScriptPath(scriptPath: string, baseURL?: string | undefined) {
8488 return workerFilePath
8589}
8690
87- function initWorkerThreadsWorker ( ) : typeof WorkerImplementation {
91+ function initWorkerThreadsWorker ( ) : ImplementationExport {
8892 // Webpack hack
8993 const NativeWorker = typeof __non_webpack_require__ === "function"
9094 ? __non_webpack_require__ ( "worker_threads" ) . Worker
@@ -95,10 +99,16 @@ function initWorkerThreadsWorker(): typeof WorkerImplementation {
9599 class Worker extends NativeWorker {
96100 private mappedEventListeners : WeakMap < EventListener , EventListener >
97101
98- constructor ( scriptPath : string , options ?: ThreadsWorkerOptions ) {
99- const resolvedScriptPath = resolveScriptPath ( scriptPath , ( options || { } ) . _baseURL )
102+ constructor ( scriptPath : string , options ?: ThreadsWorkerOptions & { fromSource : boolean } ) {
103+ const resolvedScriptPath = options && options . fromSource
104+ ? null
105+ : resolveScriptPath ( scriptPath , ( options || { } ) . _baseURL )
100106
101- if ( resolvedScriptPath . match ( / \. t s x ? $ / i) && detectTsNode ( ) ) {
107+ if ( ! resolvedScriptPath ) {
108+ // `options.fromSource` is true
109+ const sourceCode = scriptPath
110+ super ( sourceCode , { ...options , eval : true } )
111+ } else if ( resolvedScriptPath . match ( / \. t s x ? $ / i) && detectTsNode ( ) ) {
102112 super ( createTsNodeModule ( resolvedScriptPath ) , { ...options , eval : true } )
103113 } else if ( resolvedScriptPath . match ( / \. a s a r [ \/ \\ ] / ) ) {
104114 // See <https://github.com/andywer/threads-plugin/issues/17>
@@ -138,25 +148,44 @@ function initWorkerThreadsWorker(): typeof WorkerImplementation {
138148 process . on ( "SIGINT" , ( ) => terminateWorkersAndMaster ( ) )
139149 process . on ( "SIGTERM" , ( ) => terminateWorkersAndMaster ( ) )
140150
141- return Worker as any
151+ class BlobWorker extends Worker {
152+ constructor ( blob : Uint8Array , options ?: ThreadsWorkerOptions ) {
153+ super ( Buffer . from ( blob ) . toString ( "utf-8" ) , { ...options , fromSource : true } )
154+ }
155+
156+ public static fromText ( source : string , options ?: ThreadsWorkerOptions ) : WorkerImplementation {
157+ return new Worker ( source , { ...options , fromSource : true } ) as any
158+ }
159+ }
160+
161+ return {
162+ blob : BlobWorker as any ,
163+ default : Worker as any
164+ }
142165}
143166
144- function initTinyWorker ( ) : typeof WorkerImplementation {
167+ function initTinyWorker ( ) : ImplementationExport {
145168 const TinyWorker = require ( "tiny-worker" )
146169
147170 let allWorkers : Array < typeof TinyWorker > = [ ]
148171
149172 class Worker extends TinyWorker {
150173 private emitter : EventEmitter
151174
152- constructor ( scriptPath : string ) {
175+ constructor ( scriptPath : string , options ?: ThreadsWorkerOptions & { fromSource ?: boolean } ) {
153176 // Need to apply a work-around for Windows or it will choke upon the absolute path
154177 // (`Error [ERR_INVALID_PROTOCOL]: Protocol 'c:' not supported`)
155- const resolvedScriptPath = process . platform === "win32"
156- ? `file:///${ resolveScriptPath ( scriptPath ) . replace ( / \\ / g, "/" ) } `
157- : resolveScriptPath ( scriptPath )
158-
159- if ( resolvedScriptPath . match ( / \. t s x ? $ / i) && detectTsNode ( ) ) {
178+ const resolvedScriptPath = options && options . fromSource
179+ ? null
180+ : process . platform === "win32"
181+ ? `file:///${ resolveScriptPath ( scriptPath ) . replace ( / \\ / g, "/" ) } `
182+ : resolveScriptPath ( scriptPath )
183+
184+ if ( ! resolvedScriptPath ) {
185+ // `options.fromSource` is true
186+ const sourceCode = scriptPath
187+ super ( new Function ( sourceCode ) , [ ] , { esm : true } )
188+ } else if ( resolvedScriptPath . match ( / \. t s x ? $ / i) && detectTsNode ( ) ) {
160189 super ( new Function ( createTsNodeModule ( resolveScriptPath ( scriptPath ) ) ) , [ ] , { esm : true } )
161190 } else if ( resolvedScriptPath . match ( / \. a s a r [ \/ \\ ] / ) ) {
162191 // See <https://github.com/andywer/threads-plugin/issues/17>
@@ -171,12 +200,15 @@ function initTinyWorker(): typeof WorkerImplementation {
171200 this . onerror = ( error : Error ) => this . emitter . emit ( "error" , error )
172201 this . onmessage = ( message : MessageEvent ) => this . emitter . emit ( "message" , message )
173202 }
203+
174204 public addEventListener ( eventName : WorkerEventName , listener : EventListener ) {
175205 this . emitter . addListener ( eventName , listener )
176206 }
207+
177208 public removeEventListener ( eventName : WorkerEventName , listener : EventListener ) {
178209 this . emitter . removeListener ( eventName , listener )
179210 }
211+
180212 public terminate ( ) {
181213 allWorkers = allWorkers . filter ( worker => worker !== this )
182214 return super . terminate ( )
@@ -197,13 +229,26 @@ function initTinyWorker(): typeof WorkerImplementation {
197229 process . on ( "SIGINT" , ( ) => terminateWorkersAndMaster ( ) )
198230 process . on ( "SIGTERM" , ( ) => terminateWorkersAndMaster ( ) )
199231
200- return Worker as any
232+ class BlobWorker extends Worker {
233+ constructor ( blob : Uint8Array , options ?: ThreadsWorkerOptions ) {
234+ super ( Buffer . from ( blob ) . toString ( "utf-8" ) , { ...options , fromSource : true } )
235+ }
236+
237+ public static fromText ( source : string , options ?: ThreadsWorkerOptions ) : WorkerImplementation {
238+ return new Worker ( source , { ...options , fromSource : true } ) as any
239+ }
240+ }
241+
242+ return {
243+ blob : BlobWorker as any ,
244+ default : Worker as any
245+ }
201246}
202247
203- let implementation : typeof WorkerImplementation
248+ let implementation : ImplementationExport
204249let isTinyWorker : boolean
205250
206- function selectWorkerImplementation ( ) : typeof WorkerImplementation {
251+ function selectWorkerImplementation ( ) : ImplementationExport {
207252 try {
208253 isTinyWorker = false
209254 return initWorkerThreadsWorker ( )
@@ -215,7 +260,7 @@ function selectWorkerImplementation(): typeof WorkerImplementation {
215260 }
216261}
217262
218- export function getWorkerImplementation ( ) : typeof WorkerImplementation {
263+ export function getWorkerImplementation ( ) : ImplementationExport {
219264 if ( ! implementation ) {
220265 implementation = selectWorkerImplementation ( )
221266 }
0 commit comments