vitest-pool-assemblyscript 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -35
- package/binding.gyp +6 -6
- package/dist/{compiler-CBBHCPAU.mjs → addon-interface-7FPjYh7J.mjs} +8 -138
- package/dist/addon-interface-7FPjYh7J.mjs.map +1 -0
- package/dist/{compile-runner-DrDjhdPG.mjs → compile-runner-C-05LdGX.mjs} +3 -3
- package/dist/{compile-runner-DrDjhdPG.mjs.map → compile-runner-C-05LdGX.mjs.map} +1 -1
- package/dist/compiler/transforms/strip-inline.mjs +1 -2
- package/dist/compiler/transforms/strip-inline.mjs.map +1 -1
- package/dist/compiler-YMrl5MY_.mjs +147 -0
- package/dist/compiler-YMrl5MY_.mjs.map +1 -0
- package/dist/config/index-v3.d.mts +2 -2
- package/dist/config/index.d.mts +3 -3
- package/dist/coverage-provider/index.mjs +4 -4
- package/dist/coverage-provider/index.mjs.map +1 -1
- package/dist/{custom-provider-options-39YrzdqD.d.mts → custom-provider-options-YTk1m7At.d.mts} +2 -2
- package/dist/{custom-provider-options-39YrzdqD.d.mts.map → custom-provider-options-YTk1m7At.d.mts.map} +1 -1
- package/dist/feature-check-CNyjFX9M.mjs +82 -0
- package/dist/feature-check-CNyjFX9M.mjs.map +1 -0
- package/dist/index-internal.d.mts +1 -1
- package/dist/index-internal.d.mts.map +1 -1
- package/dist/index-internal.mjs +2 -1
- package/dist/index.d.mts +2 -2
- package/dist/{load-user-imports-BIQvqM7K.mjs → load-user-imports-B3Iy_K8k.mjs} +2 -3
- package/dist/{load-user-imports-BIQvqM7K.mjs.map → load-user-imports-B3Iy_K8k.mjs.map} +1 -1
- package/dist/{pool-runner-init-DVk4hB5d.d.mts → pool-runner-init-CvnB0-iN.d.mts} +2 -2
- package/dist/pool-runner-init-CvnB0-iN.d.mts.map +1 -0
- package/dist/pool-thread/compile-worker-thread.d.mts +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.d.mts +1 -1
- package/dist/pool-thread/test-worker-thread.mjs +4 -4
- package/dist/pool-thread/test-worker-thread.mjs.map +1 -1
- package/dist/pool-thread/v3-tinypool-thread.d.mts +1 -1
- package/dist/pool-thread/v3-tinypool-thread.mjs +6 -6
- package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -1
- package/dist/resolve-config-BFNr7LW7.mjs.map +1 -1
- package/dist/{test-runner-DNGLk7lx.mjs → test-runner-WF857_Bk.mjs} +2 -2
- package/dist/{test-runner-DNGLk7lx.mjs.map → test-runner-WF857_Bk.mjs.map} +1 -1
- package/dist/{types-6ta3lLJM.d.mts → types-D0nprJo1.d.mts} +1 -1
- package/dist/types-D0nprJo1.d.mts.map +1 -0
- package/package.json +17 -16
- package/prebuilds/darwin-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/darwin-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/linux-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/linux-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/linux-x64/vitest-pool-assemblyscript.musl.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 +53 -16
- package/src/{native-instrumentation → instrumentation/native}/addon.cpp +8 -8
- package/dist/compiler-CBBHCPAU.mjs.map +0 -1
- package/dist/node-check-CcKfvjM4.mjs +0 -16
- package/dist/node-check-CcKfvjM4.mjs.map +0 -1
- package/dist/pool-runner-init-DVk4hB5d.d.mts.map +0 -1
- package/dist/types-6ta3lLJM.d.mts.map +0 -1
|
@@ -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// 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\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":";;;;;AAwIA,MAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;ACrID,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-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,6 +1,6 @@
|
|
|
1
1
|
import { debug } from "./debug-Cm1VFmaz.mjs";
|
|
2
2
|
import { checkFailsAndInvertResult, finalizeSuiteResult, flagTestFinalized, getRunnableTasks, getTaskLogPrefix, isSuiteOwnFile, resetTestForRetry, setSuitePrepareResult, setTestResultForTestPrepare, shouldRetryTask, updateSuiteFinishedResult, updateTestResultAfterRun } from "./vitest-tasks--ow4pacR.mjs";
|
|
3
|
-
import { executeWASMTest, reportSuiteFinished, reportSuitePrepare, reportTestFinished, reportTestPrepare, reportTestRetried, reportUserConsoleLogs } from "./load-user-imports-
|
|
3
|
+
import { executeWASMTest, reportSuiteFinished, reportSuitePrepare, reportTestFinished, reportTestPrepare, reportTestRetried, reportUserConsoleLogs } from "./load-user-imports-B3Iy_K8k.mjs";
|
|
4
4
|
import { mergeCoverageData } from "./coverage-merge-CBXkpM1O.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/pool-thread/runner/test-runner.ts
|
|
@@ -139,4 +139,4 @@ async function runSuite(rpc, port, base, collectCoverage, compilation, suite, lo
|
|
|
139
139
|
|
|
140
140
|
//#endregion
|
|
141
141
|
export { runSuite };
|
|
142
|
-
//# sourceMappingURL=test-runner-
|
|
142
|
+
//# sourceMappingURL=test-runner-WF857_Bk.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner-DNGLk7lx.mjs","names":[],"sources":["../src/pool-thread/runner/test-runner.ts"],"sourcesContent":["/**\n * Worker thread test runner logic for AssemblyScript Pool\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { File, Suite, Task, Test } from '@vitest/runner/types';\nimport type { SerializedDiffOptions } from '@vitest/utils/diff';\n\nimport type {\n AssemblyScriptConsoleLog,\n AssemblyScriptConsoleLogHandler,\n AssemblyScriptSuiteTaskMeta,\n AssemblyScriptTestTaskMeta,\n ResolvedAssemblyScriptPoolOptions,\n TestExecutionEnd,\n TestExecutionStart,\n ThreadImports,\n VitestVersion,\n WASMCompilation,\n WorkerRPC,\n} from '../../types/types.js';\nimport { AS_POOL_WORKER_MSG_FLAG } from '../../types/constants.js';\nimport { executeWASMTest } from '../../wasm-executor/index.js';\nimport { debug } from '../../util/debug.js';\nimport {\n reportTestPrepare,\n reportTestFinished,\n reportTestRetried,\n reportUserConsoleLogs,\n reportSuitePrepare,\n reportSuiteFinished,\n} from '../rpc-reporter.js';\nimport {\n checkFailsAndInvertResult,\n finalizeSuiteResult,\n flagTestFinalized,\n getRunnableTasks,\n getTaskLogPrefix,\n resetTestForRetry,\n setSuitePrepareResult,\n setTestResultForTestPrepare,\n shouldRetryTask,\n updateSuiteFinishedResult,\n updateTestResultAfterRun,\n isSuiteOwnFile\n} from '../../util/vitest-tasks.js';\nimport { mergeCoverageData } from '../../coverage-provider/coverage-merge.js';\n\nasync function bailIfNeeded(\n rpc: WorkerRPC,\n bailConfig: number | undefined,\n testWithResult: Test,\n logPrefix: string,\n logModule: string,\n): Promise<void> {\n if (bailConfig && testWithResult.result?.state !== 'pass') {\n const previousFailures = await rpc.getCountOfFailedTests();\n const currentFailures = 1 + previousFailures;\n\n if (currentFailures >= bailConfig) {\n debug(`${logPrefix} bailing: ${currentFailures} failures >= ${bailConfig} to bail`);\n debug(`[${logModule}] -------- BAIL! ${currentFailures} failures >= ${bailConfig} to bail --------`);\n return rpc.onCancel('test-failure');\n }\n }\n}\n\nasync function postProcessTestResult(\n rpc: WorkerRPC,\n bailConfig: number | undefined,\n testWithResult: Test,\n logPrefix: string,\n logModule: string,\n): Promise<void> {\n // invert result if test configured as 'fails'\n checkFailsAndInvertResult(testWithResult, logPrefix);\n\n // bail now if this is a failed test above bail threshold\n return bailIfNeeded(rpc, bailConfig, testWithResult, logPrefix, logModule);\n}\n\nfunction notifyTestStart(port: MessagePort, test: Test): void {\n port.postMessage({\n executionStart: Date.now(),\n test,\n type: 'execution-start',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestExecutionStart);\n}\n\nfunction notifyTestEnd(port: MessagePort, test: Test): void {\n port.postMessage({\n executionEnd: Date.now(),\n testTaskId: test.id,\n type: 'execution-end',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestExecutionEnd);\n}\n\nasync function runTest(\n rpc: WorkerRPC,\n port: MessagePort,\n base: string,\n collectCoverage: boolean,\n compilation: WASMCompilation,\n test: Test,\n logModule: string,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n threadImports: ThreadImports,\n bail?: number,\n diffOptions?: SerializedDiffOptions,\n): Promise<void> {\n const testLogPrefix = getTaskLogPrefix(logModule, base, test);\n const logMessages: AssemblyScriptConsoleLog[] = [];\n const handleLog: AssemblyScriptConsoleLogHandler = (msg: string, isError: boolean = false): void => {\n logMessages.push({ msg, time: Date.now(), isError });\n };\n\n const executionStart = Date.now();\n\n let thisRunIsARetry: boolean = false;\n let testPreparePromise: Promise<void> = Promise.resolve();\n \n if (!test.retry || !test.result) {\n debug(`${testLogPrefix} - Beginning test run`);\n\n // first/only attempt: create test result and report test-prepare\n setTestResultForTestPrepare(test, executionStart);\n testPreparePromise = reportTestPrepare(rpc, test, logModule, base);\n } else if (test.retry && test.result ) {\n debug(`${testLogPrefix} - Beginning test retry run`);\n thisRunIsARetry = true;\n\n // this is a retry, reset the result state and meta\n resetTestForRetry(test, executionStart);\n }\n \n // inform pool of test task start so it can enforce timeouts\n notifyTestStart(port, test);\n\n const [_reported, { testTimings }] = await Promise.all([\n testPreparePromise,\n executeWASMTest(\n test,\n compilation,\n base,\n poolOptions,\n collectCoverage,\n handleLog,\n logModule,\n threadImports,\n diffOptions\n )\n ]);\n\n // inform pool of test task end to stop timeout if under threshold\n notifyTestEnd(port, test);\n\n // update run->pass if appropriate, accumulate duration using executor timings\n updateTestResultAfterRun(test, testTimings);\n\n let willRetry = shouldRetryTask(test);\n\n await Promise.all([\n reportUserConsoleLogs(rpc, logMessages, logModule, base, test),\n\n willRetry ? reportTestRetried(rpc, test, logModule, base) : Promise.resolve(),\n ]);\n\n if (thisRunIsARetry) {\n debug(`${testLogPrefix} - Completed test retry run`);\n return;\n }\n\n // non-timeout retry handling\n while (willRetry) {\n // increment the retry count\n test.result!.retryCount = (test.result?.retryCount ?? 0) + 1;\n\n debug(`${testLogPrefix} - Retrying after failure`\n + ` | Retry ${test.result?.retryCount || 0} / ${test.retry} ` \n + ` | ${test.result?.errors?.length ?? 0} errors`\n );\n\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n test, logModule, poolOptions, threadImports, bail, diffOptions\n );\n\n willRetry = shouldRetryTask(test);\n\n if (!willRetry) {\n debug(`${testLogPrefix} - Max retries ${test.result?.retryCount || 0} / ${test.retry} ` \n + ` | ${test.result?.errors?.length ?? 0} errors`\n );\n }\n }\n\n await Promise.all([\n // as needed: invert if `fails`, bail\n postProcessTestResult(rpc, bail, test, testLogPrefix, logModule),\n\n reportTestFinished(rpc, test, logModule, base),\n ]);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n flagTestFinalized(test);\n\n debug(`${testLogPrefix} - Completed test run`);\n}\n\nexport async function runSuite(\n rpc: WorkerRPC,\n port: MessagePort,\n base: string,\n collectCoverage: boolean,\n compilation: WASMCompilation,\n suite: Suite | File,\n logModule: string,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n threadImports: ThreadImports,\n vitestVersion: VitestVersion,\n bail?: number,\n diffOptions?: SerializedDiffOptions,\n timedOutTest?: Test,\n): Promise<Suite> {\n const suiteStart = performance.now();\n const suiteMeta = suite.meta as AssemblyScriptSuiteTaskMeta;\n const suiteLogPrefix = getTaskLogPrefix(logModule, base, suite);\n const isTimedOutTestInSuite: boolean = timedOutTest?.suite?.id === suite.id;\n\n if (suiteMeta.resultFinal) {\n debug(`${suiteLogPrefix} - Skipping completed suite | state: \"${suite.result?.state}\"`);\n\n return suite;\n } else {\n const threadRestartTime = Date.now() - ((timedOutTest?.meta as AssemblyScriptTestTaskMeta)?.lastTimeoutTerminationTime ?? 0);\n const showRestart = !!timedOutTest && isSuiteOwnFile(suite)\n debug(`${showRestart ? `(thread resumed in ${threadRestartTime} ms) ` : ''}${suiteLogPrefix} - runSuite ${!!timedOutTest\n ? `resuming after timeout \"${timedOutTest.name}\" | isTestInSuite: ${isTimedOutTestInSuite}`\n : 'beginning'\n }`);\n }\n\n if (!suiteMeta.suitePreparedSent) {\n setSuitePrepareResult(suite);\n await reportSuitePrepare(rpc, suite, logModule, base);\n\n // ensure suite-prepare will only be sent once if a test\n // times out and the file worker thread gets re-launched\n suiteMeta.suitePreparedSent = true;\n }\n\n // restore suite coverage collected so far from the timed out test, if provided.\n // otherwise create a suite-level coverage data object to aggregate all subtask coverage\n if (isTimedOutTestInSuite) {\n suiteMeta.coverageData = (timedOutTest!.suite!.meta as AssemblyScriptSuiteTaskMeta).coverageData;\n \n const coverageKeys: number = Object.keys(suiteMeta.coverageData ?? {}).length;\n debug(`${suiteLogPrefix} - Restored suite coverage data after timeout (${coverageKeys} unique positions)`);\n } {\n // initialize aggregated coverage data for suite, which gets updated as each subtask completes\n suiteMeta.coverageData = { hitCountsByFileAndPosition: {} };\n }\n\n let tasksToRun: Task[] = getRunnableTasks(suite);\n debug(`${suiteLogPrefix} - Runnable tasks:`, tasksToRun.length);\n\n for (const task of tasksToRun) {\n if (task.type === 'suite') {\n const suiteTaskMeta = task.meta as AssemblyScriptSuiteTaskMeta;\n\n await runSuite(\n rpc, port, base, collectCoverage, compilation, task, logModule,\n poolOptions, threadImports, vitestVersion, bail, diffOptions, timedOutTest\n );\n\n // merge suite task coverage into parent suite coverage\n if (suiteMeta.coverageData && suiteTaskMeta.coverageData) {\n mergeCoverageData(suiteMeta.coverageData, suiteTaskMeta.coverageData);\n }\n \n } else {\n const testLogPrefix = getTaskLogPrefix(logModule, base, task);\n const testTaskMeta = task.meta as AssemblyScriptTestTaskMeta;\n\n const testCompleted = testTaskMeta.resultFinal;\n const testTimedOutPreviously = !!timedOutTest && task.id === timedOutTest.id;\n\n if (testCompleted) {\n debug(`${testLogPrefix} - Skipping completed test | state: \"${task.result?.state}\"`);\n } else if (testTimedOutPreviously) {\n if (shouldRetryTask(task)) {\n const previousRetryCount = task.result?.retryCount ?? 0;\n const newRetryCount = previousRetryCount + 1;\n\n debug(`${testLogPrefix} - Retrying after test timeout`\n + ` | retry attempt ${newRetryCount} / ${task.retry} ` \n + ` | ${task.result?.errors?.length ?? 0} errors`\n + ` | state: \"${task.result?.state}\"`\n );\n \n // report retried for the previous timeout failure, which won't\n // have been reported because the thread was killed to timeout\n await reportTestRetried(rpc, task, logModule, base);\n\n // increment the retry count (after reporting retried)\n task.result!.retryCount = newRetryCount;\n \n // retry timed out test\n // - if it passes, process as normal\n // - if it fails again, it will end up in the else block below\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n task, logModule, poolOptions, threadImports, bail, diffOptions\n );\n } else {\n debug(`${testLogPrefix} - Timed-out test has no retries left`\n + ` | retries attempted ${task.result?.retryCount || 0} / ${task.retry} ` \n + ` | ${task.result?.errors?.length ?? 0} errors`\n + ` | state: \"${task.result?.state}\"`\n );\n\n await Promise.all([\n // as needed: invert if `fails`, bail\n postProcessTestResult(rpc, bail, task, testLogPrefix, logModule),\n \n reportTestFinished(rpc, task, logModule, base),\n ]);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n flagTestFinalized(task);\n\n debug(`${testLogPrefix} - Completed timed out test run`);\n }\n } else {\n debug(`${testLogPrefix} - Running test task | state: \"${task.result?.state}\"`);\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n task, logModule, poolOptions, threadImports, bail, diffOptions\n );\n }\n\n // merge test coverage into suite coverage\n if (suiteMeta.coverageData && testTaskMeta.coverageData) {\n mergeCoverageData(suiteMeta.coverageData, testTaskMeta.coverageData);\n }\n }\n }\n\n // update suite result based on its tasks, report coverage data, report suite task result\n updateSuiteFinishedResult(suite, suiteLogPrefix);\n await reportSuiteFinished(rpc, suite, logModule, base, vitestVersion);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n finalizeSuiteResult(suite);\n\n const suiteTime = performance.now() - suiteStart;\n debug(`${suiteLogPrefix} - Suite Run Complete | TIMING ${suiteTime.toFixed(2)} ms`);\n\n return suite;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"test-runner-WF857_Bk.mjs","names":[],"sources":["../src/pool-thread/runner/test-runner.ts"],"sourcesContent":["/**\n * Worker thread test runner logic for AssemblyScript Pool\n */\n\nimport type { MessagePort } from 'node:worker_threads';\nimport type { File, Suite, Task, Test } from '@vitest/runner/types';\nimport type { SerializedDiffOptions } from '@vitest/utils/diff';\n\nimport type {\n AssemblyScriptConsoleLog,\n AssemblyScriptConsoleLogHandler,\n AssemblyScriptSuiteTaskMeta,\n AssemblyScriptTestTaskMeta,\n ResolvedAssemblyScriptPoolOptions,\n TestExecutionEnd,\n TestExecutionStart,\n ThreadImports,\n VitestVersion,\n WASMCompilation,\n WorkerRPC,\n} from '../../types/types.js';\nimport { AS_POOL_WORKER_MSG_FLAG } from '../../types/constants.js';\nimport { executeWASMTest } from '../../wasm-executor/index.js';\nimport { debug } from '../../util/debug.js';\nimport {\n reportTestPrepare,\n reportTestFinished,\n reportTestRetried,\n reportUserConsoleLogs,\n reportSuitePrepare,\n reportSuiteFinished,\n} from '../rpc-reporter.js';\nimport {\n checkFailsAndInvertResult,\n finalizeSuiteResult,\n flagTestFinalized,\n getRunnableTasks,\n getTaskLogPrefix,\n resetTestForRetry,\n setSuitePrepareResult,\n setTestResultForTestPrepare,\n shouldRetryTask,\n updateSuiteFinishedResult,\n updateTestResultAfterRun,\n isSuiteOwnFile\n} from '../../util/vitest-tasks.js';\nimport { mergeCoverageData } from '../../coverage-provider/coverage-merge.js';\n\nasync function bailIfNeeded(\n rpc: WorkerRPC,\n bailConfig: number | undefined,\n testWithResult: Test,\n logPrefix: string,\n logModule: string,\n): Promise<void> {\n if (bailConfig && testWithResult.result?.state !== 'pass') {\n const previousFailures = await rpc.getCountOfFailedTests();\n const currentFailures = 1 + previousFailures;\n\n if (currentFailures >= bailConfig) {\n debug(`${logPrefix} bailing: ${currentFailures} failures >= ${bailConfig} to bail`);\n debug(`[${logModule}] -------- BAIL! ${currentFailures} failures >= ${bailConfig} to bail --------`);\n return rpc.onCancel('test-failure');\n }\n }\n}\n\nasync function postProcessTestResult(\n rpc: WorkerRPC,\n bailConfig: number | undefined,\n testWithResult: Test,\n logPrefix: string,\n logModule: string,\n): Promise<void> {\n // invert result if test configured as 'fails'\n checkFailsAndInvertResult(testWithResult, logPrefix);\n\n // bail now if this is a failed test above bail threshold\n return bailIfNeeded(rpc, bailConfig, testWithResult, logPrefix, logModule);\n}\n\nfunction notifyTestStart(port: MessagePort, test: Test): void {\n port.postMessage({\n executionStart: Date.now(),\n test,\n type: 'execution-start',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestExecutionStart);\n}\n\nfunction notifyTestEnd(port: MessagePort, test: Test): void {\n port.postMessage({\n executionEnd: Date.now(),\n testTaskId: test.id,\n type: 'execution-end',\n [AS_POOL_WORKER_MSG_FLAG]: true\n } satisfies TestExecutionEnd);\n}\n\nasync function runTest(\n rpc: WorkerRPC,\n port: MessagePort,\n base: string,\n collectCoverage: boolean,\n compilation: WASMCompilation,\n test: Test,\n logModule: string,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n threadImports: ThreadImports,\n bail?: number,\n diffOptions?: SerializedDiffOptions,\n): Promise<void> {\n const testLogPrefix = getTaskLogPrefix(logModule, base, test);\n const logMessages: AssemblyScriptConsoleLog[] = [];\n const handleLog: AssemblyScriptConsoleLogHandler = (msg: string, isError: boolean = false): void => {\n logMessages.push({ msg, time: Date.now(), isError });\n };\n\n const executionStart = Date.now();\n\n let thisRunIsARetry: boolean = false;\n let testPreparePromise: Promise<void> = Promise.resolve();\n \n if (!test.retry || !test.result) {\n debug(`${testLogPrefix} - Beginning test run`);\n\n // first/only attempt: create test result and report test-prepare\n setTestResultForTestPrepare(test, executionStart);\n testPreparePromise = reportTestPrepare(rpc, test, logModule, base);\n } else if (test.retry && test.result ) {\n debug(`${testLogPrefix} - Beginning test retry run`);\n thisRunIsARetry = true;\n\n // this is a retry, reset the result state and meta\n resetTestForRetry(test, executionStart);\n }\n \n // inform pool of test task start so it can enforce timeouts\n notifyTestStart(port, test);\n\n const [_reported, { testTimings }] = await Promise.all([\n testPreparePromise,\n executeWASMTest(\n test,\n compilation,\n base,\n poolOptions,\n collectCoverage,\n handleLog,\n logModule,\n threadImports,\n diffOptions\n )\n ]);\n\n // inform pool of test task end to stop timeout if under threshold\n notifyTestEnd(port, test);\n\n // update run->pass if appropriate, accumulate duration using executor timings\n updateTestResultAfterRun(test, testTimings);\n\n let willRetry = shouldRetryTask(test);\n\n await Promise.all([\n reportUserConsoleLogs(rpc, logMessages, logModule, base, test),\n\n willRetry ? reportTestRetried(rpc, test, logModule, base) : Promise.resolve(),\n ]);\n\n if (thisRunIsARetry) {\n debug(`${testLogPrefix} - Completed test retry run`);\n return;\n }\n\n // non-timeout retry handling\n while (willRetry) {\n // increment the retry count\n test.result!.retryCount = (test.result?.retryCount ?? 0) + 1;\n\n debug(`${testLogPrefix} - Retrying after failure`\n + ` | Retry ${test.result?.retryCount || 0} / ${test.retry} ` \n + ` | ${test.result?.errors?.length ?? 0} errors`\n );\n\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n test, logModule, poolOptions, threadImports, bail, diffOptions\n );\n\n willRetry = shouldRetryTask(test);\n\n if (!willRetry) {\n debug(`${testLogPrefix} - Max retries ${test.result?.retryCount || 0} / ${test.retry} ` \n + ` | ${test.result?.errors?.length ?? 0} errors`\n );\n }\n }\n\n await Promise.all([\n // as needed: invert if `fails`, bail\n postProcessTestResult(rpc, bail, test, testLogPrefix, logModule),\n\n reportTestFinished(rpc, test, logModule, base),\n ]);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n flagTestFinalized(test);\n\n debug(`${testLogPrefix} - Completed test run`);\n}\n\nexport async function runSuite(\n rpc: WorkerRPC,\n port: MessagePort,\n base: string,\n collectCoverage: boolean,\n compilation: WASMCompilation,\n suite: Suite | File,\n logModule: string,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n threadImports: ThreadImports,\n vitestVersion: VitestVersion,\n bail?: number,\n diffOptions?: SerializedDiffOptions,\n timedOutTest?: Test,\n): Promise<Suite> {\n const suiteStart = performance.now();\n const suiteMeta = suite.meta as AssemblyScriptSuiteTaskMeta;\n const suiteLogPrefix = getTaskLogPrefix(logModule, base, suite);\n const isTimedOutTestInSuite: boolean = timedOutTest?.suite?.id === suite.id;\n\n if (suiteMeta.resultFinal) {\n debug(`${suiteLogPrefix} - Skipping completed suite | state: \"${suite.result?.state}\"`);\n\n return suite;\n } else {\n const threadRestartTime = Date.now() - ((timedOutTest?.meta as AssemblyScriptTestTaskMeta)?.lastTimeoutTerminationTime ?? 0);\n const showRestart = !!timedOutTest && isSuiteOwnFile(suite)\n debug(`${showRestart ? `(thread resumed in ${threadRestartTime} ms) ` : ''}${suiteLogPrefix} - runSuite ${!!timedOutTest\n ? `resuming after timeout \"${timedOutTest.name}\" | isTestInSuite: ${isTimedOutTestInSuite}`\n : 'beginning'\n }`);\n }\n\n if (!suiteMeta.suitePreparedSent) {\n setSuitePrepareResult(suite);\n await reportSuitePrepare(rpc, suite, logModule, base);\n\n // ensure suite-prepare will only be sent once if a test\n // times out and the file worker thread gets re-launched\n suiteMeta.suitePreparedSent = true;\n }\n\n // restore suite coverage collected so far from the timed out test, if provided.\n // otherwise create a suite-level coverage data object to aggregate all subtask coverage\n if (isTimedOutTestInSuite) {\n suiteMeta.coverageData = (timedOutTest!.suite!.meta as AssemblyScriptSuiteTaskMeta).coverageData;\n \n const coverageKeys: number = Object.keys(suiteMeta.coverageData ?? {}).length;\n debug(`${suiteLogPrefix} - Restored suite coverage data after timeout (${coverageKeys} unique positions)`);\n } {\n // initialize aggregated coverage data for suite, which gets updated as each subtask completes\n suiteMeta.coverageData = { hitCountsByFileAndPosition: {} };\n }\n\n let tasksToRun: Task[] = getRunnableTasks(suite);\n debug(`${suiteLogPrefix} - Runnable tasks:`, tasksToRun.length);\n\n for (const task of tasksToRun) {\n if (task.type === 'suite') {\n const suiteTaskMeta = task.meta as AssemblyScriptSuiteTaskMeta;\n\n await runSuite(\n rpc, port, base, collectCoverage, compilation, task, logModule,\n poolOptions, threadImports, vitestVersion, bail, diffOptions, timedOutTest\n );\n\n // merge suite task coverage into parent suite coverage\n if (suiteMeta.coverageData && suiteTaskMeta.coverageData) {\n mergeCoverageData(suiteMeta.coverageData, suiteTaskMeta.coverageData);\n }\n \n } else {\n const testLogPrefix = getTaskLogPrefix(logModule, base, task);\n const testTaskMeta = task.meta as AssemblyScriptTestTaskMeta;\n\n const testCompleted = testTaskMeta.resultFinal;\n const testTimedOutPreviously = !!timedOutTest && task.id === timedOutTest.id;\n\n if (testCompleted) {\n debug(`${testLogPrefix} - Skipping completed test | state: \"${task.result?.state}\"`);\n } else if (testTimedOutPreviously) {\n if (shouldRetryTask(task)) {\n const previousRetryCount = task.result?.retryCount ?? 0;\n const newRetryCount = previousRetryCount + 1;\n\n debug(`${testLogPrefix} - Retrying after test timeout`\n + ` | retry attempt ${newRetryCount} / ${task.retry} ` \n + ` | ${task.result?.errors?.length ?? 0} errors`\n + ` | state: \"${task.result?.state}\"`\n );\n \n // report retried for the previous timeout failure, which won't\n // have been reported because the thread was killed to timeout\n await reportTestRetried(rpc, task, logModule, base);\n\n // increment the retry count (after reporting retried)\n task.result!.retryCount = newRetryCount;\n \n // retry timed out test\n // - if it passes, process as normal\n // - if it fails again, it will end up in the else block below\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n task, logModule, poolOptions, threadImports, bail, diffOptions\n );\n } else {\n debug(`${testLogPrefix} - Timed-out test has no retries left`\n + ` | retries attempted ${task.result?.retryCount || 0} / ${task.retry} ` \n + ` | ${task.result?.errors?.length ?? 0} errors`\n + ` | state: \"${task.result?.state}\"`\n );\n\n await Promise.all([\n // as needed: invert if `fails`, bail\n postProcessTestResult(rpc, bail, task, testLogPrefix, logModule),\n \n reportTestFinished(rpc, task, logModule, base),\n ]);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n flagTestFinalized(task);\n\n debug(`${testLogPrefix} - Completed timed out test run`);\n }\n } else {\n debug(`${testLogPrefix} - Running test task | state: \"${task.result?.state}\"`);\n await runTest(\n rpc, port, base, collectCoverage, compilation,\n task, logModule, poolOptions, threadImports, bail, diffOptions\n );\n }\n\n // merge test coverage into suite coverage\n if (suiteMeta.coverageData && testTaskMeta.coverageData) {\n mergeCoverageData(suiteMeta.coverageData, testTaskMeta.coverageData);\n }\n }\n }\n\n // update suite result based on its tasks, report coverage data, report suite task result\n updateSuiteFinishedResult(suite, suiteLogPrefix);\n await reportSuiteFinished(rpc, suite, logModule, base, vitestVersion);\n\n // ensure completed test will not be run again if another test\n // times out later and the file worker thread gets re-launched\n finalizeSuiteResult(suite);\n\n const suiteTime = performance.now() - suiteStart;\n debug(`${suiteLogPrefix} - Suite Run Complete | TIMING ${suiteTime.toFixed(2)} ms`);\n\n return suite;\n}\n"],"mappings":"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"}
|
|
@@ -234,4 +234,4 @@ interface ProcessPoolRunFileTask {
|
|
|
234
234
|
}
|
|
235
235
|
//#endregion
|
|
236
236
|
export { AssemblyScriptCompilerOptions, AssemblyScriptCompilerResult, AssemblyScriptPoolOptions, HybridProviderOptions, ProcessPoolRunFileTask, RunCompileAndDiscoverTask, RunTestsTask, ThreadSpec, WasmImportsFactory, WasmImportsFactoryInfo };
|
|
237
|
-
//# sourceMappingURL=types-
|
|
237
|
+
//# sourceMappingURL=types-D0nprJo1.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-D0nprJo1.d.mts","names":[],"sources":["../src/types/types.ts"],"mappings":";;;;;;;;;;;UAsEiB,yBAAA;;EAEf,KAAA;EACA,WAAA;EACA,oBAAA;EAuEF;EApEE,wBAAA;;;;;;;;;AA2IF;EAhIE,WAAA;;;;;;;;EASA,YAAA;EAEA,0BAAA;EACA,sBAAA;EAEA,sBAAA;EACA,kBAAA;EAEA,kBAAA;EAEA,kBAAA;AAAA;;;;UAMe,qBAAA;EACf,QAAA;EACA,oBAAA;EAEA,aAAA;EAgHA;AAGF;;;;;;;EAzGE,qBAAA;;;;;;EAOA,qBAAA;AAAA;AAAA,UAGe,sBAAA;EACf,MAAA,EAAQ,WAAA,CAAY,MAAA;EACpB,MAAA,EAAQ,WAAA,CAAY,MAAA;EACpB,KAAA;IACE,UAAA,GAAa,SAAA;EAAA;AAAA;AAAA,KAIL,kBAAA,IAAsB,UAAA,EAAY,sBAAA,KAA2B,WAAA,CAAY,OAAA;AAAA,UAuEpE,6BAAA;EACf,gBAAA;EACA,WAAA;EACA,sBAAA,GAAyB,sBAAA;EACzB,WAAA;EACA,UAAA;AAAA;AAAA,UAGe,4BAAA;EACf,MAAA,EAAQ,UAAA;EACR,SAAA;EACA,SAAA,GAAY,eAAA;EACZ,cAAA;EACA,aAAA;AAAA;AAAA,UAGe,sBAAA;;EAEf,WAAA;;EAEA,qBAAA;EACA,yBAAA;EACA,sBAAA;EACA,sBAAA;EACA,iCAAA;EACA,KAAA;AAAA;;;;AA0aF;;;UAjZiB,cAAA;;EAEf,QAAA;EACA,IAAA;EACA,MAAA;AAAA;;;AAsaF;UAlWiB,mBAAA;;EAEf,gBAAA;;EAEA,qBAAA;AAAA;;;;;;;UASe,mBAAA;;EAEf,IAAA;;EAEA,QAAA,GAAW,cAAA;;EAEX,QAAA;;EAEA,WAAA;;;;;EAKA,mBAAA;AAAA;;;;;;;UASe,mBAAA;;EAEf,KAAA;;EAEA,iBAAA;;EAEA,QAAA,EAAU,mBAAA;;;;;EAKV,mBAAA;AAAA;;;;UAMe,iBAAA;;EAEf,SAAA;;EAEA,IAAA;;;;;EAKA,sBAAA,EAAwB,cAAA;;EAExB,mBAAA;;EAEA,WAAA,EAAa,mBAAA;;EAEb,WAAA,EAAa,mBAAA;AAAA;;;;;;;UASE,eAAA;;EAEf,gBAAA;;;;;;EAMA,0BAAA,EAA4B,MAAA,SAAe,MAAA,SAAe,iBAAA;EAE1D,yBAAA;AAAA;AAAA,UAsOe,eAAA;EACf,QAAA;EACA,MAAA,EAAQ,UAAA;EACR,SAAA;EACA,SAAA,GAAY,eAAA;AAAA;AAAA,UASG,UAAA;EACf,IAAA,EAAM,IAAA;EACN,WAAA,GAAc,eAAA;AAAA;AAAA,UAGC,yBAAA;EACf,aAAA;EACA,QAAA;EACA,IAAA,EAAM,WAAA;EACN,IAAA,EAAM,IAAA;EACN,MAAA,EAAQ,gBAAA;EACR,kBAAA;AAAA;AAAA,UAGe,YAAA;EACf,aAAA;EACA,QAAA;EACA,IAAA,EAAM,WAAA;EACN,IAAA,EAAM,IAAA;EACN,WAAA,EAAa,eAAA;EACb,MAAA,EAAQ,gBAAA;EACR,kBAAA;EACA,YAAA,GAAe,IAAA;AAAA;AAAA,UAGA,sBAAA;EACf,aAAA;EACA,IAAA,EAAM,WAAA;EACN,IAAA,EAAM,IAAA;EACN,MAAA,EAAQ,gBAAA;EACR,kBAAA;EACA,YAAA,GAAe,IAAA;EACf,mBAAA,GAAsB,eAAA;AAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-pool-assemblyscript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
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",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"dist",
|
|
56
56
|
"prebuilds",
|
|
57
57
|
"binding.gyp",
|
|
58
|
-
"src/
|
|
58
|
+
"src/instrumentation/native/addon.cpp",
|
|
59
59
|
"scripts/setup-binaryen.js",
|
|
60
60
|
"scripts/install.js",
|
|
61
61
|
"BINARYEN_VERSION",
|
|
@@ -80,13 +80,15 @@
|
|
|
80
80
|
"ctest": "npm run build && vitest run",
|
|
81
81
|
"tctest": "npm run tc && npm run build && vitest run",
|
|
82
82
|
"test:watch": "vitest",
|
|
83
|
-
"test:
|
|
84
|
-
"
|
|
85
|
-
"test:
|
|
86
|
-
"test:
|
|
87
|
-
"test:
|
|
88
|
-
"test:
|
|
89
|
-
"
|
|
83
|
+
"test:ext:setup": "node scripts/setup-test-external.js",
|
|
84
|
+
"test:ext:run": "node scripts/run-test-external.js",
|
|
85
|
+
"test:ext:pass": "node scripts/setup-test-external.js && node scripts/run-test-external.js -c vitest.pass.config.ts",
|
|
86
|
+
"test:ext:pass:no-cov": "node scripts/setup-test-external.js && node scripts/run-test-external.js -c vitest.pass.config.ts --coverage.enabled=false",
|
|
87
|
+
"test:ext:err": "node scripts/setup-test-external.js && node scripts/run-test-external.js -c vitest.errors.config.ts",
|
|
88
|
+
"test:ext:all": "node scripts/setup-test-external.js && node scripts/run-test-external.js",
|
|
89
|
+
"etestp": "npm run test:ext:pass",
|
|
90
|
+
"eteste": "npm run test:ext:err",
|
|
91
|
+
"etest": "npm run test:ext:all",
|
|
90
92
|
"//------------ Native Addon ------------": "",
|
|
91
93
|
"setup-binaryen": "node scripts/setup-binaryen.js",
|
|
92
94
|
"build:native": "node-gyp rebuild",
|
|
@@ -96,9 +98,9 @@
|
|
|
96
98
|
"dependencies": {
|
|
97
99
|
"birpc": "^4.0.0",
|
|
98
100
|
"node-addon-api": "^8.5.0",
|
|
99
|
-
"node-gyp-build": "^4.8.
|
|
100
|
-
"source-map": "
|
|
101
|
-
"tinyglobby": "
|
|
101
|
+
"node-gyp-build": "^4.8.4",
|
|
102
|
+
"source-map": "~0.7.6",
|
|
103
|
+
"tinyglobby": "~0.2.15",
|
|
102
104
|
"tinypool": "^2.1.0",
|
|
103
105
|
"tinyrainbow": "^3.0.3"
|
|
104
106
|
},
|
|
@@ -115,18 +117,17 @@
|
|
|
115
117
|
"@semantic-release/npm": "^13.1.3",
|
|
116
118
|
"@types/istanbul-lib-coverage": "^2.0.6",
|
|
117
119
|
"@types/node": "22.19.1",
|
|
118
|
-
"@types/
|
|
119
|
-
"@types/source-map": "^0.5.2",
|
|
120
|
+
"@types/source-map": "~0.5.2",
|
|
120
121
|
"@vitest/coverage-v8": "^4.0.18",
|
|
121
122
|
"@vitest/runner": "^4.0.18",
|
|
122
123
|
"@vitest/utils": "^4.0.18",
|
|
123
|
-
"assemblyscript": "
|
|
124
|
+
"assemblyscript": "~0.28.9",
|
|
124
125
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
125
126
|
"istanbul-lib-coverage": "^3.2.2",
|
|
126
127
|
"node-gyp": "^12.2.0",
|
|
127
128
|
"prebuildify": "^6.0.1",
|
|
128
129
|
"semantic-release": "^25.0.3",
|
|
129
|
-
"tsdown": "^0.20.
|
|
130
|
+
"tsdown": "^0.20.3",
|
|
130
131
|
"tsx": "^4.21.0",
|
|
131
132
|
"typescript": "^5.9.3",
|
|
132
133
|
"vitest": "^4.0.18"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/scripts/install.js
CHANGED
|
@@ -4,17 +4,19 @@
|
|
|
4
4
|
* Flow:
|
|
5
5
|
* 1. Try to load a prebuilt or locally-built native addon via node-gyp-build
|
|
6
6
|
* 2. If found → clean up non-matching prebuilds to save disk space, then exit
|
|
7
|
-
* 3. If not found → download Binaryen dependencies
|
|
7
|
+
* 3. If not found → attempt to download Binaryen dependencies and compile from source
|
|
8
|
+
* 4. If compilation fails → write error to marker file and exit successfully
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* Installation always succeeds. Users on unsupported platforms without a C++ toolchain
|
|
11
|
+
* can still run tests - they just won't have coverage instrumentation. The pool checks
|
|
12
|
+
* for the marker file at runtime and displays a warning with the build error details.
|
|
11
13
|
*/
|
|
12
14
|
|
|
13
15
|
import { execSync } from 'child_process';
|
|
14
16
|
import { createRequire } from 'node:module';
|
|
15
17
|
import { resolve, dirname, join } from 'node:path';
|
|
16
18
|
import { fileURLToPath } from 'node:url';
|
|
17
|
-
import { readdirSync, rmSync, existsSync } from 'node:fs';
|
|
19
|
+
import { readdirSync, rmSync, existsSync, writeFileSync } from 'node:fs';
|
|
18
20
|
|
|
19
21
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
22
|
const __dirname = dirname(__filename);
|
|
@@ -22,6 +24,41 @@ const packageRoot = resolve(__dirname, '..');
|
|
|
22
24
|
|
|
23
25
|
const require = createRequire(import.meta.url);
|
|
24
26
|
|
|
27
|
+
// Marker file written when native build fails - checked at runtime to warn users
|
|
28
|
+
const NATIVE_BUILD_ERROR_FILE = join(packageRoot, '.native-build-error');
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Write a marker file indicating native build failure.
|
|
32
|
+
* The pool reads this at runtime to display a warning to users.
|
|
33
|
+
*/
|
|
34
|
+
function writeNativeBuildError(stage, errorMessage) {
|
|
35
|
+
const content = JSON.stringify({
|
|
36
|
+
stage,
|
|
37
|
+
error: errorMessage,
|
|
38
|
+
platform: `${process.platform}-${process.arch}`,
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
}, null, 2);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
writeFileSync(NATIVE_BUILD_ERROR_FILE, content, 'utf8');
|
|
44
|
+
} catch {
|
|
45
|
+
// Non-critical - worst case user just doesn't see the detailed error
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Remove the marker file if it exists (on successful build).
|
|
51
|
+
*/
|
|
52
|
+
function clearNativeBuildError() {
|
|
53
|
+
try {
|
|
54
|
+
if (existsSync(NATIVE_BUILD_ERROR_FILE)) {
|
|
55
|
+
rmSync(NATIVE_BUILD_ERROR_FILE);
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// Non-critical
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
25
62
|
/**
|
|
26
63
|
* Remove prebuild directories that don't match the current platform.
|
|
27
64
|
* Prebuilds ship for all 6 platforms (~21 MB each uncompressed), but only
|
|
@@ -49,8 +86,9 @@ function cleanUnusedPrebuilds() {
|
|
|
49
86
|
try {
|
|
50
87
|
const nodeGypBuild = require('node-gyp-build');
|
|
51
88
|
nodeGypBuild(packageRoot);
|
|
52
|
-
// Addon loaded successfully — clean up unused prebuilds and exit
|
|
89
|
+
// Addon loaded successfully — clean up unused prebuilds and marker file, then exit
|
|
53
90
|
cleanUnusedPrebuilds();
|
|
91
|
+
clearNativeBuildError();
|
|
54
92
|
process.exit(0);
|
|
55
93
|
} catch {
|
|
56
94
|
// No prebuild or local build found — fall through to source build
|
|
@@ -64,28 +102,27 @@ try {
|
|
|
64
102
|
console.log('Downloading Binaryen dependencies...');
|
|
65
103
|
execSync('node scripts/setup-binaryen.js', {
|
|
66
104
|
cwd: packageRoot,
|
|
67
|
-
stdio: '
|
|
105
|
+
stdio: 'pipe',
|
|
68
106
|
});
|
|
69
107
|
} catch (err) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
process.exit(1);
|
|
108
|
+
const errorOutput = err?.stderr?.toString() || err?.stdout?.toString() || (err instanceof Error ? err.message : String(err));
|
|
109
|
+
writeNativeBuildError('binaryen-download', errorOutput);
|
|
110
|
+
process.exit(0);
|
|
74
111
|
}
|
|
75
112
|
|
|
76
113
|
// Step 3: Compile native addon from source
|
|
77
114
|
try {
|
|
78
115
|
console.log('');
|
|
79
116
|
console.log('Compiling native addon...');
|
|
80
|
-
execSync('node-gyp rebuild', {
|
|
117
|
+
execSync('npx node-gyp rebuild', {
|
|
81
118
|
cwd: packageRoot,
|
|
82
|
-
stdio: '
|
|
119
|
+
stdio: 'pipe',
|
|
83
120
|
});
|
|
84
121
|
console.log('');
|
|
85
122
|
console.log('Native addon compiled successfully.');
|
|
123
|
+
clearNativeBuildError();
|
|
86
124
|
} catch (err) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
process.exit(1);
|
|
125
|
+
const errorOutput = err?.stderr?.toString() || err?.stdout?.toString() || (err instanceof Error ? err.message : String(err));
|
|
126
|
+
writeNativeBuildError('native-compile', errorOutput);
|
|
127
|
+
process.exit(0);
|
|
91
128
|
}
|
|
@@ -37,10 +37,10 @@ thread_local bool DEBUG = false;
|
|
|
37
37
|
thread_local std::string LOG_PREFIX = "InstNative";
|
|
38
38
|
|
|
39
39
|
struct SourceDebugLocation {
|
|
40
|
-
bool exists;
|
|
41
|
-
uint32_t fileIndex;
|
|
42
|
-
uint32_t lineNumber;
|
|
43
|
-
uint32_t columnNumber;
|
|
40
|
+
bool exists = false;
|
|
41
|
+
uint32_t fileIndex = 0; // Debug location file index
|
|
42
|
+
uint32_t lineNumber = 0; // Debug location line number
|
|
43
|
+
uint32_t columnNumber = 0; // Debug location column number
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -272,7 +272,7 @@ SourceDebugLocation getRepresentativeLocationInBlockBody(
|
|
|
272
272
|
Block* blockBody,
|
|
273
273
|
const std::unordered_map<wasm::Expression*, std::optional<wasm::Function::DebugLocation>> debugLocations
|
|
274
274
|
) {
|
|
275
|
-
SourceDebugLocation repLoc
|
|
275
|
+
SourceDebugLocation repLoc;
|
|
276
276
|
|
|
277
277
|
if (DEBUG) {
|
|
278
278
|
std::cout << LOG_PREFIX << " - Checking func Block body: " << blockBody->list.size() << " body expressions" << std::endl;
|
|
@@ -310,8 +310,8 @@ SourceDebugLocation getRepresentativeLocationInBlockBody(
|
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
SourceDebugLocation getRepresentativeLocation(Function* func) {
|
|
313
|
-
SourceDebugLocation repLoc
|
|
314
|
-
|
|
313
|
+
SourceDebugLocation repLoc;
|
|
314
|
+
|
|
315
315
|
// Get body expression debug location
|
|
316
316
|
Expression* body = func->body;
|
|
317
317
|
|
|
@@ -811,4 +811,4 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
|
811
811
|
return exports;
|
|
812
812
|
}
|
|
813
813
|
|
|
814
|
-
NODE_API_MODULE(
|
|
814
|
+
NODE_API_MODULE(wasm_binaryen_debug_instrumenter, Init);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compiler-CBBHCPAU.mjs","names":["ascMain"],"sources":["../src/native-instrumentation/addon-interface.ts","../src/compiler/index.ts"],"sourcesContent":["/**\n * Native addon interface for extracting debug information from WebAssembly binaries\n *\n * This module wraps Binaryen's C++ API to provide expression-level debug locations\n * and basic block information that the JavaScript API doesn't expose.\n *\n * The native addon outputs raw data (0-based columns, relative paths) which this\n * wrapper transforms into the final BinaryDebugInfo format (1-based columns,\n * absolute paths, grouped by file and position).\n */\n\nimport { createRequire } from 'node:module';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { debug } from '../util/debug.js';\nimport { toForwardSlash } from '../util/path-utils.js';\nimport {\n NativeAddon,\n NativeInstrumentationResult,\n NativeDebugInfoOutput,\n NativeFunctionDebugInfo,\n NativeExpressionDebugInfo,\n NativeSourceLocation,\n BinaryDebugInfo,\n FunctionDebugInfo,\n SourceLocation,\n ExpressionDebugInfo,\n InstrumentationResult,\n NativeInstrumentationOptions,\n InstrumentationOptions,\n} from '../types/types.js';\nimport { POOL_ERROR_NAMES, INTERNAL_PATH_LIB_PREFIX } from '../types/constants.js';\nimport { createPoolError } from '../util/pool-errors.js';\nimport { getShortFunctionName } from '../wasm-executor/wasm-names.js';\n\n// Load the native addon via node-gyp-build\n// node-gyp-build checks: prebuilds/ first, then build/Release/\n// It searches from the given directory for a package.json to find the package root.\n// We run from dist/ (published) or src/ (dev/tests), so we try both root paths.\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst rootFromDist = resolve(__dirname, '..');\nconst rootFromSrc = resolve(__dirname, '../..');\n\nconst require = createRequire(import.meta.url);\nconst nodeGypBuild: (dir: string) => NativeAddon = require('node-gyp-build');\n\nlet addon: NativeAddon;\ntry {\n addon = nodeGypBuild(rootFromDist);\n} catch {\n try {\n addon = nodeGypBuild(rootFromSrc);\n } catch (err) {\n throw createPoolError(\n `Native addon not found. Searched from ${rootFromDist} and ${rootFromSrc}. ` +\n `Ensure prebuilds are available or run 'npm run build:native' to compile from source. ` +\n `Original error: ${err instanceof Error ? err.message : String(err)}`,\n POOL_ERROR_NAMES.WASMInstrumentationError\n );\n }\n}\n\n/**\n * Convert a raw location (0-indexed columns, path indexes) to\n * processed location (1-indexed columns, absolute path strings)\n *\n * Source map paths vary by import style and project structure:\n * - Relative imports: \"assembly/compare.ts\"\n * - Bare package imports: \"~lib/vitest-pool-assemblyscript/assembly/compare.ts\"\n * - Source outside project root: \"../assembly/compare.ts\" (e.g. test-external importing parent sources)\n *\n * All are normalized to absolute filesystem paths for consistent coverage key matching.\n */\nfunction convertLocation(\n rawLocation: NativeSourceLocation,\n debugSourceFiles: string[],\n projectRoot: string\n): SourceLocation {\n let filePath = debugSourceFiles[rawLocation.fileIndex];\n\n if (!filePath) {\n throw createPoolError(\n `No debug source file with index: ${rawLocation.fileIndex}}`,\n POOL_ERROR_NAMES.WASMInstrumentationError\n );\n }\n\n // Normalize to absolute path for consistent coverage key matching\n if (filePath.startsWith(INTERNAL_PATH_LIB_PREFIX)) {\n // ~lib/vitest-pool-assemblyscript/assembly/X.ts -> projectRoot/assembly/X.ts\n const relativePart = filePath.slice(INTERNAL_PATH_LIB_PREFIX.length);\n filePath = toForwardSlash(resolve(projectRoot, 'assembly', relativePart));\n } else {\n // Resolve relative path (handles both 'assembly/X.ts' and '../assembly/X.ts')\n filePath = toForwardSlash(resolve(projectRoot, filePath));\n }\n\n return {\n filePath,\n line: rawLocation.line,\n column: rawLocation.column + 1, // convert from 0-indexed to 1-indexed\n };\n}\n\n/**\n * Convert a raw expression to processed format\n */\nfunction convertExpression(\n rawExpr: NativeExpressionDebugInfo,\n debugSourceFiles: string[],\n projectRoot: string\n): ExpressionDebugInfo {\n const converted: ExpressionDebugInfo = {\n type: rawExpr.type,\n isBranch: rawExpr.isBranch,\n };\n\n if (rawExpr.branchPaths !== undefined) {\n converted.branchPaths = rawExpr.branchPaths;\n }\n\n if (rawExpr.location) {\n const convertedLocation = convertLocation(rawExpr.location, debugSourceFiles, projectRoot);\n if (convertedLocation) {\n converted.location = convertedLocation;\n }\n }\n\n return converted;\n}\n\n/**\n * Generate a position key to identify the SourceLocation uniquely\n * within a file. Does NOT include the file identifier.\n */\nfunction getPositionKey(location: SourceLocation) {\n return `${location.line}:${location.column}`;\n}\n\n/**\n * Convert a raw function to processed format and compute position key\n * Returns undefined if function has no valid representative location\n */\nfunction convertFunction(\n rawFunc: NativeFunctionDebugInfo,\n debugSourceFiles: string[],\n projectRoot: string\n): { func: FunctionDebugInfo; filePath: string; positionKey: string } | undefined {\n const representativeLocation = convertLocation(rawFunc.representativeLocation, debugSourceFiles, projectRoot);\n\n // Convert expressions\n const expressions: ExpressionDebugInfo[] = [];\n if (rawFunc.expressions) {\n for (const expr of rawFunc.expressions) {\n expressions.push(convertExpression(expr, debugSourceFiles, projectRoot));\n }\n }\n\n const converted: FunctionDebugInfo = {\n wasmIndex: rawFunc.wasmIndex,\n name: rawFunc.name,\n representativeLocation,\n coverageMemoryIndex: rawFunc.coverageMemoryIndex,\n expressions,\n basicBlocks: rawFunc.basicBlocks,\n };\n\n const filePath = representativeLocation.filePath;\n const positionKey = getPositionKey(representativeLocation);\n\n return { func: converted, filePath, positionKey };\n}\n\n/**\n * Check if two WASM function names are monomorphizations of the same generic function.\n * Generic monomorphizations share the same base name and suffix, differing only in\n * the type parameters inside angle brackets.\n *\n * e.g. \"assembly/compare/closeTo<bool\\2cbool>\" and \"assembly/compare/closeTo<bool\\2cu8>\"\n * e.g. \"assembly/expect/BaseExpectMatcher<bool>#constructor\" and \"assembly/expect/BaseExpectMatcher<i8>#constructor\"\n */\nfunction isGenericMonomorphizationMatch(nameA: string, nameB: string): boolean {\n const openA = nameA.indexOf('<');\n const openB = nameB.indexOf('<');\n\n // Both must contain generic type parameters\n if (openA === -1 || openB === -1) return false;\n\n const lastCloseA = nameA.lastIndexOf('>');\n const lastCloseB = nameB.lastIndexOf('>');\n\n if (lastCloseA === -1 || lastCloseB === -1) return false;\n\n // Prefix before '<' must match (includes module path, class, function name)\n const prefixA = nameA.substring(0, openA);\n const prefixB = nameB.substring(0, openB);\n if (prefixA !== prefixB) return false;\n\n // Suffix after last '>' must match (e.g. \"#constructor\", or empty)\n const suffixA = nameA.substring(lastCloseA + 1);\n const suffixB = nameB.substring(lastCloseB + 1);\n if (suffixA !== suffixB) return false;\n\n return true;\n}\n\n/**\n * Transform raw native addon output to processed BinaryDebugInfo\n */\nfunction transformDebugInfo(\n raw: NativeDebugInfoOutput,\n logPrefix: string,\n projectRoot: string,\n): BinaryDebugInfo {\n const functionsByFileAndPosition: Record<string, Record<string, FunctionDebugInfo[]>> = {};\n\n debug(`${logPrefix} - Converting ${raw.functions.length} functions`);\n\n let genericCollisionCount = 0;\n let skippedCount = 0;\n let instrumentedFunctionCount = 0;\n\n for (const rawFunc of raw.functions) {\n const result = convertFunction(rawFunc, raw.debugSourceFiles, projectRoot);\n if (!result) {\n debug(`${logPrefix} - WARNING: Skipped function (bad conversion): \"${rawFunc.name}\"`);\n skippedCount++;\n continue;\n }\n\n const { func, filePath, positionKey } = result;\n\n // Check for position collisions\n const existingAtPosition = functionsByFileAndPosition[filePath]?.[positionKey];\n if (existingAtPosition) {\n const existingName = existingAtPosition[0]!.name;\n\n // Only allow collision if both are monomorphizations of the same generic\n if (isGenericMonomorphizationMatch(existingName, func.name)) {\n existingAtPosition.push(func);\n genericCollisionCount++;\n instrumentedFunctionCount++;\n debug(\n `${logPrefix} - Generic monomorphization at ${filePath}:${positionKey}:`\n + ` \"${getShortFunctionName(func.name)}\" grouped with \"${getShortFunctionName(existingName)}\"`\n );\n continue;\n }\n\n throw createPoolError(\n `ERROR - Function Debug Position Collision at ${filePath}:${positionKey}: \"${getShortFunctionName(existingName)}\"`\n + ` will be replaced by \"${getShortFunctionName(func.name)}\". This is a bug. Please report it at:`\n + ` https://github.com/themattspiral/vitest-pool-assemblyscript/issues/new`,\n POOL_ERROR_NAMES.WASMInstrumentationError\n );\n }\n\n instrumentedFunctionCount++;\n\n // Group by file and position\n if (!functionsByFileAndPosition[filePath]) {\n functionsByFileAndPosition[filePath] = {};\n }\n\n functionsByFileAndPosition[filePath][positionKey] = [func];\n }\n\n debug(\n `${logPrefix} - BinaryDebugInfo transform complete: ${instrumentedFunctionCount} instrumented functions`\n + ` (${genericCollisionCount} generic collisions, ${skippedCount} skipped)`\n );\n\n return {\n debugSourceFiles: raw.debugSourceFiles,\n functionsByFileAndPosition,\n instrumentedFunctionCount,\n };\n}\n\n/**\n * Instrument a WASM binary for coverage collection and regenerate source map\n *\n * This function:\n * 1. Adds __coverage_memory import (multi-memory for coverage counters)\n * 2. Injects coverage counter increments at each function entry\n * 3. Regenerates source map with correct offsets after instrumentation\n * 4. Extracts debug info with coverageMemoryIndex assigned\n *\n * @param wasmBuffer - Buffer containing the clean WASM binary\n * @param sourceMapBuffer - Buffer containing the source map JSON\n * @returns Instrumented binary, regenerated source map, and debug info\n *\n * @throws {TypeError} If wasmBuffer or sourceMapBuffer are not Buffers\n * @throws {Error} If WASM binary or source map is invalid\n */\nexport function instrumentForCoverage(\n wasmBuffer: Buffer,\n sourceMapBuffer: Buffer,\n instrumentationOptions: InstrumentationOptions,\n logModule: string,\n logLabel: string,\n): InstrumentationResult {\n if (!Buffer.isBuffer(wasmBuffer)) {\n throw createPoolError(\n 'instrumentForCoverage - wasmBuffer must be a Buffer',\n POOL_ERROR_NAMES.WASMInstrumentationError\n );\n }\n if (!Buffer.isBuffer(sourceMapBuffer)) {\n throw createPoolError(\n 'instrumentForCoverage - sourceMapBuffer must be a Buffer',\n POOL_ERROR_NAMES.WASMInstrumentationError\n );\n }\n\n const interfaceLogPrefix = `[${logModule} Inst] ${logLabel}`;\n const nativeLogPrefix = `[${logModule} InstNative] ${logLabel}`;\n\n debug(`${interfaceLogPrefix} - Calling native instrumentForCoverage`);\n const startTime = performance.now();\n\n const options: NativeInstrumentationOptions = {\n coverageMemoryPagesMin: instrumentationOptions.coverageMemoryPagesMin,\n coverageMemoryPagesMax: instrumentationOptions.coverageMemoryPagesMax,\n excludedFiles: instrumentationOptions.relativeExcludedFiles,\n excludedLibraryFilePrefix: instrumentationOptions.excludedLibraryFilePrefix,\n excludedLibraryFileOverridePrefix: instrumentationOptions.excludedLibraryFileOverridePrefix,\n debug: instrumentationOptions.debug,\n logPrefix: nativeLogPrefix\n };\n const nativeResult: NativeInstrumentationResult = addon.instrumentForCoverage(wasmBuffer, sourceMapBuffer, options);\n const addonTime = performance.now();\n debug(`${interfaceLogPrefix} - TIMING Native addon: ${(addonTime - startTime).toFixed(2)} ms`);\n\n if (nativeResult.errors?.length) {\n throw createPoolError(\n `Errors encountered duriing native instrumentation: ${nativeResult.errors.join('\\n')}`,\n POOL_ERROR_NAMES.WASMInstrumentationError,\n );\n }\n\n const debugInfo = transformDebugInfo(nativeResult.debugInfo, interfaceLogPrefix, instrumentationOptions.projectRoot);\n \n const transformTime = performance.now();\n debug(`${interfaceLogPrefix} - TIMING DebugInfo Transform: ${(transformTime - addonTime).toFixed(2)} ms`);\n debug(`${interfaceLogPrefix} - Binary size: ${nativeResult.instrumentedWasm.length} bytes | Source map size: ${nativeResult.sourceMap.length * 2} bytes`);\n\n return {\n instrumentedWasm: nativeResult.instrumentedWasm,\n sourceMap: nativeResult.sourceMap,\n debugInfo,\n };\n}\n","/**\n * AssemblyScript Compiler\n *\n * Handles compilation of AssemblyScript source code to WASM binaries.\n * Manages compiler options, transforms, and in-memory compilation.\n */\n\nimport { main as ascMain } from 'assemblyscript/asc';\nimport { basename, resolve } from 'node:path';\nimport { access, readFile, writeFile, mkdir } from 'node:fs/promises';\n\nimport { AssemblyScriptCompilerResult, AssemblyScriptCompilerOptions } from '../types/types.js';\nimport { POOL_ERROR_NAMES } from '../types/constants.js';\nimport { debug } from '../util/debug.js';\nimport { instrumentForCoverage } from '../native-instrumentation/addon-interface.js';\nimport { createPoolError, throwPoolErrorIfAborted } from '../util/pool-errors.js';\n\nconst DEBUG_WRITE_FILES = false;\n\n// Path prefix the AS compiler uses when resolving bare `vitest-pool-assemblyscript/assembly` imports\n// via node_modules. Used to detect self-imports and redirect to local assembly/ dir when running in-tree.\nconst POOL_ASSEMBLY_NODE_MODULES_PREFIX = 'node_modules/vitest-pool-assemblyscript/assembly/';\n\n// path assumes that we're running from dist/\nconst STRIP_INLINE_TRANSFORM = resolve(import.meta.dirname, './compiler/transforms/strip-inline.mjs');\n\nsetImmediate(async () => {\n try {\n await access(STRIP_INLINE_TRANSFORM);\n } catch {\n throw createPoolError(\n `AS Compiler strip inline transform file not found at \"${STRIP_INLINE_TRANSFORM}\"`,\n POOL_ERROR_NAMES.CompilationError\n );\n }\n});\n\n/**\n * Compile AssemblyScript source code to WASM binary\n */\nexport async function compileAssemblyScript(\n filename: string,\n options: AssemblyScriptCompilerOptions,\n logModule: string,\n logLabel: string,\n signal?: AbortSignal\n): Promise<AssemblyScriptCompilerResult> {\n throwPoolErrorIfAborted(signal);\n\n const compileStart = performance.now();\n const logPrefix = `[${logModule} ASC] ${logLabel}`;\n\n const { shouldInstrument, instrumentationOptions, extraFlags } = options;\n\n if (shouldInstrument && !instrumentationOptions) {\n throw createPoolError(\n 'Instrumentation options are required for coverage instrumentation',\n POOL_ERROR_NAMES.CompilationError\n );\n }\n\n const stdoutLines: string[] = [];\n const stderrLines: string[] = [];\n let binary: Uint8Array | undefined;\n let sourceMap: string | undefined;\n\n // Use full path as entry file so AS compiler can resolve relative imports\n const entryFile = filename;\n // Use simple output name to avoid AS compiler prepending it to source map paths\n const outputFile = 'output.wasm';\n\n debug(`${logPrefix} - Compiling: \"${filename}\"`);\n\n // Capture stdout/stderr (for potential error reporting)\n const stdout = {\n write: (text: string) => {\n stdoutLines.push(text);\n return true;\n }\n };\n\n const stderr = {\n write: (text: string) => {\n stderrLines.push(text);\n return true;\n }\n };\n\n // Build compiler flags\n const compilerFlags = [\n entryFile,\n\n // overrideable, though not recommended\n '--optimizeLevel', '0', // No optimization for easier debugging\n '--shrinkLevel', '0', // No shrink\n '--runtime', 'stub', // stub runtime (no GC)\n\n ...(extraFlags || []),\n\n // non-overrideable\n '--outFile', outputFile,\n '--importMemory', // Import memory from JS (enables imports during WASM start)\n '--debug', // Include debug info\n '--sourceMap', // Generate source maps for error reporting\n '--exportStart', '_start', // Export start function for explicit initialization control\n '--exportTable' // Export function table for direct test execution\n ];\n\n // Add transform to strip @inline decorators if requested\n // This improves coverage accuracy by preventing functions from being inlined,\n // and enables correct source-mapped error reporting for errors originating\n // inside inlined functions.\n if (options.stripInline === true) {\n compilerFlags.push(\n '--transform', STRIP_INLINE_TRANSFORM\n );\n debug(`${logPrefix} - Added Transform - Stripping @inline decorators`);\n }\n\n // Compile with AssemblyScript compiler\n const ascStart = performance.now();\n const result = await ascMain(compilerFlags, {\n stdout,\n stderr,\n // Let AS read from filesystem for import resolution\n // WASM binary and source map are captured in memory via writeFile callback\n writeFile: (name: string, contents: string | Uint8Array, _baseDir: string) => {\n throwPoolErrorIfAborted(signal);\n\n if (name.endsWith('.wasm') && contents instanceof Uint8Array) {\n binary = contents;\n debug(`${logPrefix} - Captured binary in memory: \"${name}\"`);\n } else if (name.endsWith('.wasm.map') && typeof contents === 'string') {\n debug(`${logPrefix} - Captured source map in memory: \"${name}\"`);\n sourceMap = contents;\n } else {\n debug(`${logPrefix} - WARNING - Captured Unexpected File: \"${name}\" at baseDir: \"${_baseDir}\"`);\n }\n },\n \n // Custom readFile enables in-tree resolution of bare pool assembly imports.\n // When a test file imports 'vitest-pool-assemblyscript/assembly', the AS compiler\n // resolves it to a node_modules path. This works when the package is installed,\n // but fails in-tree (the package isn't in its own node_modules). The fallback\n // redirects these to the local assembly/ directory when the normal path isn't found.\n readFile: async (filename, baseDir): Promise<string | null> => {\n const filePath = resolve(baseDir, filename);\n\n try {\n return await readFile(filePath, { encoding: 'utf-8' });\n } catch {\n // Fallback: when running in-tree, redirect pool assembly imports to local assembly/ dir\n if (filename.startsWith(POOL_ASSEMBLY_NODE_MODULES_PREFIX)) {\n const localSubpath = filename.substring(POOL_ASSEMBLY_NODE_MODULES_PREFIX.length);\n const localPath = resolve(baseDir, 'assembly', localSubpath);\n\n try {\n return await readFile(localPath, { encoding: 'utf-8' });\n } catch {\n return null;\n }\n }\n\n return null;\n }\n },\n });\n\n debug(`${logPrefix} - TIMING asc.main: ${(performance.now() - ascStart).toFixed(2)} ms`);\n\n if (result.error) {\n const errorMessage = stderrLines.length > 0\n ? `${result.error.message}\\n\\n${stderrLines.join('')}`\n : result.error.message;\n\n throw createPoolError(errorMessage, POOL_ERROR_NAMES.CompilationError, errorMessage);\n }\n\n if (!binary) {\n const errorMessage = stderrLines.length > 0\n ? `No WASM binary was generated\\n\\nAS Compiler output:\\n${stderrLines.join('')}`\n : 'No WASM binary was generated';\n\n throw createPoolError(errorMessage, POOL_ERROR_NAMES.CompilationError);\n }\n\n if (!sourceMap) {\n throw createPoolError('Source map not captured from AssemblyScript Compiler', POOL_ERROR_NAMES.CompilationError);\n }\n\n const cleanBinary: Uint8Array = binary;\n const wasmSourceMap: string = sourceMap;\n\n debug(`${logPrefix} - Compilation successful, clean binary size: ${cleanBinary.length} bytes`);\n debug(`${logPrefix} - Source map generated, size: ${wasmSourceMap.length * 2} bytes`);\n \n if (DEBUG_WRITE_FILES) {\n // Write source map for debugging\n const dir = './debug';\n // TODO - handle non-.ts extensions\n const sourceMapFileName = `${basename(filename, '.ts')}.ts.map`;\n const sourceMapPath = `${dir}/${sourceMapFileName}`;\n\n // Create directory if it doesn't exist\n try {\n await mkdir(dir, { recursive: true });\n } catch {\n // Directory already exists or creation failed, continue\n }\n\n // Format as well-formed JSON\n const formattedSourceMap = JSON.stringify(JSON.parse(wasmSourceMap), null, 2);\n\n writeFile(sourceMapPath, formattedSourceMap, { encoding: 'utf8' });\n debug(`${logPrefix} - Wrote source map to: \"${sourceMapPath}\"`);\n\n // Also write WASM binary for inspection\n const wasmPath = sourceMapPath.replace('.map', '.wasm');\n writeFile(wasmPath, cleanBinary);\n debug(`${logPrefix} - Wrote WASM binary to: \"${wasmPath}\"`);\n }\n\n // Instrument binary for coverage if requested\n if (options.shouldInstrument) {\n throwPoolErrorIfAborted(signal);\n\n const instrumentStart = performance.now();\n const wasmBuffer = Buffer.from(cleanBinary);\n const sourceMapBuffer = Buffer.from(wasmSourceMap);\n\n const instrumentResult = instrumentForCoverage(wasmBuffer, sourceMapBuffer, options.instrumentationOptions!, logModule, logLabel);\n const instCount = instrumentResult.debugInfo.instrumentedFunctionCount;\n\n const instrumentEnd = performance.now();\n debug(`${logPrefix} - TIMING Instrumented ${instCount} functions: ${(performance.now() - instrumentStart).toFixed(2)} ms`);\n\n return {\n binary: instrumentResult.instrumentedWasm,\n sourceMap: instrumentResult.sourceMap,\n debugInfo: instrumentResult.debugInfo,\n isInstrumented: true,\n compileTiming: instrumentEnd - compileStart,\n };\n }\n\n // No instrumentation requested\n return {\n binary: cleanBinary,\n sourceMap: wasmSourceMap,\n isInstrumented: false,\n compileTiming: performance.now() - compileStart,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import c from "tinyrainbow";
|
|
2
|
-
import { versions } from "node:process";
|
|
3
|
-
|
|
4
|
-
//#region src/util/node-check.ts
|
|
5
|
-
const NODE_VERSION = versions.node;
|
|
6
|
-
const NODE_MAJOR_VERSION = parseInt(NODE_VERSION.split(".")[0], 10);
|
|
7
|
-
function isCoverageSupported() {
|
|
8
|
-
return NODE_MAJOR_VERSION >= 22;
|
|
9
|
-
}
|
|
10
|
-
function warnIfASCoverageNotSupported() {
|
|
11
|
-
if (!isCoverageSupported()) console.warn(`\n` + c.yellow(`Warning:`) + c.gray(` Coverage is enabled, but current Node version (${versions.node})\n does not support required WASM multi-memory features.\n Coverage collection will be `) + c.yellow(`disabled`) + c.gray(" for AssemblyScript WASM.\n Please upgrade to Node 22 or above if you need WASM coverage support."));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
//#endregion
|
|
15
|
-
export { isCoverageSupported, warnIfASCoverageNotSupported };
|
|
16
|
-
//# sourceMappingURL=node-check-CcKfvjM4.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node-check-CcKfvjM4.mjs","names":[],"sources":["../src/util/node-check.ts"],"sourcesContent":["import { versions } from 'node:process';\nimport c from 'tinyrainbow';\n\nconst NODE_VERSION = versions.node;\nconst NODE_MAJOR_VERSION = parseInt(NODE_VERSION.split('.')[0]!, 10);\n\nexport function isCoverageSupported(): boolean {\n return NODE_MAJOR_VERSION >= 22;\n}\n\nexport function warnIfASCoverageNotSupported(): void {\n if (!isCoverageSupported()) {\n console.warn(`\\n`\n + c.yellow(`Warning:`)\n + c.gray(` Coverage is enabled, but current Node version (${versions.node})\\n`\n + ` does not support required WASM multi-memory features.\\n`\n + ` Coverage collection will be `) + c.yellow(`disabled`) + c.gray(` for AssemblyScript WASM.\\n`\n + ` Please upgrade to Node 22 or above if you need WASM coverage support.`)\n );\n }\n}\n"],"mappings":";;;;AAGA,MAAM,eAAe,SAAS;AAC9B,MAAM,qBAAqB,SAAS,aAAa,MAAM,IAAI,CAAC,IAAK,GAAG;AAEpE,SAAgB,sBAA+B;AAC7C,QAAO,sBAAsB;;AAG/B,SAAgB,+BAAqC;AACnD,KAAI,CAAC,qBAAqB,CACxB,SAAQ,KAAK,OACT,EAAE,OAAO,WAAW,GACpB,EAAE,KAAK,mDAAmD,SAAS,KAAK,0GAEhC,GAAG,EAAE,OAAO,WAAW,GAAG,EAAE,KAAK,4GACQ,CACpF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pool-runner-init-DVk4hB5d.d.mts","names":[],"sources":["../src/pool/pool-runner-init.ts"],"mappings":";;;;iBAUgB,wBAAA,CAAyB,eAAA,GAAkB,yBAAA,GAA4B,qBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-6ta3lLJM.d.mts","names":[],"sources":["../src/types/types.ts"],"mappings":";;;;;;;;;;;UA0DiB,yBAAA;EAmEjB;EAjEE,KAAA;EACA,WAAA;EACA,oBAAA;;EAGA,wBAAA;;;;;;;;;;EAWA,WAAA;EAyDU;;;;;;;EAhDV,YAAA;EAEA,0BAAA;EACA,sBAAA;EAEA,sBAAA;EACA,kBAAA;EAEA,kBAAA;EAEA,kBAAA;AAAA;;;;UAMe,qBAAA;EACf,QAAA;EACA,oBAAA;EAEA,aAAA;EA2Ge;;;;;;;;EAjGf,qBAAA;;;;AAyGF;;EAlGE,qBAAA;AAAA;AAAA,UAGe,sBAAA;EACf,MAAA,EAAQ,WAAA,CAAY,MAAA;EACpB,MAAA,EAAQ,WAAA,CAAY,MAAA;EACpB,KAAA;IACE,UAAA,GAAa,SAAA;EAAA;AAAA;AAAA,KAIL,kBAAA,IAAsB,UAAA,EAAY,sBAAA,KAA2B,WAAA,CAAY,OAAA;AAAA,UAuEpE,6BAAA;EACf,gBAAA;EACA,WAAA;EACA,sBAAA,GAAyB,sBAAA;EACzB,WAAA;EACA,UAAA;AAAA;AAAA,UAGe,4BAAA;EACf,MAAA,EAAQ,UAAA;EACR,SAAA;EACA,SAAA,GAAY,eAAA;EACZ,cAAA;EACA,aAAA;AAAA;AAAA,UAGe,sBAAA;;EAEf,WAAA;;EAEA,qBAAA;EACA,yBAAA;EACA,sBAAA;EACA,sBAAA;EACA,iCAAA;EACA,KAAA;AAAA;;;AAiZF;;;;UAxXiB,cAAA;;EAEf,QAAA;EACA,IAAA;EACA,MAAA;AAAA;;;;UAoEe,mBAAA;;EAEf,gBAAA;;EAEA,qBAAA;AAAA;;;;;AAkVF;;UAzUiB,mBAAA;;EAEf,IAAA;;EAEA,QAAA,GAAW,cAAA;;EAEX,QAAA;EA0UsB;EAxUtB,WAAA;;;;;EAKA,mBAAA;AAAA;;;;;;;UASe,mBAAA;;EAEf,KAAA;;EAEA,iBAAA;;EAEA,QAAA,EAAU,mBAAA;;;;;EAKV,mBAAA;AAAA;;;;UAMe,iBAAA;;EAEf,SAAA;;EAEA,IAAA;;;;;EAKA,sBAAA,EAAwB,cAAA;;EAExB,mBAAA;;EAEA,WAAA,EAAa,mBAAA;;EAEb,WAAA,EAAa,mBAAA;AAAA;;;;;;;UASE,eAAA;;EAEf,gBAAA;;;;;;EAMA,0BAAA,EAA4B,MAAA,SAAe,MAAA,SAAe,iBAAA;EAE1D,yBAAA;AAAA;AAAA,UA0Ne,eAAA;EACf,QAAA;EACA,MAAA,EAAQ,UAAA;EACR,SAAA;EACA,SAAA,GAAY,eAAA;AAAA;AAAA,UASG,UAAA;EACf,IAAA,EAAM,IAAA;EACN,WAAA,GAAc,eAAA;AAAA;AAAA,UAGC,yBAAA;EACf,aAAA;EACA,QAAA;EACA,IAAA,EAAM,WAAA;EACN,IAAA,EAAM,IAAA;EACN,MAAA,EAAQ,gBAAA;EACR,kBAAA;AAAA;AAAA,UAGe,YAAA;EACf,aAAA;EACA,QAAA;EACA,IAAA,EAAM,WAAA;EACN,IAAA,EAAM,IAAA;EACN,WAAA,EAAa,eAAA;EACb,MAAA,EAAQ,gBAAA;EACR,kBAAA;EACA,YAAA,GAAe,IAAA;AAAA;AAAA,UAGA,sBAAA;EACf,aAAA;EACA,IAAA,EAAM,WAAA;EACN,IAAA,EAAM,IAAA;EACN,MAAA,EAAQ,gBAAA;EACR,kBAAA;EACA,YAAA,GAAe,IAAA;EACf,mBAAA,GAAsB,eAAA;AAAA"}
|