vitest-pool-assemblyscript 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -12
- package/assembly/compare.ts +37 -27
- package/dist/{addon-interface-7FPjYh7J.mjs → addon-interface-_pNXcbib.mjs} +2 -2
- package/dist/addon-interface-_pNXcbib.mjs.map +1 -0
- package/dist/{compile-runner-C-05LdGX.mjs → compile-runner-DOMhsLQE.mjs} +2 -2
- package/dist/{compile-runner-C-05LdGX.mjs.map → compile-runner-DOMhsLQE.mjs.map} +1 -1
- package/dist/{compiler-YMrl5MY_.mjs → compiler-CIXpfKq0.mjs} +3 -3
- package/dist/{compiler-YMrl5MY_.mjs.map → compiler-CIXpfKq0.mjs.map} +1 -1
- package/dist/config/index.mjs +2 -2
- package/dist/coverage-provider/index.mjs +2 -2
- package/dist/{feature-check-CNyjFX9M.mjs → feature-check-ELxw_Mji.mjs} +2 -2
- package/dist/{feature-check-CNyjFX9M.mjs.map → feature-check-ELxw_Mji.mjs.map} +1 -1
- package/dist/index-internal.mjs +2 -2
- package/dist/index-v3.mjs +12 -9
- package/dist/index-v3.mjs.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{pool-runner-init-D8Ei957C.mjs → pool-runner-init-BDQtAGwQ.mjs} +3 -3
- package/dist/pool-runner-init-BDQtAGwQ.mjs.map +1 -0
- package/dist/pool-thread/compile-worker-thread.d.mts +2 -2
- package/dist/pool-thread/compile-worker-thread.d.mts.map +1 -1
- package/dist/pool-thread/compile-worker-thread.mjs +5 -5
- package/dist/pool-thread/compile-worker-thread.mjs.map +1 -1
- package/dist/pool-thread/test-worker-thread.mjs +1 -1
- package/dist/pool-thread/v3-tinypool-thread.mjs +3 -3
- package/dist/{resolve-config-BFNr7LW7.mjs → resolve-config-DhZ4lOSK.mjs} +17 -12
- package/dist/{resolve-config-BFNr7LW7.mjs.map → resolve-config-DhZ4lOSK.mjs.map} +1 -1
- package/package.json +44 -17
- package/prebuilds/darwin-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/darwin-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/win32-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/win32-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/scripts/{install.js → install-native-addon.js} +12 -2
- package/dist/addon-interface-7FPjYh7J.mjs.map +0 -1
- package/dist/pool-runner-init-D8Ei957C.mjs.map +0 -1
package/dist/index-v3.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-v3.mjs","names":[],"sources":["../src/pool/v3-process-pool.ts","../src/index-v3.ts"],"sourcesContent":["/**\n * AssemblyScript Pool for Vitest\n */\n\nimport { resolve, basename } from 'node:path';\nimport { access } from 'node:fs/promises';\nimport Tinypool from 'tinypool';\nimport type { SerializedConfig } from 'vitest';\nimport type { Vitest, ProcessPool, TestSpecification } from 'vitest/node';\nimport type { Test } from '@vitest/runner/types';\n\nimport {\n AS_POOL_WORKER_MSG_FLAG,\n ASSEMBLYSCRIPT_POOL_NAME,\n POOL_ERROR_NAMES,\n} from '../types/constants.js';\nimport type {\n ResolvedHybridProviderOptions,\n ProcessPoolRunFileTask,\n WASMCompilation,\n TestRunRecord,\n AssemblyScriptPoolWorkerMessage,\n WorkerThreadInitData,\n} from '../types/types.js';\nimport { setGlobalDebugMode, debug } from '../util/debug.js';\nimport { createWorkerRPCChannel } from './worker-rpc-channel.js';\nimport {\n createPoolErrorFromAnyError,\n isAbortError,\n} from '../util/pool-errors.js';\nimport {\n failTestWithTimeoutError,\n flagTestTerminated,\n} from '../util/vitest-tasks.js';\nimport { createInitialFileTask } from '../util/vitest-file-tasks.js';\nimport { getProjectSerializedOrGlobalConfig, resolvePoolOptions } from '../util/resolve-config.js';\n\n// path assumes that we're running from dist/\nconst WORKER_PATH = resolve(import.meta.dirname, 'pool-thread/v3-tinypool-thread.mjs');\n\nconst POOL_THREAD_IDLE_TIMEOUT_MS = 3_600_000;\n\nasync function dispatchFullWorkerRun(\n spec: TestSpecification,\n config: SerializedConfig,\n isCollectTestsMode: boolean,\n pool: Tinypool,\n poolAbortSignal: AbortSignal,\n fileCache: Map<string, WASMCompilation>,\n testTimeoutCache: Map<string, TestRunRecord>,\n previousTimedOutTest?: Test,\n): Promise<Test | undefined> {\n const fileRunStart = Date.now();\n const testFilePath: string = spec.moduleId; // absolute path\n const base = basename(testFilePath);\n\n debug(`[Pool] ${base} - Starting file worker run at ${fileRunStart} for \"${testFilePath}\"`);\n\n let fileCompilation: WASMCompilation | undefined = fileCache.get(spec.moduleId);\n const isTimeoutRedispatch: boolean = !!previousTimedOutTest && !!fileCompilation;\n\n let timedOutTestThisRun: Test | undefined;\n\n try {\n const fileAbortController = new AbortController();\n const file = isTimeoutRedispatch\n ? previousTimedOutTest!.file\n : createInitialFileTask(spec.moduleId, spec.project.name, config.root, config.testTimeout, config.retry);\n\n const { workerPort, poolPort } = createWorkerRPCChannel(spec.project, isCollectTestsMode);\n\n // Enforce test timeout using setTimeout() and worker messages.\n // 1. worker sends a start message to indicate when the test has started\n // 2. pool starts a timer using setTimeout() when worker start message is received\n // 3. worker sends an end message to indicate when the test has completed\n // - if test completes before the timeout expires, the timer is cleared and everything proceeds\n // - if timeout expires, the test worker is actively aborted using the test-specific AbortController\n //\n // Monitoring from the pool main thread and actively aborting the runner allows for accurate enforcement of the test timeout,\n // which is much harder/impossible to control from within the worker thread itself, which is busy/blocked running \n // the long-running WASM test.\n poolPort.on('message', event => {\n if (!event[AS_POOL_WORKER_MSG_FLAG]) return;\n\n const msg = event as AssemblyScriptPoolWorkerMessage;\n if (msg.type === 'file-compiled') {\n const { compilation } = msg;\n fileCache.set(compilation.filePath, compilation);\n debug(`[Pool] ${basename(compilation.filePath)} - Got compiled file cache for \"${compilation.filePath}\"`);\n } else if (msg.type === 'execution-start') {\n const poolReceivedExecutionStart = Date.now();\n const { executionStart, test } = msg;\n\n const transitDuration = poolReceivedExecutionStart - executionStart;\n const adjustedTimeout = Math.max(test.timeout - transitDuration, 0);\n\n debug(`[Pool] ${base} - \"${test.name}\": Received worker execution start (transit ${transitDuration} ms)`\n + ` - Beginning test timeout timer ${test.timeout} ms (adjusted timeout: ${adjustedTimeout} ms)`\n );\n \n // Enforce test timeout\n const testTimeoutId = setTimeout(async () => {\n const poolTimeoutTime = Date.now();\n const record = testTimeoutCache.get(test.id);\n testTimeoutCache.delete(test.id);\n\n if (record) {\n const elapsedFromWorkerExecutionStart = poolTimeoutTime - record.executionStart;\n\n failTestWithTimeoutError(record.test, poolTimeoutTime, elapsedFromWorkerExecutionStart);\n\n flagTestTerminated(record.test);\n\n timedOutTestThisRun = test;\n fileAbortController.abort(POOL_ERROR_NAMES.WASMExecutionTimeoutError);\n\n debug(`[Pool] ${base} - \"${record.test.name}\" timed out (threshold ${record.test.timeout} ms)`\n + ` - Aborted worker job (duration before abort: ${elapsedFromWorkerExecutionStart} ms)`\n );\n }\n }, adjustedTimeout);\n\n testTimeoutCache.set(test.id, {\n test: test,\n executionStart: executionStart,\n timeoutId: testTimeoutId,\n });\n\n } else if (msg.type === 'execution-end') {\n const poolReceivedExecutionEnd = Date.now();\n const { executionEnd, testTaskId } = msg;\n const record = testTimeoutCache.get(testTaskId);\n testTimeoutCache.delete(testTaskId);\n\n if (record) {\n clearTimeout(record.timeoutId);\n\n const elapsedFromWorkerExecutionStart = executionEnd - record.executionStart!;\n const transitDuration = poolReceivedExecutionEnd - executionEnd;\n debug(`[Pool] ${base} - \"${record.test.name}\": Received worker execution end (transit: ${transitDuration} ms)`\n + ` - Clearing test timeout timer - Actual duration from worker exection start: ${elapsedFromWorkerExecutionStart} ms`\n );\n }\n }\n });\n \n const workerTaskData: ProcessPoolRunFileTask = {\n dispatchStart: Date.now(),\n port: workerPort,\n file,\n config,\n isCollectTestsMode,\n timedOutTest: previousTimedOutTest,\n timedOutCompilation: fileCompilation\n };\n\n try {\n await pool.run(workerTaskData, {\n name: 'runTestFile',\n transferList: [workerPort],\n signal: AbortSignal.any([poolAbortSignal, fileAbortController.signal]),\n });\n } finally {\n workerPort.close();\n poolPort.close();\n }\n \n return;\n } catch (error) {\n if (isAbortError(error)) {\n debug(`[Pool] ${base} - file worker aborted during run: ${String(error)}`);\n \n if (!!timedOutTestThisRun) {\n // swallow abort error, return timed out test so worker can be re-launched\n return timedOutTestThisRun;\n } else {\n // swallow abort error, this file worker run is done\n return;\n }\n }\n\n throw createPoolErrorFromAnyError(`${base} - unhandled file worker failure`, POOL_ERROR_NAMES.PoolError, error);\n } finally {\n debug(`[Pool] ${base} - Finished File Worker Execution`);\n }\n}\n\n/**\n * Run / Collect tests\n */\nasync function runTests(\n specs: TestSpecification[],\n isCollectTestsMode: boolean,\n pool: Tinypool,\n poolAbortController: AbortController,\n _invalidatedFiles?: string[]\n): Promise<void> {\n const mode = isCollectTestsMode ? 'collectTests' : 'runTests';\n debug(`[Pool] -------- ${mode} called for ${specs.length} specs --------`);\n\n // TODO - invalidation\n // const invalidCount = invalidatedFiles?.length ?? 0;\n // debug('[Pool] Invalidated files:', invalidCount);\n\n // if (invalidCount > 0) {\n // // probably:\n // // 0. pre-build a cached map of source files to specs that import them (using debuginfo?)\n // // 1. check if invalidated file is in map: if NOT ignore & continue loop to next file\n // // 2. create file worker for each spec the invalidated file maps to\n // }\n\n const fileCache: Map<string, WASMCompilation> = new Map();\n const testTimeoutCache: Map<string, TestRunRecord> = new Map();\n\n // Create worker for each file\n const fileWorkers: Promise<void>[] = specs.map(async (spec: TestSpecification): Promise<void> => {\n const { serializedConfig } = spec.project;\n let timedOutTest = await dispatchFullWorkerRun(spec, serializedConfig, isCollectTestsMode, pool, poolAbortController.signal, fileCache, testTimeoutCache);\n \n while (timedOutTest) {\n timedOutTest = await dispatchFullWorkerRun(spec, serializedConfig, isCollectTestsMode, pool, poolAbortController.signal, fileCache, testTimeoutCache, timedOutTest);\n }\n });\n\n if (isCollectTestsMode) {\n try {\n await Promise.all(fileWorkers);\n debug('[Pool] collectTests - All file workers resolved');\n } catch (err) {\n debug('[Pool] collectTests - File worker REJECTED, Calling Pool Abort to bail this collectTests run');\n poolAbortController.abort();\n }\n } else {\n const results = await Promise.allSettled(fileWorkers);\n const unexpectedErrors: any[] = [];\n results.forEach(r => {\n if (r.status === 'rejected') {\n unexpectedErrors.push(r.reason);\n }\n });\n\n if (unexpectedErrors.length === 0) {\n debug(`[Pool] ${mode} - All file workers resolved`);\n } else {\n debug(`[Pool] ${mode} - Some file workers REJECTED unexpectedly. Throwing error(s) to vitest:`, unexpectedErrors);\n throw {\n name: POOL_ERROR_NAMES.PoolError,\n message: `Unexpected AssemblyScript Pool Error(s) Encountered during ${mode}`,\n cause: unexpectedErrors[0]\n };\n }\n }\n\n debug(`[Pool] Timeout Cache Size: ${testTimeoutCache.size}`);\n testTimeoutCache.forEach((record: TestRunRecord, testId: string) => {\n if (record) {\n debug(`[Pool] Leftover timeout entry for task: ${record.test.name}`);\n clearTimeout(record.timeoutId);\n } else {\n debug(`[Pool] Empty test timeout entry for task: ${testId}`);\n }\n });\n\n debug(`[Pool] -------- ${mode} completed --------`);\n}\n\nexport function createAssemblyScriptProcessPool(ctx: Vitest): ProcessPool {\n const { config, foundProjectSerializedConfig } = getProjectSerializedOrGlobalConfig(ctx);\n \n // Resolve pool options and initialize debug mode\n // @ts-ignore - we build with v4, but this is correct for v3 (has Config.poolOptions)\n const poolOptions = resolvePoolOptions(config?.poolOptions);\n setGlobalDebugMode(poolOptions.debug);\n\n debug('[Pool] Initializing AssemblyScript Pool');\n\n if (foundProjectSerializedConfig) {\n debug(`[Pool] Multi-project mode: Using config from project: \"${config.name}\"`);\n } else {\n debug('[Pool] Single-project mode: No project config found using vitest-pool-assemblyscript pool - Using global config with AssemblyScript pool defaults');\n }\n\n debug(`[Pool] Worker thread path: \"${WORKER_PATH}\"`);\n debug(`[Pool] Worker thread configuration - maxThreads: ${poolOptions.maxThreadsV3}`);\n\n setImmediate(async () => {\n const userImportsFactoryPath = resolve(config.root, poolOptions.wasmImportsFactory ?? '');\n const results = await Promise.allSettled([\n access(WORKER_PATH),\n poolOptions.wasmImportsFactory ? access(userImportsFactoryPath) : Promise.resolve()\n ]);\n\n if (results[0].status === 'rejected') {\n throw new Error(`Cannot access worker thread file at path: \"${WORKER_PATH}\"`);\n }\n if (results[1].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 // Initialize Tinypool for worker management\n const pool = new Tinypool({\n filename: WORKER_PATH,\n minThreads: 1,\n maxThreads: poolOptions.maxThreadsV3,\n idleTimeout: POOL_THREAD_IDLE_TIMEOUT_MS,\n isolateWorkers: false,\n workerData: {\n asPoolOptions: poolOptions,\n asCoverageOptions: config.coverage as ResolvedHybridProviderOptions,\n projectRoot: config.root,\n } satisfies WorkerThreadInitData,\n });\n\n // For explicitly terminating all worker threads because of\n // ctrl+c in terminal, or bail after test failures exceed bail count\n const poolAbortController = new AbortController();\n ctx.onCancel(reason => {\n const reasonMsg = reason === 'test-failure' ? 'Bail after test failure' : reason;\n console.log(`${ASSEMBLYSCRIPT_POOL_NAME} - Aborting all tests: ${reasonMsg}`);\n poolAbortController.abort();\n });\n\n return {\n name: ASSEMBLYSCRIPT_POOL_NAME,\n\n // runs when executing vitest list\n async collectTests(specs: TestSpecification[]) {\n const isCollectTestsMode = true;\n return runTests(specs, isCollectTestsMode, pool, poolAbortController);\n },\n\n async runTests(specs: TestSpecification[], invalidates?: string[]) {\n const isCollectTestsMode = false;\n return runTests(specs, isCollectTestsMode, pool, poolAbortController, invalidates);\n },\n\n // Cleanup when shutting down\n async close() {\n debug('[Pool] AbortController called');\n poolAbortController.abort();\n \n debug('[Pool] Tinypool destroyed');\n await pool.destroy();\n\n debug('[Pool] Exiting');\n },\n };\n}\n","// default export for v3 pool\nimport { createAssemblyScriptProcessPool } from './pool/v3-process-pool.js';\nexport default createAssemblyScriptProcessPool;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-v3.mjs","names":[],"sources":["../src/pool/v3-process-pool.ts","../src/index-v3.ts"],"sourcesContent":["/**\n * AssemblyScript Pool for Vitest\n */\n\nimport { resolve, basename } from 'node:path';\nimport { access } from 'node:fs/promises';\nimport Tinypool from 'tinypool';\nimport type { SerializedConfig } from 'vitest';\nimport type { Vitest, ProcessPool, TestSpecification } from 'vitest/node';\nimport type { Test } from '@vitest/runner/types';\n\nimport {\n AS_POOL_WORKER_MSG_FLAG,\n ASSEMBLYSCRIPT_POOL_NAME,\n POOL_ERROR_NAMES,\n} from '../types/constants.js';\nimport type {\n ResolvedHybridProviderOptions,\n ProcessPoolRunFileTask,\n WASMCompilation,\n TestRunRecord,\n AssemblyScriptPoolWorkerMessage,\n WorkerThreadInitData,\n} from '../types/types.js';\nimport { setGlobalDebugMode, debug } from '../util/debug.js';\nimport { createWorkerRPCChannel } from './worker-rpc-channel.js';\nimport {\n createPoolErrorFromAnyError,\n isAbortError,\n} from '../util/pool-errors.js';\nimport {\n failTestWithTimeoutError,\n flagTestTerminated,\n} from '../util/vitest-tasks.js';\nimport { createInitialFileTask } from '../util/vitest-file-tasks.js';\nimport { getProjectSerializedOrGlobalConfig } from '../util/resolve-config.js';\n\n// path assumes that we're running from dist/\nconst WORKER_PATH = resolve(import.meta.dirname, 'pool-thread/v3-tinypool-thread.mjs');\n\nconst POOL_THREAD_IDLE_TIMEOUT_MS = 3_600_000;\n\nasync function dispatchFullWorkerRun(\n spec: TestSpecification,\n config: SerializedConfig,\n isCollectTestsMode: boolean,\n pool: Tinypool,\n poolAbortSignal: AbortSignal,\n fileCache: Map<string, WASMCompilation>,\n testTimeoutCache: Map<string, TestRunRecord>,\n previousTimedOutTest?: Test,\n): Promise<Test | undefined> {\n const fileRunStart = Date.now();\n const testFilePath: string = spec.moduleId; // absolute path\n const base = basename(testFilePath);\n\n debug(`[Pool] ${base} - Starting file worker run at ${fileRunStart} for \"${testFilePath}\"`);\n\n let fileCompilation: WASMCompilation | undefined = fileCache.get(spec.moduleId);\n const isTimeoutRedispatch: boolean = !!previousTimedOutTest && !!fileCompilation;\n\n let timedOutTestThisRun: Test | undefined;\n\n try {\n const fileAbortController = new AbortController();\n const file = isTimeoutRedispatch\n ? previousTimedOutTest!.file\n : createInitialFileTask(spec.moduleId, spec.project.name, config.root, config.testTimeout, config.retry);\n\n const { workerPort, poolPort } = createWorkerRPCChannel(spec.project, isCollectTestsMode);\n\n // Enforce test timeout using setTimeout() and worker messages.\n // 1. worker sends a start message to indicate when the test has started\n // 2. pool starts a timer using setTimeout() when worker start message is received\n // 3. worker sends an end message to indicate when the test has completed\n // - if test completes before the timeout expires, the timer is cleared and everything proceeds\n // - if timeout expires, the test worker is actively aborted using the test-specific AbortController\n //\n // Monitoring from the pool main thread and actively aborting the runner allows for accurate enforcement of the test timeout,\n // which is much harder/impossible to control from within the worker thread itself, which is busy/blocked running \n // the long-running WASM test.\n poolPort.on('message', event => {\n if (!event[AS_POOL_WORKER_MSG_FLAG]) return;\n\n const msg = event as AssemblyScriptPoolWorkerMessage;\n if (msg.type === 'file-compiled') {\n const { compilation } = msg;\n fileCache.set(compilation.filePath, compilation);\n debug(`[Pool] ${basename(compilation.filePath)} - Got compiled file cache for \"${compilation.filePath}\"`);\n } else if (msg.type === 'execution-start') {\n const poolReceivedExecutionStart = Date.now();\n const { executionStart, test } = msg;\n\n const transitDuration = poolReceivedExecutionStart - executionStart;\n const adjustedTimeout = Math.max(test.timeout - transitDuration, 0);\n\n debug(`[Pool] ${base} - \"${test.name}\": Received worker execution start (transit ${transitDuration} ms)`\n + ` - Beginning test timeout timer ${test.timeout} ms (adjusted timeout: ${adjustedTimeout} ms)`\n );\n \n // Enforce test timeout\n const testTimeoutId = setTimeout(async () => {\n const poolTimeoutTime = Date.now();\n const record = testTimeoutCache.get(test.id);\n testTimeoutCache.delete(test.id);\n\n if (record) {\n const elapsedFromWorkerExecutionStart = poolTimeoutTime - record.executionStart;\n\n failTestWithTimeoutError(record.test, poolTimeoutTime, elapsedFromWorkerExecutionStart);\n\n flagTestTerminated(record.test);\n\n timedOutTestThisRun = test;\n fileAbortController.abort(POOL_ERROR_NAMES.WASMExecutionTimeoutError);\n\n debug(`[Pool] ${base} - \"${record.test.name}\" timed out (threshold ${record.test.timeout} ms)`\n + ` - Aborted worker job (duration before abort: ${elapsedFromWorkerExecutionStart} ms)`\n );\n }\n }, adjustedTimeout);\n\n testTimeoutCache.set(test.id, {\n test: test,\n executionStart: executionStart,\n timeoutId: testTimeoutId,\n });\n\n } else if (msg.type === 'execution-end') {\n const poolReceivedExecutionEnd = Date.now();\n const { executionEnd, testTaskId } = msg;\n const record = testTimeoutCache.get(testTaskId);\n testTimeoutCache.delete(testTaskId);\n\n if (record) {\n clearTimeout(record.timeoutId);\n\n const elapsedFromWorkerExecutionStart = executionEnd - record.executionStart!;\n const transitDuration = poolReceivedExecutionEnd - executionEnd;\n debug(`[Pool] ${base} - \"${record.test.name}\": Received worker execution end (transit: ${transitDuration} ms)`\n + ` - Clearing test timeout timer - Actual duration from worker exection start: ${elapsedFromWorkerExecutionStart} ms`\n );\n }\n }\n });\n \n const workerTaskData: ProcessPoolRunFileTask = {\n dispatchStart: Date.now(),\n port: workerPort,\n file,\n config,\n isCollectTestsMode,\n timedOutTest: previousTimedOutTest,\n timedOutCompilation: fileCompilation\n };\n\n try {\n await pool.run(workerTaskData, {\n name: 'runTestFile',\n transferList: [workerPort],\n signal: AbortSignal.any([poolAbortSignal, fileAbortController.signal]),\n });\n } finally {\n workerPort.close();\n poolPort.close();\n }\n \n return;\n } catch (error) {\n if (isAbortError(error)) {\n debug(`[Pool] ${base} - file worker aborted during run: ${String(error)}`);\n \n if (!!timedOutTestThisRun) {\n // swallow abort error, return timed out test so worker can be re-launched\n return timedOutTestThisRun;\n } else {\n // swallow abort error, this file worker run is done\n return;\n }\n }\n\n throw createPoolErrorFromAnyError(`${base} - unhandled file worker failure`, POOL_ERROR_NAMES.PoolError, error);\n } finally {\n debug(`[Pool] ${base} - Finished File Worker Execution`);\n }\n}\n\n/**\n * Run / Collect tests\n */\nasync function runTests(\n specs: TestSpecification[],\n isCollectTestsMode: boolean,\n pool: Tinypool,\n poolAbortController: AbortController,\n _invalidatedFiles?: string[]\n): Promise<void> {\n const mode = isCollectTestsMode ? 'collectTests' : 'runTests';\n debug(`[Pool] -------- ${mode} called for ${specs.length} specs --------`);\n\n // TODO - invalidation\n // const invalidCount = invalidatedFiles?.length ?? 0;\n // debug('[Pool] Invalidated files:', invalidCount);\n\n // if (invalidCount > 0) {\n // // probably:\n // // 0. pre-build a cached map of source files to specs that import them (using debuginfo?)\n // // 1. check if invalidated file is in map: if NOT ignore & continue loop to next file\n // // 2. create file worker for each spec the invalidated file maps to\n // }\n\n const fileCache: Map<string, WASMCompilation> = new Map();\n const testTimeoutCache: Map<string, TestRunRecord> = new Map();\n\n // Create worker for each file\n const fileWorkers: Promise<void>[] = specs.map(async (spec: TestSpecification): Promise<void> => {\n const { serializedConfig } = spec.project;\n let timedOutTest = await dispatchFullWorkerRun(spec, serializedConfig, isCollectTestsMode, pool, poolAbortController.signal, fileCache, testTimeoutCache);\n \n while (timedOutTest) {\n timedOutTest = await dispatchFullWorkerRun(spec, serializedConfig, isCollectTestsMode, pool, poolAbortController.signal, fileCache, testTimeoutCache, timedOutTest);\n }\n });\n\n if (isCollectTestsMode) {\n try {\n await Promise.all(fileWorkers);\n debug('[Pool] collectTests - All file workers resolved');\n } catch (err) {\n debug('[Pool] collectTests - File worker REJECTED, Calling Pool Abort to bail this collectTests run');\n poolAbortController.abort();\n }\n } else {\n const results = await Promise.allSettled(fileWorkers);\n const unexpectedErrors: any[] = [];\n results.forEach(r => {\n if (r.status === 'rejected') {\n unexpectedErrors.push(r.reason);\n }\n });\n\n if (unexpectedErrors.length === 0) {\n debug(`[Pool] ${mode} - All file workers resolved`);\n } else {\n debug(`[Pool] ${mode} - Some file workers REJECTED unexpectedly. Throwing error(s) to vitest:`, unexpectedErrors);\n throw {\n name: POOL_ERROR_NAMES.PoolError,\n message: `Unexpected AssemblyScript Pool Error(s) Encountered during ${mode}`,\n cause: unexpectedErrors[0]\n };\n }\n }\n\n debug(`[Pool] Timeout Cache Size: ${testTimeoutCache.size}`);\n testTimeoutCache.forEach((record: TestRunRecord, testId: string) => {\n if (record) {\n debug(`[Pool] Leftover timeout entry for task: ${record.test.name}`);\n clearTimeout(record.timeoutId);\n } else {\n debug(`[Pool] Empty test timeout entry for task: ${testId}`);\n }\n });\n\n debug(`[Pool] -------- ${mode} completed --------`);\n}\n\nexport function createAssemblyScriptProcessPool(ctx: Vitest): ProcessPool {\n const { config, foundProjectSerializedConfig, v3PoolOptions } = getProjectSerializedOrGlobalConfig(ctx);\n \n if (!v3PoolOptions) {\n throw {\n name: POOL_ERROR_NAMES.PoolError,\n message: `Could not parse poot options or generate defaults. This is a bug in vitest-pool-assemblyscript, please report it.`,\n };\n }\n setGlobalDebugMode(v3PoolOptions.debug);\n\n debug('[Pool] Initializing AssemblyScript Pool');\n\n if (foundProjectSerializedConfig) {\n debug(`[Pool] Multi-project mode: Using config from project: \"${config.name}\"`);\n } else {\n debug('[Pool] Single-project mode: No project config found using vitest-pool-assemblyscript pool - Using global config with AssemblyScript pool defaults');\n }\n\n debug(`[Pool] Worker thread path: \"${WORKER_PATH}\"`);\n debug(`[Pool] Worker thread configuration - maxThreads: ${v3PoolOptions.maxThreadsV3}`);\n\n setImmediate(async () => {\n const userImportsFactoryPath = resolve(config.root, v3PoolOptions.wasmImportsFactory ?? '');\n const results = await Promise.allSettled([\n access(WORKER_PATH),\n v3PoolOptions.wasmImportsFactory ? access(userImportsFactoryPath) : Promise.resolve()\n ]);\n\n if (results[0].status === 'rejected') {\n throw new Error(`Cannot access worker thread file at path: \"${WORKER_PATH}\"`);\n }\n if (results[1].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 // Initialize Tinypool for worker management\n const pool = new Tinypool({\n filename: WORKER_PATH,\n minThreads: 1,\n maxThreads: v3PoolOptions.maxThreadsV3,\n idleTimeout: POOL_THREAD_IDLE_TIMEOUT_MS,\n isolateWorkers: false,\n workerData: {\n asPoolOptions: v3PoolOptions,\n asCoverageOptions: config.coverage as ResolvedHybridProviderOptions,\n projectRoot: config.root,\n } satisfies WorkerThreadInitData,\n });\n\n // For explicitly terminating all worker threads because of\n // ctrl+c in terminal, or bail after test failures exceed bail count\n const poolAbortController = new AbortController();\n ctx.onCancel(reason => {\n const reasonMsg = reason === 'test-failure' ? 'Bail after test failure' : reason;\n console.log(`${ASSEMBLYSCRIPT_POOL_NAME} - Aborting all tests: ${reasonMsg}`);\n poolAbortController.abort();\n });\n\n return {\n name: ASSEMBLYSCRIPT_POOL_NAME,\n\n // runs when executing vitest list\n async collectTests(specs: TestSpecification[]) {\n const isCollectTestsMode = true;\n return runTests(specs, isCollectTestsMode, pool, poolAbortController);\n },\n\n async runTests(specs: TestSpecification[], invalidates?: string[]) {\n const isCollectTestsMode = false;\n return runTests(specs, isCollectTestsMode, pool, poolAbortController, invalidates);\n },\n\n // Cleanup when shutting down\n async close() {\n debug('[Pool] AbortController called');\n poolAbortController.abort();\n \n debug('[Pool] Tinypool destroyed');\n await pool.destroy();\n\n debug('[Pool] Exiting');\n },\n };\n}\n","// default export for v3 pool\nimport { createAssemblyScriptProcessPool } from './pool/v3-process-pool.js';\nexport default createAssemblyScriptProcessPool;\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "./constants-DuBLuMjt.mjs";
|
|
2
|
-
import "./resolve-config-
|
|
2
|
+
import "./resolve-config-DhZ4lOSK.mjs";
|
|
3
3
|
import "./debug-Cm1VFmaz.mjs";
|
|
4
4
|
import "./vitest-file-tasks-Bn9CrWt_.mjs";
|
|
5
5
|
import "./vitest-tasks--ow4pacR.mjs";
|
|
6
6
|
import "./worker-rpc-channel-CZZIxtv5.mjs";
|
|
7
|
-
import { createAssemblyScriptPool } from "./pool-runner-init-
|
|
7
|
+
import { createAssemblyScriptPool } from "./pool-runner-init-BDQtAGwQ.mjs";
|
|
8
8
|
|
|
9
9
|
export { createAssemblyScriptPool };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { POOL_ERROR_NAMES } from "./constants-DuBLuMjt.mjs";
|
|
2
|
-
import { resolvePoolOptions } from "./resolve-config-
|
|
2
|
+
import { resolvePoolOptions } from "./resolve-config-DhZ4lOSK.mjs";
|
|
3
3
|
import { createPoolError, createPoolErrorFromAnyError, debug, isAbortError, setGlobalDebugMode } from "./debug-Cm1VFmaz.mjs";
|
|
4
4
|
import { toForwardSlash } from "./path-utils-t9OzjXYF.mjs";
|
|
5
5
|
import { createInitialFileTask } from "./vitest-file-tasks-Bn9CrWt_.mjs";
|
|
@@ -226,7 +226,7 @@ var AssemblyScriptPoolWorker = class {
|
|
|
226
226
|
config: this.config,
|
|
227
227
|
isCollectTestsMode: this.isCollectTestsMode
|
|
228
228
|
}, {
|
|
229
|
-
name: "
|
|
229
|
+
name: "runCompileAndDiscoverSpec",
|
|
230
230
|
transferList: [workerPort],
|
|
231
231
|
signal: GLOBAL_POOL_ABORT_CONTROLLER.signal
|
|
232
232
|
});
|
|
@@ -398,4 +398,4 @@ function createAssemblyScriptPool(userPoolOptions) {
|
|
|
398
398
|
|
|
399
399
|
//#endregion
|
|
400
400
|
export { createAssemblyScriptPool };
|
|
401
|
-
//# sourceMappingURL=pool-runner-init-
|
|
401
|
+
//# sourceMappingURL=pool-runner-init-BDQtAGwQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool-runner-init-BDQtAGwQ.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 { toForwardSlash } from '../util/path-utils.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 vitest 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 toForwardSlash(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 // pools are never explicitly destroyed.\n // - vitest processes are short-lived\n // - when PoolWorkers are stopped, they cleanup actively-running thread tasks\n // - in practice stop happens after every run, even in watch mode\n // - keeping pools hot is desirable for watch mode re-runs, so we maintain our pools\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: 'runCompileAndDiscoverSpec',\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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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RunCompileAndDiscoverTask, ThreadSpec } from "../types-D0nprJo1.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/pool-thread/compile-worker-thread.d.ts
|
|
4
|
-
declare function
|
|
4
|
+
declare function runCompileAndDiscoverSpec(data: RunCompileAndDiscoverTask): Promise<ThreadSpec>;
|
|
5
5
|
//#endregion
|
|
6
|
-
export {
|
|
6
|
+
export { runCompileAndDiscoverSpec };
|
|
7
7
|
//# sourceMappingURL=compile-worker-thread.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-worker-thread.d.mts","names":[],"sources":["../../src/pool-thread/compile-worker-thread.ts"],"mappings":";;;iBAkCsB,
|
|
1
|
+
{"version":3,"file":"compile-worker-thread.d.mts","names":[],"sources":["../../src/pool-thread/compile-worker-thread.ts"],"mappings":";;;iBAkCsB,yBAAA,CAA0B,IAAA,EAAM,yBAAA,GAA4B,OAAA,CAAQ,UAAA"}
|
|
@@ -3,9 +3,9 @@ import { debug, setGlobalDebugMode } from "../debug-Cm1VFmaz.mjs";
|
|
|
3
3
|
import "../vitest-file-tasks-Bn9CrWt_.mjs";
|
|
4
4
|
import "../vitest-tasks--ow4pacR.mjs";
|
|
5
5
|
import { createRpcClient, loadUserWasmImportsFactory } from "../load-user-imports-B3Iy_K8k.mjs";
|
|
6
|
-
import { isNodeVersionSupportedForCoverage } from "../feature-check-
|
|
7
|
-
import "../compiler-
|
|
8
|
-
import { runCompileAndDiscover } from "../compile-runner-
|
|
6
|
+
import { isNodeVersionSupportedForCoverage } from "../feature-check-ELxw_Mji.mjs";
|
|
7
|
+
import "../compiler-CIXpfKq0.mjs";
|
|
8
|
+
import { runCompileAndDiscover } from "../compile-runner-DOMhsLQE.mjs";
|
|
9
9
|
import { threadId, workerData } from "node:worker_threads";
|
|
10
10
|
import { highlight } from "@vitest/utils/highlight";
|
|
11
11
|
|
|
@@ -20,7 +20,7 @@ setGlobalDebugMode(asPoolOptions.debug);
|
|
|
20
20
|
debug(`[${logModule}] New compile pool thread created`);
|
|
21
21
|
const COVERAGE_SUPPORTED = isNodeVersionSupportedForCoverage();
|
|
22
22
|
const createUserWasmImports = await loadUserWasmImportsFactory(asPoolOptions.wasmImportsFactory, projectRoot, logModule);
|
|
23
|
-
async function
|
|
23
|
+
async function runCompileAndDiscoverSpec(data) {
|
|
24
24
|
const { dispatchStart, workerId, file, port, config } = data;
|
|
25
25
|
const dispatchToInit = Date.now() - dispatchStart;
|
|
26
26
|
const logModuleWithId = `${logModule} ${workerId} (t ${threadId})`;
|
|
@@ -41,5 +41,5 @@ async function runCompileAndDisoverSpec(data) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
//#endregion
|
|
44
|
-
export {
|
|
44
|
+
export { runCompileAndDiscoverSpec };
|
|
45
45
|
//# sourceMappingURL=compile-worker-thread.mjs.map
|
|
@@ -1 +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';\nimport { isNodeVersionSupportedForCoverage } from '../util/feature-check.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 COVERAGE_SUPPORTED = isNodeVersionSupportedForCoverage();\n\nconst createUserWasmImports: WasmImportsFactory | undefined = await loadUserWasmImportsFactory(\n asPoolOptions.wasmImportsFactory,\n projectRoot,\n logModule\n);\n\nexport async function
|
|
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';\nimport { isNodeVersionSupportedForCoverage } from '../util/feature-check.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 COVERAGE_SUPPORTED = isNodeVersionSupportedForCoverage();\n\nconst createUserWasmImports: WasmImportsFactory | undefined = await loadUserWasmImportsFactory(\n asPoolOptions.wasmImportsFactory,\n projectRoot,\n logModule\n);\n\nexport async function runCompileAndDiscoverSpec(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 && COVERAGE_SUPPORTED,\n asCoverageOptions.globbedAssemblyScriptProjectRelativeExcludeOnly ?? [],\n { highlight, createUserWasmImports } 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":";;;;;;;;;;;;;;;AAmBA,MAAM,YAAY;AAClB,MAAM,CAAC,SAAS,YAAY;AAC5B,MAAM,EAAE,aAAa,eAAe,sBAAsB;AAE1D,mBAAmB,cAAc,MAAM;AACvC,MAAM,IAAI,UAAU,mCAAmC;AAEvD,MAAM,qBAAqB,mCAAmC;AAE9D,MAAM,wBAAwD,MAAM,2BAClE,cAAc,oBACd,aACA,UACD;AAED,eAAsB,0BAA0B,MAAsD;CACpG,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,WAAW,oBAC3B,kBAAkB,mDAAmD,EAAE,EACvE;EAAE;EAAW;EAAuB,EACpC,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,QAChD,OAAO,iBACP,OAAO,UACR;AAED,OAAM,IAAI,gBAAgB,wDAAwD;AAElF,MAAK,OAAO;AAEZ,QAAO;EAAE;EAAa;EAAM"}
|
|
@@ -2,7 +2,7 @@ import "../constants-DuBLuMjt.mjs";
|
|
|
2
2
|
import { debug, setGlobalDebugMode } from "../debug-Cm1VFmaz.mjs";
|
|
3
3
|
import "../vitest-tasks--ow4pacR.mjs";
|
|
4
4
|
import { createRpcClient, loadUserWasmImportsFactory } from "../load-user-imports-B3Iy_K8k.mjs";
|
|
5
|
-
import { isNodeVersionSupportedForCoverage } from "../feature-check-
|
|
5
|
+
import { isNodeVersionSupportedForCoverage } from "../feature-check-ELxw_Mji.mjs";
|
|
6
6
|
import { runSuite } from "../test-runner-WF857_Bk.mjs";
|
|
7
7
|
import { basename } from "node:path";
|
|
8
8
|
import { threadId, workerData } from "node:worker_threads";
|
|
@@ -3,9 +3,9 @@ import { debug, setGlobalDebugMode } from "../debug-Cm1VFmaz.mjs";
|
|
|
3
3
|
import "../vitest-file-tasks-Bn9CrWt_.mjs";
|
|
4
4
|
import "../vitest-tasks--ow4pacR.mjs";
|
|
5
5
|
import { createRpcClient, loadUserWasmImportsFactory } from "../load-user-imports-B3Iy_K8k.mjs";
|
|
6
|
-
import { isNodeVersionSupportedForCoverage } from "../feature-check-
|
|
7
|
-
import "../compiler-
|
|
8
|
-
import { runCompileAndDiscover } from "../compile-runner-
|
|
6
|
+
import { isNodeVersionSupportedForCoverage } from "../feature-check-ELxw_Mji.mjs";
|
|
7
|
+
import "../compiler-CIXpfKq0.mjs";
|
|
8
|
+
import { runCompileAndDiscover } from "../compile-runner-DOMhsLQE.mjs";
|
|
9
9
|
import { runSuite } from "../test-runner-WF857_Bk.mjs";
|
|
10
10
|
import { basename } from "node:path";
|
|
11
11
|
import { workerId } from "tinypool";
|
|
@@ -44,6 +44,7 @@ function resolvePoolOptions(userPoolOptions) {
|
|
|
44
44
|
function getProjectSerializedOrGlobalConfig(ctx) {
|
|
45
45
|
let testProject;
|
|
46
46
|
let foundProjectSerializedConfig = false;
|
|
47
|
+
let v3PoolOptions;
|
|
47
48
|
if (ctx.projects && ctx.projects.length > 0) {
|
|
48
49
|
const project = ctx.projects.find((p) => p.config.pool.includes("assemblyscript"));
|
|
49
50
|
if (project) {
|
|
@@ -51,21 +52,25 @@ function getProjectSerializedOrGlobalConfig(ctx) {
|
|
|
51
52
|
foundProjectSerializedConfig = true;
|
|
52
53
|
}
|
|
53
54
|
}
|
|
55
|
+
const config = !!testProject ? {
|
|
56
|
+
...testProject.serializedConfig,
|
|
57
|
+
coverage: {
|
|
58
|
+
...testProject.serializedConfig.coverage,
|
|
59
|
+
...ctx.config.coverage
|
|
60
|
+
}
|
|
61
|
+
} : {
|
|
62
|
+
...ctx.config,
|
|
63
|
+
coverage: ctx.config.coverage
|
|
64
|
+
};
|
|
65
|
+
const maybeOptions = !!testProject ? testProject.config?.poolOptions?.assemblyScript : config?.poolOptions?.assemblyScript;
|
|
66
|
+
if (maybeOptions) v3PoolOptions = resolvePoolOptions(maybeOptions);
|
|
54
67
|
return {
|
|
55
|
-
config
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
...testProject.serializedConfig.coverage,
|
|
59
|
-
...ctx.config.coverage
|
|
60
|
-
}
|
|
61
|
-
} : {
|
|
62
|
-
...ctx.config,
|
|
63
|
-
coverage: ctx.config.coverage
|
|
64
|
-
},
|
|
65
|
-
foundProjectSerializedConfig
|
|
68
|
+
config,
|
|
69
|
+
foundProjectSerializedConfig,
|
|
70
|
+
v3PoolOptions
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
//#endregion
|
|
70
75
|
export { getProjectSerializedOrGlobalConfig, resolvePoolOptions };
|
|
71
|
-
//# sourceMappingURL=resolve-config-
|
|
76
|
+
//# sourceMappingURL=resolve-config-DhZ4lOSK.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-config-BFNr7LW7.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 * Native build error marker file content.\n * Written by install script when native addon compilation fails.\n * Read at runtime to display detailed error information to users.\n */\nexport interface NativeBuildError {\n stage: 'binaryen-download' | 'native-compile';\n error: string;\n platform: string;\n timestamp: string;\n}\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 debugNative?: boolean;\n debugCoverageExtract?: boolean;\n\n /** enable to collect coverage instrumentation on the pool's assembly/* files */\n _instrumentPoolInternals?: boolean;\n\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 debugIstanbul?: boolean;\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 'debugNative',\n 'debugCoverageExtract',\n '_instrumentPoolInternals',\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 & 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 createUserWasmImports?: 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 /** Project root for resolving source map paths to absolute paths */\n projectRoot: string;\n /** List of relative file paths to exclude from instrumentation */\n relativeExcludedFiles: string[];\n excludedLibraryFilePrefix: string;\n coverageMemoryPagesMin: number;\n coverageMemoryPagesMax: number;\n excludedLibraryFileOverridePrefix?: string;\n debug?: boolean;\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 /** Absolute file path (normalized from source map during debug info extraction) */\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 * Array value accommodates generic monomorphizations that share a source position.\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' | 'projectRoot'> {\n excludedFiles?: string[];\n logPrefix?: string;\n}\n\nexport type InstrumentForCoverageFunc = (\n wasmBuffer: Buffer,\n sourceMapBuffer: Buffer,\n instrumentationOptions: InstrumentationOptions,\n logModule: string,\n logLabel: string,\n) => InstrumentationResult;\n\nexport interface NativeAddonInterface {\n instrumentForCoverage: InstrumentForCoverageFunc;\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 debugNative: false,\n debugCoverageExtract: false,\n _instrumentPoolInternals: 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":";;;;;AAoJA,MAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;ACjJD,MAAM,qCAAsH;CAC1H,OAAO;CACP,aAAa;CACb,sBAAsB;CACtB,0BAA0B;CAC1B,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"}
|
|
1
|
+
{"version":3,"file":"resolve-config-DhZ4lOSK.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 * Native build error marker file content.\n * Written by install script when native addon compilation fails.\n * Read at runtime to display detailed error information to users.\n */\nexport interface NativeBuildError {\n stage: 'binaryen-download' | 'native-compile';\n error: string;\n platform: string;\n timestamp: string;\n}\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 debugNative?: boolean;\n debugCoverageExtract?: boolean;\n\n /** enable to collect coverage instrumentation on the pool's assembly/* files */\n _instrumentPoolInternals?: boolean;\n\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 debugIstanbul?: boolean;\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 'debugNative',\n 'debugCoverageExtract',\n '_instrumentPoolInternals',\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 & 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 createUserWasmImports?: 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 /** Project root for resolving source map paths to absolute paths */\n projectRoot: string;\n /** List of relative file paths to exclude from instrumentation */\n relativeExcludedFiles: string[];\n excludedLibraryFilePrefix: string;\n coverageMemoryPagesMin: number;\n coverageMemoryPagesMax: number;\n excludedLibraryFileOverridePrefix?: string;\n debug?: boolean;\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 /** Absolute file path (normalized from source map during debug info extraction) */\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 * Array value accommodates generic monomorphizations that share a source position.\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' | 'projectRoot'> {\n excludedFiles?: string[];\n logPrefix?: string;\n}\n\nexport type InstrumentForCoverageFunc = (\n wasmBuffer: Buffer,\n sourceMapBuffer: Buffer,\n instrumentationOptions: InstrumentationOptions,\n logModule: string,\n logLabel: string,\n) => InstrumentationResult;\n\nexport interface NativeAddonInterface {\n instrumentForCoverage: InstrumentForCoverageFunc;\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 debugNative: false,\n debugCoverageExtract: false,\n _instrumentPoolInternals: 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 directly\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\n// poolOptions will be undefined for v4 in coverage provider, but it doesn't need them\nexport function getProjectSerializedOrGlobalConfig(ctx: Vitest): {\n config: AssemblyScriptProjectConfig;\n foundProjectSerializedConfig: boolean;\n v3PoolOptions?: ResolvedAssemblyScriptPoolOptions;\n} {\n let testProject: TestProject | undefined;\n let foundProjectSerializedConfig: boolean = false;\n let v3PoolOptions: ResolvedAssemblyScriptPoolOptions | undefined;\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 // @ts-ignore - we build with v4, but this is correct for v3 (has config.poolOptions)\n const maybeOptions: any = !!testProject ? testProject.config?.poolOptions?.assemblyScript : config?.poolOptions?.assemblyScript;\n if (maybeOptions) {\n v3PoolOptions = resolvePoolOptions(maybeOptions);\n }\n\n return {\n config,\n foundProjectSerializedConfig,\n v3PoolOptions\n };\n}"],"mappings":";;;;;AAoJA,MAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;ACjJD,MAAM,qCAAsH;CAC1H,OAAO;CACP,aAAa;CACb,sBAAsB;CACtB,0BAA0B;CAC1B,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;;AAKT,SAAgB,mCAAmC,KAIjD;CACA,IAAI;CACJ,IAAI,+BAAwC;CAC5C,IAAI;AAKJ,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;;;CAInC,MAAM,SAAS,CAAC,CAAC,cAAc;EAC7B,GAAG,YAAY;EACf,UAAU;GACR,GAAG,YAAY,iBAAiB;GAChC,GAAI,IAAI,OAAO;GAChB;EACF,GAAG;EACF,GAAG,IAAI;EACP,UAAU,IAAI,OAAO;EACtB;CAGD,MAAM,eAAoB,CAAC,CAAC,cAAc,YAAY,QAAQ,aAAa,iBAAiB,QAAQ,aAAa;AACjH,KAAI,aACF,iBAAgB,mBAAmB,aAAa;AAGlD,QAAO;EACL;EACA;EACA;EACD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-pool-assemblyscript",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "AssemblyScript testing with Vitest - Simple, fast, familiar, AS-native, with full coverage output",
|
|
5
5
|
"author": "Matt Ritter <matthew.d.ritter@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"binding.gyp",
|
|
58
58
|
"src/instrumentation/native/addon.cpp",
|
|
59
59
|
"scripts/setup-binaryen.js",
|
|
60
|
-
"scripts/install.js",
|
|
60
|
+
"scripts/install-native-addon.js",
|
|
61
61
|
"BINARYEN_VERSION",
|
|
62
62
|
"assembly"
|
|
63
63
|
],
|
|
@@ -73,27 +73,53 @@
|
|
|
73
73
|
},
|
|
74
74
|
"homepage": "https://github.com/themattspiral/vitest-pool-assemblyscript#readme",
|
|
75
75
|
"scripts": {
|
|
76
|
-
"build": "tsdown",
|
|
77
76
|
"//------------ Testing ------------": "",
|
|
78
77
|
"tc": "tsc --noEmit",
|
|
79
|
-
"test": "vitest run",
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"test:
|
|
78
|
+
"test": "vitest run && npm run test:meta:verify",
|
|
79
|
+
"test:pass": "vitest run",
|
|
80
|
+
"test:meta": "vitest run -c vitest.meta.config.ts",
|
|
81
|
+
"test:meta:verify": "cross-env RUN_CONTEXT=local vitest run -c vitest.meta-verify.config.ts",
|
|
82
|
+
"//---- install pool externally and run our tests from there ----": "",
|
|
83
83
|
"test:ext:setup": "node scripts/setup-test-external.js",
|
|
84
|
-
"test:ext:
|
|
85
|
-
"test:ext:pass": "node scripts/
|
|
86
|
-
"test:ext:pass:no-cov": "node scripts/
|
|
87
|
-
"test:ext:
|
|
88
|
-
"test:ext:
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
84
|
+
"test:ext:setup:v3": "cross-env VITEST_VERSION=3 node scripts/setup-test-external.js",
|
|
85
|
+
"test:ext:pass": "node scripts/run-vitest.js -c vitest.pass.config.ts",
|
|
86
|
+
"test:ext:pass:no-cov": "node scripts/run-vitest.js -c vitest.pass.config.ts --coverage.enabled=false",
|
|
87
|
+
"test:ext:meta": "node scripts/run-vitest.js -c vitest.meta.config.ts",
|
|
88
|
+
"test:ext:meta:verify": "cross-env RUN_CONTEXT=external vitest run -c vitest.meta-verify.config.ts",
|
|
89
|
+
"test:ext:meta:verify:no-cov": "cross-env RUN_CONTEXT=external_no_coverage vitest run -c vitest.meta-verify.config.ts",
|
|
90
|
+
"//---- test shortcuts ----": "",
|
|
91
|
+
"ptest": "npm run test:pass",
|
|
92
|
+
"mtest": "npm run test:meta",
|
|
93
|
+
"mvtest": "npm run test:meta:verify",
|
|
94
|
+
"//---- external test shortcuts ----": "",
|
|
95
|
+
"eptest": "npm run test:ext:setup && npm run test:ext:pass",
|
|
96
|
+
"emtest": "npm run test:ext:setup && npm run test:ext:meta",
|
|
97
|
+
"emvtest": "npm run test:ext:setup && npm run test:ext:meta:verify",
|
|
98
|
+
"//---- external v3 test shortcuts ----": "",
|
|
99
|
+
"ep3test": "npm run test:ext:setup:v3 && npm run test:ext:pass",
|
|
100
|
+
"em3test": "npm run test:ext:setup:v3 && npm run test:ext:meta",
|
|
101
|
+
"emv3test": "npm run test:ext:setup:v3 && npm run test:ext:meta:verify",
|
|
102
|
+
"//---- compile & test shortcuts ----": "",
|
|
103
|
+
"tcptest": "npm run tc && npm run build && npm run ptest",
|
|
104
|
+
"cptest": "npm run build && npm run ptest",
|
|
105
|
+
"cmtest": "npm run build && npm run mtest",
|
|
106
|
+
"cmvtest": "npm run build && npm run mvtest",
|
|
107
|
+
"//---- compile & external test shortcuts ----": "",
|
|
108
|
+
"ceptest": "npm run build && npm run eptest",
|
|
109
|
+
"cemtest": "npm run build && npm run emtest",
|
|
110
|
+
"cemvtest": "npm run build && npm run emvtest",
|
|
111
|
+
"//---- compile & external v3 test shortcuts ----": "",
|
|
112
|
+
"cep3test": "npm run build && npm run ep3test",
|
|
113
|
+
"cem3test": "npm run build && npm run em3test",
|
|
114
|
+
"cemv3test": "npm run build && npm run emv3test",
|
|
115
|
+
"//------------ Compile/Build TypeScript Pool ------------": "",
|
|
116
|
+
"build": "tsdown",
|
|
117
|
+
"//------------ Compile/Build Native Addon ------------": "",
|
|
93
118
|
"setup-binaryen": "node scripts/setup-binaryen.js",
|
|
94
119
|
"build:native": "node-gyp rebuild",
|
|
95
120
|
"build:prebuild": "prebuildify --napi --strip --tag-libc",
|
|
96
|
-
"
|
|
121
|
+
"//------------ npm Lifecycle ------------": "",
|
|
122
|
+
"install": "node scripts/install-native-addon.js"
|
|
97
123
|
},
|
|
98
124
|
"dependencies": {
|
|
99
125
|
"birpc": "^4.0.0",
|
|
@@ -123,6 +149,7 @@
|
|
|
123
149
|
"@vitest/utils": "^4.0.18",
|
|
124
150
|
"assemblyscript": "~0.28.9",
|
|
125
151
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
152
|
+
"cross-env": "^10.1.0",
|
|
126
153
|
"istanbul-lib-coverage": "^3.2.2",
|
|
127
154
|
"node-gyp": "^12.2.0",
|
|
128
155
|
"prebuildify": "^6.0.1",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|