| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | const path = require("path"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = ({ outputDirectory }) => | 
					
						
							|  |  |  | 	class Worker { | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 		constructor(resource, options = {}) { | 
					
						
							| 
									
										
										
										
											2024-11-20 10:02:54 +08:00
										 |  |  | 			const isFileURL = /^file:/i.test(resource); | 
					
						
							| 
									
										
										
										
											2025-02-07 04:25:59 +08:00
										 |  |  | 			const isBlobURL = /^blob:/i.test(resource); | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-07 04:25:59 +08:00
										 |  |  | 			if (!isFileURL && !isBlobURL) { | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 				expect(resource.origin).toBe("https://test.cases"); | 
					
						
							|  |  |  | 				expect(resource.pathname.startsWith("/path/")).toBe(true); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			this.url = resource; | 
					
						
							|  |  |  | 			const file = isFileURL | 
					
						
							| 
									
										
										
										
											2024-11-20 22:17:01 +08:00
										 |  |  | 				? resource | 
					
						
							| 
									
										
										
										
											2025-02-07 04:25:59 +08:00
										 |  |  | 				: path.resolve( | 
					
						
							|  |  |  | 						outputDirectory, | 
					
						
							|  |  |  | 						isBlobURL | 
					
						
							|  |  |  | 							? options.originalURL.pathname.slice(6) | 
					
						
							|  |  |  | 							: resource.pathname.slice(6) | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2024-11-20 10:02:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 			const workerBootstrap = `
 | 
					
						
							|  |  |  | const { parentPort } = require("worker_threads"); | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | const { URL, fileURLToPath } = require("url"); | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | const path = require("path"); | 
					
						
							|  |  |  | const fs = require("fs"); | 
					
						
							|  |  |  | global.self = global; | 
					
						
							|  |  |  | self.URL = URL; | 
					
						
							| 
									
										
										
										
											2025-02-07 04:25:59 +08:00
										 |  |  | self.location = new URL(${JSON.stringify( | 
					
						
							|  |  |  | 				isBlobURL | 
					
						
							|  |  |  | 					? resource.toString().replace("nodedata:", "https://test.cases/path/") | 
					
						
							|  |  |  | 					: resource.toString() | 
					
						
							|  |  |  | 			)}); | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | const urlToPath = url => { | 
					
						
							| 
									
										
										
										
											2024-11-20 22:17:01 +08:00
										 |  |  |   if (/^file:/i.test(url)) return fileURLToPath(url); | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 	if (url.startsWith("https://test.cases/path/")) url = url.slice(24); | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 	return path.resolve(${JSON.stringify(outputDirectory)}, \`./\${url}\`);
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | self.importScripts = url => { | 
					
						
							| 
									
										
										
										
											2021-02-23 01:43:38 +08:00
										 |  |  | 	${ | 
					
						
							|  |  |  | 		options.type === "module" | 
					
						
							| 
									
										
										
										
											2024-10-14 11:02:08 +08:00
										 |  |  | 			? 'throw new Error("importScripts is not supported in module workers")' | 
					
						
							| 
									
										
										
										
											2024-07-31 12:23:44 +08:00
										 |  |  | 			: "require(urlToPath(url))" | 
					
						
							| 
									
										
										
										
											2021-02-23 01:43:38 +08:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | self.fetch = async url => { | 
					
						
							|  |  |  | 	try { | 
					
						
							|  |  |  | 		const buffer = await new Promise((resolve, reject) => | 
					
						
							|  |  |  | 			fs.readFile(urlToPath(url), (err, b) => | 
					
						
							|  |  |  | 				err ? reject(err) : resolve(b) | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		return { | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 		  headers: { get(name) { } }, | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 			status: 200, | 
					
						
							|  |  |  | 			ok: true, | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 			arrayBuffer() { return buffer; }, | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 			json: async () => JSON.parse(buffer.toString("utf-8")) | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	} catch(err) { | 
					
						
							|  |  |  | 		if(err.code === "ENOENT") { | 
					
						
							|  |  |  | 			return { | 
					
						
							|  |  |  | 				status: 404, | 
					
						
							|  |  |  | 				ok: false | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		throw err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | self.postMessage = data => { | 
					
						
							|  |  |  | 	parentPort.postMessage(data); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | if (${options.type === "module"}) { | 
					
						
							| 
									
										
										
										
											2024-11-20 22:17:01 +08:00
										 |  |  | 	import(${JSON.stringify(file)}).then(() => { | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | 		parentPort.on("message", data => { | 
					
						
							|  |  |  | 			if(self.onmessage) self.onmessage({ | 
					
						
							|  |  |  | 				data | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  | 	parentPort.on("message", data => { | 
					
						
							|  |  |  | 		if(self.onmessage) self.onmessage({ | 
					
						
							|  |  |  | 			data | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2024-11-20 22:17:01 +08:00
										 |  |  | 	require(${JSON.stringify(file)}); | 
					
						
							| 
									
										
										
										
											2024-11-14 22:03:02 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | `;
 | 
					
						
							|  |  |  | 			this.worker = new (require("worker_threads").Worker)(workerBootstrap, { | 
					
						
							|  |  |  | 				eval: true | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2021-05-27 05:29:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			this._onmessage = undefined; | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		set onmessage(value) { | 
					
						
							| 
									
										
										
										
											2021-05-27 05:29:49 +08:00
										 |  |  | 			if (this._onmessage) this.worker.off("message", this._onmessage); | 
					
						
							|  |  |  | 			this.worker.on( | 
					
						
							|  |  |  | 				"message", | 
					
						
							|  |  |  | 				(this._onmessage = data => { | 
					
						
							|  |  |  | 					value({ | 
					
						
							|  |  |  | 						data | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		postMessage(data) { | 
					
						
							|  |  |  | 			this.worker.postMessage(data); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-09 17:47:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		terminate() { | 
					
						
							|  |  |  | 			return this.worker.terminate(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-28 19:42:03 +08:00
										 |  |  | 	}; |