vitest-pool-assemblyscript 0.2.0
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.
- package/BINARYEN_VERSION +1 -0
- package/LICENSE +53 -0
- package/README.md +607 -0
- package/assembly/compare.ts +219 -0
- package/assembly/describe.ts +104 -0
- package/assembly/expect.ts +335 -0
- package/assembly/index.ts +14 -0
- package/assembly/options.ts +198 -0
- package/assembly/test.ts +147 -0
- package/assembly/tsconfig.json +6 -0
- package/binding.gyp +62 -0
- package/dist/ast-visitor-DC3SuTzs.mjs +310 -0
- package/dist/ast-visitor-DC3SuTzs.mjs.map +1 -0
- package/dist/compile-runner-8h0dBwG2.mjs +80 -0
- package/dist/compile-runner-8h0dBwG2.mjs.map +1 -0
- package/dist/compiler/transforms/strip-inline.d.mts +18 -0
- package/dist/compiler/transforms/strip-inline.d.mts.map +1 -0
- package/dist/compiler/transforms/strip-inline.mjs +38 -0
- package/dist/compiler/transforms/strip-inline.mjs.map +1 -0
- package/dist/compiler-CN6BRK_N.mjs +295 -0
- package/dist/compiler-CN6BRK_N.mjs.map +1 -0
- package/dist/config/index-v3.d.mts +111 -0
- package/dist/config/index-v3.d.mts.map +1 -0
- package/dist/config/index-v3.mjs +11 -0
- package/dist/config/index-v3.mjs.map +1 -0
- package/dist/config/index.d.mts +4 -0
- package/dist/config/index.mjs +8 -0
- package/dist/constants-CA50WBdr.mjs +130 -0
- package/dist/constants-CA50WBdr.mjs.map +1 -0
- package/dist/coverage-merge-0WqdC-dq.mjs +22 -0
- package/dist/coverage-merge-0WqdC-dq.mjs.map +1 -0
- package/dist/coverage-provider/index.d.mts +15 -0
- package/dist/coverage-provider/index.d.mts.map +1 -0
- package/dist/coverage-provider/index.mjs +535 -0
- package/dist/coverage-provider/index.mjs.map +1 -0
- package/dist/custom-provider-options-CF5C1kXb.d.mts +26 -0
- package/dist/custom-provider-options-CF5C1kXb.d.mts.map +1 -0
- package/dist/debug-IeEHsxy0.mjs +195 -0
- package/dist/debug-IeEHsxy0.mjs.map +1 -0
- package/dist/index-internal.d.mts +23 -0
- package/dist/index-internal.d.mts.map +1 -0
- package/dist/index-internal.mjs +4 -0
- package/dist/index-v3.d.mts +7 -0
- package/dist/index-v3.d.mts.map +1 -0
- package/dist/index-v3.mjs +206 -0
- package/dist/index-v3.mjs.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +8 -0
- package/dist/load-user-imports-J9eaAW0_.mjs +801 -0
- package/dist/load-user-imports-J9eaAW0_.mjs.map +1 -0
- package/dist/pool-runner-init-CEwLyNI3.d.mts +8 -0
- package/dist/pool-runner-init-CEwLyNI3.d.mts.map +1 -0
- package/dist/pool-runner-init-d5qScS41.mjs +400 -0
- package/dist/pool-runner-init-d5qScS41.mjs.map +1 -0
- package/dist/pool-thread/compile-worker-thread.d.mts +7 -0
- package/dist/pool-thread/compile-worker-thread.d.mts.map +1 -0
- package/dist/pool-thread/compile-worker-thread.mjs +42 -0
- package/dist/pool-thread/compile-worker-thread.mjs.map +1 -0
- package/dist/pool-thread/test-worker-thread.d.mts +7 -0
- package/dist/pool-thread/test-worker-thread.d.mts.map +1 -0
- package/dist/pool-thread/test-worker-thread.mjs +39 -0
- package/dist/pool-thread/test-worker-thread.mjs.map +1 -0
- package/dist/pool-thread/v3-tinypool-thread.d.mts +7 -0
- package/dist/pool-thread/v3-tinypool-thread.d.mts.map +1 -0
- package/dist/pool-thread/v3-tinypool-thread.mjs +57 -0
- package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -0
- package/dist/resolve-config-as1w-Qyz.mjs +65 -0
- package/dist/resolve-config-as1w-Qyz.mjs.map +1 -0
- package/dist/test-runner-B2BpyPNK.mjs +142 -0
- package/dist/test-runner-B2BpyPNK.mjs.map +1 -0
- package/dist/types-8KKo9Hbf.d.mts +228 -0
- package/dist/types-8KKo9Hbf.d.mts.map +1 -0
- package/dist/vitest-file-tasks-BUwzh375.mjs +61 -0
- package/dist/vitest-file-tasks-BUwzh375.mjs.map +1 -0
- package/dist/vitest-tasks-BKS7689f.mjs +319 -0
- package/dist/vitest-tasks-BKS7689f.mjs.map +1 -0
- package/dist/worker-rpc-channel-lbhK7Qz8.mjs +25 -0
- package/dist/worker-rpc-channel-lbhK7Qz8.mjs.map +1 -0
- package/package.json +112 -0
- package/prebuilds/linux-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/scripts/install.js +91 -0
- package/scripts/setup-binaryen.js +179 -0
- package/src/native-instrumentation/addon.cpp +788 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool-runner-init-d5qScS41.mjs","names":[],"sources":["../src/pool/pool-worker.ts","../src/pool/pool-runner-init.ts"],"sourcesContent":["import { availableParallelism } from 'node:os';\nimport { resolve } from 'node:path';\nimport { access } from 'node:fs/promises';\nimport type { MessagePort } from 'node:worker_threads';\nimport type { Test } from '@vitest/runner/types';\nimport type { SerializedConfig } from 'vitest';\nimport type { PoolWorker, PoolOptions, WorkerRequest, PoolTask, WorkerResponse } from 'vitest/node';\nimport Tinypool from 'tinypool';\n\nimport type {\n AssemblyScriptPoolWorkerMessage,\n ResolvedAssemblyScriptPoolOptions,\n ResolvedHybridProviderOptions,\n RunCompileAndDiscoverTask,\n RunTestsTask,\n TestExecutionEnd,\n TestExecutionStart,\n TestRunRecord,\n ThreadSpec,\n WorkerThreadInitData,\n} from '../types/types.js';\nimport { createInitialFileTask } from '../util/vitest-file-tasks.js';\nimport { failTestWithTimeoutError, flagTestTerminated } from '../util/vitest-tasks.js';\nimport {\n AS_POOL_WORKER_MSG_FLAG,\n ASSEMBLYSCRIPT_POOL_NAME,\n POOL_ERROR_NAMES,\n VITEST_WORKER_RESPONSE_MSG_FLAG\n} from '../types/constants.js';\nimport { debug, setGlobalDebugMode } from '../util/debug.js';\nimport { createPoolError, createPoolErrorFromAnyError, isAbortError } from '../util/pool-errors.js';\nimport { createWorkerRPCChannel } from './worker-rpc-channel.js';\n\ntype GlobalThreadPools = { compilePool: Tinypool, runPool: Tinypool };\ntype EventCallback = (arg: any) => void;\n\nconst THREAD_RESOLVE_TIMEOUT_MS = 2000 as const;\nconst POOL_THREAD_IDLE_TIMEOUT_MS = 3_600_000 as const;\nconst IDLE_RUN_THREADS_FACTOR = 1 as const;\n// @ts-ignore - see note in getGlobalThreadPools\nconst IDLE_COMPILE_THREADS_FACTOR = 0.25 as const;\n\n// path assumes that we're running from dist/\nconst COMPILE_WORKER_PATH = resolve(import.meta.dirname, 'pool-thread/compile-worker-thread.mjs');\nconst TEST_WORKER_PATH = resolve(import.meta.dirname, 'pool-thread/test-worker-thread.mjs');\n\nvar GLOBAL_POOLS_PROMISE: Promise<GlobalThreadPools> | undefined;\nvar GLOBAL_POOL_ABORT_CONTROLLER: AbortController | undefined;\nvar GLOBAL_RUNNING_POOLWORKER_COUNT: number = 0;\n\nexport class AssemblyScriptPoolWorker implements PoolWorker {\n readonly logModule = 'PoolWorker' as const;\n readonly name: typeof ASSEMBLYSCRIPT_POOL_NAME = ASSEMBLYSCRIPT_POOL_NAME;\n readonly poolOptions: PoolOptions;\n readonly asPoolOptions: ResolvedAssemblyScriptPoolOptions;\n readonly asCoverageOptions: ResolvedHybridProviderOptions;\n\n // for the currently running thread preforming a test run (if any)\n private threadAbortController: AbortController | undefined;\n private threadControlPort: MessagePort | undefined;\n private threadRunPromise: Promise<void> | undefined;\n\n private threadSpecs: ThreadSpec[] = [];\n \n // cached data for possible timeout resume\n private currentTestRun: TestRunRecord | undefined;\n \n // for this particular PoolWorker instance (1 per `maxWorkers`)\n private currentWorkerId: number | undefined;\n private isWorkerRunning: boolean = false;\n private config: SerializedConfig | undefined; // provided with \"start\" message\n\n // registry holding vitest callbacks so we can communicate on behalf of the worker thread\n private listenerRegistry: Map<string, Set<EventCallback>>;\n\n constructor(\n options: PoolOptions,\n resolvedUserPoolOptions: ResolvedAssemblyScriptPoolOptions,\n resolvedCoverageOptions: ResolvedHybridProviderOptions,\n ) {\n const start = performance.now();\n\n this.poolOptions = options;\n this.asPoolOptions = resolvedUserPoolOptions;\n this.asCoverageOptions = resolvedCoverageOptions;\n this.listenerRegistry = new Map<string, Set<EventCallback>>();\n\n setImmediate(async () => {\n const userImportsFactoryPath = resolve(\n this.poolOptions.project.config.root,\n this.asPoolOptions.wasmImportsFactory ?? ''\n );\n\n const results = await Promise.allSettled([\n access(COMPILE_WORKER_PATH),\n access(TEST_WORKER_PATH),\n this.asPoolOptions.wasmImportsFactory ? access(userImportsFactoryPath) : Promise.resolve()\n ]);\n\n const failedThreadAccess: string[] = [];\n if (results[0].status === 'rejected') failedThreadAccess.push(COMPILE_WORKER_PATH);\n if (results[1].status === 'rejected') failedThreadAccess.push(TEST_WORKER_PATH);\n\n if (failedThreadAccess.length) {\n throw new Error(`Cannot access worker thread file(s) at path(s): ${failedThreadAccess}`);\n }\n if (results[2].status === 'rejected') {\n throw new Error(`Cannot access user WasmImportsFactory at path: \"${userImportsFactoryPath}\".`\n + ` Ensure that your module path is relative to the project root (location of shallowest vitest config),`\n + ` and that it has a default export matching () => WebAssembly.Imports`\n );\n }\n });\n \n setGlobalDebugMode(this.asPoolOptions.debug);\n\n debug(`[${this.logModule}] Created AssemblyScriptPoolWorker in ${(performance.now() - start).toFixed(2)} ms`\n + ` | method: \"${this.poolOptions.method}\" | project: \"${this.poolOptions.project.name}\"`\n );\n }\n\n private get isCollectTestsMode(): boolean {\n return this.poolOptions.method === 'collect';\n }\n\n async start(): Promise<void> {\n // do all work in send() message intercept handler so we have access to the config\n }\n\n async stop(): Promise<void> {\n debug(`[${this.logModuleWithId}] stop | running PoolWorker count: ${GLOBAL_RUNNING_POOLWORKER_COUNT}`);\n\n this.listenerRegistry.clear();\n GLOBAL_RUNNING_POOLWORKER_COUNT--;\n this.isWorkerRunning = false;\n\n debug(`[${this.logModuleWithId}] AssemblyScriptPoolWorker STOPPED | running PoolWorker count: ${GLOBAL_RUNNING_POOLWORKER_COUNT}`);\n this.currentWorkerId = undefined;\n }\n\n send(message: WorkerRequest): void {\n switch(message.type) {\n \n // this happens AFTER start() is called (start() is for PoolWorker, \"start\" is for thread)\n case 'start':\n this.currentWorkerId = message.workerId;\n this.config = message.context.config;\n debug(`[${this.logModuleWithId}] send: vitest sent \"start\" message | Captured workerId and config`);\n\n setImmediate(async () => {\n const start = performance.now();\n const { compilePool, runPool } = await this.getGlobalThreadPools(this.config?.maxWorkers);\n \n debug(`[${this.logModuleWithId}] start: fetched global thread pools in ${(performance.now() - start).toFixed(2)} ms`\n + ` | compilePool queueSize: ${compilePool.queueSize} | runPool queueSize: ${runPool.queueSize}`\n );\n \n this.isWorkerRunning = true;\n GLOBAL_RUNNING_POOLWORKER_COUNT++;\n debug(`[${this.logModuleWithId}] start | new running PoolWorker count: ${GLOBAL_RUNNING_POOLWORKER_COUNT}`);\n \n this.notifyVitest('started');\n debug(`[${this.logModuleWithId}] send: responded \"started\" to vitest`);\n });\n \n break;\n \n // this happens BEFORE stop() is called (stop() is for PoolWorker, \"stop\" is for thread)\n case 'stop':\n setImmediate(async () => {\n await this.stopThread();\n this.notifyVitest('stopped');\n });\n break;\n \n case 'cancel':\n debug(`[${this.logModuleWithId}] send: got \"cancel\" unexpectedly`, message);\n break;\n \n case 'collect':\n case 'run':\n this.currentWorkerId = message.context.workerId;\n this.threadSpecs = message.context.files.map((fileSpec): ThreadSpec => ({\n file: createInitialFileTask(\n fileSpec.filepath,\n this.config!.name ?? '',\n this.config!.root,\n this.config!.testTimeout,\n this.config!.retry\n )\n }));\n\n debug(`[${this.logModuleWithId}] send: vitest sent \"${message.type}\" message`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n\n setImmediate(async () => {\n debug(`[${this.logModuleWithId}] send: dispatched \"${message.type}\" job to worker thread`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n \n this.threadRunPromise = this.orchestrateFileRuns();\n\n try {\n await this.threadRunPromise;\n this.notifyVitest('testfileFinished');\n debug(`[${this.logModuleWithId}] send: responded \"testfileFinished\" to vitest`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n\n this.threadSpecs = [];\n } catch (error) {\n if (!isAbortError(error)) {\n throw createPoolErrorFromAnyError(`PoolWorker send() \"${message.type}\"`, POOL_ERROR_NAMES.PoolError, error);\n }\n } finally {\n this.threadControlPort?.close();\n this.threadAbortController = undefined;\n this.threadControlPort = undefined;\n this.threadRunPromise = undefined;\n }\n });\n break;\n }\n }\n\n on(event: string, callback: EventCallback): void {\n this.addEventCallback(event, callback);\n debug(`[${this.logModuleWithId}] ON \"${event}\" - saved listener`);\n }\n\n off(event: string, callback: EventCallback): void {\n if (this.removeEventCallback(event, callback)) {\n debug(`[${this.logModuleWithId}] OFF \"${event}\" - removed callback from registry`);\n } else {\n debug(`[${this.logModuleWithId}] OFF \"${event}\" - callback not found in registry`);\n }\n }\n\n deserialize(data: unknown): unknown {\n return data;\n }\n\n canReuse(_task: PoolTask): boolean {\n return true;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Thread Pool Management\n // ─────────────────────────────────────────────────────────────────────────────\n\n private async getGlobalThreadPools(workerCount?: number): Promise<GlobalThreadPools> {\n if (GLOBAL_POOLS_PROMISE) {\n return GLOBAL_POOLS_PROMISE;\n }\n\n GLOBAL_POOLS_PROMISE = new Promise<GlobalThreadPools>(async (resolve, _reject) => {\n const workers = workerCount ?? availableParallelism();\n\n // TODO - decide which is better when scaling\n // Empirical observations seem to show that minimum parallelization for compilation\n // tends to *dramatically* improve compilation times because of v8 warmpup on repeated calls to asc.main,\n // so much so that this time savings **almost always** outweighs the benefits of speading over many\n // available threads. The **almost** is the key word here- this needs to be tested on platforms with\n // higher available paralellism (> 8) to see if it holds true.\n const actualCompileThreadCount = workers > 1 ? 2 : 1;\n // const actualCompileThreadCount = Math.max(Math.ceil(workers * IDLE_COMPILE_THREADS_FACTOR), 1);\n\n debug(`[${this.logModuleWithId}] Creating global compile thread pool | ${actualCompileThreadCount} threads`);\n \n const start = performance.now();\n \n const compilePool = new Tinypool({\n filename: COMPILE_WORKER_PATH,\n minThreads: 1,\n maxThreads: actualCompileThreadCount,\n isolateWorkers: false,\n idleTimeout: POOL_THREAD_IDLE_TIMEOUT_MS,\n env: this.poolOptions.env as Record<string, string>,\n execArgv: this.poolOptions.execArgv,\n workerData: {\n asPoolOptions: this.asPoolOptions,\n asCoverageOptions: this.asCoverageOptions,\n projectRoot: this.poolOptions.project.config.root,\n } satisfies WorkerThreadInitData\n });\n\n const actualRunThreadCount = Math.max(Math.ceil(workers * IDLE_RUN_THREADS_FACTOR), 1);\n debug(`[${this.logModuleWithId}] Creating global run thread pool | ${actualRunThreadCount} threads`);\n\n const runPool = new Tinypool({\n filename: TEST_WORKER_PATH,\n minThreads: 1,\n maxThreads: actualRunThreadCount,\n isolateWorkers: false,\n idleTimeout: POOL_THREAD_IDLE_TIMEOUT_MS,\n env: this.poolOptions.env as Record<string, string>,\n execArgv: this.poolOptions.execArgv,\n workerData: {\n asPoolOptions: this.asPoolOptions,\n asCoverageOptions: this.asCoverageOptions,\n projectRoot: this.poolOptions.project.config.root\n } satisfies WorkerThreadInitData\n });\n\n debug(`[${this.logModuleWithId}] Created global thread pools in ${(performance.now() - start).toFixed(2)} ms`);\n\n GLOBAL_POOL_ABORT_CONTROLLER = new AbortController();\n resolve({ compilePool, runPool });\n });\n \n return GLOBAL_POOLS_PROMISE;\n }\n\n // @ts-ignore\n private async destroyGlobalPoolsIfNeeded(): Promise<void> {\n if (GLOBAL_RUNNING_POOLWORKER_COUNT === 0 && GLOBAL_POOLS_PROMISE) {\n const destroyStart = performance.now();\n debug(`[${this.logModuleWithId}] Destroying Tinypools...`);\n\n try {\n const { compilePool, runPool } = await GLOBAL_POOLS_PROMISE;\n await Promise.all([ compilePool.destroy(), runPool.destroy() ]);\n } catch {}\n\n GLOBAL_POOLS_PROMISE = undefined;\n GLOBAL_POOL_ABORT_CONTROLLER = undefined;\n\n debug(`[${this.logModuleWithId}] Destroyed tinypools in ${(performance.now() - destroyStart).toFixed(2)} ms`);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Listener Registry Helpers\n // ─────────────────────────────────────────────────────────────────────────────\n\n private getEventCallbacks(event: string): Set<EventCallback> {\n let callbacks: Set<EventCallback> | undefined = this.listenerRegistry.get(event);\n if (!callbacks) {\n callbacks = new Set<EventCallback>();\n this.listenerRegistry.set(event, callbacks);\n }\n return callbacks;\n }\n\n private addEventCallback(event: string, callback: EventCallback): void {\n this.getEventCallbacks(event).add(callback);\n }\n \n private removeEventCallback(event: string, callback: EventCallback): boolean {\n const callbacks = this.getEventCallbacks(event);\n if (callbacks) {\n return callbacks.delete(callback);\n } else {\n return false;\n }\n }\n\n private notifyVitest(responseType: WorkerResponse['type']): void {\n const messageCallbacks = this.getEventCallbacks('message');\n for (const cb of messageCallbacks) {\n cb({ type: responseType, [VITEST_WORKER_RESPONSE_MSG_FLAG]: true } satisfies WorkerResponse)\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Worker Thread Control/Orchestration\n // ─────────────────────────────────────────────────────────────────────────────\n \n private async dispatchCompile(\n spec: ThreadSpec,\n compilePool: Tinypool,\n ): Promise<void> {\n const { workerPort, poolPort } = createWorkerRPCChannel(this.poolOptions.project, this.isCollectTestsMode);\n this.threadControlPort = poolPort;\n \n const compilePromise: Promise<ThreadSpec> = compilePool.run({\n dispatchStart: Date.now(),\n workerId: this.currentWorkerId!,\n port: workerPort,\n file: spec.file,\n config: this.config!,\n isCollectTestsMode: this.isCollectTestsMode,\n } satisfies RunCompileAndDiscoverTask, {\n name: 'runCompileAndDisoverSpec',\n transferList: [workerPort],\n signal: GLOBAL_POOL_ABORT_CONTROLLER!.signal,\n });\n\n try {\n const { compilation, file } = await compilePromise;\n spec.file = file;\n spec.compilation = compilation;\n } finally {\n this.threadControlPort.close();\n this.threadControlPort = undefined;\n }\n }\n \n private async dispatchRunTests(\n spec: ThreadSpec,\n runPool: Tinypool,\n timedOutTest?: Test,\n ): Promise<void> {\n const { workerPort, poolPort } = createWorkerRPCChannel(this.poolOptions.project, this.isCollectTestsMode);\n \n this.threadAbortController = new AbortController();\n this.threadControlPort = poolPort;\n this.threadControlPort.on('message', this.getWorkerThreadMessageHandler());\n\n const runPromise: Promise<void> = !spec.compilation ? Promise.resolve() : runPool.run({\n dispatchStart: Date.now(),\n workerId: this.currentWorkerId!,\n port: workerPort,\n file: timedOutTest?.file ?? spec.file,\n compilation: spec.compilation,\n config: this.config!,\n isCollectTestsMode: this.isCollectTestsMode,\n timedOutTest,\n } satisfies RunTestsTask, {\n name: 'runFileSpec',\n transferList: [workerPort],\n signal: AbortSignal.any([this.threadAbortController.signal, GLOBAL_POOL_ABORT_CONTROLLER!.signal]),\n });\n\n try {\n return await runPromise;\n } finally {\n this.threadControlPort.close();\n this.threadControlPort = undefined;\n }\n }\n\n private async orchestrateFileRuns(timedOutTest?: Test): Promise<void> {\n const modeStr = this.isCollectTestsMode ? 'collectTests' : 'runTests';\n const isResume: boolean = !!timedOutTest;\n const desc = `${modeStr} ${isResume ? '(RESUME)' : '(INITIAL)'}`;\n\n debug(`[${this.logModuleWithId}] orchestrateFileRuns: dispatching ${desc} to worker thread`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n\n const { compilePool, runPool } = await this.getGlobalThreadPools(this.config?.maxWorkers);\n\n // compile\n if (!isResume) {\n await Promise.all(\n this.threadSpecs.map(spec => this.dispatchCompile(spec, compilePool))\n );\n }\n\n // test\n if (!this.isCollectTestsMode) {\n await Promise.all(\n this.threadSpecs.map(spec => this.dispatchRunTests(spec, runPool, timedOutTest))\n );\n }\n\n debug(`[${this.logModuleWithId}] orchestrateFileRuns: ${desc} thread work complete`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n }\n\n private async stopThread(): Promise<void> {\n this.clearTestTimeoutTimer(); // if any\n this.currentTestRun = undefined;\n \n const mod = this.logModuleWithId;\n const start = performance.now();\n\n debug('setting graceful resolve timeout');\n const abortTimeout = setTimeout(() => {\n debug(`[${mod}] stop: timed out waiting on pool worker run resolve ${(performance.now() - start).toFixed(2)} ms | Aborting thread`);\n this.threadAbortController?.abort();\n }, THREAD_RESOLVE_TIMEOUT_MS);\n \n try {\n debug(`[${mod}] stop: awaiting pool worker run resolve: ${!!this.threadRunPromise}`);\n await this.threadRunPromise;\n clearTimeout(abortTimeout);\n debug(`[${this.logModuleWithId}] stop: pool worker run resolved cleanly after ${(performance.now() - start).toFixed(2)} ms`);\n } catch {\n } finally {\n this.threadControlPort?.close();\n debug(`[${this.logModuleWithId}] stop: closed pool port`);\n }\n \n this.threadAbortController = undefined;\n this.threadControlPort = undefined;\n this.threadRunPromise = undefined;\n this.threadSpecs = [];\n }\n\n private getWorkerThreadMessageHandler(): EventCallback {\n return (message: any): void => {\n if (message[AS_POOL_WORKER_MSG_FLAG]) {\n const poolMessage = message as AssemblyScriptPoolWorkerMessage;\n\n switch (poolMessage.type) {\n case 'execution-start':\n this.handleTestExecutionStart(message);\n break;\n case 'execution-end':\n this.handleTestExecutionEnd(message);\n break;\n }\n\n return;\n }\n };\n }\n\n private handleTestExecutionStart(msg: TestExecutionStart): void {\n if (!this.isWorkerRunning) return;\n \n const { executionStart, test } = msg;\n const now = Date.now();\n const transitDuration = now - executionStart;\n const adjustedTimeout = Math.max(test.timeout - transitDuration, 0);\n\n this.currentTestRun = {\n test,\n executionStart,\n timeoutId: setTimeout(() => this.handleTimeout(), adjustedTimeout)\n };\n\n debug(`[${this.logModuleWithId}] START test timeout timer for \"${this.currentTestRun.test.name}\"`);\n }\n\n private handleTestExecutionEnd(_msg: TestExecutionEnd): void {\n this.clearTestTimeoutTimer();\n this.currentTestRun = undefined;\n }\n\n private clearTestTimeoutTimer(): void {\n if (this.currentTestRun) {\n const elapsed = Date.now() - this.currentTestRun.executionStart;\n debug(`[${this.logModuleWithId}] CLEAR test timeout timer (${elapsed.toFixed(2)} ms) for \"${this.currentTestRun?.test.name}\"`);\n clearTimeout(this.currentTestRun.timeoutId);\n }\n }\n\n private async handleTimeout(): Promise<void> {\n if (!this.isWorkerRunning) return;\n\n if (!this.threadSpecs.length || !this.currentTestRun || !this.currentTestRun.test) {\n const missingStr = \n + (this.threadSpecs.length ? '' : 'threadSpecs')\n + (this.currentTestRun ? '' : ' currentTestRecord')\n + (this.currentTestRun?.test ? '' : ' currentTestRecord.test')\n throw createPoolError(\n `Cannot timeout/resume worker thread for workerId ${this.currentWorkerId} - missing data: ${missingStr}`,\n POOL_ERROR_NAMES.PoolError\n );\n }\n\n const duration = Date.now() - this.currentTestRun.executionStart;\n failTestWithTimeoutError(this.currentTestRun.test, this.currentTestRun.executionStart, duration);\n\n // set termination time metadata for measuring resume latency\n flagTestTerminated(this.currentTestRun.test);\n\n debug(`[${this.logModuleWithId}] handleTimeout: TEST TIMEOUT \"${this.currentTestRun.test.name}\" after ${duration.toFixed(2)} ms`\n +` - Terminating worker thread job`\n );\n\n const termStart = performance.now();\n \n try {\n this.threadAbortController?.abort();\n await this.threadRunPromise;\n } catch (error) {\n if (!isAbortError(error)) {\n throw createPoolErrorFromAnyError(`PoolWorker handleTimeout`, POOL_ERROR_NAMES.PoolError, error);\n }\n } finally {\n this.threadControlPort?.close();\n this.threadAbortController = undefined;\n this.threadControlPort = undefined;\n this.threadRunPromise = undefined;\n }\n\n debug(`[${this.logModuleWithId}] handleTimeout: Worker thread job aborted for timeout in ${(performance.now() - termStart).toFixed(2)} ms`);\n \n if (!this.isWorkerRunning) return;\n\n // supply timed-out test (includes entire file hierarchy & coverage)\n // to resume testing where we leftoff when aborting for timeout\n this.threadRunPromise = this.orchestrateFileRuns(this.currentTestRun.test);\n\n debug(`[${this.logModuleWithId}] handleTimeout: re-dispatched job to worker thread`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n\n try {\n await this.threadRunPromise;\n this.notifyVitest('testfileFinished');\n debug(`[${this.logModuleWithId}] handleTimeout: file run completed - responded \"testfileFinished\" to vitest`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n \n this.threadSpecs = [];\n } catch (error) {\n if (!isAbortError(error)) {\n throw createPoolErrorFromAnyError(`PoolWorker handleTimeout`, POOL_ERROR_NAMES.PoolError, error);\n } else {\n debug(`[${this.logModuleWithId}] send: caught and ignored timeout awaiting timeout re-run`\n + ` | files: \"${this.threadSpecs.map(s => s.file.filepath).join(',')}\"`\n );\n }\n } finally {\n //@ts-ignore\n this.threadControlPort?.close();\n this.threadControlPort = undefined;\n this.threadAbortController = undefined;\n this.threadRunPromise = undefined;\n }\n }\n\n private get logModuleWithId(): string {\n return `${this.logModule}${this.currentWorkerId === undefined ? '' : ` ${this.currentWorkerId}`}`;\n }\n}\n","import type { PoolOptions, PoolRunnerInitializer } from 'vitest/node';\n\nimport type {\n AssemblyScriptPoolOptions,\n ResolvedHybridProviderOptions\n} from '../types/types.js';\nimport { ASSEMBLYSCRIPT_POOL_NAME } from '../types/constants.js';\nimport { resolvePoolOptions } from '../util/resolve-config.js';\nimport { AssemblyScriptPoolWorker } from './pool-worker.js';\n\nexport function createAssemblyScriptPool(userPoolOptions?: AssemblyScriptPoolOptions): PoolRunnerInitializer {\n const resolvedUserPoolOptions = resolvePoolOptions(userPoolOptions);\n\n return {\n name: ASSEMBLYSCRIPT_POOL_NAME,\n createPoolWorker: (opts: PoolOptions) => {\n const resolvedCoverageOptions = opts.project.config.coverage as ResolvedHybridProviderOptions;\n return new AssemblyScriptPoolWorker(opts, resolvedUserPoolOptions, resolvedCoverageOptions);\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RunCompileAndDiscoverTask, ThreadSpec } from "../types-8KKo9Hbf.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/pool-thread/compile-worker-thread.d.ts
|
|
4
|
+
declare function runCompileAndDisoverSpec(data: RunCompileAndDiscoverTask): Promise<ThreadSpec>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { runCompileAndDisoverSpec };
|
|
7
|
+
//# sourceMappingURL=compile-worker-thread.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-worker-thread.d.mts","names":[],"sources":["../../src/pool-thread/compile-worker-thread.ts"],"mappings":";;;iBA+BsB,wBAAA,CAAyB,IAAA,EAAM,yBAAA,GAA4B,OAAA,CAAQ,UAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { debug, setGlobalDebugMode } from "../debug-IeEHsxy0.mjs";
|
|
2
|
+
import "../vitest-file-tasks-BUwzh375.mjs";
|
|
3
|
+
import "../vitest-tasks-BKS7689f.mjs";
|
|
4
|
+
import { createRpcClient, loadUserWasmImportsFactory } from "../load-user-imports-J9eaAW0_.mjs";
|
|
5
|
+
import "../compiler-CN6BRK_N.mjs";
|
|
6
|
+
import { runCompileAndDiscover } from "../compile-runner-8h0dBwG2.mjs";
|
|
7
|
+
import { threadId, workerData } from "node:worker_threads";
|
|
8
|
+
import { highlight } from "@vitest/utils/highlight";
|
|
9
|
+
|
|
10
|
+
//#region src/pool-thread/compile-worker-thread.ts
|
|
11
|
+
/**
|
|
12
|
+
* Worker entry point - Compile Worker (vitest v4)
|
|
13
|
+
*/
|
|
14
|
+
const logModule = `WorkerThread`;
|
|
15
|
+
const [_unused, initData] = workerData;
|
|
16
|
+
const { projectRoot, asPoolOptions, asCoverageOptions } = initData;
|
|
17
|
+
setGlobalDebugMode(asPoolOptions.debug);
|
|
18
|
+
debug(`[${logModule}] New compile pool thread created`);
|
|
19
|
+
const createWasmImports = await loadUserWasmImportsFactory(asPoolOptions.wasmImportsFactory, projectRoot, logModule);
|
|
20
|
+
async function runCompileAndDisoverSpec(data) {
|
|
21
|
+
const { dispatchStart, workerId, file, port, config } = data;
|
|
22
|
+
const dispatchToInit = Date.now() - dispatchStart;
|
|
23
|
+
const logModuleWithId = `${logModule} ${workerId} (t ${threadId})`;
|
|
24
|
+
const rpc = createRpcClient(port);
|
|
25
|
+
port.unref();
|
|
26
|
+
debug(`[${logModuleWithId}] -------- compile and discover starting -------- | dispatchToInit: ${dispatchToInit.toFixed(2)}ms`);
|
|
27
|
+
debug(`[${logModuleWithId}] Awaiting compilation | projectName: "${config.name}" | file: "${file.filepath}"`);
|
|
28
|
+
const compilation = await runCompileAndDiscover(file, logModuleWithId, rpc, asPoolOptions, config.root, config.coverage.enabled, asCoverageOptions.globbedAssemblyScriptProjectRelativeExcludeOnly ?? [], {
|
|
29
|
+
highlight,
|
|
30
|
+
createWasmImports
|
|
31
|
+
}, typeof config.diff === "object" ? config.diff : void 0, config.testNamePattern, config.allowOnly);
|
|
32
|
+
debug(`[${logModuleWithId}] -------- compile and discover completed run --------`);
|
|
33
|
+
port.close();
|
|
34
|
+
return {
|
|
35
|
+
compilation,
|
|
36
|
+
file
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { runCompileAndDisoverSpec };
|
|
42
|
+
//# sourceMappingURL=compile-worker-thread.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-worker-thread.mjs","names":[],"sources":["../../src/pool-thread/compile-worker-thread.ts"],"sourcesContent":["/**\n * Worker entry point - Compile Worker (vitest v4)\n */\nimport { threadId, workerData } from 'node:worker_threads';\nimport { highlight } from '@vitest/utils/highlight';\n\nimport type {\n WorkerThreadInitData,\n RunCompileAndDiscoverTask,\n ThreadSpec,\n ThreadImports,\n WasmImportsFactory,\n} from '../types/types.js';\nimport { runCompileAndDiscover } from './runner/compile-runner.js';\nimport { debug, setGlobalDebugMode } from '../util/debug.js';\nimport { createRpcClient } from './rpc-reporter.js';\nimport { loadUserWasmImportsFactory } from './load-user-imports.js';\n\nconst logModule = `WorkerThread` as const;\nconst [_unused, initData] = workerData;\nconst { projectRoot, asPoolOptions, asCoverageOptions } = initData as WorkerThreadInitData;\n\nsetGlobalDebugMode(asPoolOptions.debug);\ndebug(`[${logModule}] New compile pool thread created`);\n\nconst createWasmImports: WasmImportsFactory | undefined = await loadUserWasmImportsFactory(\n asPoolOptions.wasmImportsFactory,\n projectRoot,\n logModule\n);\n\nexport async function runCompileAndDisoverSpec(data: RunCompileAndDiscoverTask): Promise<ThreadSpec> {\n const { dispatchStart, workerId, file, port, config } = data;\n\n const dispatchToInit = Date.now() - dispatchStart;\n const logModuleWithId = `${logModule} ${workerId} (t ${threadId})`;\n \n const rpc = createRpcClient(port);\n port.unref();\n\n debug(`[${logModuleWithId}] -------- compile and discover starting -------- | dispatchToInit: ${dispatchToInit.toFixed(2)}ms`);\n debug(`[${logModuleWithId}] Awaiting compilation | projectName: \"${config.name}\" | file: \"${file.filepath}\"`);\n\n const compilation = await runCompileAndDiscover(\n file,\n logModuleWithId,\n rpc,\n asPoolOptions,\n config.root,\n config.coverage.enabled,\n asCoverageOptions.globbedAssemblyScriptProjectRelativeExcludeOnly ?? [],\n { highlight, createWasmImports } satisfies ThreadImports,\n typeof config.diff === 'object' ? config.diff : undefined,\n config.testNamePattern,\n config.allowOnly,\n );\n\n debug(`[${logModuleWithId}] -------- compile and discover completed run --------`);\n\n port.close();\n\n return { compilation, file };\n}\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,YAAY;AAClB,MAAM,CAAC,SAAS,YAAY;AAC5B,MAAM,EAAE,aAAa,eAAe,sBAAsB;AAE1D,mBAAmB,cAAc,MAAM;AACvC,MAAM,IAAI,UAAU,mCAAmC;AAEvD,MAAM,oBAAoD,MAAM,2BAC9D,cAAc,oBACd,aACA,UACD;AAED,eAAsB,yBAAyB,MAAsD;CACnG,MAAM,EAAE,eAAe,UAAU,MAAM,MAAM,WAAW;CAExD,MAAM,iBAAiB,KAAK,KAAK,GAAG;CACpC,MAAM,kBAAkB,GAAG,UAAU,GAAG,SAAS,MAAM,SAAS;CAEhE,MAAM,MAAM,gBAAgB,KAAK;AACjC,MAAK,OAAO;AAEZ,OAAM,IAAI,gBAAgB,sEAAsE,eAAe,QAAQ,EAAE,CAAC,IAAI;AAC9H,OAAM,IAAI,gBAAgB,yCAAyC,OAAO,KAAK,aAAa,KAAK,SAAS,GAAG;CAE7G,MAAM,cAAc,MAAM,sBACxB,MACA,iBACA,KACA,eACA,OAAO,MACP,OAAO,SAAS,SAChB,kBAAkB,mDAAmD,EAAE,EACvE;EAAE;EAAW;EAAmB,EAChC,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,QAChD,OAAO,iBACP,OAAO,UACR;AAED,OAAM,IAAI,gBAAgB,wDAAwD;AAElF,MAAK,OAAO;AAEZ,QAAO;EAAE;EAAa;EAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-worker-thread.d.mts","names":[],"sources":["../../src/pool-thread/test-worker-thread.ts"],"mappings":";;;iBA0BsB,WAAA,CAAY,IAAA,EAAM,YAAA,GAAe,OAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { debug, setGlobalDebugMode } from "../debug-IeEHsxy0.mjs";
|
|
2
|
+
import "../vitest-tasks-BKS7689f.mjs";
|
|
3
|
+
import { createRpcClient, loadUserWasmImportsFactory } from "../load-user-imports-J9eaAW0_.mjs";
|
|
4
|
+
import { runSuite } from "../test-runner-B2BpyPNK.mjs";
|
|
5
|
+
import { basename } from "node:path";
|
|
6
|
+
import { threadId, workerData } from "node:worker_threads";
|
|
7
|
+
import { highlight } from "@vitest/utils/highlight";
|
|
8
|
+
|
|
9
|
+
//#region src/pool-thread/test-worker-thread.ts
|
|
10
|
+
/**
|
|
11
|
+
* Worker entry point - Node Worker (vitest v4)
|
|
12
|
+
*/
|
|
13
|
+
const logModule = `WorkerThread`;
|
|
14
|
+
const [_unused, initData] = workerData;
|
|
15
|
+
const { asPoolOptions, projectRoot } = initData;
|
|
16
|
+
setGlobalDebugMode(asPoolOptions.debug);
|
|
17
|
+
debug(`[${logModule}] New test run pool thread created`);
|
|
18
|
+
const createWasmImports = await loadUserWasmImportsFactory(asPoolOptions.wasmImportsFactory, projectRoot, logModule);
|
|
19
|
+
async function runFileSpec(data) {
|
|
20
|
+
const { dispatchStart, workerId, file, port, config, isCollectTestsMode, compilation, timedOutTest } = data;
|
|
21
|
+
const dispatchToInit = Date.now() - dispatchStart;
|
|
22
|
+
const logModuleWithId = `${logModule} ${workerId} (t ${threadId})`;
|
|
23
|
+
const rpc = createRpcClient(port);
|
|
24
|
+
port.unref();
|
|
25
|
+
const mode = isCollectTestsMode ? "collectTests" : "runTests";
|
|
26
|
+
debug(`[${logModuleWithId}] -------- ${mode} starting -------- | dispatchToInit: ${dispatchToInit.toFixed(2)}ms`);
|
|
27
|
+
debug(`[${logModuleWithId}] projectName: "${config.name}" | file: "${file.filepath}"`);
|
|
28
|
+
debug(`[${logModuleWithId}] ${mode} | awaiting file run`);
|
|
29
|
+
await runSuite(rpc, port, basename(file.filepath), config.coverage.enabled, compilation, file, logModuleWithId, asPoolOptions, {
|
|
30
|
+
highlight,
|
|
31
|
+
createWasmImports
|
|
32
|
+
}, "v4", config.bail, typeof config.diff === "object" ? config.diff : void 0, timedOutTest);
|
|
33
|
+
debug(`[${logModuleWithId}] -------- ${mode} completed file run --------`);
|
|
34
|
+
port.close();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
export { runFileSpec };
|
|
39
|
+
//# sourceMappingURL=test-worker-thread.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-worker-thread.mjs","names":[],"sources":["../../src/pool-thread/test-worker-thread.ts"],"sourcesContent":["/**\n * Worker entry point - Node Worker (vitest v4)\n */\nimport { basename } from 'node:path';\nimport { threadId, workerData } from 'node:worker_threads';\nimport { highlight } from '@vitest/utils/highlight';\n\nimport type { RunTestsTask, ThreadImports, WasmImportsFactory, WorkerThreadInitData } from '../types/types.js';\nimport { debug, setGlobalDebugMode } from '../util/debug.js';\nimport { createRpcClient } from './rpc-reporter.js';\nimport { runSuite } from './runner/test-runner.js';\nimport { loadUserWasmImportsFactory } from './load-user-imports.js';\n\nconst logModule = `WorkerThread` as const;\nconst [_unused, initData] = workerData;\nconst { asPoolOptions, projectRoot } = initData as WorkerThreadInitData;\n\nsetGlobalDebugMode(asPoolOptions.debug);\ndebug(`[${logModule}] New test run pool thread created`);\n\nconst createWasmImports: WasmImportsFactory | undefined = await loadUserWasmImportsFactory(\n asPoolOptions.wasmImportsFactory,\n projectRoot,\n logModule\n);\n\nexport async function runFileSpec(data: RunTestsTask): Promise<void> {\n const {\n dispatchStart, workerId, file, port, config,\n isCollectTestsMode, compilation, timedOutTest\n } = data;\n\n const dispatchToInit = Date.now() - dispatchStart;\n const logModuleWithId = `${logModule} ${workerId} (t ${threadId})`;\n \n const rpc = createRpcClient(port);\n port.unref();\n\n const mode = isCollectTestsMode ? 'collectTests' : 'runTests';\n\n debug(`[${logModuleWithId}] -------- ${mode} starting -------- | dispatchToInit: ${dispatchToInit.toFixed(2)}ms`);\n debug(`[${logModuleWithId}] projectName: \"${config.name}\" | file: \"${file.filepath}\"`);\n\n debug(`[${logModuleWithId}] ${mode} | awaiting file run`);\n\n await runSuite(\n rpc,\n port,\n basename(file.filepath),\n config.coverage.enabled,\n compilation,\n file,\n logModuleWithId,\n asPoolOptions,\n { highlight, createWasmImports } satisfies ThreadImports,\n 'v4',\n config.bail,\n typeof config.diff === 'object' ? config.diff : undefined,\n timedOutTest,\n );\n\n debug(`[${logModuleWithId}] -------- ${mode} completed file run --------`);\n\n port.close();\n\n return;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,YAAY;AAClB,MAAM,CAAC,SAAS,YAAY;AAC5B,MAAM,EAAE,eAAe,gBAAgB;AAEvC,mBAAmB,cAAc,MAAM;AACvC,MAAM,IAAI,UAAU,oCAAoC;AAExD,MAAM,oBAAoD,MAAM,2BAC9D,cAAc,oBACd,aACA,UACD;AAED,eAAsB,YAAY,MAAmC;CACnE,MAAM,EACJ,eAAe,UAAU,MAAM,MAAM,QACrC,oBAAoB,aAAa,iBAC/B;CAEJ,MAAM,iBAAiB,KAAK,KAAK,GAAG;CACpC,MAAM,kBAAkB,GAAG,UAAU,GAAG,SAAS,MAAM,SAAS;CAEhE,MAAM,MAAM,gBAAgB,KAAK;AACjC,MAAK,OAAO;CAEZ,MAAM,OAAO,qBAAqB,iBAAiB;AAEnD,OAAM,IAAI,gBAAgB,aAAa,KAAK,uCAAuC,eAAe,QAAQ,EAAE,CAAC,IAAI;AACjH,OAAM,IAAI,gBAAgB,kBAAkB,OAAO,KAAK,aAAa,KAAK,SAAS,GAAG;AAEtF,OAAM,IAAI,gBAAgB,IAAI,KAAK,sBAAsB;AAEzD,OAAM,SACJ,KACA,MACA,SAAS,KAAK,SAAS,EACvB,OAAO,SAAS,SAChB,aACA,MACA,iBACA,eACA;EAAE;EAAW;EAAmB,EAChC,MACA,OAAO,MACP,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,QAChD,aACD;AAED,OAAM,IAAI,gBAAgB,aAAa,KAAK,8BAA8B;AAE1E,MAAK,OAAO"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ProcessPoolRunFileTask } from "../types-8KKo9Hbf.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/pool-thread/v3-tinypool-thread.d.ts
|
|
4
|
+
declare function runTestFile(taskData: ProcessPoolRunFileTask): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { runTestFile };
|
|
7
|
+
//# sourceMappingURL=v3-tinypool-thread.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3-tinypool-thread.d.mts","names":[],"sources":["../../src/pool-thread/v3-tinypool-thread.ts"],"mappings":";;;iBA8BsB,WAAA,CAAY,QAAA,EAAU,sBAAA,GAAyB,OAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { debug, setGlobalDebugMode } from "../debug-IeEHsxy0.mjs";
|
|
2
|
+
import "../vitest-file-tasks-BUwzh375.mjs";
|
|
3
|
+
import "../vitest-tasks-BKS7689f.mjs";
|
|
4
|
+
import { createRpcClient, loadUserWasmImportsFactory } from "../load-user-imports-J9eaAW0_.mjs";
|
|
5
|
+
import "../compiler-CN6BRK_N.mjs";
|
|
6
|
+
import { runCompileAndDiscover } from "../compile-runner-8h0dBwG2.mjs";
|
|
7
|
+
import { runSuite } from "../test-runner-B2BpyPNK.mjs";
|
|
8
|
+
import { basename } from "node:path";
|
|
9
|
+
import { workerId } from "tinypool";
|
|
10
|
+
import { threadId, workerData } from "node:worker_threads";
|
|
11
|
+
import { highlight } from "@vitest/utils";
|
|
12
|
+
|
|
13
|
+
//#region src/pool-thread/v3-tinypool-thread.ts
|
|
14
|
+
/**
|
|
15
|
+
* Worker entry point - Tinypool (vitest v3)
|
|
16
|
+
*/
|
|
17
|
+
const logModule = `WorkerThread`;
|
|
18
|
+
const [_unused, initData] = workerData;
|
|
19
|
+
const { asPoolOptions, asCoverageOptions, projectRoot } = initData;
|
|
20
|
+
setGlobalDebugMode(asPoolOptions.debug);
|
|
21
|
+
debug(`[${logModule}] New pool thread created`);
|
|
22
|
+
const createWasmImports = await loadUserWasmImportsFactory(asPoolOptions.wasmImportsFactory, projectRoot, logModule);
|
|
23
|
+
async function runTestFile(taskData) {
|
|
24
|
+
const { dispatchStart, port, file, config, isCollectTestsMode, timedOutTest, timedOutCompilation } = taskData;
|
|
25
|
+
const dispatchToInit = Date.now() - dispatchStart;
|
|
26
|
+
const logModuleWithId = `WorkerThread ${workerId} (t ${threadId})`;
|
|
27
|
+
const rpc = createRpcClient(port);
|
|
28
|
+
port.unref();
|
|
29
|
+
const mode = isCollectTestsMode ? "collectTests" : "runTests";
|
|
30
|
+
debug(`[${logModuleWithId}] -------- ${mode} starting -------- | dispatchToInit: ${dispatchToInit.toFixed(2)}ms`);
|
|
31
|
+
debug(`[${logModuleWithId}] projectName: "${config.name}" | file: "${file.filepath}"`);
|
|
32
|
+
const compilation = timedOutCompilation ?? await runCompileAndDiscover(file, logModuleWithId, rpc, asPoolOptions, config.root, config.coverage.enabled, asCoverageOptions.globbedAssemblyScriptProjectRelativeExcludeOnly ?? [], {
|
|
33
|
+
highlight,
|
|
34
|
+
createWasmImports
|
|
35
|
+
}, typeof config.diff === "object" ? config.diff : void 0, config.testNamePattern, config.allowOnly);
|
|
36
|
+
if (compilation && !timedOutCompilation) {
|
|
37
|
+
port.postMessage({
|
|
38
|
+
compilation,
|
|
39
|
+
type: "file-compiled",
|
|
40
|
+
["__as_pool__"]: true
|
|
41
|
+
});
|
|
42
|
+
debug(`[${logModuleWithId}] sent compilation to pool for "${compilation.filePath}"`);
|
|
43
|
+
}
|
|
44
|
+
if (compilation && !isCollectTestsMode) {
|
|
45
|
+
debug(`[${logModuleWithId}] Running file suite`);
|
|
46
|
+
await runSuite(rpc, port, basename(file.filepath), config.coverage.enabled, compilation, file, logModuleWithId, asPoolOptions, {
|
|
47
|
+
highlight,
|
|
48
|
+
createWasmImports
|
|
49
|
+
}, "v3", config.bail, typeof config.diff === "object" ? config.diff : void 0, timedOutTest);
|
|
50
|
+
} else debug(`[${logModuleWithId}] Skipping file suite run`);
|
|
51
|
+
debug(`[${logModuleWithId}] -------- ${mode} completed file run --------`);
|
|
52
|
+
port.close();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
export { runTestFile };
|
|
57
|
+
//# sourceMappingURL=v3-tinypool-thread.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3-tinypool-thread.mjs","names":[],"sources":["../../src/pool-thread/v3-tinypool-thread.ts"],"sourcesContent":["/**\n * Worker entry point - Tinypool (vitest v3)\n */\nimport { basename } from 'node:path';\nimport { threadId, workerData } from 'node:worker_threads';\nimport { workerId } from 'tinypool';\n// @ts-ignore - we build with v4, but this is correct for v3 runtime\nimport { highlight } from '@vitest/utils';\n\nimport type { ProcessPoolRunFileTask, TestFileCompiled, ThreadImports, WasmImportsFactory, WorkerThreadInitData } from '../types/types.js';\nimport { AS_POOL_WORKER_MSG_FLAG } from '../types/constants.js';\nimport { debug, setGlobalDebugMode } from '../util/debug.js';\nimport { createRpcClient } from './rpc-reporter.js';\nimport { runCompileAndDiscover } from './runner/compile-runner.js';\nimport { runSuite } from './runner/test-runner.js';\nimport { loadUserWasmImportsFactory } from './load-user-imports.js';\n\nconst logModule = `WorkerThread` as const;\nconst [_unused, initData] = workerData;\nconst { asPoolOptions, asCoverageOptions, projectRoot } = initData as WorkerThreadInitData;\n\nsetGlobalDebugMode(asPoolOptions.debug);\ndebug(`[${logModule}] New pool thread created`);\n\nconst createWasmImports: WasmImportsFactory | undefined = await loadUserWasmImportsFactory(\n asPoolOptions.wasmImportsFactory,\n projectRoot,\n logModule\n);\n\nexport async function runTestFile(taskData: ProcessPoolRunFileTask): Promise<void> {\n const {\n dispatchStart, port, file, config, isCollectTestsMode,\n timedOutTest, timedOutCompilation\n } = taskData;\n\n const dispatchToInit = Date.now() - dispatchStart;\n const logModuleWithId = `WorkerThread ${workerId} (t ${threadId})`;\n const rpc = createRpcClient(port);\n port.unref();\n\n const mode = isCollectTestsMode ? 'collectTests' : 'runTests';\n debug(`[${logModuleWithId}] -------- ${mode} starting -------- | dispatchToInit: ${dispatchToInit.toFixed(2)}ms`);\n debug(`[${logModuleWithId}] projectName: \"${config.name}\" | file: \"${file.filepath}\"`);\n \n const compilation = timedOutCompilation ?? await runCompileAndDiscover(\n file,\n logModuleWithId,\n rpc,\n asPoolOptions,\n config.root,\n config.coverage.enabled,\n asCoverageOptions.globbedAssemblyScriptProjectRelativeExcludeOnly ?? [],\n { highlight, createWasmImports } satisfies ThreadImports,\n typeof config.diff === 'object' ? config.diff : undefined,\n config.testNamePattern,\n config.allowOnly,\n );\n\n if (compilation && !timedOutCompilation) {\n port.postMessage({\n compilation,\n type: 'file-compiled',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestFileCompiled);\n debug(`[${logModuleWithId}] sent compilation to pool for \"${compilation.filePath}\"`);\n }\n \n if (compilation && !isCollectTestsMode) {\n\t\tdebug(`[${logModuleWithId}] Running file suite`);\n await runSuite(\n rpc,\n port,\n basename(file.filepath),\n config.coverage.enabled,\n compilation,\n file,\n logModuleWithId,\n asPoolOptions,\n { highlight, createWasmImports } satisfies ThreadImports,\n 'v3',\n config.bail,\n typeof config.diff === 'object' ? config.diff : undefined,\n timedOutTest,\n );\n } else {\n\t\tdebug(`[${logModuleWithId}] Skipping file suite run`);\n\t}\n\n debug(`[${logModuleWithId}] -------- ${mode} completed file run --------`);\n port.close();\n\n return;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,MAAM,YAAY;AAClB,MAAM,CAAC,SAAS,YAAY;AAC5B,MAAM,EAAE,eAAe,mBAAmB,gBAAgB;AAE1D,mBAAmB,cAAc,MAAM;AACvC,MAAM,IAAI,UAAU,2BAA2B;AAE/C,MAAM,oBAAoD,MAAM,2BAC9D,cAAc,oBACd,aACA,UACD;AAED,eAAsB,YAAY,UAAiD;CACjF,MAAM,EACJ,eAAe,MAAM,MAAM,QAAQ,oBACnC,cAAc,wBACZ;CAEJ,MAAM,iBAAiB,KAAK,KAAK,GAAG;CACpC,MAAM,kBAAkB,gBAAgB,SAAS,MAAM,SAAS;CAChE,MAAM,MAAM,gBAAgB,KAAK;AACjC,MAAK,OAAO;CAEZ,MAAM,OAAO,qBAAqB,iBAAiB;AACnD,OAAM,IAAI,gBAAgB,aAAa,KAAK,uCAAuC,eAAe,QAAQ,EAAE,CAAC,IAAI;AACjH,OAAM,IAAI,gBAAgB,kBAAkB,OAAO,KAAK,aAAa,KAAK,SAAS,GAAG;CAEtF,MAAM,cAAc,uBAAuB,MAAM,sBAC/C,MACA,iBACA,KACA,eACA,OAAO,MACP,OAAO,SAAS,SAChB,kBAAkB,mDAAmD,EAAE,EACvE;EAAE;EAAW;EAAmB,EAChC,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,QAChD,OAAO,iBACP,OAAO,UACR;AAED,KAAI,eAAe,CAAC,qBAAqB;AACvC,OAAK,YAAY;GACf;GACA,MAAM;oBACqB;GAC5B,CAA4B;AAC7B,QAAM,IAAI,gBAAgB,kCAAkC,YAAY,SAAS,GAAG;;AAGtF,KAAI,eAAe,CAAC,oBAAoB;AACxC,QAAM,IAAI,gBAAgB,sBAAsB;AAC9C,QAAM,SACJ,KACA,MACA,SAAS,KAAK,SAAS,EACvB,OAAO,SAAS,SAChB,aACA,MACA,iBACA,eACA;GAAE;GAAW;GAAmB,EAChC,MACA,OAAO,MACP,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,QAChD,aACD;OAEH,OAAM,IAAI,gBAAgB,2BAA2B;AAGrD,OAAM,IAAI,gBAAgB,aAAa,KAAK,8BAA8B;AAC1E,MAAK,OAAO"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { POOL_ERROR_NAMES } from "./constants-CA50WBdr.mjs";
|
|
2
|
+
import { createPoolError } from "./debug-IeEHsxy0.mjs";
|
|
3
|
+
import { availableParallelism } from "node:os";
|
|
4
|
+
|
|
5
|
+
//#region src/types/types.ts
|
|
6
|
+
const AS_POOL_FIELDS_WITH_DEFAULTS = [
|
|
7
|
+
"debug",
|
|
8
|
+
"stripInline",
|
|
9
|
+
"maxThreadsV3",
|
|
10
|
+
"coverageMemoryPagesInitial",
|
|
11
|
+
"coverageMemoryPagesMax",
|
|
12
|
+
"testMemoryPagesInitial",
|
|
13
|
+
"extraCompilerFlags"
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/util/resolve-config.ts
|
|
18
|
+
const DEFAULT_ASSEMBLYSCRIPT_POOL_OTIONS = {
|
|
19
|
+
debug: false,
|
|
20
|
+
stripInline: true,
|
|
21
|
+
maxThreadsV3: availableParallelism() - 1,
|
|
22
|
+
coverageMemoryPagesInitial: 1,
|
|
23
|
+
coverageMemoryPagesMax: 4,
|
|
24
|
+
testMemoryPagesInitial: 1,
|
|
25
|
+
extraCompilerFlags: []
|
|
26
|
+
};
|
|
27
|
+
function resolvePoolOptions(userPoolOptions) {
|
|
28
|
+
const poolOptions = userPoolOptions ?? DEFAULT_ASSEMBLYSCRIPT_POOL_OTIONS;
|
|
29
|
+
for (const configKey of AS_POOL_FIELDS_WITH_DEFAULTS) if (poolOptions[configKey] === void 0) poolOptions[configKey] = DEFAULT_ASSEMBLYSCRIPT_POOL_OTIONS[configKey];
|
|
30
|
+
const resolved = {
|
|
31
|
+
...poolOptions,
|
|
32
|
+
isResolved: true
|
|
33
|
+
};
|
|
34
|
+
if (resolved.coverageMemoryPagesInitial < 1 || resolved.coverageMemoryPagesMax < 1) throw createPoolError(`Coverage memory page size options must be positive - coverageMemoryPagesMin: ${resolved.coverageMemoryPagesInitial} | coverageMemoryPagesMax: ${resolved.coverageMemoryPagesMax}`, POOL_ERROR_NAMES.PoolConfigError);
|
|
35
|
+
if (resolved.testMemoryPagesInitial < 1 || resolved.testMemoryPagesMax !== void 0 && resolved.testMemoryPagesMax < 1) throw createPoolError(`Test memory page size options must be positive - testMemoryPagesMin: ${resolved.testMemoryPagesInitial} | testMemoryPagesMax: ${resolved.testMemoryPagesMax}`, POOL_ERROR_NAMES.PoolConfigError);
|
|
36
|
+
return resolved;
|
|
37
|
+
}
|
|
38
|
+
function getProjectSerializedOrGlobalConfig(ctx) {
|
|
39
|
+
let testProject;
|
|
40
|
+
let foundProjectSerializedConfig = false;
|
|
41
|
+
if (ctx.projects && ctx.projects.length > 0) {
|
|
42
|
+
const project = ctx.projects.find((p) => p.config.pool.includes("assemblyscript"));
|
|
43
|
+
if (project) {
|
|
44
|
+
testProject = project;
|
|
45
|
+
foundProjectSerializedConfig = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
config: !!testProject ? {
|
|
50
|
+
...testProject.serializedConfig,
|
|
51
|
+
coverage: {
|
|
52
|
+
...testProject.serializedConfig.coverage,
|
|
53
|
+
...ctx.config.coverage
|
|
54
|
+
}
|
|
55
|
+
} : {
|
|
56
|
+
...ctx.config,
|
|
57
|
+
coverage: ctx.config.coverage
|
|
58
|
+
},
|
|
59
|
+
foundProjectSerializedConfig
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
export { getProjectSerializedOrGlobalConfig, resolvePoolOptions };
|
|
65
|
+
//# sourceMappingURL=resolve-config-as1w-Qyz.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-config-as1w-Qyz.mjs","names":[],"sources":["../src/types/types.ts","../src/util/resolve-config.ts"],"sourcesContent":["/*\n * Shared TypeScript types and interfaces\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { BirpcReturn } from 'birpc';\nimport type { RunnerRPC, RuntimeRPC, SerializedConfig, SerializedCoverageConfig } from 'vitest';\nimport type { TestError } from '@vitest/utils';\nimport type { ResolvedConfig, ResolvedCoverageOptions } from 'vitest/node';\nimport type { File, Test, TaskMeta, TestOptions } from '@vitest/runner/types';\nimport type { Colors } from 'tinyrainbow';\n\nimport {\n AS_POOL_WORKER_MSG_FLAG,\n AS_POOL_ERROR_TYPE_FLAG,\n COVERAGE_PAYLOAD_FORMATS,\n POOL_ERROR_NAMES,\n TEST_ERROR_NAMES,\n} from './constants.js';\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/** Error name type derived from TEST_ERROR_NAMES values */\nexport type TestErrorName = typeof TEST_ERROR_NAMES[keyof typeof TEST_ERROR_NAMES];\n\n/** Error name type derived from POOL_ERROR_NAMES values */\nexport type PoolErrorName = typeof POOL_ERROR_NAMES[keyof typeof POOL_ERROR_NAMES];\n\n/**\n * Conforms to Error interface but with required, strictly-typed name field.\n * Thrown internally for all pool errors.\n * \n * Must be thrown as a POJO (not using the Error() constructor!) to be properly\n * serialized across worker-pool boundery.\n */\nexport interface AssemblyScriptPoolError extends Error {\n readonly [AS_POOL_ERROR_TYPE_FLAG]: true;\n name: PoolErrorName;\n rawCallStack?: NodeJS.CallSite[];\n causeIsEnhancedError?: boolean;\n}\n\n/**\n * Extended vitest TestError with required, strictly-typed name field.\n * This is an explicitly serializable error format constructred to report\n * Test/Suite failures to vitest.\n */\nexport type AssemblyScriptTestError = TestError & { name: TestErrorName | PoolErrorName };\n\n// ============================================================================\n// User Configuration\n// ============================================================================\n\n/**\n * AssemblyScript pool configuration options\n */\nexport interface AssemblyScriptPoolOptions {\n /** Enable verbose debug logging */\n debug?: boolean;\n /**\n * Strip `@inline` decorators during compilation to improve error message and coverage accuracy\n *\n * - When true (default): `@inline` decorators removed, functions become visible in coverage\n * and source mapped errors point to the correct lines\n * - When false: `@inline` functions are inlined by compiler, missing from coverage, and \n * error line numbers don't match the non-inlined source\n * @default true\n */\n stripInline?: boolean;\n\n /**\n * Maximum number of worker threads to spawn with vitest 3.x.\n * Defaults to os.availableParallelism() - 1\n * \n * Use project config `test.maxWorkers` with vitest 4.x to control\n * the number of cuncurrently executing tests. \n */\n maxThreadsV3?: number;\n\n coverageMemoryPagesInitial?: number;\n coverageMemoryPagesMax?: number;\n\n testMemoryPagesInitial?: number;\n testMemoryPagesMax?: number;\n\n extraCompilerFlags?: string[];\n\n wasmImportsFactory?: string;\n}\n\n/**\n * HybridCoverageProvider configuration options.\n */\nexport interface HybridProviderOptions {\n provider: 'custom',\n customProviderModule: string;\n\n /**\n * Glob patterns for AssemblyScript source files to include in coverage.\n * Used to build the complete AS coverage map.\n *\n * The standard `include` patterns are used by the v8 provider for JS/TS files.\n *\n * @example ['assembly/**\\/*.as.ts']\n */\n assemblyScriptInclude?: string[];\n\n /**\n * Glob patterns for AssemblyScript files to exclude from coverage.\n *\n * @example ['**\\/*.as.test.ts']\n */\n assemblyScriptExclude?: string[];\n}\n\nexport interface WasmImportsFactoryInfo {\n module: WebAssembly.Module;\n memory: WebAssembly.Memory;\n utils: {\n liftString: (stringPtr: number) => string | undefined;\n }\n}\n\nexport type WasmImportsFactory = (moduleInfo: WasmImportsFactoryInfo) => WebAssembly.Imports;\n\n// define these constants here so they make sense in context\nexport const AS_POOL_FIELDS_WITH_DEFAULTS = [\n 'debug',\n 'stripInline',\n 'maxThreadsV3',\n 'coverageMemoryPagesInitial',\n 'coverageMemoryPagesMax',\n 'testMemoryPagesInitial',\n 'extraCompilerFlags'\n] as const;\nexport const AS_POOL_OPTIONAL_FIELDS = ['testMemoryPagesMax', 'wasmImportsFactory'] as const;\n\n/** Fields that have default values. Internally these will always be defined. */\nexport type ASPoolOptionsFieldsWithDefaultValues = typeof AS_POOL_FIELDS_WITH_DEFAULTS[number];\n\n/** Fields with optional values and NO defaults */\nexport type ASPoolOptionsOptionalFields = typeof AS_POOL_OPTIONAL_FIELDS[number];\n\nexport type AssemblyScriptProjectConfig = (SerializedConfig & {\n coverage: SerializedCoverageConfig & ResolvedHybridProviderOptions;\n}) | ResolvedConfig & {\n coverage: ResolvedHybridProviderOptions;\n};\n\n /**\n * Pool options resolved so that all fields are filled with user values preferentially, \n * with required fields being guaranteed to be populated with defaults otherwise.\n */\nexport type ResolvedAssemblyScriptPoolOptions =\n Required<Pick<AssemblyScriptPoolOptions, ASPoolOptionsFieldsWithDefaultValues>>\n & Partial<Pick<AssemblyScriptPoolOptions, ASPoolOptionsOptionalFields>>\n & { readonly isResolved: true };\n\nexport type ResolvedHybridProviderOptions = \n Required<HybridProviderOptions>\n\n & Omit<ResolvedCoverageOptions<'v8'>, 'provider'>\n & {\n globbedAssemblyScriptInclude: GlobResult[],\n globbedAssemblyScriptProjectRelativeExcludeOnly: string[],\n };\n\n// vitest TestOptions fields that are supported by AssemblyScript tests in this pool\nexport type AssemblyScriptTestOptions = Required<Pick<TestOptions, 'timeout' | 'retry' | 'skip' | 'only' | 'fails'>>;\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport type VitestVersion = 'v3' | 'v4';\n\nexport interface ThreadImports {\n highlight: HighlightFunc;\n createWasmImports?: WasmImportsFactory;\n}\n\nexport type HighlightFunc = (code: string, options: { colors: Colors }) => string;\n\nexport interface GlobResult {\n absolute: string;\n projectRootRelative: string;\n}\n\n// ============================================================================\n// Compilation & Results\n// ============================================================================\n\nexport interface AssemblyScriptCompilerOptions {\n shouldInstrument: boolean;\n projectRoot: string;\n instrumentationOptions?: InstrumentationOptions;\n stripInline?: boolean;\n extraFlags?: string[];\n}\n\nexport interface AssemblyScriptCompilerResult {\n binary: Uint8Array;\n sourceMap: string;\n debugInfo?: BinaryDebugInfo;\n isInstrumented: boolean;\n compileTiming: number;\n}\n\nexport interface InstrumentationOptions {\n /** List of relative file paths to exclude from instrumentation */\n relativeExcludedFiles: string[];\n excludedLibraryFilePrefix: string;\n coverageMemoryPagesMin: number;\n coverageMemoryPagesMax: number;\n}\n\n/**\n * Result of instrumenting a WASM binary for coverage\n */\nexport interface InstrumentationResult {\n /** Instrumented WASM binary with coverage counter increments */\n instrumentedWasm: Buffer;\n /** Regenerated source map (offsets adjusted for instrumentation) */\n sourceMap: string;\n /** Debug info with coverageMemoryIndex assigned to each function */\n debugInfo: BinaryDebugInfo;\n}\n\n// ============================================================================\n// Error Source Mapping\n// ============================================================================\n\n/**\n * Source location in original AssemblyScript code (a point, not a range)\n *\n * All values are 1-based for internal consistency.\n * Conversion to 0-based columns happens at Istanbul output boundary.\n */\nexport interface SourceLocation {\n /** Relative file path */\n filePath: string;\n line: number;\n column: number;\n}\n\n/**\n * WebAssembly call site with mapped source location\n */\nexport interface WebAssemblyCallSite {\n functionName: string;\n location: SourceLocation;\n}\n\n// ============================================================================\n// Coverage Data (Runtime Hit Counts)\n// ============================================================================\n\n/**\n * Coverage data collected during test execution\n *\n * Simple hit count storage using position-based keys for stable merging.\n * Note: Function source metadata (names, ranges) comes from ParsedSourceInfo.\n *\n * Outer Record: keyed by absolute file path\n * Inner Record: keyed by position (\"line:column\") → hit count\n */\nexport interface CoverageData {\n hitCountsByFileAndPosition: Record<string, Record<string, number>>;\n}\n\n/**\n * Coverage payload sent via RPC from worker to hybrid coverage provider\n *\n * The __format marker distinguishes AS coverage from JS coverage in onAfterSuiteRun.\n */\nexport interface AssemblyScriptCoveragePayload {\n readonly __format: typeof COVERAGE_PAYLOAD_FORMATS.AssemblyScript;\n coverageData: CoverageData;\n suiteLogLabel: string;\n}\n\n\n// ============================================================================\n// Binary Debug Info (returned from native instrumentation addon)\n// ============================================================================\n//\n// These types represent debug information extracted from compiled WASM binaries\n// via the native addon. Binary debug info only has POINTS (from source map),\n// not ranges. Ranges come from source parsing (ParsedSource* types below).\n//\n// Naming convention: *DebugInfo suffix indicates binary-extracted data.\n\n/**\n * Source range in original AssemblyScript code (start and end points)\n *\n * All values are 1-based for internal consistency.\n * Conversion to 0-based columns happens at Istanbul output boundary.\n */\nexport interface SourceRange {\n /** Relative file path */\n filePath: string;\n startLine: number;\n startColumn: number;\n endLine: number;\n endColumn: number;\n}\n\n/**\n * Branch edge in control flow graph\n */\nexport interface BranchEdgeDebugInfo {\n /** Target basic block index */\n targetBlockIndex: number;\n /** Index of the expression that creates this branch (e.g., if condition) */\n sourceExpressionIndex?: number;\n}\n\n/**\n * Expression debug info extracted from WASM binary\n *\n * Expressions are the smallest unit of execution in WASM.\n * In v2, each expression can be mapped to a source statement for line-level coverage.\n */\nexport interface ExpressionDebugInfo {\n /** WASM expression type (e.g., \"call\", \"if\", \"block\") */\n type: string;\n /** Source location (POINT, not range) from source map */\n location?: SourceLocation;\n /** Whether this expression is a branch point (if, switch, select) */\n isBranch: boolean;\n /** Number of branch paths (for branch coverage) */\n branchPaths?: number;\n /**\n * Index into coverage memory counters\n * v2 only: Propagated from containing BasicBlockDebugInfo by TS wrapper\n */\n coverageMemoryIndex?: number;\n}\n\n/**\n * Basic block debug info from CFG analysis\n *\n * Basic blocks are sequences of expressions with single entry/exit points.\n * In v2, counters are placed at basic block boundaries for efficient coverage.\n */\nexport interface BasicBlockDebugInfo {\n /** Block index within the function */\n index: number;\n /** Indices of expressions contained in this block */\n expressionIndices: number[];\n /** Outgoing branch edges */\n branches: BranchEdgeDebugInfo[];\n /**\n * Index into coverage memory counters\n * v2 only: Source of truth for block-level coverage\n */\n coverageMemoryIndex?: number;\n}\n\n/**\n * Function debug info extracted from WASM binary via native addon\n */\nexport interface FunctionDebugInfo {\n /** WASM function index */\n wasmIndex: number;\n /** Function name from WASM (informational) */\n name: string;\n /**\n * Representative source location (a point within the function).\n * Used for containment matching to find the parsedsource function.\n */\n representativeLocation: SourceLocation;\n /** Index into coverage memory counters */\n coverageMemoryIndex: number;\n /** All expressions in this function */\n expressions: ExpressionDebugInfo[];\n /** Basic blocks from CFG analysis */\n basicBlocks: BasicBlockDebugInfo[];\n}\n\n/**\n * Binary debug info extracted from WASM + source map via native addon\n *\n * This is the processed output after TS wrapper transforms NativeDebugInfoOutput.\n * Functions are grouped by file and keyed by position for stable identity.\n */\nexport interface BinaryDebugInfo {\n /** All source files represented in extracted debug info (directly or inlined) */\n debugSourceFiles: string[];\n /**\n * Functions grouped by file path, then keyed by position (\"line:column\")\n * Position key enables stable identity across compilations\n */\n functionsByFileAndPosition: Record<string, Record<string, FunctionDebugInfo>>;\n\n instrumentedFunctionCount: number;\n}\n\n/**\n * Raw output from native addon's instrumentForCoverage() C++ function\n */\nexport interface NativeInstrumentationResult {\n instrumentedWasm: Buffer;\n sourceMap: string;\n debugInfo: NativeDebugInfoOutput;\n errors?: string[];\n}\n\nexport interface NativeDebugInfoOutput {\n /** All source files represented in extracted debug info (directly or inlined) */\n debugSourceFiles: string[];\n /** Flat list of all functions with their debug info */\n functions: NativeFunctionDebugInfo[];\n}\n\nexport interface NativeFunctionDebugInfo extends Omit<FunctionDebugInfo, 'expressions' | 'representativeLocation'> {\n representativeLocation: NativeSourceLocation;\n expressions: NativeExpressionDebugInfo[];\n}\n\nexport interface NativeExpressionDebugInfo extends Omit<ExpressionDebugInfo, 'location'> {\n location?: NativeSourceLocation;\n}\n\nexport interface NativeSourceLocation extends Omit<SourceLocation, 'filePath'> {\n /** Index into NativeDebugInfoOutput.debugSourceFiles */\n fileIndex: number;\n}\n\nexport interface NativeInstrumentationOptions extends Omit<InstrumentationOptions, 'relativeExcludedFiles'> {\n excludedFiles?: string[];\n debug?: boolean;\n logPrefix?: string;\n}\n\n/**\n * Typed interface for the native addon's exported methods.\n * The addon is loaded via node-gyp-build at runtime (CJS .node binary).\n */\nexport interface NativeAddon {\n instrumentForCoverage(\n wasmBuffer: Buffer,\n sourceMapBuffer: Buffer,\n options: NativeInstrumentationOptions,\n ): NativeInstrumentationResult;\n}\n\n// ============================================================================\n// Parsed Source Info (from AST Parser)\n// ============================================================================\n//\n// These types represent information parsed from source files via AST.\n// Parsed source info has *ranges* (start and end positions) for containment matching.\n\n/**\n * Function info parsed from AssemblyScript source via AST\n */\nexport interface ParsedSourceFunctionInfo {\n /** Fully \"qualified\" (WASM debug) name */\n qualifiedName: string;\n /** Short name for display */\n shortName: string;\n /** Source range for containment matching */\n range: SourceRange;\n}\n\n/**\n * Statement info parsed from AssemblyScript source via AST\n *\n * v2 only: Used for line-level statement coverage.\n * Binary expression points are matched to source statement ranges.\n */\nexport interface ParsedSourceStatementInfo {\n /** Source range for containment matching */\n range: SourceRange;\n /** Statement type (e.g., \"variable\", \"expression\", \"return\") */\n statementType?: string;\n}\n\n/**\n * Branch info parsed from AssemblyScript source via AST\n *\n * v2 only: Used for branch coverage.\n * Binary branch expressions are matched to source branch ranges.\n */\nexport interface ParsedSourceBranchInfo {\n /** Source range for containment matching */\n range: SourceRange;\n /** Type of branch construct */\n branchType: 'if' | 'ternary' | 'switch' | 'logical';\n}\n\n/**\n * Complete parsed source info from AST parser\n *\n * Generated by coverage provider when processing coverage (not during compilation).\n * Provides the \"what SHOULD be covered\" view from source code.\n */\nexport interface ParsedSourceInfo {\n /**\n * Functions grouped by file path, then by start line for containment matching.\n * Multiple functions can start on the same line, but limiting matching to checking\n * only the functions grouped on the input position's line is very performant.\n */\n functionsByFileAndStartLine: Record<string, Record<number, ParsedSourceFunctionInfo[]>>;\n /**\n * Statements grouped by file path, then keyed by position (\"line:column\")\n * v2 only: For line-level statement coverage\n */\n statementsByFileAndPosition: Record<string, Record<string, ParsedSourceStatementInfo>>;\n /**\n * Branches grouped by file path, then keyed by position (\"line:column\")\n * v2 only: For branch coverage\n */\n branchesByFileAndPosition: Record<string, Record<string, ParsedSourceBranchInfo>>;\n}\n\n// ============================================================================\n// Worker Communication & RPC\n// ============================================================================\n\nexport interface AssemblyScriptConsoleLog {\n msg: string;\n time: number;\n isError: boolean;\n}\n\nexport type AssemblyScriptConsoleLogHandler = (msg: string, isError?: boolean) => void;\n\nexport interface FailedAssertion {\n expected?: string;\n actual?: string;\n valuesProvided?: boolean;\n typeName?: string;\n message?: string;\n}\n\nexport interface AssemblyScriptSuiteTaskMeta extends TaskMeta {\n idxInParentTasks: number;\n defaultTestOptions: AssemblyScriptTestOptions;\n suitePreparedSent: boolean;\n resultFinal: boolean;\n coverageData?: CoverageData;\n}\n\nexport interface AssemblyScriptTestTaskMeta extends TaskMeta {\n idxInParentTasks: number;\n fnIndex: number;\n assertionsPassedCount: number;\n assertionsFailed: FailedAssertion[];\n resultFinal: boolean;\n coverageData?: CoverageData;\n lastError?: AssemblyScriptTestError;\n lastErrorValuesProvided?: boolean;\n lastErrorRawCallStack?: NodeJS.CallSite[];\n lastTimeoutTerminationTime?: number;\n};\n\nexport interface WASMExecutorPerfTimings {\n /** function start */\n fnInit: number;\n /** test start: execStart - fnInit = env init time */\n execStart: number;\n /** test end: execEnd - execStart = test duration */\n execEnd: number;\n /** function end: fnFinal - execEnd = error prep and/or coverage extraction time */\n fnfinal: number;\n}\n\nexport type WorkerRPC = BirpcReturn<RuntimeRPC, RunnerRPC>;\n\n/**\n * Worker channel with RPC for suite-level communication\n */\nexport interface WorkerChannel {\n /** Port to send to worker for RPC communication */\n workerPort: MessagePort;\n /** Pool-side port for cleanup */\n poolPort: MessagePort;\n /** RPC client for calling Vitest methods (only remote functions matter for our usage) */\n rpc: WorkerRPC;\n}\n\nexport interface WorkerThreadInitData {\n projectRoot: string,\n asPoolOptions: ResolvedAssemblyScriptPoolOptions;\n asCoverageOptions: ResolvedHybridProviderOptions;\n}\n\nexport interface AssemblyScriptPoolWorkerMessageBase {\n readonly [AS_POOL_WORKER_MSG_FLAG]: true;\n readonly type: string;\n}\n\nexport interface TestFileCompiled extends AssemblyScriptPoolWorkerMessageBase {\n readonly type: 'file-compiled';\n compilation: WASMCompilation;\n}\n\n\nexport interface TestExecutionStart extends AssemblyScriptPoolWorkerMessageBase {\n readonly type: 'execution-start';\n executionStart: number;\n test: Test;\n}\n\nexport interface TestExecutionEnd extends AssemblyScriptPoolWorkerMessageBase {\n readonly type: 'execution-end';\n executionEnd: number;\n testTaskId: string;\n}\n\nexport type AssemblyScriptPoolWorkerMessage = TestExecutionStart | TestExecutionEnd | TestFileCompiled;\n\nexport interface WASMCompilation {\n filePath: string;\n binary: Uint8Array;\n sourceMap: string;\n debugInfo?: BinaryDebugInfo;\n}\n\nexport interface TestRunRecord {\n test: Test;\n executionStart: number;\n timeoutId: NodeJS.Timeout;\n}\n\nexport interface ThreadSpec {\n file: File;\n compilation?: WASMCompilation;\n}\n\nexport interface RunCompileAndDiscoverTask {\n dispatchStart: number;\n workerId: number;\n port: MessagePort;\n file: File;\n config: SerializedConfig;\n isCollectTestsMode: boolean;\n}\n\nexport interface RunTestsTask {\n dispatchStart: number;\n workerId: number;\n port: MessagePort;\n file: File;\n compilation: WASMCompilation;\n config: SerializedConfig;\n isCollectTestsMode: boolean;\n timedOutTest?: Test;\n}\n\nexport interface ProcessPoolRunFileTask {\n dispatchStart: number;\n port: MessagePort;\n file: File;\n config: SerializedConfig;\n isCollectTestsMode: boolean;\n timedOutTest?: Test;\n timedOutCompilation?: WASMCompilation;\n}\n","import type { TestProject, Vitest } from 'vitest/node';\nimport { availableParallelism } from 'node:os';\n\nimport type {\n AssemblyScriptPoolOptions,\n ASPoolOptionsFieldsWithDefaultValues,\n ResolvedAssemblyScriptPoolOptions,\n ResolvedHybridProviderOptions,\n AssemblyScriptProjectConfig,\n} from '../types/types.js';\nimport { AS_POOL_FIELDS_WITH_DEFAULTS } from '../types/types.js';\nimport { ASSEMBLYSCRIPT_POOL_NAME, POOL_ERROR_NAMES } from '../types/constants.js';\nimport { createPoolError } from '../util/pool-errors.js';\n\nconst DEFAULT_ASSEMBLYSCRIPT_POOL_OTIONS: Required<Pick<AssemblyScriptPoolOptions, ASPoolOptionsFieldsWithDefaultValues>> = {\n debug: false,\n stripInline: true,\n maxThreadsV3: availableParallelism() - 1,\n coverageMemoryPagesInitial: 1,\n coverageMemoryPagesMax: 4,\n testMemoryPagesInitial: 1,\n extraCompilerFlags: [],\n} as const;\n\n// v4: used in runner init to parse user-provided param\nexport function resolvePoolOptions(userPoolOptions?: any): ResolvedAssemblyScriptPoolOptions {\n const poolOptions: AssemblyScriptPoolOptions = userPoolOptions ?? DEFAULT_ASSEMBLYSCRIPT_POOL_OTIONS;\n\n // resolve fields with defaults if user hasn't provided them\n for (const configKey of AS_POOL_FIELDS_WITH_DEFAULTS) {\n if (poolOptions[configKey] === undefined) {\n poolOptions[configKey] = DEFAULT_ASSEMBLYSCRIPT_POOL_OTIONS[configKey] as any;\n }\n }\n\n const resolved = { ...poolOptions, isResolved: true } as ResolvedAssemblyScriptPoolOptions;\n\n if (resolved.coverageMemoryPagesInitial < 1 || resolved.coverageMemoryPagesMax < 1) {\n throw createPoolError(\n `Coverage memory page size options must be positive - coverageMemoryPagesMin: ${resolved.coverageMemoryPagesInitial}`\n + ` | coverageMemoryPagesMax: ${resolved.coverageMemoryPagesMax}`,\n POOL_ERROR_NAMES.PoolConfigError\n );\n }\n \n if (resolved.testMemoryPagesInitial < 1 || (resolved.testMemoryPagesMax !== undefined && resolved.testMemoryPagesMax < 1)) {\n throw createPoolError(\n `Test memory page size options must be positive - testMemoryPagesMin: ${resolved.testMemoryPagesInitial}`\n + ` | testMemoryPagesMax: ${resolved.testMemoryPagesMax}`,\n POOL_ERROR_NAMES.PoolConfigError\n );\n }\n\n return resolved;\n}\n\n// v3 & hybrid coverage provider: used to get project config & poolOptions, with global coverage on project config\nexport function getProjectSerializedOrGlobalConfig(ctx: Vitest): {\n config: AssemblyScriptProjectConfig;\n foundProjectSerializedConfig: boolean;\n} {\n let testProject: TestProject | undefined;\n let foundProjectSerializedConfig: boolean = false;\n\n // In multi-project mode, ctx.config is the global config, not the project-specific config\n // We need to find our project in ctx.projects to get project-specific config at the \"pool level\" in v3,\n // and in the hybrid coverage provider regardless of version (specifically the project root)\n if (ctx.projects && ctx.projects.length > 0) {\n // Multi-project mode: find the first project using this pool\n // Use string.includes because project.config.pool resolves to the *path* of the dist file\n const project = ctx.projects.find(p => p.config.pool.includes(ASSEMBLYSCRIPT_POOL_NAME));\n\n if (project) {\n testProject = project;\n foundProjectSerializedConfig = true;\n }\n }\n\n const config = !!testProject ? {\n ...testProject.serializedConfig,\n coverage: {\n ...testProject.serializedConfig.coverage,\n ...(ctx.config.coverage as ResolvedHybridProviderOptions)\n }\n } : {\n ...ctx.config,\n coverage: ctx.config.coverage as ResolvedHybridProviderOptions\n };\n\n return {\n config,\n foundProjectSerializedConfig\n };\n}"],"mappings":";;;;;AAgIA,MAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;AC1HD,MAAM,qCAAsH;CAC1H,OAAO;CACP,aAAa;CACb,cAAc,sBAAsB,GAAG;CACvC,4BAA4B;CAC5B,wBAAwB;CACxB,wBAAwB;CACxB,oBAAoB,EAAE;CACvB;AAGD,SAAgB,mBAAmB,iBAA0D;CAC3F,MAAM,cAAyC,mBAAmB;AAGlE,MAAK,MAAM,aAAa,6BACtB,KAAI,YAAY,eAAe,OAC7B,aAAY,aAAa,mCAAmC;CAIhE,MAAM,WAAW;EAAE,GAAG;EAAa,YAAY;EAAM;AAErD,KAAI,SAAS,6BAA6B,KAAK,SAAS,yBAAyB,EAC/E,OAAM,gBACJ,gFAAgF,SAAS,wDACzD,SAAS,0BACzC,iBAAiB,gBAClB;AAGH,KAAI,SAAS,yBAAyB,KAAM,SAAS,uBAAuB,UAAa,SAAS,qBAAqB,EACrH,OAAM,gBACJ,wEAAwE,SAAS,gDACrD,SAAS,sBACrC,iBAAiB,gBAClB;AAGH,QAAO;;AAIT,SAAgB,mCAAmC,KAGjD;CACA,IAAI;CACJ,IAAI,+BAAwC;AAK5C,KAAI,IAAI,YAAY,IAAI,SAAS,SAAS,GAAG;EAG3C,MAAM,UAAU,IAAI,SAAS,MAAK,MAAK,EAAE,OAAO,KAAK,0BAAkC,CAAC;AAExF,MAAI,SAAS;AACX,iBAAc;AACd,kCAA+B;;;AAenC,QAAO;EACL,QAZa,CAAC,CAAC,cAAc;GAC7B,GAAG,YAAY;GACf,UAAU;IACR,GAAG,YAAY,iBAAiB;IAChC,GAAI,IAAI,OAAO;IAChB;GACF,GAAG;GACF,GAAG,IAAI;GACP,UAAU,IAAI,OAAO;GACtB;EAIC;EACD"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { debug } from "./debug-IeEHsxy0.mjs";
|
|
2
|
+
import { checkFailsAndInvertResult, finalizeSuiteResult, flagTestFinalized, getRunnableTasks, getTaskLogPrefix, isSuiteOwnFile, resetTestForRetry, setSuitePrepareResult, setTestResultForTestPrepare, shouldRetryTask, updateSuiteFinishedResult, updateTestResultAfterRun } from "./vitest-tasks-BKS7689f.mjs";
|
|
3
|
+
import { executeWASMTest, reportSuiteFinished, reportSuitePrepare, reportTestFinished, reportTestPrepare, reportTestRetried, reportUserConsoleLogs } from "./load-user-imports-J9eaAW0_.mjs";
|
|
4
|
+
import { mergeCoverageData } from "./coverage-merge-0WqdC-dq.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/pool-thread/runner/test-runner.ts
|
|
7
|
+
async function bailIfNeeded(rpc, bailConfig, testWithResult, logPrefix, logModule) {
|
|
8
|
+
if (bailConfig && testWithResult.result?.state !== "pass") {
|
|
9
|
+
const currentFailures = 1 + await rpc.getCountOfFailedTests();
|
|
10
|
+
if (currentFailures >= bailConfig) {
|
|
11
|
+
debug(`${logPrefix} bailing: ${currentFailures} failures >= ${bailConfig} to bail`);
|
|
12
|
+
debug(`[${logModule}] -------- BAIL! ${currentFailures} failures >= ${bailConfig} to bail --------`);
|
|
13
|
+
return rpc.onCancel("test-failure");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function postProcessTestResult(rpc, bailConfig, testWithResult, logPrefix, logModule) {
|
|
18
|
+
checkFailsAndInvertResult(testWithResult, logPrefix);
|
|
19
|
+
return bailIfNeeded(rpc, bailConfig, testWithResult, logPrefix, logModule);
|
|
20
|
+
}
|
|
21
|
+
function notifyTestStart(port, test) {
|
|
22
|
+
port.postMessage({
|
|
23
|
+
executionStart: Date.now(),
|
|
24
|
+
test,
|
|
25
|
+
type: "execution-start",
|
|
26
|
+
["__as_pool__"]: true
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function notifyTestEnd(port, test) {
|
|
30
|
+
port.postMessage({
|
|
31
|
+
executionEnd: Date.now(),
|
|
32
|
+
testTaskId: test.id,
|
|
33
|
+
type: "execution-end",
|
|
34
|
+
["__as_pool__"]: true
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async function runTest(rpc, port, base, collectCoverage, compilation, test, logModule, poolOptions, threadImports, bail, diffOptions) {
|
|
38
|
+
const testLogPrefix = getTaskLogPrefix(logModule, base, test);
|
|
39
|
+
const logMessages = [];
|
|
40
|
+
const handleLog = (msg, isError = false) => {
|
|
41
|
+
logMessages.push({
|
|
42
|
+
msg,
|
|
43
|
+
time: Date.now(),
|
|
44
|
+
isError
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const executionStart = Date.now();
|
|
48
|
+
let thisRunIsARetry = false;
|
|
49
|
+
let testPreparePromise = Promise.resolve();
|
|
50
|
+
if (!test.retry || !test.result) {
|
|
51
|
+
debug(`${testLogPrefix} - Beginning test run`);
|
|
52
|
+
setTestResultForTestPrepare(test, executionStart);
|
|
53
|
+
testPreparePromise = reportTestPrepare(rpc, test, logModule, base);
|
|
54
|
+
} else if (test.retry && test.result) {
|
|
55
|
+
debug(`${testLogPrefix} - Beginning test retry run`);
|
|
56
|
+
thisRunIsARetry = true;
|
|
57
|
+
resetTestForRetry(test, executionStart);
|
|
58
|
+
}
|
|
59
|
+
notifyTestStart(port, test);
|
|
60
|
+
const [_reported, { testTimings }] = await Promise.all([testPreparePromise, executeWASMTest(test, compilation, base, poolOptions, collectCoverage, handleLog, logModule, threadImports, diffOptions)]);
|
|
61
|
+
notifyTestEnd(port, test);
|
|
62
|
+
updateTestResultAfterRun(test, testTimings);
|
|
63
|
+
let willRetry = shouldRetryTask(test);
|
|
64
|
+
await Promise.all([reportUserConsoleLogs(rpc, logMessages, logModule, base, test), willRetry ? reportTestRetried(rpc, test, logModule, base) : Promise.resolve()]);
|
|
65
|
+
if (thisRunIsARetry) {
|
|
66
|
+
debug(`${testLogPrefix} - Completed test retry run`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
while (willRetry) {
|
|
70
|
+
test.result.retryCount = (test.result?.retryCount ?? 0) + 1;
|
|
71
|
+
debug(`${testLogPrefix} - Retrying after failure | Retry ${test.result?.retryCount || 0} / ${test.retry} | ${test.result?.errors?.length ?? 0} errors`);
|
|
72
|
+
await runTest(rpc, port, base, collectCoverage, compilation, test, logModule, poolOptions, threadImports, bail, diffOptions);
|
|
73
|
+
willRetry = shouldRetryTask(test);
|
|
74
|
+
if (!willRetry) debug(`${testLogPrefix} - Max retries ${test.result?.retryCount || 0} / ${test.retry} | ${test.result?.errors?.length ?? 0} errors`);
|
|
75
|
+
}
|
|
76
|
+
await Promise.all([postProcessTestResult(rpc, bail, test, testLogPrefix, logModule), reportTestFinished(rpc, test, logModule, base)]);
|
|
77
|
+
flagTestFinalized(test);
|
|
78
|
+
debug(`${testLogPrefix} - Completed test run`);
|
|
79
|
+
}
|
|
80
|
+
async function runSuite(rpc, port, base, collectCoverage, compilation, suite, logModule, poolOptions, threadImports, vitestVersion, bail, diffOptions, timedOutTest) {
|
|
81
|
+
const suiteStart = performance.now();
|
|
82
|
+
const suiteMeta = suite.meta;
|
|
83
|
+
const suiteLogPrefix = getTaskLogPrefix(logModule, base, suite);
|
|
84
|
+
const isTimedOutTestInSuite = timedOutTest?.suite?.id === suite.id;
|
|
85
|
+
if (suiteMeta.resultFinal) {
|
|
86
|
+
debug(`${suiteLogPrefix} - Skipping completed suite | state: "${suite.result?.state}"`);
|
|
87
|
+
return suite;
|
|
88
|
+
} else {
|
|
89
|
+
const threadRestartTime = Date.now() - ((timedOutTest?.meta)?.lastTimeoutTerminationTime ?? 0);
|
|
90
|
+
debug(`${!!timedOutTest && isSuiteOwnFile(suite) ? `(thread resumed in ${threadRestartTime} ms) ` : ""}${suiteLogPrefix} - runSuite ${!!timedOutTest ? `resuming after timeout "${timedOutTest.name}" | isTestInSuite: ${isTimedOutTestInSuite}` : "beginning"}`);
|
|
91
|
+
}
|
|
92
|
+
if (!suiteMeta.suitePreparedSent) {
|
|
93
|
+
setSuitePrepareResult(suite);
|
|
94
|
+
await reportSuitePrepare(rpc, suite, logModule, base);
|
|
95
|
+
suiteMeta.suitePreparedSent = true;
|
|
96
|
+
}
|
|
97
|
+
if (isTimedOutTestInSuite) {
|
|
98
|
+
suiteMeta.coverageData = timedOutTest.suite.meta.coverageData;
|
|
99
|
+
const coverageKeys = Object.keys(suiteMeta.coverageData ?? {}).length;
|
|
100
|
+
debug(`${suiteLogPrefix} - Restored suite coverage data after timeout (${coverageKeys} unique positions)`);
|
|
101
|
+
}
|
|
102
|
+
suiteMeta.coverageData = { hitCountsByFileAndPosition: {} };
|
|
103
|
+
let tasksToRun = getRunnableTasks(suite);
|
|
104
|
+
debug(`${suiteLogPrefix} - Runnable tasks:`, tasksToRun.length);
|
|
105
|
+
for (const task of tasksToRun) if (task.type === "suite") {
|
|
106
|
+
const suiteTaskMeta = task.meta;
|
|
107
|
+
await runSuite(rpc, port, base, collectCoverage, compilation, task, logModule, poolOptions, threadImports, vitestVersion, bail, diffOptions, timedOutTest);
|
|
108
|
+
if (suiteMeta.coverageData && suiteTaskMeta.coverageData) mergeCoverageData(suiteMeta.coverageData, suiteTaskMeta.coverageData);
|
|
109
|
+
} else {
|
|
110
|
+
const testLogPrefix = getTaskLogPrefix(logModule, base, task);
|
|
111
|
+
const testTaskMeta = task.meta;
|
|
112
|
+
const testCompleted = testTaskMeta.resultFinal;
|
|
113
|
+
const testTimedOutPreviously = !!timedOutTest && task.id === timedOutTest.id;
|
|
114
|
+
if (testCompleted) debug(`${testLogPrefix} - Skipping completed test | state: "${task.result?.state}"`);
|
|
115
|
+
else if (testTimedOutPreviously) if (shouldRetryTask(task)) {
|
|
116
|
+
const newRetryCount = (task.result?.retryCount ?? 0) + 1;
|
|
117
|
+
debug(`${testLogPrefix} - Retrying after test timeout | retry attempt ${newRetryCount} / ${task.retry} | ${task.result?.errors?.length ?? 0} errors | state: "${task.result?.state}"`);
|
|
118
|
+
await reportTestRetried(rpc, task, logModule, base);
|
|
119
|
+
task.result.retryCount = newRetryCount;
|
|
120
|
+
await runTest(rpc, port, base, collectCoverage, compilation, task, logModule, poolOptions, threadImports, bail, diffOptions);
|
|
121
|
+
} else {
|
|
122
|
+
debug(`${testLogPrefix} - Timed-out test has no retries left | retries attempted ${task.result?.retryCount || 0} / ${task.retry} | ${task.result?.errors?.length ?? 0} errors | state: "${task.result?.state}"`);
|
|
123
|
+
await Promise.all([postProcessTestResult(rpc, bail, task, testLogPrefix, logModule), reportTestFinished(rpc, task, logModule, base)]);
|
|
124
|
+
flagTestFinalized(task);
|
|
125
|
+
debug(`${testLogPrefix} - Completed timed out test run`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
debug(`${testLogPrefix} - Running test task | state: "${task.result?.state}"`);
|
|
129
|
+
await runTest(rpc, port, base, collectCoverage, compilation, task, logModule, poolOptions, threadImports, bail, diffOptions);
|
|
130
|
+
}
|
|
131
|
+
if (suiteMeta.coverageData && testTaskMeta.coverageData) mergeCoverageData(suiteMeta.coverageData, testTaskMeta.coverageData);
|
|
132
|
+
}
|
|
133
|
+
updateSuiteFinishedResult(suite, suiteLogPrefix);
|
|
134
|
+
await reportSuiteFinished(rpc, suite, logModule, base, vitestVersion);
|
|
135
|
+
finalizeSuiteResult(suite);
|
|
136
|
+
debug(`${suiteLogPrefix} - Suite Run Complete | TIMING ${(performance.now() - suiteStart).toFixed(2)} ms`);
|
|
137
|
+
return suite;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
141
|
+
export { runSuite };
|
|
142
|
+
//# sourceMappingURL=test-runner-B2BpyPNK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner-B2BpyPNK.mjs","names":[],"sources":["../src/pool-thread/runner/test-runner.ts"],"sourcesContent":["/**\n * Worker thread test runner logic for AssemblyScript Pool\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { File, Suite, Task, Test } from '@vitest/runner/types';\nimport type { SerializedDiffOptions } from '@vitest/utils/diff';\n\nimport type {\n AssemblyScriptConsoleLog,\n AssemblyScriptConsoleLogHandler,\n AssemblyScriptSuiteTaskMeta,\n AssemblyScriptTestTaskMeta,\n ResolvedAssemblyScriptPoolOptions,\n TestExecutionEnd,\n TestExecutionStart,\n ThreadImports,\n VitestVersion,\n WASMCompilation,\n WorkerRPC,\n} from '../../types/types.js';\nimport { AS_POOL_WORKER_MSG_FLAG } from '../../types/constants.js';\nimport { executeWASMTest } from '../../wasm-executor/index.js';\nimport { debug } from '../../util/debug.js';\nimport {\n reportTestPrepare,\n reportTestFinished,\n reportTestRetried,\n reportUserConsoleLogs,\n reportSuitePrepare,\n reportSuiteFinished,\n} from '../rpc-reporter.js';\nimport {\n checkFailsAndInvertResult,\n finalizeSuiteResult,\n flagTestFinalized,\n getRunnableTasks,\n getTaskLogPrefix,\n resetTestForRetry,\n setSuitePrepareResult,\n setTestResultForTestPrepare,\n shouldRetryTask,\n updateSuiteFinishedResult,\n updateTestResultAfterRun,\n isSuiteOwnFile\n} from '../../util/vitest-tasks.js';\nimport { mergeCoverageData } from '../../coverage-provider/coverage-merge.js';\n\nasync function bailIfNeeded(\n rpc: WorkerRPC,\n bailConfig: number | undefined,\n testWithResult: Test,\n logPrefix: string,\n logModule: string,\n): Promise<void> {\n if (bailConfig && testWithResult.result?.state !== 'pass') {\n const previousFailures = await rpc.getCountOfFailedTests();\n const currentFailures = 1 + previousFailures;\n\n if (currentFailures >= bailConfig) {\n debug(`${logPrefix} bailing: ${currentFailures} failures >= ${bailConfig} to bail`);\n debug(`[${logModule}] -------- BAIL! ${currentFailures} failures >= ${bailConfig} to bail --------`);\n return rpc.onCancel('test-failure');\n }\n }\n}\n\nasync function postProcessTestResult(\n rpc: WorkerRPC,\n bailConfig: number | undefined,\n testWithResult: Test,\n logPrefix: string,\n logModule: string,\n): Promise<void> {\n // invert result if test configured as 'fails'\n checkFailsAndInvertResult(testWithResult, logPrefix);\n\n // bail now if this is a failed test above bail threshold\n return bailIfNeeded(rpc, bailConfig, testWithResult, logPrefix, logModule);\n}\n\nfunction notifyTestStart(port: MessagePort, test: Test): void {\n port.postMessage({\n executionStart: Date.now(),\n test,\n type: 'execution-start',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestExecutionStart);\n}\n\nfunction notifyTestEnd(port: MessagePort, test: Test): void {\n port.postMessage({\n executionEnd: Date.now(),\n testTaskId: test.id,\n type: 'execution-end',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestExecutionEnd);\n}\n\nasync function runTest(\n rpc: WorkerRPC,\n port: MessagePort,\n base: string,\n collectCoverage: boolean,\n compilation: WASMCompilation,\n test: Test,\n logModule: string,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n threadImports: ThreadImports,\n bail?: number,\n diffOptions?: SerializedDiffOptions,\n): Promise<void> {\n const testLogPrefix = getTaskLogPrefix(logModule, base, test);\n const logMessages: AssemblyScriptConsoleLog[] = [];\n const handleLog: AssemblyScriptConsoleLogHandler = (msg: string, isError: boolean = false): void => {\n logMessages.push({ msg, time: Date.now(), isError });\n };\n\n const executionStart = Date.now();\n\n let thisRunIsARetry: boolean = false;\n let testPreparePromise: Promise<void> = Promise.resolve();\n \n if (!test.retry || !test.result) {\n debug(`${testLogPrefix} - Beginning test run`);\n\n // first/only attempt: create test result and report test-prepare\n setTestResultForTestPrepare(test, executionStart);\n testPreparePromise = reportTestPrepare(rpc, test, logModule, base);\n } else if (test.retry && test.result ) {\n debug(`${testLogPrefix} - Beginning test retry run`);\n thisRunIsARetry = true;\n\n // this is a retry, reset the result state and meta\n resetTestForRetry(test, executionStart);\n }\n \n // inform pool of test task start so it can enforce timeouts\n notifyTestStart(port, test);\n\n const [_reported, { testTimings }] = await Promise.all([\n testPreparePromise,\n executeWASMTest(\n test,\n compilation,\n base,\n poolOptions,\n collectCoverage,\n handleLog,\n logModule,\n threadImports,\n diffOptions\n )\n ]);\n\n // inform pool of test task end to stop timeout if under threshold\n notifyTestEnd(port, test);\n\n // update run->pass if appropriate, accumulate duration using executor timings\n updateTestResultAfterRun(test, testTimings);\n\n let willRetry = shouldRetryTask(test);\n\n await Promise.all([\n reportUserConsoleLogs(rpc, logMessages, logModule, base, test),\n\n willRetry ? reportTestRetried(rpc, test, logModule, base) : Promise.resolve(),\n ]);\n\n if (thisRunIsARetry) {\n debug(`${testLogPrefix} - Completed test retry run`);\n return;\n }\n\n // non-timeout retry handling\n while (willRetry) {\n // increment the retry count\n test.result!.retryCount = (test.result?.retryCount ?? 0) + 1;\n\n debug(`${testLogPrefix} - Retrying after failure`\n + ` | Retry ${test.result?.retryCount || 0} / ${test.retry} ` \n + ` | ${test.result?.errors?.length ?? 0} errors`\n );\n\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n test, logModule, poolOptions, threadImports, bail, diffOptions\n );\n\n willRetry = shouldRetryTask(test);\n\n if (!willRetry) {\n debug(`${testLogPrefix} - Max retries ${test.result?.retryCount || 0} / ${test.retry} ` \n + ` | ${test.result?.errors?.length ?? 0} errors`\n );\n }\n }\n\n await Promise.all([\n // as needed: invert if `fails`, bail\n postProcessTestResult(rpc, bail, test, testLogPrefix, logModule),\n\n reportTestFinished(rpc, test, logModule, base),\n ]);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n flagTestFinalized(test);\n\n debug(`${testLogPrefix} - Completed test run`);\n}\n\nexport async function runSuite(\n rpc: WorkerRPC,\n port: MessagePort,\n base: string,\n collectCoverage: boolean,\n compilation: WASMCompilation,\n suite: Suite | File,\n logModule: string,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n threadImports: ThreadImports,\n vitestVersion: VitestVersion,\n bail?: number,\n diffOptions?: SerializedDiffOptions,\n timedOutTest?: Test,\n): Promise<Suite> {\n const suiteStart = performance.now();\n const suiteMeta = suite.meta as AssemblyScriptSuiteTaskMeta;\n const suiteLogPrefix = getTaskLogPrefix(logModule, base, suite);\n const isTimedOutTestInSuite: boolean = timedOutTest?.suite?.id === suite.id;\n\n if (suiteMeta.resultFinal) {\n debug(`${suiteLogPrefix} - Skipping completed suite | state: \"${suite.result?.state}\"`);\n\n return suite;\n } else {\n const threadRestartTime = Date.now() - ((timedOutTest?.meta as AssemblyScriptTestTaskMeta)?.lastTimeoutTerminationTime ?? 0);\n const showRestart = !!timedOutTest && isSuiteOwnFile(suite)\n debug(`${showRestart ? `(thread resumed in ${threadRestartTime} ms) ` : ''}${suiteLogPrefix} - runSuite ${!!timedOutTest\n ? `resuming after timeout \"${timedOutTest.name}\" | isTestInSuite: ${isTimedOutTestInSuite}`\n : 'beginning'\n }`);\n }\n\n if (!suiteMeta.suitePreparedSent) {\n setSuitePrepareResult(suite);\n await reportSuitePrepare(rpc, suite, logModule, base);\n\n // ensure suite-prepare will only be sent once if a test\n // times out and the file worker thread gets re-launched\n suiteMeta.suitePreparedSent = true;\n }\n\n // restore suite coverage collected so far from the timed out test, if provided.\n // otherwise create a suite-level coverage data object to aggregate all subtask coverage\n if (isTimedOutTestInSuite) {\n suiteMeta.coverageData = (timedOutTest!.suite!.meta as AssemblyScriptSuiteTaskMeta).coverageData;\n \n const coverageKeys: number = Object.keys(suiteMeta.coverageData ?? {}).length;\n debug(`${suiteLogPrefix} - Restored suite coverage data after timeout (${coverageKeys} unique positions)`);\n } {\n // initialize aggregated coverage data for suite, which gets updated as each subtask completes\n suiteMeta.coverageData = { hitCountsByFileAndPosition: {} };\n }\n\n let tasksToRun: Task[] = getRunnableTasks(suite);\n debug(`${suiteLogPrefix} - Runnable tasks:`, tasksToRun.length);\n\n for (const task of tasksToRun) {\n if (task.type === 'suite') {\n const suiteTaskMeta = task.meta as AssemblyScriptSuiteTaskMeta;\n\n await runSuite(\n rpc, port, base, collectCoverage, compilation, task, logModule,\n poolOptions, threadImports, vitestVersion, bail, diffOptions, timedOutTest\n );\n\n // merge suite task coverage into parent suite coverage\n if (suiteMeta.coverageData && suiteTaskMeta.coverageData) {\n mergeCoverageData(suiteMeta.coverageData, suiteTaskMeta.coverageData);\n }\n \n } else {\n const testLogPrefix = getTaskLogPrefix(logModule, base, task);\n const testTaskMeta = task.meta as AssemblyScriptTestTaskMeta;\n\n const testCompleted = testTaskMeta.resultFinal;\n const testTimedOutPreviously = !!timedOutTest && task.id === timedOutTest.id;\n\n if (testCompleted) {\n debug(`${testLogPrefix} - Skipping completed test | state: \"${task.result?.state}\"`);\n } else if (testTimedOutPreviously) {\n if (shouldRetryTask(task)) {\n const previousRetryCount = task.result?.retryCount ?? 0;\n const newRetryCount = previousRetryCount + 1;\n\n debug(`${testLogPrefix} - Retrying after test timeout`\n + ` | retry attempt ${newRetryCount} / ${task.retry} ` \n + ` | ${task.result?.errors?.length ?? 0} errors`\n + ` | state: \"${task.result?.state}\"`\n );\n \n // report retried for the previous timeout failure, which won't\n // have been reported because the thread was killed to timeout\n await reportTestRetried(rpc, task, logModule, base);\n\n // increment the retry count (after reporting retried)\n task.result!.retryCount = newRetryCount;\n \n // retry timed out test\n // - if it passes, process as normal\n // - if it fails again, it will end up in the else block below\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n task, logModule, poolOptions, threadImports, bail, diffOptions\n );\n } else {\n debug(`${testLogPrefix} - Timed-out test has no retries left`\n + ` | retries attempted ${task.result?.retryCount || 0} / ${task.retry} ` \n + ` | ${task.result?.errors?.length ?? 0} errors`\n + ` | state: \"${task.result?.state}\"`\n );\n\n await Promise.all([\n // as needed: invert if `fails`, bail\n postProcessTestResult(rpc, bail, task, testLogPrefix, logModule),\n \n reportTestFinished(rpc, task, logModule, base),\n ]);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n flagTestFinalized(task);\n\n debug(`${testLogPrefix} - Completed timed out test run`);\n }\n } else {\n debug(`${testLogPrefix} - Running test task | state: \"${task.result?.state}\"`);\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n task, logModule, poolOptions, threadImports, bail, diffOptions\n );\n }\n\n // merge test coverage into suite coverage\n if (suiteMeta.coverageData && testTaskMeta.coverageData) {\n mergeCoverageData(suiteMeta.coverageData, testTaskMeta.coverageData);\n }\n }\n }\n\n // update suite result based on its tasks, report coverage data, report suite task result\n updateSuiteFinishedResult(suite, suiteLogPrefix);\n await reportSuiteFinished(rpc, suite, logModule, base, vitestVersion);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n finalizeSuiteResult(suite);\n\n const suiteTime = performance.now() - suiteStart;\n debug(`${suiteLogPrefix} - Suite Run Complete | TIMING ${suiteTime.toFixed(2)} ms`);\n\n return suite;\n}\n"],"mappings":"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"}
|