vitest-pool-assemblyscript 0.2.2 → 0.2.4
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 +114 -314
- package/dist/{ast-visitor-DC3SuTzs.mjs → ast-visitor-lTahoS9R.mjs} +2 -2
- package/dist/{ast-visitor-DC3SuTzs.mjs.map → ast-visitor-lTahoS9R.mjs.map} +1 -1
- package/dist/{compile-runner-xGvQwgNf.mjs → compile-runner-C9TJrfCl.mjs} +6 -6
- package/dist/{compile-runner-xGvQwgNf.mjs.map → compile-runner-C9TJrfCl.mjs.map} +1 -1
- package/dist/compiler/transforms/strip-inline.mjs +2 -2
- package/dist/{compiler-CN6BRK_N.mjs → compiler-BaNECXMW.mjs} +3 -3
- package/dist/{compiler-CN6BRK_N.mjs.map → compiler-BaNECXMW.mjs.map} +1 -1
- package/dist/config/index.mjs +5 -4
- package/dist/{constants-CA50WBdr.mjs → constants-DX9yo-el.mjs} +11 -2
- package/dist/constants-DX9yo-el.mjs.map +1 -0
- package/dist/coverage-provider/index.mjs +6 -5
- package/dist/coverage-provider/index.mjs.map +1 -1
- package/dist/{debug-IeEHsxy0.mjs → debug-Cf2jt1kg.mjs} +2 -2
- package/dist/{debug-IeEHsxy0.mjs.map → debug-Cf2jt1kg.mjs.map} +1 -1
- package/dist/index-internal.mjs +3 -2
- package/dist/index-v3.mjs +4 -4
- package/dist/index.mjs +5 -4
- package/dist/{load-user-imports-Bbmpaciu.mjs → load-user-imports-CcIdE4_0.mjs} +4 -4
- package/dist/{load-user-imports-Bbmpaciu.mjs.map → load-user-imports-CcIdE4_0.mjs.map} +1 -1
- package/dist/{pool-runner-init-d5qScS41.mjs → pool-runner-init-Cdpz_B-F.mjs} +6 -6
- package/dist/pool-runner-init-Cdpz_B-F.mjs.map +1 -0
- package/dist/pool-thread/compile-worker-thread.mjs +6 -5
- package/dist/pool-thread/compile-worker-thread.mjs.map +1 -1
- package/dist/pool-thread/test-worker-thread.mjs +5 -4
- package/dist/pool-thread/test-worker-thread.mjs.map +1 -1
- package/dist/pool-thread/v3-tinypool-thread.mjs +7 -6
- package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -1
- package/dist/{resolve-config-as1w-Qyz.mjs → resolve-config-BKjJQyy5.mjs} +3 -3
- package/dist/{resolve-config-as1w-Qyz.mjs.map → resolve-config-BKjJQyy5.mjs.map} +1 -1
- package/dist/{test-runner-BR4XyhMA.mjs → test-runner-DZd3SxEc.mjs} +4 -4
- package/dist/{test-runner-BR4XyhMA.mjs.map → test-runner-DZd3SxEc.mjs.map} +1 -1
- package/dist/{vitest-tasks-BKS7689f.mjs → vitest-tasks-Cbri6MWZ.mjs} +3 -3
- package/dist/{vitest-tasks-BKS7689f.mjs.map → vitest-tasks-Cbri6MWZ.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/constants-CA50WBdr.mjs.map +0 -1
- package/dist/pool-runner-init-d5qScS41.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-runner-
|
|
1
|
+
{"version":3,"file":"compile-runner-C9TJrfCl.mjs","names":[],"sources":["../src/pool-thread/runner/compile-runner.ts"],"sourcesContent":["/**\n * Worker thread test runner logic for AssemblyScript Pool\n */\n\nimport { basename, relative } from 'node:path';\nimport type { File } from '@vitest/runner/types';\nimport type { SerializedDiffOptions } from '@vitest/utils/diff';\n\nimport type {\n AssemblyScriptCompilerOptions,\n AssemblyScriptConsoleLog,\n AssemblyScriptConsoleLogHandler,\n InstrumentationOptions,\n ResolvedAssemblyScriptPoolOptions,\n ThreadImports,\n WASMCompilation,\n WorkerRPC,\n} from '../../types/types.js';\nimport {\n ASSEMBLYSCRIPT_LIB_PREFIX,\n POOL_ERROR_NAMES,\n POOL_INTERNAL_PATHS,\n} from '../../types/constants.js';\nimport { executeWASMDiscovery } from '../../wasm-executor/index.js';\nimport { debug } from '../../util/debug.js';\nimport {\n reportFileQueued,\n reportFileCollected,\n reportUserConsoleLogs,\n flushRpcUpdates,\n reportFileError,\n} from '../rpc-reporter.js';\nimport { createPoolErrorFromAnyError, getTestErrorFromPoolError } from '../../util/pool-errors.js';\nimport { compileAssemblyScript } from '../../compiler/index.js';\nimport {\n getTaskLogLabel,\n getTaskLogPrefix,\n} from '../../util/vitest-tasks.js';\nimport {\n failFile,\n getFullTaskHierarchy,\n prepareFileTaskForCollection,\n} from '../../util/vitest-file-tasks.js';\n\nlet threadCompilationCount: number = 0;\n\nexport async function runCompileAndDiscover(\n file: File,\n logModule: string,\n rpc: WorkerRPC,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n projectRoot: string,\n collectCoverage: boolean,\n relativeUserCoverageExclusions: string[],\n threadImports: ThreadImports,\n diffOptions?: SerializedDiffOptions,\n testNamePattern?: RegExp,\n allowOnly?: boolean,\n): Promise<WASMCompilation | undefined> {\n const base = basename(file.filepath);\n const fileLogPrefix = getTaskLogPrefix(logModule, base, file);\n const fileLogLabel = getTaskLogLabel(base, file);\n\n debug(`${fileLogPrefix} - Beginning runCompileAndDiscover for \"${file.filepath}\" at ${Date.now()}`);\n\n const runStart = performance.now();\n let compilation: WASMCompilation | undefined;\n\n try {\n await reportFileQueued(rpc, file, logModule, fileLogLabel);\n\n // TODO - move to options helpers\n const relativeTestFilePath = relative(projectRoot, file.filepath);\n const instrumentationOptions: InstrumentationOptions = {\n relativeExcludedFiles: [\n relativeTestFilePath,\n ...POOL_INTERNAL_PATHS,\n ...relativeUserCoverageExclusions,\n ],\n excludedLibraryFilePrefix: ASSEMBLYSCRIPT_LIB_PREFIX,\n coverageMemoryPagesMin: poolOptions.coverageMemoryPagesInitial,\n coverageMemoryPagesMax: poolOptions.coverageMemoryPagesMax,\n };\n const compilerOptions: AssemblyScriptCompilerOptions = {\n stripInline: poolOptions.stripInline,\n projectRoot: projectRoot,\n shouldInstrument: collectCoverage,\n instrumentationOptions,\n extraFlags: poolOptions.extraCompilerFlags\n };\n\n const { binary, sourceMap, debugInfo, compileTiming } = await compileAssemblyScript(\n file.filepath,\n compilerOptions,\n logModule,\n fileLogLabel\n );\n file.setupDuration = compileTiming;\n threadCompilationCount++;\n\n debug(`${fileLogPrefix} - TIMING compileAssemblyScript total `\n + `(thread comp # ${threadCompilationCount}): ${compileTiming.toFixed(2)} ms`\n );\n \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 discoverStart = performance.now();\n\n await executeWASMDiscovery(\n binary,\n sourceMap,\n base,\n poolOptions,\n collectCoverage,\n handleLog,\n file,\n logModule,\n threadImports,\n diffOptions\n );\n\n // set skips when using only and/or user test name pattern, skip file task if all tests skipped\n prepareFileTaskForCollection(file, testNamePattern, allowOnly);\n\n file.collectDuration = performance.now() - discoverStart;\n debug(`${fileLogPrefix} - TIMING Discovery Phase: ${file.collectDuration.toFixed(2)} ms`);\n\n // vitest collect - report discovery results\n await Promise.all([\n // Report user console logs\n reportUserConsoleLogs(rpc, logMessages, logModule, base, file),\n\n // Report onCollected with collected and filtered tasks\n reportFileCollected(rpc, file, logModule, fileLogLabel),\n ]);\n\n debug(() => `${fileLogPrefix} - Collected Test Suite Hierarchy:\\n${getFullTaskHierarchy(file)}`);\n\n const totalTime = performance.now() - runStart;\n debug(`${fileLogPrefix} - TIMING Compilation and Discovery: ${totalTime.toFixed(2)} ms`);\n\n compilation = {\n filePath: file.filepath,\n binary,\n sourceMap,\n debugInfo,\n };\n } catch (error) {\n const poolError = createPoolErrorFromAnyError(\n `${fileLogLabel} - runCompileAndDiscover failure in worker`,\n POOL_ERROR_NAMES.WASMExecutionHarnessError,\n error\n );\n const testError = getTestErrorFromPoolError(poolError);\n\n failFile(file, testError, runStart);\n\n await reportFileQueued(rpc, file, logModule, fileLogLabel);\n await reportFileError(rpc, file, logModule, fileLogLabel);\n\n debug(`${fileLogPrefix} - Reported file error`);\n } finally {\n await flushRpcUpdates(rpc);\n debug(`${fileLogPrefix} - runCompileAndDiscover Completed`);\n }\n\n return compilation;\n}\n"],"mappings":";;;;;;;;;;;;AA4CA,IAAI,yBAAiC;AAErC,eAAsB,sBACpB,MACA,WACA,KACA,aACA,aACA,iBACA,gCACA,eACA,aACA,iBACA,WACsC;CACtC,MAAM,OAAO,SAAS,KAAK,SAAS;CACpC,MAAM,gBAAgB,iBAAiB,WAAW,MAAM,KAAK;CAC7D,MAAM,eAAe,gBAAgB,MAAM,KAAK;AAEhD,OAAM,GAAG,cAAc,0CAA0C,KAAK,SAAS,OAAO,KAAK,KAAK,GAAG;CAEnG,MAAM,WAAW,YAAY,KAAK;CAClC,IAAI;AAEJ,KAAI;AACF,QAAM,iBAAiB,KAAK,MAAM,WAAW,aAAa;EAI1D,MAAM,yBAAiD;GACrD,uBAAuB;IAFI,SAAS,aAAa,KAAK,SAAS;IAI7D,GAAG;IACH,GAAG;IACJ;GACD;GACA,wBAAwB,YAAY;GACpC,wBAAwB,YAAY;GACrC;EACD,MAAM,kBAAiD;GACrD,aAAa,YAAY;GACZ;GACb,kBAAkB;GAClB;GACA,YAAY,YAAY;GACzB;EAED,MAAM,EAAE,QAAQ,WAAW,WAAW,kBAAkB,MAAM,sBAC5D,KAAK,UACL,iBACA,WACA,aACD;AACD,OAAK,gBAAgB;AACrB;AAEA,QAAM,GAAG,cAAc,uDACD,uBAAuB,KAAK,cAAc,QAAQ,EAAE,CAAC,KAC1E;EAED,MAAM,cAA0C,EAAE;EAClD,MAAM,aAA8C,KAAa,UAAmB,UAAgB;AAClG,eAAY,KAAK;IAAE;IAAK,MAAM,KAAK,KAAK;IAAE;IAAS,CAAC;;EAGtD,MAAM,gBAAgB,YAAY,KAAK;AAEvC,QAAM,qBACJ,QACA,WACA,MACA,aACA,iBACA,WACA,MACA,WACA,eACA,YACD;AAGD,+BAA6B,MAAM,iBAAiB,UAAU;AAE9D,OAAK,kBAAkB,YAAY,KAAK,GAAG;AAC3C,QAAM,GAAG,cAAc,6BAA6B,KAAK,gBAAgB,QAAQ,EAAE,CAAC,KAAK;AAGzF,QAAM,QAAQ,IAAI,CAEhB,sBAAsB,KAAK,aAAa,WAAW,MAAM,KAAK,EAG9D,oBAAoB,KAAK,MAAM,WAAW,aAAa,CACxD,CAAC;AAEF,cAAY,GAAG,cAAc,sCAAsC,qBAAqB,KAAK,GAAG;AAGhG,QAAM,GAAG,cAAc,wCADL,YAAY,KAAK,GAAG,UACkC,QAAQ,EAAE,CAAC,KAAK;AAExF,gBAAc;GACZ,UAAU,KAAK;GACf;GACA;GACA;GACD;UACM,OAAO;AAQd,WAAS,MAFS,0BALA,4BAChB,GAAG,aAAa,6CAChB,iBAAiB,2BACjB,MACD,CACqD,EAE5B,SAAS;AAEnC,QAAM,iBAAiB,KAAK,MAAM,WAAW,aAAa;AAC1D,QAAM,gBAAgB,KAAK,MAAM,WAAW,aAAa;AAEzD,QAAM,GAAG,cAAc,wBAAwB;WACvC;AACR,QAAM,gBAAgB,IAAI;AAC1B,QAAM,GAAG,cAAc,oCAAoC;;AAG7D,QAAO"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ASDecoratorKind, ASSourceKind } from "../../constants-
|
|
2
|
-
import { ASTVisitor } from "../../ast-visitor-
|
|
1
|
+
import { ASDecoratorKind, ASSourceKind } from "../../constants-DX9yo-el.mjs";
|
|
2
|
+
import { ASTVisitor } from "../../ast-visitor-lTahoS9R.mjs";
|
|
3
3
|
import { Transform } from "assemblyscript/transform";
|
|
4
4
|
|
|
5
5
|
//#region src/compiler/transforms/strip-inline.mts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { POOL_ERROR_NAMES } from "./constants-
|
|
2
|
-
import { createPoolError, debug, throwPoolErrorIfAborted } from "./debug-
|
|
1
|
+
import { POOL_ERROR_NAMES } from "./constants-DX9yo-el.mjs";
|
|
2
|
+
import { createPoolError, debug, throwPoolErrorIfAborted } from "./debug-Cf2jt1kg.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { basename, dirname, resolve } from "node:path";
|
|
5
5
|
import { access } from "node:fs/promises";
|
|
@@ -292,4 +292,4 @@ async function compileAssemblyScript(filename, options, logModule, logLabel, sig
|
|
|
292
292
|
|
|
293
293
|
//#endregion
|
|
294
294
|
export { compileAssemblyScript };
|
|
295
|
-
//# sourceMappingURL=compiler-
|
|
295
|
+
//# sourceMappingURL=compiler-BaNECXMW.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler-CN6BRK_N.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';\nimport { debug } from '../util/debug.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 } from '../types/constants.js';\nimport { createPoolError } from '../util/pool-errors.js';\n\nconst DEBUG_NATIVE_ADDON = false;\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, path strings)\n */\nfunction convertLocation(\n rawLocation: NativeSourceLocation,\n debugSourceFiles: string[]\n): SourceLocation {\n const 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 return {\n filePath: 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): 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);\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): { func: FunctionDebugInfo; filePath: string; positionKey: string } | undefined {\n const representativeLocation = convertLocation(rawFunc.representativeLocation, debugSourceFiles);\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));\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 * Transform raw native addon output to processed BinaryDebugInfo\n */\nfunction transformDebugInfo(\n raw: NativeDebugInfoOutput,\n logPrefix: string,\n): BinaryDebugInfo {\n const functionsByFileAndPosition: Record<string, Record<string, FunctionDebugInfo>> = {};\n\n debug(`${logPrefix} - Converting ${raw.functions.length} functions`);\n\n let positionCollisionCount = 0;\n let skippedCount = 0;\n let instrumentedFunctionCount = 0;\n \n for (const rawFunc of raw.functions) {\n const result = convertFunction(rawFunc, raw.debugSourceFiles);\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 if (functionsByFileAndPosition[filePath]?.[positionKey]) {\n const existing = functionsByFileAndPosition[filePath][positionKey];\n positionCollisionCount++;\n throw createPoolError(\n `ERROR - Function Debug Position Collision at ${filePath}:${positionKey}: \"${existing.name}\" will be replaced by \"${func.name}\"`,\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 +` (${positionCollisionCount} position 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 debug: DEBUG_NATIVE_ADDON,\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);\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 } from 'node:fs/promises';\nimport { 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 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 *\n * Features:\n * - In-memory compilation (binary captured via writeFile callback)\n * - Filesystem reading enabled (for import resolution)\n * - Uses stub runtime and imported memory pattern\n * - Exports _start function for explicit initialization control\n * - Always returns clean binary\n * - Conditionally returns instrumented binary when coverage enabled\n *\n * @param filename - Full path to the source file (used as entry point)\n * @param options - Compilation options (coverage mode, etc.)\n * @returns Compilation result with clean binary and optional instrumented binary\n * @throws Error if compilation fails\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\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 to project maps directory for debugging\n const dir = './debug';\n const sourceMapFileName = `${basename(filename, '.ts')}.as.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
|
+
{"version":3,"file":"compiler-BaNECXMW.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';\nimport { debug } from '../util/debug.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 } from '../types/constants.js';\nimport { createPoolError } from '../util/pool-errors.js';\n\nconst DEBUG_NATIVE_ADDON = false;\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, path strings)\n */\nfunction convertLocation(\n rawLocation: NativeSourceLocation,\n debugSourceFiles: string[]\n): SourceLocation {\n const 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 return {\n filePath: 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): 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);\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): { func: FunctionDebugInfo; filePath: string; positionKey: string } | undefined {\n const representativeLocation = convertLocation(rawFunc.representativeLocation, debugSourceFiles);\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));\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 * Transform raw native addon output to processed BinaryDebugInfo\n */\nfunction transformDebugInfo(\n raw: NativeDebugInfoOutput,\n logPrefix: string,\n): BinaryDebugInfo {\n const functionsByFileAndPosition: Record<string, Record<string, FunctionDebugInfo>> = {};\n\n debug(`${logPrefix} - Converting ${raw.functions.length} functions`);\n\n let positionCollisionCount = 0;\n let skippedCount = 0;\n let instrumentedFunctionCount = 0;\n \n for (const rawFunc of raw.functions) {\n const result = convertFunction(rawFunc, raw.debugSourceFiles);\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 if (functionsByFileAndPosition[filePath]?.[positionKey]) {\n const existing = functionsByFileAndPosition[filePath][positionKey];\n positionCollisionCount++;\n throw createPoolError(\n `ERROR - Function Debug Position Collision at ${filePath}:${positionKey}: \"${existing.name}\" will be replaced by \"${func.name}\"`,\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 +` (${positionCollisionCount} position 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 debug: DEBUG_NATIVE_ADDON,\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);\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 } from 'node:fs/promises';\nimport { 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 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 *\n * Features:\n * - In-memory compilation (binary captured via writeFile callback)\n * - Filesystem reading enabled (for import resolution)\n * - Uses stub runtime and imported memory pattern\n * - Exports _start function for explicit initialization control\n * - Always returns clean binary\n * - Conditionally returns instrumented binary when coverage enabled\n *\n * @param filename - Full path to the source file (used as entry point)\n * @param options - Compilation options (coverage mode, etc.)\n * @returns Compilation result with clean binary and optional instrumented binary\n * @throws Error if compilation fails\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\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 to project maps directory for debugging\n const dir = './debug';\n const sourceMapFileName = `${basename(filename, '.ts')}.as.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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"}
|
package/dist/config/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
1
|
+
import "../constants-DX9yo-el.mjs";
|
|
2
|
+
import "../resolve-config-BKjJQyy5.mjs";
|
|
3
|
+
import "../debug-Cf2jt1kg.mjs";
|
|
3
4
|
import "../vitest-file-tasks-BUwzh375.mjs";
|
|
4
|
-
import "../vitest-tasks-
|
|
5
|
+
import "../vitest-tasks-Cbri6MWZ.mjs";
|
|
5
6
|
import "../worker-rpc-channel-lbhK7Qz8.mjs";
|
|
6
|
-
import { createAssemblyScriptPool } from "../pool-runner-init-
|
|
7
|
+
import { createAssemblyScriptPool } from "../pool-runner-init-Cdpz_B-F.mjs";
|
|
7
8
|
|
|
8
9
|
export { createAssemblyScriptPool };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
//#region src/types/constants.ts
|
|
2
2
|
const COVERAGE_PAYLOAD_FORMATS = { AssemblyScript: "assemblyscript" };
|
|
3
|
+
/** Prefix for AssemblyScript compiler strip-inline exclusions and instrumentation exclusions */
|
|
4
|
+
const ASSEMBLYSCRIPT_LIB_PREFIX = "~lib/";
|
|
5
|
+
const INTERNAL_PATH_LIB_PREFIX = `${"~lib/"}vitest-pool-assemblyscript/`;
|
|
3
6
|
/** Paths instrumentation exclusions and assetion error stack frame filtering */
|
|
4
7
|
const POOL_INTERNAL_PATHS = [
|
|
5
8
|
"assembly/compare.ts",
|
|
@@ -7,7 +10,13 @@ const POOL_INTERNAL_PATHS = [
|
|
|
7
10
|
"assembly/expect.ts",
|
|
8
11
|
"assembly/index.ts",
|
|
9
12
|
"assembly/options.ts",
|
|
10
|
-
"assembly/test.ts"
|
|
13
|
+
"assembly/test.ts",
|
|
14
|
+
`${INTERNAL_PATH_LIB_PREFIX}assembly/compare.ts`,
|
|
15
|
+
`${INTERNAL_PATH_LIB_PREFIX}assembly/describe.ts`,
|
|
16
|
+
`${INTERNAL_PATH_LIB_PREFIX}assembly/expect.ts`,
|
|
17
|
+
`${INTERNAL_PATH_LIB_PREFIX}assembly/index.ts`,
|
|
18
|
+
`${INTERNAL_PATH_LIB_PREFIX}assembly/options.ts`,
|
|
19
|
+
`${INTERNAL_PATH_LIB_PREFIX}assembly/test.ts`
|
|
11
20
|
];
|
|
12
21
|
/** Error names for AssemblyScript test failures reported to vitest */
|
|
13
22
|
const TEST_ERROR_NAMES = {
|
|
@@ -127,4 +136,4 @@ const ASSourceKind = {
|
|
|
127
136
|
|
|
128
137
|
//#endregion
|
|
129
138
|
export { ASCommonFlags, ASDecoratorKind, ASNodeKind, ASSourceKind, COVERAGE_PAYLOAD_FORMATS, POOL_ERROR_NAMES, POOL_INTERNAL_PATHS, TEST_ERROR_NAMES };
|
|
130
|
-
//# sourceMappingURL=constants-
|
|
139
|
+
//# sourceMappingURL=constants-DX9yo-el.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-DX9yo-el.mjs","names":[],"sources":["../src/types/constants.ts"],"sourcesContent":["/**\n * Plain Constants\n * \n * Only things that don't require importing ./types to avoid circular dependencies.\n */\n\n\n// ============================================================================\n// General / Shared Constants\n// ============================================================================\n\nexport const ASSEMBLYSCRIPT_POOL_NAME = 'assemblyscript' as const;\n\nexport const AS_POOL_ERROR_TYPE_FLAG = '__as_pool__' as const;\n\nexport const AS_POOL_WORKER_MSG_FLAG = '__as_pool__' as const;\n\nexport const AS_POOL_WASM_IMPORTS_ENV = '__as_pool_env__' as const;\n\nexport const VITEST_WORKER_REQUEST_MSG_FLAG = '__vitest_worker_request__' as const;\n\nexport const VITEST_WORKER_RESPONSE_MSG_FLAG = '__vitest_worker_response__' as const;\n\nexport const COVERAGE_PAYLOAD_FORMATS = {\n AssemblyScript: 'assemblyscript',\n} as const;\n\n/** Prefix for AssemblyScript compiler strip-inline exclusions and instrumentation exclusions */\nexport const ASSEMBLYSCRIPT_LIB_PREFIX = '~lib/' as const;\n\nconst INTERNAL_PATH_LIB_PREFIX = `${ASSEMBLYSCRIPT_LIB_PREFIX}vitest-pool-assemblyscript/`\n\n/** Paths instrumentation exclusions and assetion error stack frame filtering */\nexport const POOL_INTERNAL_PATHS: string[] = [\n // AS compiler source maps these as relative paths when running locally\n 'assembly/compare.ts',\n 'assembly/describe.ts',\n 'assembly/expect.ts',\n 'assembly/index.ts',\n 'assembly/options.ts',\n 'assembly/test.ts',\n\n // AS compiler source maps these as library paths when running published version\n `${INTERNAL_PATH_LIB_PREFIX}assembly/compare.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}assembly/describe.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}assembly/expect.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}assembly/index.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}assembly/options.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}assembly/test.ts`,\n] as const;\n\n/** Error names for AssemblyScript test failures reported to vitest */\nexport const TEST_ERROR_NAMES = {\n /** Assertion evaluated to false within a test function */\n AssertionError: 'AssertionError',\n /** WASM runtime called abort after a non-planned user code error */\n WASMRuntimeError: 'WASMRuntimeError',\n} as const;\n\n/** Error names for internal AssemblyScript pool failures */\nexport const POOL_ERROR_NAMES = {\n /** AssemblyScript compiler (asc) error */\n CompilationError: 'CompilationError',\n /** Native instrumentation and debug info extraction error */\n WASMInstrumentationError: 'WASMInstrumentationError',\n /** Unexpected WASM execution error (not a known test error path) */\n WASMExecutionHarnessError: 'WASMExecutionHarnessError',\n /** Hybrid coverage provider error */\n HybridCoverageProviderError: 'HybridCoverageProviderError',\n /** vitest RPC reporting error */\n PoolReportingError: 'PoolReportingError',\n /** User configuration error */\n PoolConfigError: 'PoolConfigError',\n /** Generic AssemblyScript pool error */\n PoolError: 'PoolError',\n /** User syntax error in test/suite/expect */\n PoolSyntaxError: 'PoolSyntaxError',\n\n /** Flow Control: Indicates intentional abort */\n PoolRunAbortedError: 'PoolRunAbortedError',\n /**\n * Flow Control: Indicates WASM execution halt through abort() handler,\n * and should be handled by reporting an AssemblyScriptTestError to vitest\n */\n WASMExecutionAbortError: 'WASMExecutionAbortError',\n /** Flow Control: Indicates WASM execution halt because test timeout elapsed */\n WASMExecutionTimeoutError: 'WASMExecutionTimeoutError',\n} as const;\n\n// ============================================================================\n// AssemblyScript Compiler\n// ============================================================================\n\n// Redefined locally to avoid isolatedModules const enum access issues\n// with assemmblyscript enum exports. Reference assemblyscript.generated.d.ts\n\nexport const ASCommonFlags = {\n Static: 32,\n Get: 2048,\n Set: 4096,\n} as const;\n\nexport const ASNodeKind = {\n Source: 0,\n NamedType: 1,\n FunctionType: 2,\n TypeName: 3,\n TypeParameter: 4,\n Parameter: 5,\n Identifier: 6,\n Assertion: 7,\n Binary: 8,\n Call: 9,\n Class: 10,\n Comma: 11,\n ElementAccess: 12,\n False: 13,\n Function: 14,\n InstanceOf: 15,\n Literal: 16,\n New: 17,\n Null: 18,\n Omitted: 19,\n Parenthesized: 20,\n PropertyAccess: 21,\n Ternary: 22,\n Super: 23,\n This: 24,\n True: 25,\n Constructor: 26,\n UnaryPostfix: 27,\n UnaryPrefix: 28,\n Compiled: 29,\n Block: 30,\n Break: 31,\n Continue: 32,\n Do: 33,\n Empty: 34,\n Export: 35,\n ExportDefault: 36,\n ExportImport: 37,\n Expression: 38,\n For: 39,\n ForOf: 40,\n If: 41,\n Import: 42,\n Return: 43,\n Switch: 44,\n Throw: 45,\n Try: 46,\n Variable: 47,\n Void: 48,\n While: 49,\n Module: 50,\n ClassDeclaration: 51,\n EnumDeclaration: 52,\n EnumValueDeclaration: 53,\n FieldDeclaration: 54,\n FunctionDeclaration: 55,\n ImportDeclaration: 56,\n InterfaceDeclaration: 57,\n MethodDeclaration: 58,\n NamespaceDeclaration: 59,\n TypeDeclaration: 60,\n VariableDeclaration: 61,\n Decorator: 62,\n ExportMember: 63,\n SwitchCase: 64,\n IndexSignature: 65,\n Comment: 66,\n} as const;\n\nexport const ASDecoratorKind = {\n Custom: 0,\n Global: 1,\n Operator: 2,\n OperatorBinary: 3,\n OperatorPrefix: 4,\n OperatorPostfix: 5,\n Unmanaged: 6,\n Final: 7,\n Inline: 8,\n External: 9,\n ExternalJs: 10,\n Builtin: 11,\n Lazy: 12,\n Unsafe: 13\n} as const;\n\nexport const ASSourceKind = {\n User: 0,\n UserEntry: 1,\n Library: 2,\n LibraryEntry: 3\n} as const;\n"],"mappings":";AAuBA,MAAa,2BAA2B,EACtC,gBAAgB,kBACjB;;AAGD,MAAa,4BAA4B;AAEzC,MAAM,2BAA2B,WAA6B;;AAG9D,MAAa,sBAAgC;CAE3C;CACA;CACA;CACA;CACA;CACA;CAGA,GAAG,yBAAyB;CAC5B,GAAG,yBAAyB;CAC5B,GAAG,yBAAyB;CAC5B,GAAG,yBAAyB;CAC5B,GAAG,yBAAyB;CAC5B,GAAG,yBAAyB;CAC7B;;AAGD,MAAa,mBAAmB;CAE9B,gBAAgB;CAEhB,kBAAkB;CACnB;;AAGD,MAAa,mBAAmB;CAE9B,kBAAkB;CAElB,0BAA0B;CAE1B,2BAA2B;CAE3B,6BAA6B;CAE7B,oBAAoB;CAEpB,iBAAiB;CAEjB,WAAW;CAEX,iBAAiB;CAGjB,qBAAqB;CAKrB,yBAAyB;CAEzB,2BAA2B;CAC5B;AASD,MAAa,gBAAgB;CAC3B,QAAQ;CACR,KAAK;CACL,KAAK;CACN;AAED,MAAa,aAAa;CACxB,QAAQ;CACR,WAAW;CACX,cAAc;CACd,UAAU;CACV,eAAe;CACf,WAAW;CACX,YAAY;CACZ,WAAW;CACX,QAAQ;CACR,MAAM;CACN,OAAO;CACP,OAAO;CACP,eAAe;CACf,OAAO;CACP,UAAU;CACV,YAAY;CACZ,SAAS;CACT,KAAK;CACL,MAAM;CACN,SAAS;CACT,eAAe;CACf,gBAAgB;CAChB,SAAS;CACT,OAAO;CACP,MAAM;CACN,MAAM;CACN,aAAa;CACb,cAAc;CACd,aAAa;CACb,UAAU;CACV,OAAO;CACP,OAAO;CACP,UAAU;CACV,IAAI;CACJ,OAAO;CACP,QAAQ;CACR,eAAe;CACf,cAAc;CACd,YAAY;CACZ,KAAK;CACL,OAAO;CACP,IAAI;CACJ,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,KAAK;CACL,UAAU;CACV,MAAM;CACN,OAAO;CACP,QAAQ;CACR,kBAAkB;CAClB,iBAAiB;CACjB,sBAAsB;CACtB,kBAAkB;CAClB,qBAAqB;CACrB,mBAAmB;CACnB,sBAAsB;CACtB,mBAAmB;CACnB,sBAAsB;CACtB,iBAAiB;CACjB,qBAAqB;CACrB,WAAW;CACX,cAAc;CACd,YAAY;CACZ,gBAAgB;CAChB,SAAS;CACV;AAED,MAAa,kBAAkB;CAC7B,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;CACjB,WAAW;CACX,OAAO;CACP,QAAQ;CACR,UAAU;CACV,YAAY;CACZ,SAAS;CACT,MAAM;CACN,QAAQ;CACT;AAED,MAAa,eAAe;CAC1B,MAAM;CACN,WAAW;CACX,SAAS;CACT,cAAc;CACf"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ASCommonFlags, ASNodeKind, COVERAGE_PAYLOAD_FORMATS, POOL_ERROR_NAMES } from "../constants-
|
|
2
|
-
import { getProjectSerializedOrGlobalConfig } from "../resolve-config-
|
|
3
|
-
import { createPoolError, debug } from "../debug-
|
|
1
|
+
import { ASCommonFlags, ASNodeKind, COVERAGE_PAYLOAD_FORMATS, POOL_ERROR_NAMES } from "../constants-DX9yo-el.mjs";
|
|
2
|
+
import { getProjectSerializedOrGlobalConfig } from "../resolve-config-BKjJQyy5.mjs";
|
|
3
|
+
import { createPoolError, debug } from "../debug-Cf2jt1kg.mjs";
|
|
4
4
|
import { mergeCoverageData } from "../coverage-merge-0WqdC-dq.mjs";
|
|
5
|
-
import { ASTVisitor } from "../ast-visitor-
|
|
5
|
+
import { ASTVisitor } from "../ast-visitor-lTahoS9R.mjs";
|
|
6
6
|
import { basename, parse, relative } from "node:path";
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
8
8
|
import v8CoverageModule from "@vitest/coverage-v8";
|
|
9
|
-
import
|
|
9
|
+
import istanbulCoverage from "istanbul-lib-coverage";
|
|
10
10
|
import { Parser } from "assemblyscript";
|
|
11
11
|
import { resolve as resolve$1 } from "path";
|
|
12
12
|
import TestExclude from "test-exclude";
|
|
@@ -355,6 +355,7 @@ function globFiles(include, exclude, projectRoot) {
|
|
|
355
355
|
* - Delegates JS coverage to Vitest's v8 provider
|
|
356
356
|
* - Merges both into a unified coverage report
|
|
357
357
|
*/
|
|
358
|
+
const { createCoverageMap } = istanbulCoverage;
|
|
358
359
|
var HybridCoverageProvider = class {
|
|
359
360
|
name = "hybrid-assemblyscript-v8";
|
|
360
361
|
v8Provider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["parsePath","AssemblyScriptParser","resolve"],"sources":["../../src/coverage-provider/containment-matcher.ts","../../src/coverage-provider/istanbul-converter.ts","../../src/coverage-provider/ast-parser.ts","../../src/coverage-provider/glob-utils.ts","../../src/coverage-provider/hybrid-coverage-provider.ts","../../src/coverage-provider/index.ts"],"sourcesContent":["/**\n * Containment Matcher\n *\n * Provides containment-based matching for coverage mapping.\n * Binary debug info provides points (representativeLocation), source parsing provides ranges.\n * We find which source range contains each binary point.\n *\n * Usage by version:\n * - v1: Function containment matching (binary representativeLocation → source function range)\n * - v2: Function containment (same) + statement containment + branch path containment\n *\n * Why containment matching (not direct position lookup):\n * AS compiler generates source map entries differently by statement type:\n * - Variable declarations: source map points to statement start (keyword)\n * - Control flow (if/switch/for): source map points to condition EXPRESSION, not keyword\n *\n * Example: `if (n < 0)` → binary reports column 7 ('n'), not column 3 ('i' of 'if')\n *\n * Containment matching is more robust:\n * - Binary gives us a position (representativeLocation) somewhere in the function\n * - Source gives us function ranges (start/end line/column)\n * - We find which source function range contains the binary position\n * - Handles nested functions with \"tightest fit\" (innermost function wins)\n */\n\nimport type { ParsedSourceFunctionInfo, SourceRange } from '../types/types.js';\n\n/**\n * Functions indexed by file path, then by start line.\n * Multiple functions can start on the same line (e.g., nested arrow functions).\n */\nexport type FunctionsByFileAndStartLine = Record<string, Record<number, ParsedSourceFunctionInfo[]>>;\n\n/**\n * Find the source function whose range contains the given position.\n *\n * For nested functions, uses \"tightest fit\" - returns the innermost function\n * (the one with the largest start position among all containing functions).\n *\n * @param functionsByStartLine - Functions for a single file, indexed by start line\n * @param line - Target line number (1-based)\n * @param column - Target column number (1-based)\n * @returns The containing function, or undefined if no match\n */\nexport function findFunctionContainingPosition(\n functionsByStartLine: Record<number, ParsedSourceFunctionInfo[]>,\n line: number,\n column: number\n): ParsedSourceFunctionInfo | undefined {\n let bestMatch: ParsedSourceFunctionInfo | undefined;\n let bestStartLine = -1;\n let bestStartColumn = -1;\n\n // Check functions starting on lines <= target line\n for (const [startLineStr, functions] of Object.entries(functionsByStartLine)) {\n const startLine = Number(startLineStr);\n if (startLine > line) continue;\n\n for (const func of functions) {\n const { range } = func;\n\n // Check if position is within this function's range\n if (!isPositionInRange(line, column, range)) continue;\n\n // Tightest fit: prefer function with largest start position (innermost)\n if (startLine > bestStartLine ||\n (startLine === bestStartLine && range.startColumn > bestStartColumn)) {\n bestMatch = func;\n bestStartLine = startLine;\n bestStartColumn = range.startColumn;\n }\n }\n }\n\n return bestMatch;\n}\n\n/**\n * Check if a position (line, column) falls within a source range.\n *\n * @param line - Target line number (1-based)\n * @param column - Target column number (1-based)\n * @param range - Source range to check against\n * @returns true if position is within range (inclusive)\n */\nexport function isPositionInRange(\n line: number,\n column: number,\n range: SourceRange\n): boolean {\n // Outside line range entirely\n if (line < range.startLine || line > range.endLine) return false;\n\n // On start line but before start column\n if (line === range.startLine && column < range.startColumn) return false;\n\n // On end line but after end column\n if (line === range.endLine && column > range.endColumn) return false;\n\n return true;\n}\n","/**\n * Istanbul Format Converter\n *\n * Converts AssemblyScript coverage data to Istanbul's FileCoverageData format.\n * This enables integration with Vitest's coverage reporting system and standard\n * coverage tools like Codecov, Coveralls, etc.\n *\n * Current Implementation: Function-level coverage only\n * - Uses containment matching: binary positions → source function ranges\n * - Each function maps to both a function entry AND a statement entry\n * - Statement coverage matches function coverage (function-level granularity)\n * - Branch coverage is 0% (no branches tracked yet)\n * - Line coverage derived from statement coverage\n *\n * Future Enhancement (v2): Block-level statement and branch coverage\n */\n\nimport type { FileCoverageData, Range, FunctionMapping, BranchMapping } from 'istanbul-lib-coverage';\nimport type { ParsedSourceFunctionInfo } from '../types/types.js';\nimport { findFunctionContainingPosition } from './containment-matcher.js';\nimport { debug } from '../util/debug.js';\n\nconst DEBUG_ISTANBUL = false;\n\nfunction istanbulDebug(...args: any[]): void {\n if (DEBUG_ISTANBUL) {\n debug(...args);\n }\n};\n\n/**\n * Convert AssemblyScript coverage data to Istanbul format for a single file\n *\n * Algorithm (containment matching):\n * 1. For each hit position in fileHitCountsByPosition:\n * - Use containment matcher to find which source function contains this position\n * - Record the hit count for that function\n * 2. For each function in fileFunctionsByStartLine:\n * - Add function mapping to fnMap\n * - Add function hit count to f (from matched hits, or 0 if not hit)\n * - Add corresponding statement mapping to statementMap\n * - Add same hit count to s (statement coverage matches function coverage)\n *\n * @param fileFunctionsByStartLine - Functions for this file, keyed by start line (from AST parser)\n * @param fileHitCountsByPosition - Hit counts for this file, keyed by position \"line:column\" (from accumulated coverage)\n * @param absoluteFilePath - Absolute path to the source file (for Istanbul output)\n * @returns Istanbul FileCoverage object\n */\nexport async function convertToIstanbulFormat(\n fileFunctionsByStartLine: Record<number, ParsedSourceFunctionInfo[]>,\n fileHitCountsByPosition: Record<string, number>,\n absoluteFilePath: string\n): Promise<FileCoverageData> {\n const startMatch = performance.now();\n\n istanbulDebug(() => {\n const sourceFunctionCount = Object.values(fileFunctionsByStartLine).reduce((sum, funcs) => sum + funcs.length, 0);\n const uniqueHitPosCount = Object.keys(fileHitCountsByPosition).length;\n const coverageEstimate = sourceFunctionCount === 0 ? Infinity : ((uniqueHitPosCount * 100) / sourceFunctionCount).toFixed(2);\n\n return `[IstanbulConverter] Processing source file: \"${absoluteFilePath}\"\\n`\n + `[IstanbulConverter] Source: ${sourceFunctionCount} total functions, Coverage: ${uniqueHitPosCount} unique hit positions\\n`\n + `[IstanbulConverter] Sanity Check - AS File Coverage Estimate: ${coverageEstimate}%\\n`\n + `[IstanbulConverter] Containment matching functions: coverage hit positions to source functions by range`;\n });\n\n // Build a map of function → hit count using containment matching\n // Key: function source identity (qualifiedName), Value: hit count\n const hitCountsBySourceFunctionName = new Map<ParsedSourceFunctionInfo, number>();\n\n // For each hit position, find which function contains it\n for (const [positionKey, hitCount] of Object.entries(fileHitCountsByPosition)) {\n // Position key format is \"line:column\"\n const parts = positionKey.split(':');\n const lineStr = parts[0];\n const columnStr = parts[1];\n\n if (lineStr && columnStr) {\n const line = parseInt(lineStr, 10);\n const column = parseInt(columnStr, 10);\n\n const containingFunction = findFunctionContainingPosition(fileFunctionsByStartLine, line, column);\n if (containingFunction) {\n // Accumulate hits (in case multiple positions map to same function)\n const existingHits = hitCountsBySourceFunctionName.get(containingFunction);\n const existingHitsCount = existingHits ?? 0;\n const max = Math.max(existingHitsCount, hitCount);\n hitCountsBySourceFunctionName.set(containingFunction, max); // <-- TODO: Explain this max logic\n\n if (existingHits !== undefined) {\n istanbulDebug(`[IstanbulConverter] Position ${positionKey} → function \"${containingFunction.shortName}\" EXISTING HITS: ${existingHits} NEW COUNT: ${max}`);\n } else {\n istanbulDebug(`[IstanbulConverter] Position ${positionKey} → function \"${containingFunction.shortName}\" (hits: ${hitCount})`);\n }\n } else {\n istanbulDebug(`[IstanbulConverter] Position ${positionKey} has no containing function`);\n }\n }\n }\n\n const startConvert = performance.now();\n istanbulDebug(`[IstanbulConverter] Matching Complete - Converting to Istanbul format`);\n\n // Initialize Istanbul data structures\n const fnMap: { [key: string]: FunctionMapping } = {};\n const f: { [key: string]: number } = {};\n const statementMap: { [key: string]: Range } = {};\n const s: { [key: string]: number } = {};\n const branchMap: { [key: string]: BranchMapping } = {};\n const b: { [key: string]: number[] } = {};\n\n // Convert function coverage to Istanbul format\n // Iterate all functions from parsed source (ensures 0-hit functions are included)\n let funcIdx = 0;\n for (const functions of Object.values(fileFunctionsByStartLine)) {\n for (const funcInfo of functions) {\n const { range, shortName } = funcInfo;\n\n // Defensive: skip functions with invalid metadata (shouldn't happen - AST parser filters these)\n if (range.startLine === 0) {\n continue;\n }\n\n // Get hit count from containment matching (or 0 if not hit)\n const hitCount = hitCountsBySourceFunctionName.get(funcInfo) ?? 0;\n const displayShortName = shortName && shortName !== '' ? shortName : '<anonymous>';\n istanbulDebug(\n `[IstanbulConverter] Istanbul function index ${funcIdx}: \"${displayShortName}\"`\n + ` (source ${range.startLine}:${range.startColumn} - ${range.endLine}:${range.endColumn}), hits: ${hitCount}`\n );\n\n // Create function mapping\n // Both 'decl' (declaration) and 'loc' (location) use the same range\n // Internal ParsedSourceFunctionInfo uses 1-based columns, Istanbul expects 0-based\n const istanbulRange: Range = {\n start: { line: range.startLine, column: range.startColumn - 1 },\n end: { line: range.endLine, column: range.endColumn - 1 }\n };\n\n const idxStr = funcIdx.toString();\n fnMap[idxStr] = {\n name: shortName,\n decl: istanbulRange,\n loc: istanbulRange,\n line: range.startLine\n };\n f[idxStr] = hitCount;\n\n // Create corresponding statement mapping\n // For function-level coverage, each function is one \"statement\"\n // The statement range matches the function range\n // This gives us statement coverage at function granularity\n statementMap[idxStr] = istanbulRange;\n s[idxStr] = hitCount;\n\n funcIdx++;\n }\n }\n\n const done = performance.now();\n const matchingMs = (startConvert - startMatch).toFixed(2);\n const convertMs = (done - startConvert).toFixed(2);\n const totalMs = (done - startMatch).toFixed(2);\n\n istanbulDebug(\n `[IstanbulConverter] Coverage Coversion Complete: ${Object.keys(fnMap).length} functions,` \n + ` ${totalMs} ms total (matching: ${matchingMs} ms, convert: ${convertMs} ms)`\n );\n\n return {\n path: absoluteFilePath,\n fnMap,\n f,\n statementMap,\n s,\n branchMap,\n b\n };\n}\n","/**\n * AST Parser for AssemblyScript Source Files\n *\n * Parses AS source files to extract function metadata for coverage.\n * Used by generateCoverage to build empty coverage map from all source files.\n *\n * Source AST is the source of truth for what SHOULD be covered.\n * Binary instrumentation tells us what we CAN measure (hit counts).\n *\n * Functions are grouped by start line for efficient containment matching.\n *\n * Architecture:\n * - Uses shared ASTVisitor for complete NodeKind coverage\n * - Overrides hooks to extract function information during traversal\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { parse as parsePath } from 'node:path';\nimport {\n Parser as AssemblyScriptParser,\n Source,\n BlockStatement,\n Node,\n FunctionDeclaration,\n MethodDeclaration,\n ClassDeclaration,\n VariableDeclaration,\n FunctionExpression,\n} from 'assemblyscript';\n\nimport type { ParsedSourceFunctionInfo, SourceRange } from '../types/types.js';\nimport { ASCommonFlags, ASNodeKind } from '../types/constants.js';\nimport { ASTVisitor } from '../util/ast-visitor.js';\n\n/**\n * Visitor that extracts function information from AST nodes\n */\nclass FunctionExtractorVisitor extends ASTVisitor {\n /** Source file being parsed */\n private source: Source;\n /** Module path for building qualified names */\n private modulePath: string;\n /** Absolute file path */\n private filePath: string;\n /** Accumulated function records, keyed by start line */\n readonly functions: Record<number, ParsedSourceFunctionInfo[]> = {};\n /** Current class name (when inside a class) */\n private currentClassName: string | null = null;\n\n constructor(source: Source, modulePath: string, filePath: string) {\n super();\n this.source = source;\n this.modulePath = modulePath;\n this.filePath = filePath;\n }\n\n /**\n * Track class context when entering a class\n */\n protected onClassEnter(node: ClassDeclaration): void {\n this.currentClassName = node.name?.text ?? 'Anonymous';\n }\n\n /**\n * Restore class context when exiting a class\n */\n protected onClassExit(_node: ClassDeclaration): void {\n this.currentClassName = null;\n }\n\n /**\n * Extract function info from function declarations\n */\n protected onFunctionDeclaration(node: FunctionDeclaration): boolean {\n if (node.body && this.hasBodyStatements(node.body)) {\n const shortName = node.name?.text ?? '~anonymous';\n const qualifiedName = `${this.modulePath}/${shortName}`;\n const range = this.buildRange(node, node.name ?? null);\n this.addFunction(qualifiedName, shortName, range);\n }\n return true; // Continue recursion into body\n }\n\n /**\n * Extract function info from method declarations\n */\n protected onMethodDeclaration(node: MethodDeclaration): boolean {\n if (node.body && this.hasBodyStatements(node.body)) {\n const methodName = node.name?.text ?? 'constructor';\n const className = this.currentClassName ?? 'Unknown';\n const flags = node.flags;\n\n // Determine method type from flags\n const isStatic = (flags & ASCommonFlags.Static) !== 0;\n const isGetter = (flags & ASCommonFlags.Get) !== 0;\n const isSetter = (flags & ASCommonFlags.Set) !== 0;\n\n // Build short name to match binary naming convention:\n // - Static: ClassName.methodName\n // - Getter: ClassName#get:propertyName\n // - Setter: ClassName#set:propertyName\n // - Instance: ClassName#methodName\n let shortName: string;\n if (isStatic) {\n shortName = `${className}.${methodName}`;\n } else if (isGetter) {\n shortName = `${className}#get:${methodName}`;\n } else if (isSetter) {\n shortName = `${className}#set:${methodName}`;\n } else {\n shortName = `${className}#${methodName}`;\n }\n\n const qualifiedName = `${this.modulePath}/${shortName}`;\n const range = this.buildRange(node, node.name ?? null);\n this.addFunction(qualifiedName, shortName, range);\n }\n return true; // Continue recursion into body\n }\n\n /**\n * Extract function info from variable declarations (arrow functions)\n */\n protected onVariableDeclaration(node: VariableDeclaration): boolean {\n if (node.initializer && node.initializer.kind === ASNodeKind.Function) {\n const funcExpr = node.initializer as FunctionExpression;\n const funcDecl = funcExpr.declaration;\n\n if (funcDecl.body && this.hasBodyStatements(funcDecl.body)) {\n // Use variable name for the function\n const shortName = node.name.text;\n const qualifiedName = `${this.modulePath}/${shortName}`;\n\n // Use the variable declaration's range\n const range: SourceRange = {\n filePath: this.filePath,\n startLine: this.source.lineAt(node.range.start),\n startColumn: this.source.columnAt(),\n endLine: this.source.lineAt(node.range.end),\n endColumn: this.source.columnAt(),\n };\n\n this.addFunction(qualifiedName, shortName, range);\n }\n\n // Visit the function body manually since we're handling this specially\n if (funcDecl.body) {\n this.visitNode(funcDecl.body);\n }\n return false; // Don't recurse again - we handled it\n }\n return true; // Continue recursion for non-function initializers\n }\n\n /**\n * Check if a function body has statements (non-empty body)\n */\n private hasBodyStatements(body: Node): boolean {\n if (body.kind === ASNodeKind.Block) {\n const blockBody = body as BlockStatement;\n return blockBody.statements.length > 0;\n }\n // Expression body (braceless arrow) - always has the expression\n return true;\n }\n\n /**\n * Add a function to the functions record, keyed by start line\n */\n private addFunction(qualifiedName: string, shortName: string, range: SourceRange): void {\n const startLine = range.startLine;\n if (!this.functions[startLine]) {\n this.functions[startLine] = [];\n }\n this.functions[startLine].push({ qualifiedName, shortName, range });\n }\n\n /**\n * Build a SourceRange for a node, using name.range.start to skip decorators\n */\n private buildRange(node: Node, nameNode: Node | null): SourceRange {\n const startNode = nameNode ?? node;\n return {\n filePath: this.filePath,\n startLine: this.source.lineAt(startNode.range.start),\n startColumn: this.source.columnAt(),\n endLine: this.source.lineAt(node.range.end),\n endColumn: this.source.columnAt(),\n };\n }\n}\n\n/**\n * Parse functions from a single AS source file\n *\n * @param absoluteSourceFilePath - Absolute path to AS source file\n * @param relativeSourceFilePath - Relative path to AS source file (derived once in caller and used several places)\n * @returns Record of start line to array of ParsedSourceFunctionInfo (multiple functions can start on same line)\n */\nexport async function parseFunctionsFromFile(\n absoluteSourceFilePath: string,\n relativeSourceFilePath: string,\n): Promise<Record<number, ParsedSourceFunctionInfo[]>> {\n const sourceCode = await readFile(absoluteSourceFilePath, 'utf8');\n\n // Build the module path (strip any extension, use forward slashes)\n const parsed = parsePath(relativeSourceFilePath);\n const modulePath = parsed.dir ? `${parsed.dir}/${parsed.name}` : parsed.name;\n\n // Parse with AssemblyScript parser\n const asParser = new AssemblyScriptParser();\n asParser.parseFile(sourceCode, relativeSourceFilePath, true);\n\n const source = asParser.currentSource;\n if (!source) {\n return {};\n }\n\n // Create visitor and traverse\n const visitor = new FunctionExtractorVisitor(source, modulePath, absoluteSourceFilePath);\n visitor.visitSource(source);\n\n return visitor.functions || {};\n}\n","/**\n * Glob Utilities for Coverage\n *\n * Uses test-exclude (same as Vitest's v8 coverage provider) to glob\n * AssemblyScript files matching coverage.include patterns.\n */\n\nimport { resolve } from 'path';\nimport TestExclude from 'test-exclude';\n\nimport { GlobResult } from '../types/types.js';\n\n/**\n * Glob files matching coverage include/exclude patterns\n *\n * Uses test-exclude for consistent behavior with Vitest's built-in\n * coverage providers.\n *\n * @param include - Include patterns (e.g., ['assembly/**\\/*.ts'])\n * @param exclude - Exclude patterns (e.g., ['**\\/*.test.ts'])\n * @param projectRoot - Project root directory\n * @returns Array of absolute file paths\n */\nexport function globFiles(\n include: string[],\n exclude: string[],\n projectRoot: string\n): GlobResult[] {\n // avoid issues with default behavior being grabbing from cwd\n if (include.length === 0) {\n return [];\n }\n\n const testExclude = new TestExclude({\n cwd: projectRoot,\n include,\n exclude,\n excludeNodeModules: true,\n });\n\n const includedFiles = testExclude.globSync(projectRoot);\n const results: GlobResult[] = includedFiles.map((file: string) => ({\n absolute: resolve(projectRoot, file),\n projectRootRelative: file\n })) || [];\n\n return results;\n}\n","/**\n * Hybrid Coverage Provider\n *\n * This provider handles both AssemblyScript and JavaScript and coverage\n * - Converts AS coverage to Istanbul format\n * - Delegates JS coverage to Vitest's v8 provider\n * - Merges both into a unified coverage report\n */\n\nimport { basename, relative } from 'node:path';\nimport type {\n CoverageProvider,\n Vitest,\n ReportContext,\n ResolvedCoverageOptions,\n CustomProviderOptions,\n ResolvedConfig,\n} from 'vitest/node';\nimport type { AfterSuiteRunMeta, SerializedConfig } from 'vitest';\nimport v8CoverageModule from '@vitest/coverage-v8';\nimport { type CoverageMap, createCoverageMap } from 'istanbul-lib-coverage';\n\n// pick up CustomProviderOptions module augmentation\nimport '../config/custom-provider-options.js';\n\nimport { convertToIstanbulFormat } from './istanbul-converter.js';\nimport { parseFunctionsFromFile } from './ast-parser.js';\nimport { globFiles } from './glob-utils.js';\nimport { getProjectSerializedOrGlobalConfig } from '../util/resolve-config.js';\nimport { mergeCoverageData } from './coverage-merge.js';\nimport { debug } from '../util/debug.js';\nimport { createPoolError } from '../util/pool-errors.js';\nimport type {\n AssemblyScriptCoveragePayload,\n CoverageData,\n GlobResult,\n ResolvedHybridProviderOptions,\n} from '../types/types.js';\nimport {\n POOL_ERROR_NAMES,\n COVERAGE_PAYLOAD_FORMATS\n} from '../types/constants.js';\n\nexport class HybridCoverageProvider implements CoverageProvider {\n name = 'hybrid-assemblyscript-v8' as const;\n\n private v8Provider: CoverageProvider | undefined;\n private accumulatedCoverageData: CoverageData = { hitCountsByFileAndPosition: {} };\n private projectConfig: SerializedConfig | ResolvedConfig = {} as SerializedConfig;\n private coverageOptions: ResolvedHybridProviderOptions = {} as ResolvedHybridProviderOptions;\n\n /**\n * Initialize the provider and get reference to v8 provider\n */\n async initialize(ctx: Vitest): Promise<void> {\n this.projectConfig = getProjectSerializedOrGlobalConfig(ctx).config;\n\n debug('[HybridCoverageProvider] Initializing Provider');\n\n // Get v8 provider from the coverage module\n this.v8Provider = await v8CoverageModule.getProvider();\n\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - initialize failed to get delegated v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n await this.v8Provider.initialize(ctx);\n this.v8Provider.name = 'hybrid-assemblyscript-v8 (delegated v8 reporter)' as const;\n debug('[HybridCoverageProvider] Initialized with delegated v8 provider');\n }\n\n /**\n * Handle suite completion - delegate based on coverage format marker\n */\n async onAfterSuiteRun(meta: AfterSuiteRunMeta): Promise<void> {\n const start = performance.now();\n const format: string | undefined = (meta?.coverage as any)?.__format;\n let suiteLogLabel = meta.testFiles.length > 0 ? basename(meta.testFiles[0]!) : '';\n\n // Check for AssemblyScript format marker\n if (format === COVERAGE_PAYLOAD_FORMATS.AssemblyScript) {\n const payload = meta.coverage as AssemblyScriptCoveragePayload;\n const { coverageData, suiteLogLabel: label } = payload;\n suiteLogLabel = label;\n\n debug(() => {\n const fileCount = Object.keys(coverageData.hitCountsByFileAndPosition).length;\n const positionCount = Object.values(coverageData.hitCountsByFileAndPosition)\n .reduce((sum, positions) => sum + Object.keys(positions).length, 0);\n return `[HybridCoverageProvider] ${suiteLogLabel} - onAfterSuiteRun - Suite payload: ${positionCount} unique positions over ${fileCount} source files`;\n });\n\n // Merge incoming coverage data into accumulated (by position, summing hit counts)\n mergeCoverageData(this.accumulatedCoverageData, coverageData);\n\n debug(() => {\n const fileCount = Object.keys(this.accumulatedCoverageData.hitCountsByFileAndPosition).length;\n const positionCount = Object.values(this.accumulatedCoverageData.hitCountsByFileAndPosition)\n .reduce((sum, positions) => sum + Object.keys(positions).length, 0);\n return `[HybridCoverageProvider] ${suiteLogLabel} - onAfterSuiteRun - Accumulated coverage: ${positionCount} unique positions over ${fileCount} source files`;\n });\n } else {\n // Delegate to v8 provider for all other formats (JS, etc.)\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - onAfterSuiteRun failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n debug(`[HybridCoverageProvider] ${suiteLogLabel} - Delegating to v8 provider`);\n await this.v8Provider.onAfterSuiteRun(meta);\n }\n\n debug(() => {\n const files = meta.testFiles.map(tf => relative(this.projectConfig.root, tf)).join(',');\n return `[HybridCoverageProvider] ${suiteLogLabel} - onAfterSuiteRun complete - TIMING ${(performance.now() - start).toFixed(2)} ms | testFiles: \"${files}\"`;\n });\n }\n\n /**\n * Generate unified coverage map (merging JS and AS coverage)\n *\n * Flow:\n * 1. Parse included AS source files to get sourceDebugInfo (source of truth for line numbers)\n * 1. Build merged CoverageData (all source functions + accumulated hit counts)\n * 4. Convert merged CoverageData to Istanbul format\n * 5. Get JS coverage from v8 provider\n * 6. Merge AS coverage into JS coverage\n */\n async generateCoverage(context: ReportContext): Promise<unknown> {\n const start = performance.now();\n\n debug('[HybridCoverageProvider] Generating coverage for test run');\n\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - generateCoverage failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n // Build AS coverage map\n let asCoverageMap = createCoverageMap();\n\n if (this.coverageOptions.globbedAssemblyScriptInclude?.length > 0) {\n debug(`[HybridCoverageProvider] Building AS coverage map with ${this.coverageOptions.globbedAssemblyScriptInclude.length} source files `);\n debug(() => {\n const accumulatedPositionCount = Object.values(this.accumulatedCoverageData.hitCountsByFileAndPosition)\n .reduce((sum, positions) => sum + Object.keys(positions)?.length, 0);\n const files = Object.keys(this.accumulatedCoverageData.hitCountsByFileAndPosition).length;\n return `[HybridCoverageProvider] Accumulated coverage data has ${accumulatedPositionCount} unique positions hit across ${files} debug source files`;\n });\n\n // parse source files with AST parser, then match to hits and convert to istanbul format\n const fileProcessingPromises = this.coverageOptions.globbedAssemblyScriptInclude.map(async (include: GlobResult) => {\n debug(`[HybridCoverageProvider] Parsing AS source for expected coverage: \"${include.absolute}\" (file key: \"${include.projectRootRelative}\")`);\n \n const functionsByStartLine = await parseFunctionsFromFile(include.absolute, include.projectRootRelative) || {};\n debug(`[HybridCoverageProvider] Parsed ${Object.keys(functionsByStartLine).length} AS source functions in \"${include.projectRootRelative}\"`);\n\n const fileHitCountsByPosition = this.accumulatedCoverageData.hitCountsByFileAndPosition[include.projectRootRelative] ?? {};\n debug(`[HybridCoverageProvider] Accumulated AS coverage has ${Object.keys(fileHitCountsByPosition).length} positions for \"${include.projectRootRelative}\"`);\n\n // Containment matching (binary hit position → source) is performed during istanbul conversion\n return convertToIstanbulFormat(functionsByStartLine, fileHitCountsByPosition, include.absolute);\n });\n\n // Wait for all files to complete\n const istanbulResults = await Promise.all(fileProcessingPromises);\n\n // Add all results to coverage map\n for (const istanbulData of istanbulResults) {\n asCoverageMap.addFileCoverage(istanbulData);\n }\n\n debug(`[HybridCoverageProvider] Built AS coverage map with ${Object.keys(asCoverageMap.data).length} files`);\n } else {\n debug('[HybridCoverageProvider] WARNING: No assemblyScriptInclude patterns yieldled files - Coverage Map will be empty!');\n }\n\n const asGenerateEnd = performance.now();\n debug(`[HybridCoverageProvider] TIMING AS generateCoverage: ${(asGenerateEnd - start).toFixed(2)} ms`);\n\n // Get JS coverage from v8 provider\n debug('[HybridCoverageProvider] Getting JS coverage from v8 provider');\n const jsCoverage = await this.v8Provider.generateCoverage(context) as CoverageMap;\n debug(`[HybridCoverageProvider] JS coverage has ${Object.keys(jsCoverage.data).length} files`);\n debug(`[HybridCoverageProvider] TIMING JS generateCoverage: ${(performance.now() - asGenerateEnd).toFixed(2)} ms`);\n\n // Merge AS coverage into JS coverage\n debug('[HybridCoverageProvider] Merging AS coverage into JS coverage');\n jsCoverage.merge(asCoverageMap);\n debug(`[HybridCoverageProvider] Final merged coverage has ${Object.keys(jsCoverage.data).length} files`);\n\n debug(`[HybridCoverageProvider] TIMING Total generateCoverage: ${(performance.now() - start).toFixed(2)} ms`);\n\n return jsCoverage;\n }\n\n /**\n * Report coverage - delegate to v8 provider\n */\n async reportCoverage(coverageMap: unknown, context: ReportContext): Promise<void> {\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - reportCoverage failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n debug(`[HybridCoverageProvider] Reporting coverage (allTestsRun=${context.allTestsRun})`);\n await this.v8Provider.reportCoverage(coverageMap, context);\n }\n\n /**\n * Resolve options\n */\n resolveOptions(): ResolvedHybridProviderOptions {\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - resolveOptions failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n \n debug(`[HybridCoverageProvider] Resolving Coverage Options`);\n \n const definedCoverageOptions = this.projectConfig.coverage as CustomProviderOptions;\n const resolvedV8Options = this.v8Provider.resolveOptions() as ResolvedCoverageOptions<'v8'>;\n\n // For some reason the v8 provider builds its `excludes` values to include a null byte.\n // Remove null bytes for logging purposes so tools like grep won't complain about binary content.\n const sanitizedV8Options: ResolvedCoverageOptions<'v8'> = {\n ...resolvedV8Options,\n include: resolvedV8Options.include?.map(i => i.replace(/\\0/g, '')) || undefined,\n exclude: resolvedV8Options.exclude?.map(i => i.replace(/\\0/g, '')) || undefined\n };\n\n debug(`[HybridCoverageProvider] AS include: ${(definedCoverageOptions.assemblyScriptInclude || []).join(', ') || '(none)'}`);\n debug(`[HybridCoverageProvider] AS exclude: ${(definedCoverageOptions.assemblyScriptExclude || []).join(', ') || '(none)'}`);\n debug(`[HybridCoverageProvider] JS include: ${(sanitizedV8Options.include || []).join(', ') || '(none)'}`);\n debug(`[HybridCoverageProvider] JS exclude: ${(sanitizedV8Options.exclude || []).join(', ') || '(none)'}`);\n\n debug(`[HybridCoverageProvider] Globbing AS source files to include for coverage map basis`);\n const globbedAssemblyScriptInclude = globFiles(\n definedCoverageOptions.assemblyScriptInclude || [],\n definedCoverageOptions.assemblyScriptExclude || [],\n this.projectConfig.root\n );\n debug(`[HybridCoverageProvider] Including ${globbedAssemblyScriptInclude.length} AS files in coverage map`);\n \n const globbedAssemblyScriptExcludeOnly = globFiles(\n definedCoverageOptions.assemblyScriptExclude || [],\n [],\n this.projectConfig.root\n );\n debug(`[HybridCoverageProvider] Excluding ${globbedAssemblyScriptExcludeOnly.length} AS files from coverage map & instrumentation`);\n \n const resolvedCoverageOptions: ResolvedHybridProviderOptions = {\n ...resolvedV8Options,\n provider: 'custom',\n customProviderModule: definedCoverageOptions.customProviderModule,\n assemblyScriptInclude: definedCoverageOptions.assemblyScriptInclude ?? [],\n assemblyScriptExclude: definedCoverageOptions.assemblyScriptExclude ?? [],\n globbedAssemblyScriptInclude,\n globbedAssemblyScriptProjectRelativeExcludeOnly : globbedAssemblyScriptExcludeOnly.map(gr => gr.projectRootRelative)\n }; \n\n this.coverageOptions = resolvedCoverageOptions;\n return resolvedCoverageOptions;\n }\n\n async clean(clean: boolean = true): Promise<void> {\n debug('[HybridCoverageProvider] Clean coverage data - clean:', clean);\n if (clean) {\n this.accumulatedCoverageData = { hitCountsByFileAndPosition: {} };\n debug('[HybridCoverageProvider] Cleaned all internal coverage data');\n }\n\n if (this.v8Provider) {\n await this.v8Provider.clean(clean);\n debug(`[HybridCoverageProvider] V8 provider finished clean(${clean})`);\n }\n }\n}\n","/**\n * Coverage Provider Module Export\n *\n * This module exports the hybrid coverage provider for Vitest to load.\n * Users configure this via:\n * coverage.provider = 'custom'\n * coverage.customProviderModule = 'vitest-pool-assemblyscript/coverage'\n */\n\nimport { CoverageProviderModule } from 'vitest/node';\nimport v8CoverageModule from '@vitest/coverage-v8';\n\nimport { POOL_ERROR_NAMES } from '../types/constants.js';\nimport { createPoolError } from '../util/pool-errors.js';\nimport { HybridCoverageProvider } from './hybrid-coverage-provider.js';\n\n/**\n * Hybrid Coverage Provider\n *\n * This provider handles both AssemblyScript and JavaScript and coverage\n * - Converts AS coverage to Istanbul format\n * - Delegates JS coverage to Vitest's v8 provider\n * - Merges both into a unified coverage report\n */\nconst hybridProviderModule: CoverageProviderModule = {\n getProvider: (): HybridCoverageProvider => new HybridCoverageProvider(),\n\n startCoverage: async (runtimeOptions: {\n isolate: boolean\n }): Promise<unknown> => {\n if (v8CoverageModule.startCoverage) {\n return await v8CoverageModule.startCoverage(runtimeOptions);\n } else {\n throw createPoolError(\n 'HybridCoverageProvider - v8 coverage module does not provide `startCoverage`',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n },\n \n takeCoverage: async (runtimeOptions?: any): Promise<unknown> => {\n if (v8CoverageModule.takeCoverage) {\n return await v8CoverageModule.takeCoverage(runtimeOptions);\n } else {\n throw createPoolError(\n 'HybridCoverageProvider - v8 coverage module does not provide `takeCoverage`',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n },\n \n stopCoverage: async (runtimeOptions: {\n isolate: boolean\n }): Promise<unknown> => {\n if (v8CoverageModule.stopCoverage) {\n return await v8CoverageModule.stopCoverage(runtimeOptions);\n } else {\n throw createPoolError(\n 'HybridCoverageProvider - v8 coverage module does not provide `stopCoverage`',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n },\n};\n\nexport default hybridProviderModule;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["parsePath","AssemblyScriptParser","resolve"],"sources":["../../src/coverage-provider/containment-matcher.ts","../../src/coverage-provider/istanbul-converter.ts","../../src/coverage-provider/ast-parser.ts","../../src/coverage-provider/glob-utils.ts","../../src/coverage-provider/hybrid-coverage-provider.ts","../../src/coverage-provider/index.ts"],"sourcesContent":["/**\n * Containment Matcher\n *\n * Provides containment-based matching for coverage mapping.\n * Binary debug info provides points (representativeLocation), source parsing provides ranges.\n * We find which source range contains each binary point.\n *\n * Usage by version:\n * - v1: Function containment matching (binary representativeLocation → source function range)\n * - v2: Function containment (same) + statement containment + branch path containment\n *\n * Why containment matching (not direct position lookup):\n * AS compiler generates source map entries differently by statement type:\n * - Variable declarations: source map points to statement start (keyword)\n * - Control flow (if/switch/for): source map points to condition EXPRESSION, not keyword\n *\n * Example: `if (n < 0)` → binary reports column 7 ('n'), not column 3 ('i' of 'if')\n *\n * Containment matching is more robust:\n * - Binary gives us a position (representativeLocation) somewhere in the function\n * - Source gives us function ranges (start/end line/column)\n * - We find which source function range contains the binary position\n * - Handles nested functions with \"tightest fit\" (innermost function wins)\n */\n\nimport type { ParsedSourceFunctionInfo, SourceRange } from '../types/types.js';\n\n/**\n * Functions indexed by file path, then by start line.\n * Multiple functions can start on the same line (e.g., nested arrow functions).\n */\nexport type FunctionsByFileAndStartLine = Record<string, Record<number, ParsedSourceFunctionInfo[]>>;\n\n/**\n * Find the source function whose range contains the given position.\n *\n * For nested functions, uses \"tightest fit\" - returns the innermost function\n * (the one with the largest start position among all containing functions).\n *\n * @param functionsByStartLine - Functions for a single file, indexed by start line\n * @param line - Target line number (1-based)\n * @param column - Target column number (1-based)\n * @returns The containing function, or undefined if no match\n */\nexport function findFunctionContainingPosition(\n functionsByStartLine: Record<number, ParsedSourceFunctionInfo[]>,\n line: number,\n column: number\n): ParsedSourceFunctionInfo | undefined {\n let bestMatch: ParsedSourceFunctionInfo | undefined;\n let bestStartLine = -1;\n let bestStartColumn = -1;\n\n // Check functions starting on lines <= target line\n for (const [startLineStr, functions] of Object.entries(functionsByStartLine)) {\n const startLine = Number(startLineStr);\n if (startLine > line) continue;\n\n for (const func of functions) {\n const { range } = func;\n\n // Check if position is within this function's range\n if (!isPositionInRange(line, column, range)) continue;\n\n // Tightest fit: prefer function with largest start position (innermost)\n if (startLine > bestStartLine ||\n (startLine === bestStartLine && range.startColumn > bestStartColumn)) {\n bestMatch = func;\n bestStartLine = startLine;\n bestStartColumn = range.startColumn;\n }\n }\n }\n\n return bestMatch;\n}\n\n/**\n * Check if a position (line, column) falls within a source range.\n *\n * @param line - Target line number (1-based)\n * @param column - Target column number (1-based)\n * @param range - Source range to check against\n * @returns true if position is within range (inclusive)\n */\nexport function isPositionInRange(\n line: number,\n column: number,\n range: SourceRange\n): boolean {\n // Outside line range entirely\n if (line < range.startLine || line > range.endLine) return false;\n\n // On start line but before start column\n if (line === range.startLine && column < range.startColumn) return false;\n\n // On end line but after end column\n if (line === range.endLine && column > range.endColumn) return false;\n\n return true;\n}\n","/**\n * Istanbul Format Converter\n *\n * Converts AssemblyScript coverage data to Istanbul's FileCoverageData format.\n * This enables integration with Vitest's coverage reporting system and standard\n * coverage tools like Codecov, Coveralls, etc.\n *\n * Current Implementation: Function-level coverage only\n * - Uses containment matching: binary positions → source function ranges\n * - Each function maps to both a function entry AND a statement entry\n * - Statement coverage matches function coverage (function-level granularity)\n * - Branch coverage is 0% (no branches tracked yet)\n * - Line coverage derived from statement coverage\n *\n * Future Enhancement (v2): Block-level statement and branch coverage\n */\n\nimport type { FileCoverageData, Range, FunctionMapping, BranchMapping } from 'istanbul-lib-coverage';\nimport type { ParsedSourceFunctionInfo } from '../types/types.js';\nimport { findFunctionContainingPosition } from './containment-matcher.js';\nimport { debug } from '../util/debug.js';\n\nconst DEBUG_ISTANBUL = false;\n\nfunction istanbulDebug(...args: any[]): void {\n if (DEBUG_ISTANBUL) {\n debug(...args);\n }\n};\n\n/**\n * Convert AssemblyScript coverage data to Istanbul format for a single file\n *\n * Algorithm (containment matching):\n * 1. For each hit position in fileHitCountsByPosition:\n * - Use containment matcher to find which source function contains this position\n * - Record the hit count for that function\n * 2. For each function in fileFunctionsByStartLine:\n * - Add function mapping to fnMap\n * - Add function hit count to f (from matched hits, or 0 if not hit)\n * - Add corresponding statement mapping to statementMap\n * - Add same hit count to s (statement coverage matches function coverage)\n *\n * @param fileFunctionsByStartLine - Functions for this file, keyed by start line (from AST parser)\n * @param fileHitCountsByPosition - Hit counts for this file, keyed by position \"line:column\" (from accumulated coverage)\n * @param absoluteFilePath - Absolute path to the source file (for Istanbul output)\n * @returns Istanbul FileCoverage object\n */\nexport async function convertToIstanbulFormat(\n fileFunctionsByStartLine: Record<number, ParsedSourceFunctionInfo[]>,\n fileHitCountsByPosition: Record<string, number>,\n absoluteFilePath: string\n): Promise<FileCoverageData> {\n const startMatch = performance.now();\n\n istanbulDebug(() => {\n const sourceFunctionCount = Object.values(fileFunctionsByStartLine).reduce((sum, funcs) => sum + funcs.length, 0);\n const uniqueHitPosCount = Object.keys(fileHitCountsByPosition).length;\n const coverageEstimate = sourceFunctionCount === 0 ? Infinity : ((uniqueHitPosCount * 100) / sourceFunctionCount).toFixed(2);\n\n return `[IstanbulConverter] Processing source file: \"${absoluteFilePath}\"\\n`\n + `[IstanbulConverter] Source: ${sourceFunctionCount} total functions, Coverage: ${uniqueHitPosCount} unique hit positions\\n`\n + `[IstanbulConverter] Sanity Check - AS File Coverage Estimate: ${coverageEstimate}%\\n`\n + `[IstanbulConverter] Containment matching functions: coverage hit positions to source functions by range`;\n });\n\n // Build a map of function → hit count using containment matching\n // Key: function source identity (qualifiedName), Value: hit count\n const hitCountsBySourceFunctionName = new Map<ParsedSourceFunctionInfo, number>();\n\n // For each hit position, find which function contains it\n for (const [positionKey, hitCount] of Object.entries(fileHitCountsByPosition)) {\n // Position key format is \"line:column\"\n const parts = positionKey.split(':');\n const lineStr = parts[0];\n const columnStr = parts[1];\n\n if (lineStr && columnStr) {\n const line = parseInt(lineStr, 10);\n const column = parseInt(columnStr, 10);\n\n const containingFunction = findFunctionContainingPosition(fileFunctionsByStartLine, line, column);\n if (containingFunction) {\n // Accumulate hits (in case multiple positions map to same function)\n const existingHits = hitCountsBySourceFunctionName.get(containingFunction);\n const existingHitsCount = existingHits ?? 0;\n const max = Math.max(existingHitsCount, hitCount);\n hitCountsBySourceFunctionName.set(containingFunction, max); // <-- TODO: Explain this max logic\n\n if (existingHits !== undefined) {\n istanbulDebug(`[IstanbulConverter] Position ${positionKey} → function \"${containingFunction.shortName}\" EXISTING HITS: ${existingHits} NEW COUNT: ${max}`);\n } else {\n istanbulDebug(`[IstanbulConverter] Position ${positionKey} → function \"${containingFunction.shortName}\" (hits: ${hitCount})`);\n }\n } else {\n istanbulDebug(`[IstanbulConverter] Position ${positionKey} has no containing function`);\n }\n }\n }\n\n const startConvert = performance.now();\n istanbulDebug(`[IstanbulConverter] Matching Complete - Converting to Istanbul format`);\n\n // Initialize Istanbul data structures\n const fnMap: { [key: string]: FunctionMapping } = {};\n const f: { [key: string]: number } = {};\n const statementMap: { [key: string]: Range } = {};\n const s: { [key: string]: number } = {};\n const branchMap: { [key: string]: BranchMapping } = {};\n const b: { [key: string]: number[] } = {};\n\n // Convert function coverage to Istanbul format\n // Iterate all functions from parsed source (ensures 0-hit functions are included)\n let funcIdx = 0;\n for (const functions of Object.values(fileFunctionsByStartLine)) {\n for (const funcInfo of functions) {\n const { range, shortName } = funcInfo;\n\n // Defensive: skip functions with invalid metadata (shouldn't happen - AST parser filters these)\n if (range.startLine === 0) {\n continue;\n }\n\n // Get hit count from containment matching (or 0 if not hit)\n const hitCount = hitCountsBySourceFunctionName.get(funcInfo) ?? 0;\n const displayShortName = shortName && shortName !== '' ? shortName : '<anonymous>';\n istanbulDebug(\n `[IstanbulConverter] Istanbul function index ${funcIdx}: \"${displayShortName}\"`\n + ` (source ${range.startLine}:${range.startColumn} - ${range.endLine}:${range.endColumn}), hits: ${hitCount}`\n );\n\n // Create function mapping\n // Both 'decl' (declaration) and 'loc' (location) use the same range\n // Internal ParsedSourceFunctionInfo uses 1-based columns, Istanbul expects 0-based\n const istanbulRange: Range = {\n start: { line: range.startLine, column: range.startColumn - 1 },\n end: { line: range.endLine, column: range.endColumn - 1 }\n };\n\n const idxStr = funcIdx.toString();\n fnMap[idxStr] = {\n name: shortName,\n decl: istanbulRange,\n loc: istanbulRange,\n line: range.startLine\n };\n f[idxStr] = hitCount;\n\n // Create corresponding statement mapping\n // For function-level coverage, each function is one \"statement\"\n // The statement range matches the function range\n // This gives us statement coverage at function granularity\n statementMap[idxStr] = istanbulRange;\n s[idxStr] = hitCount;\n\n funcIdx++;\n }\n }\n\n const done = performance.now();\n const matchingMs = (startConvert - startMatch).toFixed(2);\n const convertMs = (done - startConvert).toFixed(2);\n const totalMs = (done - startMatch).toFixed(2);\n\n istanbulDebug(\n `[IstanbulConverter] Coverage Coversion Complete: ${Object.keys(fnMap).length} functions,` \n + ` ${totalMs} ms total (matching: ${matchingMs} ms, convert: ${convertMs} ms)`\n );\n\n return {\n path: absoluteFilePath,\n fnMap,\n f,\n statementMap,\n s,\n branchMap,\n b\n };\n}\n","/**\n * AST Parser for AssemblyScript Source Files\n *\n * Parses AS source files to extract function metadata for coverage.\n * Used by generateCoverage to build empty coverage map from all source files.\n *\n * Source AST is the source of truth for what SHOULD be covered.\n * Binary instrumentation tells us what we CAN measure (hit counts).\n *\n * Functions are grouped by start line for efficient containment matching.\n *\n * Architecture:\n * - Uses shared ASTVisitor for complete NodeKind coverage\n * - Overrides hooks to extract function information during traversal\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { parse as parsePath } from 'node:path';\nimport {\n Parser as AssemblyScriptParser,\n Source,\n BlockStatement,\n Node,\n FunctionDeclaration,\n MethodDeclaration,\n ClassDeclaration,\n VariableDeclaration,\n FunctionExpression,\n} from 'assemblyscript';\n\nimport type { ParsedSourceFunctionInfo, SourceRange } from '../types/types.js';\nimport { ASCommonFlags, ASNodeKind } from '../types/constants.js';\nimport { ASTVisitor } from '../util/ast-visitor.js';\n\n/**\n * Visitor that extracts function information from AST nodes\n */\nclass FunctionExtractorVisitor extends ASTVisitor {\n /** Source file being parsed */\n private source: Source;\n /** Module path for building qualified names */\n private modulePath: string;\n /** Absolute file path */\n private filePath: string;\n /** Accumulated function records, keyed by start line */\n readonly functions: Record<number, ParsedSourceFunctionInfo[]> = {};\n /** Current class name (when inside a class) */\n private currentClassName: string | null = null;\n\n constructor(source: Source, modulePath: string, filePath: string) {\n super();\n this.source = source;\n this.modulePath = modulePath;\n this.filePath = filePath;\n }\n\n /**\n * Track class context when entering a class\n */\n protected onClassEnter(node: ClassDeclaration): void {\n this.currentClassName = node.name?.text ?? 'Anonymous';\n }\n\n /**\n * Restore class context when exiting a class\n */\n protected onClassExit(_node: ClassDeclaration): void {\n this.currentClassName = null;\n }\n\n /**\n * Extract function info from function declarations\n */\n protected onFunctionDeclaration(node: FunctionDeclaration): boolean {\n if (node.body && this.hasBodyStatements(node.body)) {\n const shortName = node.name?.text ?? '~anonymous';\n const qualifiedName = `${this.modulePath}/${shortName}`;\n const range = this.buildRange(node, node.name ?? null);\n this.addFunction(qualifiedName, shortName, range);\n }\n return true; // Continue recursion into body\n }\n\n /**\n * Extract function info from method declarations\n */\n protected onMethodDeclaration(node: MethodDeclaration): boolean {\n if (node.body && this.hasBodyStatements(node.body)) {\n const methodName = node.name?.text ?? 'constructor';\n const className = this.currentClassName ?? 'Unknown';\n const flags = node.flags;\n\n // Determine method type from flags\n const isStatic = (flags & ASCommonFlags.Static) !== 0;\n const isGetter = (flags & ASCommonFlags.Get) !== 0;\n const isSetter = (flags & ASCommonFlags.Set) !== 0;\n\n // Build short name to match binary naming convention:\n // - Static: ClassName.methodName\n // - Getter: ClassName#get:propertyName\n // - Setter: ClassName#set:propertyName\n // - Instance: ClassName#methodName\n let shortName: string;\n if (isStatic) {\n shortName = `${className}.${methodName}`;\n } else if (isGetter) {\n shortName = `${className}#get:${methodName}`;\n } else if (isSetter) {\n shortName = `${className}#set:${methodName}`;\n } else {\n shortName = `${className}#${methodName}`;\n }\n\n const qualifiedName = `${this.modulePath}/${shortName}`;\n const range = this.buildRange(node, node.name ?? null);\n this.addFunction(qualifiedName, shortName, range);\n }\n return true; // Continue recursion into body\n }\n\n /**\n * Extract function info from variable declarations (arrow functions)\n */\n protected onVariableDeclaration(node: VariableDeclaration): boolean {\n if (node.initializer && node.initializer.kind === ASNodeKind.Function) {\n const funcExpr = node.initializer as FunctionExpression;\n const funcDecl = funcExpr.declaration;\n\n if (funcDecl.body && this.hasBodyStatements(funcDecl.body)) {\n // Use variable name for the function\n const shortName = node.name.text;\n const qualifiedName = `${this.modulePath}/${shortName}`;\n\n // Use the variable declaration's range\n const range: SourceRange = {\n filePath: this.filePath,\n startLine: this.source.lineAt(node.range.start),\n startColumn: this.source.columnAt(),\n endLine: this.source.lineAt(node.range.end),\n endColumn: this.source.columnAt(),\n };\n\n this.addFunction(qualifiedName, shortName, range);\n }\n\n // Visit the function body manually since we're handling this specially\n if (funcDecl.body) {\n this.visitNode(funcDecl.body);\n }\n return false; // Don't recurse again - we handled it\n }\n return true; // Continue recursion for non-function initializers\n }\n\n /**\n * Check if a function body has statements (non-empty body)\n */\n private hasBodyStatements(body: Node): boolean {\n if (body.kind === ASNodeKind.Block) {\n const blockBody = body as BlockStatement;\n return blockBody.statements.length > 0;\n }\n // Expression body (braceless arrow) - always has the expression\n return true;\n }\n\n /**\n * Add a function to the functions record, keyed by start line\n */\n private addFunction(qualifiedName: string, shortName: string, range: SourceRange): void {\n const startLine = range.startLine;\n if (!this.functions[startLine]) {\n this.functions[startLine] = [];\n }\n this.functions[startLine].push({ qualifiedName, shortName, range });\n }\n\n /**\n * Build a SourceRange for a node, using name.range.start to skip decorators\n */\n private buildRange(node: Node, nameNode: Node | null): SourceRange {\n const startNode = nameNode ?? node;\n return {\n filePath: this.filePath,\n startLine: this.source.lineAt(startNode.range.start),\n startColumn: this.source.columnAt(),\n endLine: this.source.lineAt(node.range.end),\n endColumn: this.source.columnAt(),\n };\n }\n}\n\n/**\n * Parse functions from a single AS source file\n *\n * @param absoluteSourceFilePath - Absolute path to AS source file\n * @param relativeSourceFilePath - Relative path to AS source file (derived once in caller and used several places)\n * @returns Record of start line to array of ParsedSourceFunctionInfo (multiple functions can start on same line)\n */\nexport async function parseFunctionsFromFile(\n absoluteSourceFilePath: string,\n relativeSourceFilePath: string,\n): Promise<Record<number, ParsedSourceFunctionInfo[]>> {\n const sourceCode = await readFile(absoluteSourceFilePath, 'utf8');\n\n // Build the module path (strip any extension, use forward slashes)\n const parsed = parsePath(relativeSourceFilePath);\n const modulePath = parsed.dir ? `${parsed.dir}/${parsed.name}` : parsed.name;\n\n // Parse with AssemblyScript parser\n const asParser = new AssemblyScriptParser();\n asParser.parseFile(sourceCode, relativeSourceFilePath, true);\n\n const source = asParser.currentSource;\n if (!source) {\n return {};\n }\n\n // Create visitor and traverse\n const visitor = new FunctionExtractorVisitor(source, modulePath, absoluteSourceFilePath);\n visitor.visitSource(source);\n\n return visitor.functions || {};\n}\n","/**\n * Glob Utilities for Coverage\n *\n * Uses test-exclude (same as Vitest's v8 coverage provider) to glob\n * AssemblyScript files matching coverage.include patterns.\n */\n\nimport { resolve } from 'path';\nimport TestExclude from 'test-exclude';\n\nimport { GlobResult } from '../types/types.js';\n\n/**\n * Glob files matching coverage include/exclude patterns\n *\n * Uses test-exclude for consistent behavior with Vitest's built-in\n * coverage providers.\n *\n * @param include - Include patterns (e.g., ['assembly/**\\/*.ts'])\n * @param exclude - Exclude patterns (e.g., ['**\\/*.test.ts'])\n * @param projectRoot - Project root directory\n * @returns Array of absolute file paths\n */\nexport function globFiles(\n include: string[],\n exclude: string[],\n projectRoot: string\n): GlobResult[] {\n // avoid issues with default behavior being grabbing from cwd\n if (include.length === 0) {\n return [];\n }\n\n const testExclude = new TestExclude({\n cwd: projectRoot,\n include,\n exclude,\n excludeNodeModules: true,\n });\n\n const includedFiles = testExclude.globSync(projectRoot);\n const results: GlobResult[] = includedFiles.map((file: string) => ({\n absolute: resolve(projectRoot, file),\n projectRootRelative: file\n })) || [];\n\n return results;\n}\n","/**\n * Hybrid Coverage Provider\n *\n * This provider handles both AssemblyScript and JavaScript and coverage\n * - Converts AS coverage to Istanbul format\n * - Delegates JS coverage to Vitest's v8 provider\n * - Merges both into a unified coverage report\n */\n\nimport { basename, relative } from 'node:path';\nimport type {\n CoverageProvider,\n Vitest,\n ReportContext,\n ResolvedCoverageOptions,\n CustomProviderOptions,\n ResolvedConfig,\n} from 'vitest/node';\nimport type { AfterSuiteRunMeta, SerializedConfig } from 'vitest';\nimport v8CoverageModule from '@vitest/coverage-v8';\nimport type { CoverageMap } from 'istanbul-lib-coverage';\nimport istanbulCoverage from 'istanbul-lib-coverage';\nconst { createCoverageMap } = istanbulCoverage;\n\n// pick up CustomProviderOptions module augmentation\nimport '../config/custom-provider-options.js';\n\nimport { convertToIstanbulFormat } from './istanbul-converter.js';\nimport { parseFunctionsFromFile } from './ast-parser.js';\nimport { globFiles } from './glob-utils.js';\nimport { getProjectSerializedOrGlobalConfig } from '../util/resolve-config.js';\nimport { mergeCoverageData } from './coverage-merge.js';\nimport { debug } from '../util/debug.js';\nimport { createPoolError } from '../util/pool-errors.js';\nimport type {\n AssemblyScriptCoveragePayload,\n CoverageData,\n GlobResult,\n ResolvedHybridProviderOptions,\n} from '../types/types.js';\nimport {\n POOL_ERROR_NAMES,\n COVERAGE_PAYLOAD_FORMATS\n} from '../types/constants.js';\n\nexport class HybridCoverageProvider implements CoverageProvider {\n name = 'hybrid-assemblyscript-v8' as const;\n\n private v8Provider: CoverageProvider | undefined;\n private accumulatedCoverageData: CoverageData = { hitCountsByFileAndPosition: {} };\n private projectConfig: SerializedConfig | ResolvedConfig = {} as SerializedConfig;\n private coverageOptions: ResolvedHybridProviderOptions = {} as ResolvedHybridProviderOptions;\n\n /**\n * Initialize the provider and get reference to v8 provider\n */\n async initialize(ctx: Vitest): Promise<void> {\n this.projectConfig = getProjectSerializedOrGlobalConfig(ctx).config;\n\n debug('[HybridCoverageProvider] Initializing Provider');\n\n // Get v8 provider from the coverage module\n this.v8Provider = await v8CoverageModule.getProvider();\n\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - initialize failed to get delegated v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n await this.v8Provider.initialize(ctx);\n this.v8Provider.name = 'hybrid-assemblyscript-v8 (delegated v8 reporter)' as const;\n debug('[HybridCoverageProvider] Initialized with delegated v8 provider');\n }\n\n /**\n * Handle suite completion - delegate based on coverage format marker\n */\n async onAfterSuiteRun(meta: AfterSuiteRunMeta): Promise<void> {\n const start = performance.now();\n const format: string | undefined = (meta?.coverage as any)?.__format;\n let suiteLogLabel = meta.testFiles.length > 0 ? basename(meta.testFiles[0]!) : '';\n\n // Check for AssemblyScript format marker\n if (format === COVERAGE_PAYLOAD_FORMATS.AssemblyScript) {\n const payload = meta.coverage as AssemblyScriptCoveragePayload;\n const { coverageData, suiteLogLabel: label } = payload;\n suiteLogLabel = label;\n\n debug(() => {\n const fileCount = Object.keys(coverageData.hitCountsByFileAndPosition).length;\n const positionCount = Object.values(coverageData.hitCountsByFileAndPosition)\n .reduce((sum, positions) => sum + Object.keys(positions).length, 0);\n return `[HybridCoverageProvider] ${suiteLogLabel} - onAfterSuiteRun - Suite payload: ${positionCount} unique positions over ${fileCount} source files`;\n });\n\n // Merge incoming coverage data into accumulated (by position, summing hit counts)\n mergeCoverageData(this.accumulatedCoverageData, coverageData);\n\n debug(() => {\n const fileCount = Object.keys(this.accumulatedCoverageData.hitCountsByFileAndPosition).length;\n const positionCount = Object.values(this.accumulatedCoverageData.hitCountsByFileAndPosition)\n .reduce((sum, positions) => sum + Object.keys(positions).length, 0);\n return `[HybridCoverageProvider] ${suiteLogLabel} - onAfterSuiteRun - Accumulated coverage: ${positionCount} unique positions over ${fileCount} source files`;\n });\n } else {\n // Delegate to v8 provider for all other formats (JS, etc.)\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - onAfterSuiteRun failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n debug(`[HybridCoverageProvider] ${suiteLogLabel} - Delegating to v8 provider`);\n await this.v8Provider.onAfterSuiteRun(meta);\n }\n\n debug(() => {\n const files = meta.testFiles.map(tf => relative(this.projectConfig.root, tf)).join(',');\n return `[HybridCoverageProvider] ${suiteLogLabel} - onAfterSuiteRun complete - TIMING ${(performance.now() - start).toFixed(2)} ms | testFiles: \"${files}\"`;\n });\n }\n\n /**\n * Generate unified coverage map (merging JS and AS coverage)\n *\n * Flow:\n * 1. Parse included AS source files to get sourceDebugInfo (source of truth for line numbers)\n * 1. Build merged CoverageData (all source functions + accumulated hit counts)\n * 4. Convert merged CoverageData to Istanbul format\n * 5. Get JS coverage from v8 provider\n * 6. Merge AS coverage into JS coverage\n */\n async generateCoverage(context: ReportContext): Promise<unknown> {\n const start = performance.now();\n\n debug('[HybridCoverageProvider] Generating coverage for test run');\n\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - generateCoverage failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n // Build AS coverage map\n let asCoverageMap = createCoverageMap();\n\n if (this.coverageOptions.globbedAssemblyScriptInclude?.length > 0) {\n debug(`[HybridCoverageProvider] Building AS coverage map with ${this.coverageOptions.globbedAssemblyScriptInclude.length} source files `);\n debug(() => {\n const accumulatedPositionCount = Object.values(this.accumulatedCoverageData.hitCountsByFileAndPosition)\n .reduce((sum, positions) => sum + Object.keys(positions)?.length, 0);\n const files = Object.keys(this.accumulatedCoverageData.hitCountsByFileAndPosition).length;\n return `[HybridCoverageProvider] Accumulated coverage data has ${accumulatedPositionCount} unique positions hit across ${files} debug source files`;\n });\n\n // parse source files with AST parser, then match to hits and convert to istanbul format\n const fileProcessingPromises = this.coverageOptions.globbedAssemblyScriptInclude.map(async (include: GlobResult) => {\n debug(`[HybridCoverageProvider] Parsing AS source for expected coverage: \"${include.absolute}\" (file key: \"${include.projectRootRelative}\")`);\n \n const functionsByStartLine = await parseFunctionsFromFile(include.absolute, include.projectRootRelative) || {};\n debug(`[HybridCoverageProvider] Parsed ${Object.keys(functionsByStartLine).length} AS source functions in \"${include.projectRootRelative}\"`);\n\n const fileHitCountsByPosition = this.accumulatedCoverageData.hitCountsByFileAndPosition[include.projectRootRelative] ?? {};\n debug(`[HybridCoverageProvider] Accumulated AS coverage has ${Object.keys(fileHitCountsByPosition).length} positions for \"${include.projectRootRelative}\"`);\n\n // Containment matching (binary hit position → source) is performed during istanbul conversion\n return convertToIstanbulFormat(functionsByStartLine, fileHitCountsByPosition, include.absolute);\n });\n\n // Wait for all files to complete\n const istanbulResults = await Promise.all(fileProcessingPromises);\n\n // Add all results to coverage map\n for (const istanbulData of istanbulResults) {\n asCoverageMap.addFileCoverage(istanbulData);\n }\n\n debug(`[HybridCoverageProvider] Built AS coverage map with ${Object.keys(asCoverageMap.data).length} files`);\n } else {\n debug('[HybridCoverageProvider] WARNING: No assemblyScriptInclude patterns yieldled files - Coverage Map will be empty!');\n }\n\n const asGenerateEnd = performance.now();\n debug(`[HybridCoverageProvider] TIMING AS generateCoverage: ${(asGenerateEnd - start).toFixed(2)} ms`);\n\n // Get JS coverage from v8 provider\n debug('[HybridCoverageProvider] Getting JS coverage from v8 provider');\n const jsCoverage = await this.v8Provider.generateCoverage(context) as CoverageMap;\n debug(`[HybridCoverageProvider] JS coverage has ${Object.keys(jsCoverage.data).length} files`);\n debug(`[HybridCoverageProvider] TIMING JS generateCoverage: ${(performance.now() - asGenerateEnd).toFixed(2)} ms`);\n\n // Merge AS coverage into JS coverage\n debug('[HybridCoverageProvider] Merging AS coverage into JS coverage');\n jsCoverage.merge(asCoverageMap);\n debug(`[HybridCoverageProvider] Final merged coverage has ${Object.keys(jsCoverage.data).length} files`);\n\n debug(`[HybridCoverageProvider] TIMING Total generateCoverage: ${(performance.now() - start).toFixed(2)} ms`);\n\n return jsCoverage;\n }\n\n /**\n * Report coverage - delegate to v8 provider\n */\n async reportCoverage(coverageMap: unknown, context: ReportContext): Promise<void> {\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - reportCoverage failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n\n debug(`[HybridCoverageProvider] Reporting coverage (allTestsRun=${context.allTestsRun})`);\n await this.v8Provider.reportCoverage(coverageMap, context);\n }\n\n /**\n * Resolve options\n */\n resolveOptions(): ResolvedHybridProviderOptions {\n if (!this.v8Provider) {\n throw createPoolError(\n 'HybridCoverageProvider - resolveOptions failed to delegate to v8 provider',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n \n debug(`[HybridCoverageProvider] Resolving Coverage Options`);\n \n const definedCoverageOptions = this.projectConfig.coverage as CustomProviderOptions;\n const resolvedV8Options = this.v8Provider.resolveOptions() as ResolvedCoverageOptions<'v8'>;\n\n // For some reason the v8 provider builds its `excludes` values to include a null byte.\n // Remove null bytes for logging purposes so tools like grep won't complain about binary content.\n const sanitizedV8Options: ResolvedCoverageOptions<'v8'> = {\n ...resolvedV8Options,\n include: resolvedV8Options.include?.map(i => i.replace(/\\0/g, '')) || undefined,\n exclude: resolvedV8Options.exclude?.map(i => i.replace(/\\0/g, '')) || undefined\n };\n\n debug(`[HybridCoverageProvider] AS include: ${(definedCoverageOptions.assemblyScriptInclude || []).join(', ') || '(none)'}`);\n debug(`[HybridCoverageProvider] AS exclude: ${(definedCoverageOptions.assemblyScriptExclude || []).join(', ') || '(none)'}`);\n debug(`[HybridCoverageProvider] JS include: ${(sanitizedV8Options.include || []).join(', ') || '(none)'}`);\n debug(`[HybridCoverageProvider] JS exclude: ${(sanitizedV8Options.exclude || []).join(', ') || '(none)'}`);\n\n debug(`[HybridCoverageProvider] Globbing AS source files to include for coverage map basis`);\n const globbedAssemblyScriptInclude = globFiles(\n definedCoverageOptions.assemblyScriptInclude || [],\n definedCoverageOptions.assemblyScriptExclude || [],\n this.projectConfig.root\n );\n debug(`[HybridCoverageProvider] Including ${globbedAssemblyScriptInclude.length} AS files in coverage map`);\n \n const globbedAssemblyScriptExcludeOnly = globFiles(\n definedCoverageOptions.assemblyScriptExclude || [],\n [],\n this.projectConfig.root\n );\n debug(`[HybridCoverageProvider] Excluding ${globbedAssemblyScriptExcludeOnly.length} AS files from coverage map & instrumentation`);\n \n const resolvedCoverageOptions: ResolvedHybridProviderOptions = {\n ...resolvedV8Options,\n provider: 'custom',\n customProviderModule: definedCoverageOptions.customProviderModule,\n assemblyScriptInclude: definedCoverageOptions.assemblyScriptInclude ?? [],\n assemblyScriptExclude: definedCoverageOptions.assemblyScriptExclude ?? [],\n globbedAssemblyScriptInclude,\n globbedAssemblyScriptProjectRelativeExcludeOnly : globbedAssemblyScriptExcludeOnly.map(gr => gr.projectRootRelative)\n }; \n\n this.coverageOptions = resolvedCoverageOptions;\n return resolvedCoverageOptions;\n }\n\n async clean(clean: boolean = true): Promise<void> {\n debug('[HybridCoverageProvider] Clean coverage data - clean:', clean);\n if (clean) {\n this.accumulatedCoverageData = { hitCountsByFileAndPosition: {} };\n debug('[HybridCoverageProvider] Cleaned all internal coverage data');\n }\n\n if (this.v8Provider) {\n await this.v8Provider.clean(clean);\n debug(`[HybridCoverageProvider] V8 provider finished clean(${clean})`);\n }\n }\n}\n","/**\n * Coverage Provider Module Export\n *\n * This module exports the hybrid coverage provider for Vitest to load.\n * Users configure this via:\n * coverage.provider = 'custom'\n * coverage.customProviderModule = 'vitest-pool-assemblyscript/coverage'\n */\n\nimport { CoverageProviderModule } from 'vitest/node';\nimport v8CoverageModule from '@vitest/coverage-v8';\n\nimport { POOL_ERROR_NAMES } from '../types/constants.js';\nimport { createPoolError } from '../util/pool-errors.js';\nimport { HybridCoverageProvider } from './hybrid-coverage-provider.js';\n\n/**\n * Hybrid Coverage Provider\n *\n * This provider handles both AssemblyScript and JavaScript and coverage\n * - Converts AS coverage to Istanbul format\n * - Delegates JS coverage to Vitest's v8 provider\n * - Merges both into a unified coverage report\n */\nconst hybridProviderModule: CoverageProviderModule = {\n getProvider: (): HybridCoverageProvider => new HybridCoverageProvider(),\n\n startCoverage: async (runtimeOptions: {\n isolate: boolean\n }): Promise<unknown> => {\n if (v8CoverageModule.startCoverage) {\n return await v8CoverageModule.startCoverage(runtimeOptions);\n } else {\n throw createPoolError(\n 'HybridCoverageProvider - v8 coverage module does not provide `startCoverage`',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n },\n \n takeCoverage: async (runtimeOptions?: any): Promise<unknown> => {\n if (v8CoverageModule.takeCoverage) {\n return await v8CoverageModule.takeCoverage(runtimeOptions);\n } else {\n throw createPoolError(\n 'HybridCoverageProvider - v8 coverage module does not provide `takeCoverage`',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n },\n \n stopCoverage: async (runtimeOptions: {\n isolate: boolean\n }): Promise<unknown> => {\n if (v8CoverageModule.stopCoverage) {\n return await v8CoverageModule.stopCoverage(runtimeOptions);\n } else {\n throw createPoolError(\n 'HybridCoverageProvider - v8 coverage module does not provide `stopCoverage`',\n POOL_ERROR_NAMES.HybridCoverageProviderError\n );\n }\n },\n};\n\nexport default hybridProviderModule;\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { POOL_ERROR_NAMES, TEST_ERROR_NAMES } from "./constants-
|
|
1
|
+
import { POOL_ERROR_NAMES, TEST_ERROR_NAMES } from "./constants-DX9yo-el.mjs";
|
|
2
2
|
import { stripVTControlCharacters } from "node:util";
|
|
3
3
|
import c from "tinyrainbow";
|
|
4
4
|
|
|
@@ -192,4 +192,4 @@ function isDebugModeEnabled() {
|
|
|
192
192
|
|
|
193
193
|
//#endregion
|
|
194
194
|
export { createPoolError, createPoolErrorFromAnyError, createTestExpectedToFailError, createTestTimeoutError, debug, getSourceCodeFrameString, getTestErrorFromPoolError, isAbortError, isDebugModeEnabled, setGlobalDebugMode, throwPoolErrorIfAborted, toPlaintextStackFrameString, toVitestLikeStackFrameString };
|
|
195
|
-
//# sourceMappingURL=debug-
|
|
195
|
+
//# sourceMappingURL=debug-Cf2jt1kg.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug-IeEHsxy0.mjs","names":[],"sources":["../src/util/test-error-formatting.ts","../src/util/pool-errors.ts","../src/util/debug.ts"],"sourcesContent":["import { stripVTControlCharacters } from 'node:util';\nimport type { RawSourceMap } from 'source-map';\nimport c from 'tinyrainbow';\nimport type { ParsedStack } from '@vitest/utils';\n\nimport { HighlightFunc } from '../types/types.js';\n\nconst FRAME_POINTER = '❯' as const;\nconst CODE_FRAME_INDENT_SPACES = 4 as const;\n\n// same performance guard used in vitest `printError`\nconst MAX_CODE_HIGHLIGHT_LENGTH = 100_000 as const;\n\nexport function getYellowString(str: string): string {\n return c.yellow(str);\n}\n\nexport function toPlaintextStackFrameString(frame: ParsedStack): string {\n return ` at ${frame.method} ${frame.file}:${frame.line}:${frame.column}`;\n}\n\nexport function toVitestLikeStackFrameString(frame: ParsedStack): string {\n return c.cyan(\n ` ${c.dim(FRAME_POINTER)} ${frame.method} ${frame.file}:${c.dim(`${frame.line}:${frame.column}`)}`\n );\n}\n\nexport function getSourceCodeFrameString(\n sourceMap: RawSourceMap,\n frame: ParsedStack,\n highlight: HighlightFunc,\n): string | undefined {\n if (!sourceMap.sourcesContent) {\n return undefined;\n }\n\n const fileIndex = sourceMap.sources.indexOf(frame.file);\n if (fileIndex < 0) {\n return undefined;\n }\n\n const source = sourceMap.sourcesContent[fileIndex];\n if (!source) {\n return undefined;\n }\n\n const highlightedSource = source.length < MAX_CODE_HIGHLIGHT_LENGTH\n ? highlight(source, { colors: c })\n : source;\n\n return generateCodeFrame(highlightedSource, CODE_FRAME_INDENT_SPACES, frame);\n}\n\n\n// ============================================================================\n// Source code formatting functions borrowed from Vitest\n// ============================================================================\n\n/**\n * Vitest doesn't expose generateCodeFrame as a util, so we have\n * recreated it here with minimal changes.\n * \n * @see https://github.com/vitest-dev/vitest/blob/v3.2.4/packages/vitest/src/node/printError.ts#L424\n * \n * Vitest is released under the MIT license, included in this project's root.\n * Copyright (c) 2021-Present Vitest Team\n */\n\nconst lineSplitRE: RegExp = /\\r?\\n/;\n\nfunction generateCodeFrame(\n source: string,\n indent = 0,\n loc: { line: number; column: number } | number,\n range = 2,\n): string {\n const start\n = typeof loc === 'object'\n ? positionToOffset(source, loc.line, loc.column)\n : loc\n const end = start\n const lines = source.split(lineSplitRE)\n const nl = /\\r\\n/.test(source) ? 2 : 1\n let count = 0\n let res: string[] = []\n\n const columns = process.stdout?.columns || 80\n\n for (let i = 0; i < lines.length; i++) {\n count += lines[i]!.length + nl\n if (count >= start) {\n for (let j = i - range; j <= i + range || end > count; j++) {\n if (j < 0 || j >= lines.length) {\n continue\n }\n\n const lineLength = lines[j]!.length\n\n // too long, maybe it's a minified file, skip for codeframe\n if (stripVTControlCharacters(lines[j]!).length > 200) {\n return ''\n }\n\n res.push(\n lineNo(j + 1)\n + truncateString(lines[j]!.replace(/\\t/g, ' '), columns - 5 - indent),\n )\n\n if (j === i) {\n // push underline\n const pad = start - (count - lineLength) + (nl - 1)\n const length = Math.max(\n 1,\n end > count ? lineLength - pad : end - start,\n )\n res.push(lineNo() + ' '.repeat(pad) + c.red('^'.repeat(length)))\n }\n else if (j > i) {\n if (end > count) {\n const length = Math.max(1, Math.min(end - count, lineLength))\n res.push(lineNo() + c.red('^'.repeat(length)))\n }\n count += lineLength + 1\n }\n }\n break\n }\n }\n\n if (indent) {\n res = res.map(line => ' '.repeat(indent) + line)\n }\n\n return res.join('\\n')\n}\n\n\nfunction positionToOffset(\n source: string,\n lineNumber: number,\n columnNumber: number,\n): number {\n const lines = source.split(lineSplitRE)\n const nl = /\\r\\n/.test(source) ? 2 : 1\n let start = 0\n\n if (lineNumber > lines.length) {\n return source.length\n }\n\n for (let i = 0; i < lineNumber - 1; i++) {\n start += lines[i]!.length + nl\n }\n\n return start + columnNumber\n}\n\nfunction lineNo(no: number | string = '') {\n return c.gray(`${String(no).padStart(3, ' ')}| `)\n}\n\nfunction truncateString(text: string, maxLength: number): string {\n const plainText = stripVTControlCharacters(text)\n\n if (plainText.length <= maxLength) {\n return text\n }\n\n return `${plainText.slice(0, maxLength - 1)}…`\n}\n","import type { Test } from '@vitest/runner/types';\n\nimport type {\n AssemblyScriptPoolError,\n AssemblyScriptTestError,\n PoolErrorName,\n TestErrorName\n} from '../types/types.js';\nimport {\n AS_POOL_ERROR_TYPE_FLAG,\n POOL_ERROR_NAMES,\n TEST_ERROR_NAMES\n} from '../types/constants.js';\nimport { getYellowString } from './test-error-formatting.js';\n\nexport function createPoolError(\n message: string,\n name: PoolErrorName,\n stack?: string,\n cause?: any,\n rawCallStack?: NodeJS.CallSite[],\n): AssemblyScriptPoolError {\n return { name, message, stack, cause, rawCallStack, [AS_POOL_ERROR_TYPE_FLAG]: true };\n}\n\nexport function createTestTimeoutError(\n test: Test\n): AssemblyScriptTestError {\n const message = `Test timed out after ${test.timeout}ms`;\n const err: AssemblyScriptTestError = {\n name: POOL_ERROR_NAMES.WASMExecutionTimeoutError,\n message,\n stack: `${test.id}_${message}`,\n diff: getYellowString(` Test Timeout Exceeded (${test.timeout}ms)`)\n };\n return err;\n}\n\nexport function createTestExpectedToFailError(test: Test): AssemblyScriptTestError {\n const message = `Test is expected to fail, but all assertions passed`;\n const err: AssemblyScriptTestError = {\n name: TEST_ERROR_NAMES.AssertionError,\n message,\n stack: `${test.id}_${message}`,\n diff: getYellowString(` Expected to fail, but all assertions passed`)\n };\n return err;\n}\n\nexport function throwPoolErrorIfAborted(signal?: AbortSignal): void {\n if (!signal || !signal.aborted) {\n return;\n }\n\n throw createPoolError(signal.reason, POOL_ERROR_NAMES.PoolRunAbortedError);\n}\n\nexport function isAbortErrorString(item: any): boolean {\n return item === POOL_ERROR_NAMES.PoolRunAbortedError || item === 'AbortError';\n}\n\nexport function isAbortError(error: any): boolean {\n return isAbortErrorString(error) \n || isAbortErrorString(error?.name)\n || error?.message === 'Terminating worker thread';\n}\n\nexport function createPoolErrorFromAnyError(\n context: string,\n contextErrorName: PoolErrorName,\n error: any\n): AssemblyScriptPoolError {\n const isErrorAbortString = isAbortErrorString(error);\n if (isErrorAbortString) {\n const msg = `${contextErrorName}: ${context} - Aborted, Unknown Cause`;\n return createPoolError(msg, POOL_ERROR_NAMES.PoolRunAbortedError);\n }\n\n if (error[AS_POOL_ERROR_TYPE_FLAG]) {\n return error as AssemblyScriptPoolError;\n }\n\n if (error instanceof Error) {\n const isAbortError = isAbortErrorString(error.name);\n const asErr = createPoolError(\n `${context} - ${error.name}: ${error.message}`,\n isAbortError ? POOL_ERROR_NAMES.PoolRunAbortedError : contextErrorName,\n error.stack,\n error.cause\n );\n return asErr;\n }\n\n const errorMsg = String(error);\n return createPoolError(`${context} - ${errorMsg}`, contextErrorName);\n}\n\nexport function getTestErrorFromPoolError(error: AssemblyScriptPoolError): AssemblyScriptTestError {\n const anyCause: any = error?.cause;\n if (error.causeIsEnhancedError) {\n return error.cause as AssemblyScriptTestError;\n }\n\n const message = error.message ?? anyCause.message ?? 'Unknown error';\n return {\n name: error.name ?? anyCause.name ?? POOL_ERROR_NAMES.PoolError,\n message,\n stack: anyCause?.stack ?? error.stack ?? message,\n stacks: anyCause?.stacks ,\n cause: getTestErrorFromAnyError(anyCause?.cause),\n diff: anyCause?.diff\n };\n}\n\nexport function getTestErrorFromAnyError(\n error: any,\n context: string = '',\n fallbackName: TestErrorName | PoolErrorName = POOL_ERROR_NAMES.PoolError\n): AssemblyScriptTestError | undefined {\n if (!error) {\n return undefined;\n }\n\n const message = `${context ?? ''}${error?.message ?? ''}`;\n return {\n name: error?.name ?? fallbackName,\n message,\n stack: error?.stack ?? message,\n stacks: error?.stacks,\n cause: getTestErrorFromAnyError(error?.cause)\n };\n}\n","/**\n * Debug logging utility\n */\n\ndeclare global {\n var AS_POOL_DEBUG: boolean | undefined;\n}\n\nglobalThis.AS_POOL_DEBUG = false;\n\nconst DEBUG_ENV_ENABLED_VALUE = '1' as const;\n\nfunction isEnabled(): boolean {\n return globalThis.AS_POOL_DEBUG === true || process.env.DEBUG === DEBUG_ENV_ENABLED_VALUE;\n}\n\n/**\n * Initialize debug mode for current async context (called by worker at task start)\n * @param {boolean} debugEnabled - Enable verbose debug logging\n */\nexport function setGlobalDebugMode(debugEnabled: boolean): void {\n globalThis.AS_POOL_DEBUG = debugEnabled;\n}\n\n/**\n * Log debug message (only when debug enabled in current global context)\n * or when environment has a truthy DEBUG variable set.\n */\nexport function debug(...args: any): void {\n if (isEnabled()) {\n // if first arg is a function, execute it and then print the result\n if (args?.length > 0 && typeof args[0] === 'function') {\n const result = args[0]();\n const rest = args.length > 1 ? args.slice(1) : [];\n console.log(Date.now(), String(result), ...rest);\n } else {\n console.log(Date.now(), ...args);\n }\n }\n}\n\n/**\n * Determine if debug mode is enabled for the current global context\n */\nexport function isDebugModeEnabled(): boolean {\n return isEnabled();\n}\n\nexport async function delay(ms: number = 5000): Promise<void> {\n return new Promise<void>((resolve, _reject) => {\n setTimeout(resolve, ms);\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"debug-Cf2jt1kg.mjs","names":[],"sources":["../src/util/test-error-formatting.ts","../src/util/pool-errors.ts","../src/util/debug.ts"],"sourcesContent":["import { stripVTControlCharacters } from 'node:util';\nimport type { RawSourceMap } from 'source-map';\nimport c from 'tinyrainbow';\nimport type { ParsedStack } from '@vitest/utils';\n\nimport { HighlightFunc } from '../types/types.js';\n\nconst FRAME_POINTER = '❯' as const;\nconst CODE_FRAME_INDENT_SPACES = 4 as const;\n\n// same performance guard used in vitest `printError`\nconst MAX_CODE_HIGHLIGHT_LENGTH = 100_000 as const;\n\nexport function getYellowString(str: string): string {\n return c.yellow(str);\n}\n\nexport function toPlaintextStackFrameString(frame: ParsedStack): string {\n return ` at ${frame.method} ${frame.file}:${frame.line}:${frame.column}`;\n}\n\nexport function toVitestLikeStackFrameString(frame: ParsedStack): string {\n return c.cyan(\n ` ${c.dim(FRAME_POINTER)} ${frame.method} ${frame.file}:${c.dim(`${frame.line}:${frame.column}`)}`\n );\n}\n\nexport function getSourceCodeFrameString(\n sourceMap: RawSourceMap,\n frame: ParsedStack,\n highlight: HighlightFunc,\n): string | undefined {\n if (!sourceMap.sourcesContent) {\n return undefined;\n }\n\n const fileIndex = sourceMap.sources.indexOf(frame.file);\n if (fileIndex < 0) {\n return undefined;\n }\n\n const source = sourceMap.sourcesContent[fileIndex];\n if (!source) {\n return undefined;\n }\n\n const highlightedSource = source.length < MAX_CODE_HIGHLIGHT_LENGTH\n ? highlight(source, { colors: c })\n : source;\n\n return generateCodeFrame(highlightedSource, CODE_FRAME_INDENT_SPACES, frame);\n}\n\n\n// ============================================================================\n// Source code formatting functions borrowed from Vitest\n// ============================================================================\n\n/**\n * Vitest doesn't expose generateCodeFrame as a util, so we have\n * recreated it here with minimal changes.\n * \n * @see https://github.com/vitest-dev/vitest/blob/v3.2.4/packages/vitest/src/node/printError.ts#L424\n * \n * Vitest is released under the MIT license, included in this project's root.\n * Copyright (c) 2021-Present Vitest Team\n */\n\nconst lineSplitRE: RegExp = /\\r?\\n/;\n\nfunction generateCodeFrame(\n source: string,\n indent = 0,\n loc: { line: number; column: number } | number,\n range = 2,\n): string {\n const start\n = typeof loc === 'object'\n ? positionToOffset(source, loc.line, loc.column)\n : loc\n const end = start\n const lines = source.split(lineSplitRE)\n const nl = /\\r\\n/.test(source) ? 2 : 1\n let count = 0\n let res: string[] = []\n\n const columns = process.stdout?.columns || 80\n\n for (let i = 0; i < lines.length; i++) {\n count += lines[i]!.length + nl\n if (count >= start) {\n for (let j = i - range; j <= i + range || end > count; j++) {\n if (j < 0 || j >= lines.length) {\n continue\n }\n\n const lineLength = lines[j]!.length\n\n // too long, maybe it's a minified file, skip for codeframe\n if (stripVTControlCharacters(lines[j]!).length > 200) {\n return ''\n }\n\n res.push(\n lineNo(j + 1)\n + truncateString(lines[j]!.replace(/\\t/g, ' '), columns - 5 - indent),\n )\n\n if (j === i) {\n // push underline\n const pad = start - (count - lineLength) + (nl - 1)\n const length = Math.max(\n 1,\n end > count ? lineLength - pad : end - start,\n )\n res.push(lineNo() + ' '.repeat(pad) + c.red('^'.repeat(length)))\n }\n else if (j > i) {\n if (end > count) {\n const length = Math.max(1, Math.min(end - count, lineLength))\n res.push(lineNo() + c.red('^'.repeat(length)))\n }\n count += lineLength + 1\n }\n }\n break\n }\n }\n\n if (indent) {\n res = res.map(line => ' '.repeat(indent) + line)\n }\n\n return res.join('\\n')\n}\n\n\nfunction positionToOffset(\n source: string,\n lineNumber: number,\n columnNumber: number,\n): number {\n const lines = source.split(lineSplitRE)\n const nl = /\\r\\n/.test(source) ? 2 : 1\n let start = 0\n\n if (lineNumber > lines.length) {\n return source.length\n }\n\n for (let i = 0; i < lineNumber - 1; i++) {\n start += lines[i]!.length + nl\n }\n\n return start + columnNumber\n}\n\nfunction lineNo(no: number | string = '') {\n return c.gray(`${String(no).padStart(3, ' ')}| `)\n}\n\nfunction truncateString(text: string, maxLength: number): string {\n const plainText = stripVTControlCharacters(text)\n\n if (plainText.length <= maxLength) {\n return text\n }\n\n return `${plainText.slice(0, maxLength - 1)}…`\n}\n","import type { Test } from '@vitest/runner/types';\n\nimport type {\n AssemblyScriptPoolError,\n AssemblyScriptTestError,\n PoolErrorName,\n TestErrorName\n} from '../types/types.js';\nimport {\n AS_POOL_ERROR_TYPE_FLAG,\n POOL_ERROR_NAMES,\n TEST_ERROR_NAMES\n} from '../types/constants.js';\nimport { getYellowString } from './test-error-formatting.js';\n\nexport function createPoolError(\n message: string,\n name: PoolErrorName,\n stack?: string,\n cause?: any,\n rawCallStack?: NodeJS.CallSite[],\n): AssemblyScriptPoolError {\n return { name, message, stack, cause, rawCallStack, [AS_POOL_ERROR_TYPE_FLAG]: true };\n}\n\nexport function createTestTimeoutError(\n test: Test\n): AssemblyScriptTestError {\n const message = `Test timed out after ${test.timeout}ms`;\n const err: AssemblyScriptTestError = {\n name: POOL_ERROR_NAMES.WASMExecutionTimeoutError,\n message,\n stack: `${test.id}_${message}`,\n diff: getYellowString(` Test Timeout Exceeded (${test.timeout}ms)`)\n };\n return err;\n}\n\nexport function createTestExpectedToFailError(test: Test): AssemblyScriptTestError {\n const message = `Test is expected to fail, but all assertions passed`;\n const err: AssemblyScriptTestError = {\n name: TEST_ERROR_NAMES.AssertionError,\n message,\n stack: `${test.id}_${message}`,\n diff: getYellowString(` Expected to fail, but all assertions passed`)\n };\n return err;\n}\n\nexport function throwPoolErrorIfAborted(signal?: AbortSignal): void {\n if (!signal || !signal.aborted) {\n return;\n }\n\n throw createPoolError(signal.reason, POOL_ERROR_NAMES.PoolRunAbortedError);\n}\n\nexport function isAbortErrorString(item: any): boolean {\n return item === POOL_ERROR_NAMES.PoolRunAbortedError || item === 'AbortError';\n}\n\nexport function isAbortError(error: any): boolean {\n return isAbortErrorString(error) \n || isAbortErrorString(error?.name)\n || error?.message === 'Terminating worker thread';\n}\n\nexport function createPoolErrorFromAnyError(\n context: string,\n contextErrorName: PoolErrorName,\n error: any\n): AssemblyScriptPoolError {\n const isErrorAbortString = isAbortErrorString(error);\n if (isErrorAbortString) {\n const msg = `${contextErrorName}: ${context} - Aborted, Unknown Cause`;\n return createPoolError(msg, POOL_ERROR_NAMES.PoolRunAbortedError);\n }\n\n if (error[AS_POOL_ERROR_TYPE_FLAG]) {\n return error as AssemblyScriptPoolError;\n }\n\n if (error instanceof Error) {\n const isAbortError = isAbortErrorString(error.name);\n const asErr = createPoolError(\n `${context} - ${error.name}: ${error.message}`,\n isAbortError ? POOL_ERROR_NAMES.PoolRunAbortedError : contextErrorName,\n error.stack,\n error.cause\n );\n return asErr;\n }\n\n const errorMsg = String(error);\n return createPoolError(`${context} - ${errorMsg}`, contextErrorName);\n}\n\nexport function getTestErrorFromPoolError(error: AssemblyScriptPoolError): AssemblyScriptTestError {\n const anyCause: any = error?.cause;\n if (error.causeIsEnhancedError) {\n return error.cause as AssemblyScriptTestError;\n }\n\n const message = error.message ?? anyCause.message ?? 'Unknown error';\n return {\n name: error.name ?? anyCause.name ?? POOL_ERROR_NAMES.PoolError,\n message,\n stack: anyCause?.stack ?? error.stack ?? message,\n stacks: anyCause?.stacks ,\n cause: getTestErrorFromAnyError(anyCause?.cause),\n diff: anyCause?.diff\n };\n}\n\nexport function getTestErrorFromAnyError(\n error: any,\n context: string = '',\n fallbackName: TestErrorName | PoolErrorName = POOL_ERROR_NAMES.PoolError\n): AssemblyScriptTestError | undefined {\n if (!error) {\n return undefined;\n }\n\n const message = `${context ?? ''}${error?.message ?? ''}`;\n return {\n name: error?.name ?? fallbackName,\n message,\n stack: error?.stack ?? message,\n stacks: error?.stacks,\n cause: getTestErrorFromAnyError(error?.cause)\n };\n}\n","/**\n * Debug logging utility\n */\n\ndeclare global {\n var AS_POOL_DEBUG: boolean | undefined;\n}\n\nglobalThis.AS_POOL_DEBUG = false;\n\nconst DEBUG_ENV_ENABLED_VALUE = '1' as const;\n\nfunction isEnabled(): boolean {\n return globalThis.AS_POOL_DEBUG === true || process.env.DEBUG === DEBUG_ENV_ENABLED_VALUE;\n}\n\n/**\n * Initialize debug mode for current async context (called by worker at task start)\n * @param {boolean} debugEnabled - Enable verbose debug logging\n */\nexport function setGlobalDebugMode(debugEnabled: boolean): void {\n globalThis.AS_POOL_DEBUG = debugEnabled;\n}\n\n/**\n * Log debug message (only when debug enabled in current global context)\n * or when environment has a truthy DEBUG variable set.\n */\nexport function debug(...args: any): void {\n if (isEnabled()) {\n // if first arg is a function, execute it and then print the result\n if (args?.length > 0 && typeof args[0] === 'function') {\n const result = args[0]();\n const rest = args.length > 1 ? args.slice(1) : [];\n console.log(Date.now(), String(result), ...rest);\n } else {\n console.log(Date.now(), ...args);\n }\n }\n}\n\n/**\n * Determine if debug mode is enabled for the current global context\n */\nexport function isDebugModeEnabled(): boolean {\n return isEnabled();\n}\n\nexport async function delay(ms: number = 5000): Promise<void> {\n return new Promise<void>((resolve, _reject) => {\n setTimeout(resolve, ms);\n });\n}\n"],"mappings":"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"}
|