vitest-pool-assemblyscript 0.9.1 → 0.10.1

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.
Files changed (100) hide show
  1. package/assembly/compare.ts +11 -12
  2. package/assembly/describe.ts +4 -4
  3. package/assembly/expect.ts +44 -26
  4. package/assembly/test.ts +9 -9
  5. package/assembly/utils.ts +218 -62
  6. package/dist/{addon-interface-CYFXMbK7.mjs → addon-interface-BaUmn7uC.mjs} +12 -12
  7. package/dist/addon-interface-BaUmn7uC.mjs.map +1 -0
  8. package/dist/{ast-visitor-CWEOd3UH.mjs → ast-visitor-w1HMbuJR.mjs} +2 -2
  9. package/dist/{ast-visitor-CWEOd3UH.mjs.map → ast-visitor-w1HMbuJR.mjs.map} +1 -1
  10. package/dist/compile-runner-BGHM_85g.mjs +82 -0
  11. package/dist/compile-runner-BGHM_85g.mjs.map +1 -0
  12. package/dist/compiler/transforms/deep-equals.d.mts.map +1 -1
  13. package/dist/compiler/transforms/deep-equals.mjs +61 -22
  14. package/dist/compiler/transforms/deep-equals.mjs.map +1 -1
  15. package/dist/compiler/transforms/strip-inline.mjs +2 -2
  16. package/dist/{compiler-Dqs-qd3I.mjs → compiler-CXR5UJId.mjs} +55 -27
  17. package/dist/compiler-CXR5UJId.mjs.map +1 -0
  18. package/dist/config/index-v3.d.mts +1 -1
  19. package/dist/config/index-v3.d.mts.map +1 -1
  20. package/dist/config/index-v3.mjs.map +1 -1
  21. package/dist/config/index.d.mts +2 -2
  22. package/dist/config/index.mjs +5 -7
  23. package/dist/{constants-DbxJ3hzg.mjs → constants-Bq5KNxXJ.mjs} +4 -2
  24. package/dist/constants-Bq5KNxXJ.mjs.map +1 -0
  25. package/dist/{coverage-merge-CBXkpM1O.mjs → coverage-merge-0WqdC-dq.mjs} +1 -1
  26. package/dist/{coverage-merge-CBXkpM1O.mjs.map → coverage-merge-0WqdC-dq.mjs.map} +1 -1
  27. package/dist/coverage-provider/index.mjs +36 -36
  28. package/dist/coverage-provider/index.mjs.map +1 -1
  29. package/dist/{feature-check-Bje3ntpV.mjs → feature-check-BJpc4LoO.mjs} +4 -4
  30. package/dist/{feature-check-Bje3ntpV.mjs.map → feature-check-BJpc4LoO.mjs.map} +1 -1
  31. package/dist/index-internal.d.mts +3 -3
  32. package/dist/index-internal.d.mts.map +1 -1
  33. package/dist/index-internal.mjs +5 -4
  34. package/dist/index-v3.d.mts.map +1 -1
  35. package/dist/index-v3.mjs +19 -33
  36. package/dist/index-v3.mjs.map +1 -1
  37. package/dist/index.d.mts +1 -1
  38. package/dist/index.mjs +5 -7
  39. package/dist/{load-user-imports-Bx5ZlhSm.mjs → load-user-imports-Bcx9NOt9.mjs} +119 -232
  40. package/dist/load-user-imports-Bcx9NOt9.mjs.map +1 -0
  41. package/dist/pool-errors-Bn6YaguR.mjs +630 -0
  42. package/dist/pool-errors-Bn6YaguR.mjs.map +1 -0
  43. package/dist/{pool-runner-init-CNpRdA5u.d.mts → pool-runner-init-CCvnKt5o.d.mts} +2 -2
  44. package/dist/pool-runner-init-CCvnKt5o.d.mts.map +1 -0
  45. package/dist/{pool-runner-init-BqkwQ2tk.mjs → pool-runner-init-DjRCbiX-.mjs} +15 -30
  46. package/dist/pool-runner-init-DjRCbiX-.mjs.map +1 -0
  47. package/dist/pool-thread/compile-worker-thread.d.mts +1 -1
  48. package/dist/pool-thread/compile-worker-thread.d.mts.map +1 -1
  49. package/dist/pool-thread/compile-worker-thread.mjs +29 -19
  50. package/dist/pool-thread/compile-worker-thread.mjs.map +1 -1
  51. package/dist/pool-thread/test-worker-thread.d.mts +1 -1
  52. package/dist/pool-thread/test-worker-thread.d.mts.map +1 -1
  53. package/dist/pool-thread/test-worker-thread.mjs +25 -18
  54. package/dist/pool-thread/test-worker-thread.mjs.map +1 -1
  55. package/dist/pool-thread/v3-tinypool-thread.d.mts +1 -1
  56. package/dist/pool-thread/v3-tinypool-thread.d.mts.map +1 -1
  57. package/dist/pool-thread/v3-tinypool-thread.mjs +43 -33
  58. package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -1
  59. package/dist/test-runner-BeP8ClnE.mjs +147 -0
  60. package/dist/test-runner-BeP8ClnE.mjs.map +1 -0
  61. package/dist/{types-DHVk5iAx.d.mts → types-CoroKYxB.d.mts} +39 -16
  62. package/dist/types-CoroKYxB.d.mts.map +1 -0
  63. package/dist/vitest-file-tasks-vvZzigcF.mjs +473 -0
  64. package/dist/vitest-file-tasks-vvZzigcF.mjs.map +1 -0
  65. package/dist/wasm-memory-C8Nkl2Sz.mjs +134 -0
  66. package/dist/wasm-memory-C8Nkl2Sz.mjs.map +1 -0
  67. package/dist/{worker-rpc-channel-CZZIxtv5.mjs → worker-rpc-channel-CvCrc8aa.mjs} +1 -1
  68. package/dist/{worker-rpc-channel-CZZIxtv5.mjs.map → worker-rpc-channel-CvCrc8aa.mjs.map} +1 -1
  69. package/package.json +1 -1
  70. package/prebuilds/darwin-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
  71. package/prebuilds/darwin-x64/vitest-pool-assemblyscript.glibc.node +0 -0
  72. package/prebuilds/linux-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
  73. package/prebuilds/linux-x64/vitest-pool-assemblyscript.glibc.node +0 -0
  74. package/prebuilds/linux-x64/vitest-pool-assemblyscript.musl.node +0 -0
  75. package/prebuilds/win32-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
  76. package/prebuilds/win32-x64/vitest-pool-assemblyscript.glibc.node +0 -0
  77. package/src/instrumentation/native/addon.cpp +71 -32
  78. package/dist/addon-interface-CYFXMbK7.mjs.map +0 -1
  79. package/dist/compile-runner-BNFHRGZO.mjs +0 -85
  80. package/dist/compile-runner-BNFHRGZO.mjs.map +0 -1
  81. package/dist/compiler-Dqs-qd3I.mjs.map +0 -1
  82. package/dist/constants-DbxJ3hzg.mjs.map +0 -1
  83. package/dist/debug-DtRAL4rM.mjs +0 -232
  84. package/dist/debug-DtRAL4rM.mjs.map +0 -1
  85. package/dist/load-user-imports-Bx5ZlhSm.mjs.map +0 -1
  86. package/dist/path-utils-t9OzjXYF.mjs +0 -24
  87. package/dist/path-utils-t9OzjXYF.mjs.map +0 -1
  88. package/dist/pool-runner-init-BqkwQ2tk.mjs.map +0 -1
  89. package/dist/pool-runner-init-CNpRdA5u.d.mts.map +0 -1
  90. package/dist/resolve-config-s9gSJSMc.mjs +0 -85
  91. package/dist/resolve-config-s9gSJSMc.mjs.map +0 -1
  92. package/dist/test-runner-BGqc9uCK.mjs +0 -138
  93. package/dist/test-runner-BGqc9uCK.mjs.map +0 -1
  94. package/dist/types-DHVk5iAx.d.mts.map +0 -1
  95. package/dist/vitest-file-tasks-D8sOClGX.mjs +0 -149
  96. package/dist/vitest-file-tasks-D8sOClGX.mjs.map +0 -1
  97. package/dist/vitest-tasks-BZ24sghI.mjs +0 -321
  98. package/dist/vitest-tasks-BZ24sghI.mjs.map +0 -1
  99. package/dist/wasm-names-BFtzQCH4.mjs +0 -124
  100. package/dist/wasm-names-BFtzQCH4.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-runner-BGHM_85g.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 AS_POOL_WASM_COVERAGE_MEM_IMPORT_NAME,\n AS_POOL_WASM_IMPORTS_MODULE_NAME,\n ASSEMBLYSCRIPT_LIB_PREFIX,\n INTERNAL_FUNCTION_NAME_SUBSTRING,\n INTERNAL_PATH_LIB_PREFIX,\n POOL_INTERNAL_PATHS,\n} from '../../types/constants.js';\nimport { executeWASMDiscovery } from '../../wasm-executor/index.js';\nimport { debug } from '../../util/debug.js';\nimport { toForwardSlash } from '../../util/path-utils.js';\nimport {\n reportFileQueued,\n reportFileCollected,\n reportUserConsoleLogs,\n flushRpcUpdates,\n reportFileError,\n} from '../rpc-reporter.js';\nimport { compileAssemblyScript } from '../../compiler/index.js';\nimport { getTaskLogLabel, getTaskLogPrefix } from '../../util/vitest-tasks.js';\nimport {\n failFile,\n getFullTaskHierarchy,\n prepareFileTaskForCollection,\n} from '../../util/vitest-file-tasks.js';\nimport { buildEnhancedFileError } from '../../util/pool-errors.js';\n\nlet threadCompilationCount: number = 0;\n\nexport async function runCompileAndDiscover(\n file: File,\n logModule: string,\n rpc: WorkerRPC,\n asPoolOptions: 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 let compilation: WASMCompilation | undefined;\n let reportedQueued: boolean = false;\n \n const runStartPerf = performance.now();\n\n try {\n await reportFileQueued(rpc, file, logModule, fileLogLabel);\n reportedQueued = true;\n\n const relativeTestFilePath = toForwardSlash(relative(projectRoot, file.filepath));\n const instrumentationOptions: InstrumentationOptions = {\n projectRoot,\n relativeExcludedFiles: [\n relativeTestFilePath,\n ...(asPoolOptions._instrumentPoolInternals ? [] : POOL_INTERNAL_PATHS),\n ...relativeUserCoverageExclusions,\n ],\n excludedLibraryFilePrefix: ASSEMBLYSCRIPT_LIB_PREFIX,\n excludedLibraryFileOverridePrefix: asPoolOptions._instrumentPoolInternals ? INTERNAL_PATH_LIB_PREFIX : undefined,\n excludedInternalFunctionSubstring: INTERNAL_FUNCTION_NAME_SUBSTRING,\n coverageMemoryPagesMin: asPoolOptions.coverageMemoryPagesInitial ?? 1,\n coverageMemoryPagesMax: asPoolOptions.coverageMemoryPagesMax,\n debug: asPoolOptions.debugNative,\n coverageMemoryModule: AS_POOL_WASM_IMPORTS_MODULE_NAME,\n coverageMemoryName: AS_POOL_WASM_COVERAGE_MEM_IMPORT_NAME\n };\n const compilerOptions: AssemblyScriptCompilerOptions = {\n stripInline: asPoolOptions.stripInline,\n projectRoot,\n shouldInstrument: collectCoverage,\n instrumentationOptions,\n extraFlags: asPoolOptions.extraCompilerFlags\n };\n\n compilation = await compileAssemblyScript(\n file.filepath,\n compilerOptions,\n logModule,\n fileLogLabel\n );\n file.setupDuration = compilation.compileTiming;\n threadCompilationCount++;\n\n debug(`${fileLogPrefix} - TIMING compileAssemblyScript total `\n + `(thread comp # ${threadCompilationCount}): ${compilation.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 discoverStartPerf = performance.now();\n\n await executeWASMDiscovery(\n compilation,\n asPoolOptions,\n collectCoverage,\n handleLog,\n file,\n logModule,\n threadImports,\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() - discoverStartPerf;\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() - runStartPerf;\n debug(`${fileLogPrefix} - TIMING Compilation and Discovery: ${totalTime.toFixed(2)} ms`);\n } catch (error) {\n const testError = await buildEnhancedFileError(\n error,\n file,\n compilation?.sourceMap,\n fileLogPrefix,\n projectRoot,\n 'compile runner',\n diffOptions\n );\n\n failFile(file, testError, runStartPerf);\n\n if (!reportedQueued) {\n await reportFileQueued(rpc, file, logModule, fileLogLabel);\n }\n await reportFileError(rpc, file, logModule, fileLogLabel);\n\n debug(`${fileLogPrefix} - runCompileAndDiscover - Reported file error:`, testError);\n } finally {\n await flushRpcUpdates(rpc);\n debug(`${fileLogPrefix} - runCompileAndDiscover Completed`);\n }\n\n return compilation;\n}\n"],"mappings":";;;;;;;;;;;AA6CA,IAAI,yBAAiC;AAErC,eAAsB,sBACpB,MACA,WACA,KACA,eACA,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,IAAI;CACJ,IAAI,iBAA0B;CAE9B,MAAM,eAAe,YAAY,KAAK;AAEtC,KAAI;AACF,QAAM,iBAAiB,KAAK,MAAM,WAAW,aAAa;AAC1D,mBAAiB;EAGjB,MAAM,yBAAiD;GACrD;GACA,uBAAuB;IAHI,eAAe,SAAS,aAAa,KAAK,SAAS,CAAC;IAK7E,GAAI,cAAc,2BAA2B,EAAE,GAAG;IAClD,GAAG;IACJ;GACD;GACA,mCAAmC,cAAc,2BAA2B,2BAA2B;GACvG;GACA,wBAAwB,cAAc,8BAA8B;GACpE,wBAAwB,cAAc;GACtC,OAAO,cAAc;GACrB;GACA;GACD;EACD,MAAM,kBAAiD;GACrD,aAAa,cAAc;GAC3B;GACA,kBAAkB;GAClB;GACA,YAAY,cAAc;GAC3B;AAED,gBAAc,MAAM,sBAClB,KAAK,UACL,iBACA,WACA,aACD;AACD,OAAK,gBAAgB,YAAY;AACjC;AAEA,QAAM,GAAG,cAAc,uDACD,uBAAuB,KAAK,YAAY,cAAc,QAAQ,EAAE,CAAC,KACtF;EAED,MAAM,cAA0C,EAAE;EAClD,MAAM,aAA8C,KAAa,UAAmB,UAAgB;AAClG,eAAY,KAAK;IAAE;IAAK,MAAM,KAAK,KAAK;IAAE;IAAS,CAAC;;EAGtD,MAAM,oBAAoB,YAAY,KAAK;AAE3C,QAAM,qBACJ,aACA,eACA,iBACA,WACA,MACA,WACA,cACD;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,cACkC,QAAQ,EAAE,CAAC,KAAK;UACjF,OAAO;EACd,MAAM,YAAY,MAAM,uBACtB,OACA,MACA,aAAa,WACb,eACA,aACA,kBACA,YACD;AAED,WAAS,MAAM,WAAW,aAAa;AAEvC,MAAI,CAAC,eACH,OAAM,iBAAiB,KAAK,MAAM,WAAW,aAAa;AAE5D,QAAM,gBAAgB,KAAK,MAAM,WAAW,aAAa;AAEzD,QAAM,GAAG,cAAc,kDAAkD,UAAU;WAC3E;AACR,QAAM,gBAAgB,IAAI;AAC1B,QAAM,GAAG,cAAc,oCAAoC;;AAG7D,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"deep-equals.d.mts","names":[],"sources":["../../../src/compiler/transforms/deep-equals.mts"],"mappings":";;;;;;;;cAuFM,mBAAA,SAA4B,SAAA;EAChC,UAAA,CAAW,MAAA,EAAQ,MAAA;AAAA"}
1
+ {"version":3,"file":"deep-equals.d.mts","names":[],"sources":["../../../src/compiler/transforms/deep-equals.mts"],"mappings":";;;;;;;;cA2FM,mBAAA,SAA4B,SAAA;EAChC,UAAA,CAAW,MAAA,EAAQ,MAAA;AAAA"}
@@ -1,5 +1,5 @@
1
- import { ASCommonFlags, ASDecoratorKind, ASNodeKind, ASSourceKind, INTERNAL_PATH_LIB_PREFIX } from "../../constants-DbxJ3hzg.mjs";
2
- import { ASTVisitor } from "../../ast-visitor-CWEOd3UH.mjs";
1
+ import { ASCommonFlags, ASDecoratorKind, ASNodeKind, ASSourceKind, INTERNAL_PATH_LIB_PREFIX } from "../../constants-Bq5KNxXJ.mjs";
2
+ import { ASTVisitor } from "../../ast-visitor-w1HMbuJR.mjs";
3
3
  import { Source, Tokenizer } from "assemblyscript";
4
4
  import { Transform } from "assemblyscript/transform";
5
5
 
@@ -22,6 +22,7 @@ import { Transform } from "assemblyscript/transform";
22
22
  * - Always stringifies all stored instance fields regardless of operator==/equals()
23
23
  * - Follows super chain via isDefined guard, same pattern as deep equality
24
24
  * - Uses @global bridge __vitest_assemblyscript_stringify_value to call stringifyValue()
25
+ * - Threads a `budget` parameter through the generated body for short-form truncation
25
26
  *
26
27
  * Scoping:
27
28
  * - Only user source files (not node_modules, not AS stdlib)
@@ -115,16 +116,13 @@ function injectTypename(parser, classDecl, className, typeSuffix, sourcePath) {
115
116
  /**
116
117
  * Inject the stringify method into a class.
117
118
  *
118
- * Returns comma-separated "fieldName: value" entries for all stored instance fields.
119
- * Always stringifies all fields regardless of operator==/equals() — stringify shows
120
- * full object state, not equality-relevant fields only.
121
- *
122
- * Follows the super chain via isDefined guard, same pattern as deep equality.
123
- * Uses @global bridge __vitest_assemblyscript_stringify_value to call stringifyValue().
119
+ * Returns "fieldName: value" entries for all stored instance fields, regardless of
120
+ * operator==/equals() — stringify shows full object state, not equality-relevant
121
+ * fields only. See generateStringifyBody for how budget is threaded through fields.
124
122
  */
125
123
  function injectStringify(parser, classDecl, sourcePath) {
126
124
  if (hasMethod(classDecl, "__vitest_assemblyscript_stringify")) return;
127
- injectClassMember(parser, classDecl, `${"__vitest_assemblyscript_stringify"}(): string { ${generateStringifyBody(classDecl)} }`, sourcePath);
125
+ injectClassMember(parser, classDecl, `${"__vitest_assemblyscript_stringify"}(formatForDiff: bool = true, depth: i32 = 0, budget: i32 = -1): string { ${generateStringifyBody(classDecl)} }`, sourcePath);
128
126
  }
129
127
  /**
130
128
  * Check if a class has a specific instance method by name
@@ -193,30 +191,71 @@ function generateStructuralBody(classDecl) {
193
191
  if (hasSuper) comparisons.push(`if (isDefined(super.${"__vitest_assemblyscript_deep_equals"})) { __result = super.${"__vitest_assemblyscript_deep_equals"}(__other); if (__result != ${EQ}.Equal) return __result; }`);
194
192
  for (const field of fields) {
195
193
  const fieldName = field.name.text;
196
- comparisons.push(`${"__vitest_assemblyscript_equals_path_push"}(".${fieldName}"); __result = ${"__vitest_assemblyscript_compare_equals"}(this.${fieldName}, other.${fieldName}); if (__result != ${EQ}.Equal) return __result; ${"__vitest_assemblyscript_equals_path_pop"}();`);
194
+ comparisons.push(`${"__vitest_assemblyscript_compare_equals_path_push"}(".${fieldName}"); __result = ${"__vitest_assemblyscript_compare_equals"}(this.${fieldName}, other.${fieldName}); if (__result != ${EQ}.Equal) return __result; ${"__vitest_assemblyscript_compare_equals_path_pop"}();`);
197
195
  }
198
196
  return comparisons.join(" ") + ` return ${EQ}.Equal;`;
199
197
  }
200
198
  /**
201
- * Generate the stringify body for a class.
202
- * Produces comma-separated "fieldName: value" entries using the @global stringify bridge.
203
- * Follows the super chain if the class extends another class.
199
+ * Generate the stringify body for a class — produces "fieldName: value" entries
200
+ * (and an atomic super piece, if any) via the global stringify bridge, with each
201
+ * piece guarded by a shared `truncated` flag so the budget is respected.
204
202
  */
205
203
  function generateStringifyBody(classDecl) {
206
204
  const fields = getStoredInstanceFields(classDecl);
207
205
  const hasSuper = classDecl.extendsType !== null;
208
- const SV = "__vitest_assemblyscript_stringify_value";
209
- const SUPER_METHOD = "__vitest_assemblyscript_stringify";
210
206
  if (fields.length === 0 && !hasSuper) return `return "";`;
211
207
  const parts = [];
208
+ parts.push(`const sep: string = formatForDiff ? ",\\n" : ", ";`);
209
+ parts.push(`const linePrefix: string = formatForDiff ? ${"__vitest_assemblyscript_stringify_indent"}(depth + 1) : "";`);
212
210
  parts.push(`let s = "";`);
213
- if (hasSuper) parts.push(`if (isDefined(super.${SUPER_METHOD})) { s += super.${SUPER_METHOD}(); if (s != "") s += ", "; }`);
214
- let firstField = true;
215
- for (const field of fields) {
216
- const fieldName = field.name.text;
217
- if (!firstField) parts.push(`s += ", ";`);
218
- parts.push(`s += "${fieldName}: " + ${SV}(this.${fieldName});`);
219
- firstField = false;
211
+ parts.push(`let used: i32 = 0;`);
212
+ parts.push(`let truncated: bool = false;`);
213
+ if (hasSuper) {
214
+ const totalIncludingSuper = fields.length + 1;
215
+ const superTrailingSepLen = fields.length > 0 ? "sep.length" : "0";
216
+ parts.push(`if (!truncated) {`);
217
+ parts.push(` if (isDefined(super.${"__vitest_assemblyscript_stringify"})) {`);
218
+ parts.push(` const superStr: string = super.${"__vitest_assemblyscript_stringify"}(formatForDiff, depth, -1);`);
219
+ parts.push(` if (superStr != "") {`);
220
+ parts.push(` const truncMarker: string = budget >= 0 ? "…(${totalIncludingSuper})" : "";`);
221
+ parts.push(` const trailingSepLen: i32 = ${superTrailingSepLen};`);
222
+ parts.push(` if (${"__vitest_assemblyscript_stringify_exceeds_budget"}(used, superStr.length, trailingSepLen, truncMarker.length, budget)) {`);
223
+ parts.push(` s += truncMarker;`);
224
+ parts.push(` truncated = true;`);
225
+ parts.push(` } else {`);
226
+ parts.push(` s += superStr;`);
227
+ parts.push(` used += superStr.length;`);
228
+ if (fields.length > 0) {
229
+ parts.push(` s += sep;`);
230
+ parts.push(` used += sep.length;`);
231
+ }
232
+ parts.push(` }`);
233
+ parts.push(` }`);
234
+ parts.push(` }`);
235
+ parts.push(`}`);
236
+ }
237
+ for (let i = 0; i < fields.length; i++) {
238
+ const fieldName = fields[i]?.name?.text;
239
+ const isLast = i === fields.length - 1;
240
+ const remainingPieces = fields.length - i;
241
+ parts.push(`if (!truncated) {`);
242
+ parts.push(` const fieldName: string = formatForDiff ? ${"__vitest_assemblyscript_escape_to_diff_string"}("${fieldName}") : "${fieldName}";`);
243
+ parts.push(` const truncMarker: string = budget >= 0 ? "…(${remainingPieces})" : "";`);
244
+ parts.push(` const fieldSepLen: i32 = ${isLast ? "0" : "sep.length"};`);
245
+ parts.push(` const childBudget: i32 = budget < 0 ? -1 : max(0, budget - used - fieldSepLen - truncMarker.length);`);
246
+ parts.push(` const piece: string = \`\${linePrefix}\${fieldName}: \${${"__vitest_assemblyscript_stringify_value"}(this.${fieldName}, formatForDiff, depth + 1, childBudget)}\`;`);
247
+ parts.push(` if (${"__vitest_assemblyscript_stringify_exceeds_budget"}(used, piece.length, fieldSepLen, truncMarker.length, budget)) {`);
248
+ parts.push(` s += truncMarker;`);
249
+ parts.push(` truncated = true;`);
250
+ parts.push(` } else {`);
251
+ parts.push(` s += piece;`);
252
+ parts.push(` used += piece.length;`);
253
+ if (!isLast) {
254
+ parts.push(` s += sep;`);
255
+ parts.push(` used += sep.length;`);
256
+ }
257
+ parts.push(` }`);
258
+ parts.push(`}`);
220
259
  }
221
260
  parts.push(`return s;`);
222
261
  return parts.join(" ");
@@ -1 +1 @@
1
- {"version":3,"file":"deep-equals.mjs","names":[],"sources":["../../../src/compiler/transforms/deep-equals.mts"],"sourcesContent":["/**\n * AssemblyScript Compiler Transform: Deep Equality & Stringification for User-Defined Objects\n *\n * Injects three methods into user-defined classes at `afterParse`:\n *\n * 1. `__vitest_assemblyscript_deep_equals` — deep equality comparison for `toEqual()`\n * - If the class defines `@operator(\"==\")`: delegates to `this == other`\n * - If the class defines `.equals()`: delegates to `this.equals(other)`\n * - Otherwise: compares all stored instance fields via the pool's `equals()` function\n *\n * 2. `__vitest_assemblyscript_typename` — returns the runtime class name via `nameof<ClassName>()`\n * - Virtual dispatch ensures correct runtime name even for base-typed variables\n * - Used by stringifyValue() for user-facing output and by RTM type name tracking\n *\n * 3. `__vitest_assemblyscript_stringify` — returns comma-separated field entries for stringification\n * - Always stringifies all stored instance fields regardless of operator==/equals()\n * - Follows super chain via isDefined guard, same pattern as deep equality\n * - Uses @global bridge __vitest_assemblyscript_stringify_value to call stringifyValue()\n *\n * Scoping:\n * - Only user source files (not node_modules, not AS stdlib)\n * - Blanket injection into all user classes (always enabled)\n *\n * Cross-module function availability:\n * - Structural bodies reference @global functions from assembly/compare.ts and assembly/utils.ts\n * which are available in all source files without import\n * - Loaded transitively: user test → vitest-pool-assemblyscript/assembly → compare.ts → utils.ts\n *\n * AST injection:\n * - Method source is generated as a string, then parsed into an AST node using\n * `Parser.parseClassMember()` via a temporary `Source` + `Tokenizer`\n *\n * @see https://www.assemblyscript.org/compiler.html#transforms\n * @see https://github.com/AssemblyScript/assemblyscript/blob/main/src/ast.ts\n */\n\nimport {\n ClassDeclaration,\n DeclarationStatement,\n DecoratorNode,\n FieldDeclaration,\n MethodDeclaration,\n Parser,\n Source,\n Tokenizer,\n} from 'assemblyscript';\nimport { Transform } from 'assemblyscript/transform';\n\nimport { ASTVisitor } from '../../util/ast-visitor.js';\nimport {\n ASSEMBLYSCRIPT_LIB_PREFIX,\n COMPARE_EQUALS_EXPORT_ALIAS,\n DEEP_EQUALS_INJECTED_METHOD_NAME,\n EQUALITY_RESULT_ENUM_NAME,\n EQUALS_PATH_POP_GLOBAL_ALIAS,\n EQUALS_PATH_PUSH_GLOBAL_ALIAS,\n INTERNAL_PATH_LIB_PREFIX,\n STRINGIFY_INJECTED_METHOD_NAME,\n STRINGIFY_VALUE_GLOBAL_ALIAS,\n TYPENAME_INJECTED_METHOD_NAME,\n ASCommonFlags,\n ASDecoratorKind,\n ASNodeKind,\n ASSourceKind,\n} from '../../types/constants.js';\n\n/**\n * Visitor that finds class declarations and injects deep equality, typename, and stringify methods.\n * Uses ASTVisitor for full recursive traversal (finds classes inside namespaces, etc).\n */\nclass DeepEqualsVisitor extends ASTVisitor {\n constructor(\n private parser: Parser,\n private barrelPath: string,\n ) {\n super();\n }\n\n protected onClassEnter(node: ClassDeclaration): void {\n processClass(this.parser, node, this.barrelPath);\n }\n}\n\n/**\n * AssemblyScript compiler transform that injects deep equality, typename, and stringify methods\n * into user-defined classes\n */\nclass DeepEqualsTransform extends Transform {\n afterParse(parser: Parser): void {\n const sources = (this as Transform).program.sources;\n\n // Find the pool's assembly barrel file — used as the normalizedPath for injected\n // methods so the source map attributes them to pool internals, not user code.\n // The AS compiler requires a real source in the compilation for identifier resolution.\n const barrelPath = `${INTERNAL_PATH_LIB_PREFIX}index.ts`;\n const barrelSource = sources.find((s: Source) => s.normalizedPath === barrelPath);\n if (!barrelSource) {\n // This should never happen — the barrel is always loaded transitively via user imports.\n // If it does, fall back to the class's own source path (incorrect attribution but functional).\n console.warn(`[deep-equals transform] WARNING: Could not find barrel source \"${barrelPath}\" in compilation`);\n }\n\n const resolvedBarrelPath = barrelSource ? barrelPath : '';\n const visitor = new DeepEqualsVisitor(parser, resolvedBarrelPath);\n\n // Filter to user source files only (same scoping as strip-inline transform)\n const userSources = sources.filter((source: Source) =>\n (source.sourceKind === ASSourceKind.User || source.sourceKind === ASSourceKind.UserEntry)\n && !source.normalizedPath.startsWith(ASSEMBLYSCRIPT_LIB_PREFIX)\n );\n\n for (const source of userSources) {\n visitor.visitSource(source);\n }\n }\n}\n\n/**\n * Process a class declaration: inject deep equality, typename, and stringify methods.\n */\nfunction processClass(parser: Parser, classDecl: ClassDeclaration, barrelPath: string): void {\n const className = classDecl.name.text;\n\n // Use the barrel path if available, otherwise fall back to the class's own source path\n const sourcePath = barrelPath || classDecl.range.source.normalizedPath;\n\n // Build the type suffix for generic classes (e.g. \"Pair\" → \"Pair<T>\" or \"Pair<K, V>\")\n const typeSuffix = getTypeParameterSuffix(classDecl);\n\n injectDeepEquals(parser, classDecl, className, typeSuffix, sourcePath);\n injectTypename(parser, classDecl, className, typeSuffix, sourcePath);\n injectStringify(parser, classDecl, sourcePath);\n}\n\n/**\n * Inject the deep equality comparison method into a class.\n *\n * Behavior depends on user-defined equality semantics:\n * - @operator(\"==\") present: delegates to `this == other`\n * - .equals() present: delegates to `this.equals(other)`\n * - Neither: field-by-field structural comparison\n *\n * All methods use a usize parameter for inheritance compatibility — AS treats child methods\n * with the same name as overrides, requiring compatible parameter types. Each body casts\n * the pointer to its own type via changetype.\n */\nfunction injectDeepEquals(\n parser: Parser, classDecl: ClassDeclaration,\n className: string, typeSuffix: string, sourcePath: string,\n): void {\n if (hasMethod(classDecl, DEEP_EQUALS_INJECTED_METHOD_NAME)) return;\n\n const typedCast = `const other = changetype<${className}${typeSuffix}>(__other);`;\n const EQ = EQUALITY_RESULT_ENUM_NAME;\n let methodBody: string;\n\n if (hasOperatorEquals(classDecl)) {\n methodBody = `${typedCast} return (this == other) ? ${EQ}.Equal : ${EQ}.NotEqual;`;\n } else if (hasMethod(classDecl, 'equals')) {\n methodBody = `${typedCast} return this.equals(other) ? ${EQ}.Equal : ${EQ}.NotEqual;`;\n } else {\n methodBody = `${typedCast} ${generateStructuralBody(classDecl)}`;\n }\n\n const methodSource =\n `${DEEP_EQUALS_INJECTED_METHOD_NAME}(__other: usize): ${EQ} { ${methodBody} }`;\n\n injectClassMember(parser, classDecl, methodSource, sourcePath);\n}\n\n/**\n * Inject the typename method into a class.\n *\n * Returns the class's own name via nameof<ClassName>(). No super chain — each class returns\n * its own name. Virtual dispatch ensures the correct runtime class name is returned even\n * when the variable is typed as a base class.\n */\nfunction injectTypename(\n parser: Parser, classDecl: ClassDeclaration,\n className: string, typeSuffix: string, sourcePath: string,\n): void {\n if (hasMethod(classDecl, TYPENAME_INJECTED_METHOD_NAME)) return;\n\n const methodSource =\n `${TYPENAME_INJECTED_METHOD_NAME}(): string { return nameof<${className}${typeSuffix}>(); }`;\n\n injectClassMember(parser, classDecl, methodSource, sourcePath);\n}\n\n/**\n * Inject the stringify method into a class.\n *\n * Returns comma-separated \"fieldName: value\" entries for all stored instance fields.\n * Always stringifies all fields regardless of operator==/equals() — stringify shows\n * full object state, not equality-relevant fields only.\n *\n * Follows the super chain via isDefined guard, same pattern as deep equality.\n * Uses @global bridge __vitest_assemblyscript_stringify_value to call stringifyValue().\n */\nfunction injectStringify(\n parser: Parser, classDecl: ClassDeclaration,\n sourcePath: string,\n): void {\n if (hasMethod(classDecl, STRINGIFY_INJECTED_METHOD_NAME)) return;\n\n const methodBody = generateStringifyBody(classDecl);\n const methodSource =\n `${STRINGIFY_INJECTED_METHOD_NAME}(): string { ${methodBody} }`;\n\n injectClassMember(parser, classDecl, methodSource, sourcePath);\n}\n\n// =============================================================================\n// Detection helpers\n// =============================================================================\n\n/**\n * Check if a class has a specific instance method by name\n */\nfunction hasMethod(classDecl: ClassDeclaration, methodName: string): boolean {\n return classDecl.members.some(member =>\n member.kind === ASNodeKind.MethodDeclaration\n && (member as MethodDeclaration).name.text === methodName\n && member.is(ASCommonFlags.Instance)\n );\n}\n\n/**\n * Check if a class has an @operator(\"==\") decorator on any method.\n * The AS compiler uses DecoratorKind.Operator (2) for @operator and\n * DecoratorKind.OperatorBinary (3) for @operator.binary — check both.\n */\nfunction hasOperatorEquals(classDecl: ClassDeclaration): boolean {\n for (const member of classDecl.members) {\n if (member.kind !== ASNodeKind.MethodDeclaration) continue;\n\n const decorators = member.decorators;\n if (!decorators) continue;\n\n for (const decorator of decorators) {\n const kind = (decorator as DecoratorNode).decoratorKind;\n if (kind !== ASDecoratorKind.Operator && kind !== ASDecoratorKind.OperatorBinary) continue;\n\n // Check if the decorator argument is \"==\"\n const args = (decorator as DecoratorNode).args;\n if (!args || args.length === 0) continue;\n\n // The first argument is a string literal with the operator name.\n // At the AST level, LiteralExpression has a .value property for string literals.\n // The AS type declarations expose it as Expression, but the runtime type is\n // StringLiteralExpression with a .value: string property.\n const firstArg = args[0] as any;\n if (firstArg.value === '==') {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Get the type parameter suffix for a class declaration.\n * Returns empty string for non-generic classes, \"<T>\" for single param,\n * \"<K, V>\" for multiple params, etc.\n */\nfunction getTypeParameterSuffix(classDecl: ClassDeclaration): string {\n const typeParams = classDecl.typeParameters;\n if (!typeParams || typeParams.length === 0) {\n return '';\n }\n\n const paramNames = typeParams.map(param => param.name.text);\n return `<${paramNames.join(', ')}>`;\n}\n\n// =============================================================================\n// Structural body generation\n// =============================================================================\n\n/**\n * Collect stored instance fields from a class declaration.\n * Includes public, private, protected fields.\n * Excludes: static fields, getters, setters, constructors, methods.\n */\nfunction getStoredInstanceFields(classDecl: ClassDeclaration): FieldDeclaration[] {\n return classDecl.members.filter(member => {\n if (member.kind !== ASNodeKind.FieldDeclaration) return false;\n\n // Exclude static fields\n if (member.is(ASCommonFlags.Static)) return false;\n\n // Exclude getters and setters (these are MethodDeclarations in AS,\n // but guard against FieldDeclarations with these flags just in case)\n if (member.is(ASCommonFlags.Get) || member.is(ASCommonFlags.Set)) return false;\n\n return true;\n }) as FieldDeclaration[];\n}\n\n/**\n * Generate the structural comparison body for a class.\n * Delegates all field comparisons to the pool's equals function, which handles\n * primitives, strings, containers, nullables, and nested user types recursively.\n *\n * Uses a shared `__result` variable to capture and propagate EqualityResult from\n * each comparison, so type mismatch information from nested comparisons is preserved.\n */\nfunction generateStructuralBody(classDecl: ClassDeclaration): string {\n const fields = getStoredInstanceFields(classDecl);\n const EQ = EQUALITY_RESULT_ENUM_NAME;\n\n // No fields: always equal (two instances of an empty class are structurally identical)\n if (fields.length === 0) {\n return `return ${EQ}.Equal;`;\n }\n\n // Check if class extends another class — if so, include super comparison\n const hasSuper = classDecl.extendsType !== null;\n\n const comparisons: string[] = [];\n\n // Declare a shared result variable for capturing and propagating EqualityResult\n comparisons.push(`let __result: ${EQ};`);\n\n // Super class comparison: delegate to superclass's deep equality comparison method if it exists.\n // Passes __other (raw usize) since the parent's method also takes usize.\n if (hasSuper) {\n comparisons.push(\n `if (isDefined(super.${DEEP_EQUALS_INJECTED_METHOD_NAME})) { `\n + `__result = super.${DEEP_EQUALS_INJECTED_METHOD_NAME}(__other); `\n + `if (__result != ${EQ}.Equal) return __result; `\n + `}`\n );\n }\n\n for (const field of fields) {\n const fieldName = field.name.text;\n comparisons.push(\n `${EQUALS_PATH_PUSH_GLOBAL_ALIAS}(\".${fieldName}\"); `\n + `__result = ${COMPARE_EQUALS_EXPORT_ALIAS}(this.${fieldName}, other.${fieldName}); `\n + `if (__result != ${EQ}.Equal) return __result; `\n + `${EQUALS_PATH_POP_GLOBAL_ALIAS}();`\n );\n }\n\n return comparisons.join(' ') + ` return ${EQ}.Equal;`;\n}\n\n/**\n * Generate the stringify body for a class.\n * Produces comma-separated \"fieldName: value\" entries using the @global stringify bridge.\n * Follows the super chain if the class extends another class.\n */\nfunction generateStringifyBody(classDecl: ClassDeclaration): string {\n const fields = getStoredInstanceFields(classDecl);\n const hasSuper = classDecl.extendsType !== null;\n const SV = STRINGIFY_VALUE_GLOBAL_ALIAS;\n const SUPER_METHOD = STRINGIFY_INJECTED_METHOD_NAME;\n\n // No fields and no super: return empty string\n if (fields.length === 0 && !hasSuper) {\n return `return \"\";`;\n }\n\n const parts: string[] = [];\n parts.push(`let s = \"\";`);\n\n if (hasSuper) {\n parts.push(\n `if (isDefined(super.${SUPER_METHOD})) { `\n + `s += super.${SUPER_METHOD}(); `\n + `if (s != \"\") s += \", \"; `\n + `}`\n );\n }\n\n let firstField = true;\n for (const field of fields) {\n const fieldName = field.name.text;\n if (!firstField) {\n parts.push(`s += \", \";`);\n }\n parts.push(`s += \"${fieldName}: \" + ${SV}(this.${fieldName});`);\n firstField = false;\n }\n\n parts.push(`return s;`);\n return parts.join(' ');\n}\n\n// =============================================================================\n// AST injection\n// =============================================================================\n\n/**\n * Parse a method source string and inject it as a member of the given class.\n *\n * Creates a temporary Source and Tokenizer, uses the parser's parseClassMember()\n * to produce a proper AST node, then appends it to the class's members array.\n *\n * The temporary source uses the pool's assembly barrel file (assembly/index.ts) as its\n * normalizedPath instead of the user's source file. This prevents the source map from\n * incorrectly attributing generated code to user source lines. The AS compiler requires\n * the normalizedPath to be a real source in the compilation for identifier resolution\n * (synthetic paths cause assertion failures in maybeCompileEnclosingSource).\n */\nfunction injectClassMember(\n parser: Parser,\n classDecl: ClassDeclaration,\n memberSource: string,\n barrelPath: string,\n): void {\n const tempSource = new Source(\n ASSourceKind.User,\n barrelPath,\n memberSource,\n );\n\n const tokenizer = new Tokenizer(tempSource);\n\n // Advance past the initial token so the parser is positioned correctly\n tokenizer.next();\n\n const member = parser.parseClassMember(tokenizer, classDecl);\n if (member) {\n classDecl.members.push(member as DeclarationStatement);\n }\n}\n\nexport default DeepEqualsTransform;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsEA,IAAM,oBAAN,cAAgC,WAAW;CACzC,YACE,AAAQ,QACR,AAAQ,YACR;AACA,SAAO;EAHC;EACA;;CAKV,AAAU,aAAa,MAA8B;AACnD,eAAa,KAAK,QAAQ,MAAM,KAAK,WAAW;;;;;;;AAQpD,IAAM,sBAAN,cAAkC,UAAU;CAC1C,WAAW,QAAsB;EAC/B,MAAM,UAAW,KAAmB,QAAQ;EAK5C,MAAM,aAAa,GAAG,yBAAyB;EAC/C,MAAM,eAAe,QAAQ,MAAM,MAAc,EAAE,mBAAmB,WAAW;AACjF,MAAI,CAAC,aAGH,SAAQ,KAAK,kEAAkE,WAAW,kBAAkB;EAI9G,MAAM,UAAU,IAAI,kBAAkB,QADX,eAAe,aAAa,GACU;EAGjE,MAAM,cAAc,QAAQ,QAAQ,YACjC,OAAO,eAAe,aAAa,QAAQ,OAAO,eAAe,aAAa,cAC5E,CAAC,OAAO,eAAe,mBAAqC,CAChE;AAED,OAAK,MAAM,UAAU,YACnB,SAAQ,YAAY,OAAO;;;;;;AAQjC,SAAS,aAAa,QAAgB,WAA6B,YAA0B;CAC3F,MAAM,YAAY,UAAU,KAAK;CAGjC,MAAM,aAAa,cAAc,UAAU,MAAM,OAAO;CAGxD,MAAM,aAAa,uBAAuB,UAAU;AAEpD,kBAAiB,QAAQ,WAAW,WAAW,YAAY,WAAW;AACtE,gBAAe,QAAQ,WAAW,WAAW,YAAY,WAAW;AACpE,iBAAgB,QAAQ,WAAW,WAAW;;;;;;;;;;;;;;AAehD,SAAS,iBACP,QAAgB,WAChB,WAAmB,YAAoB,YACjC;AACN,KAAI,UAAU,iDAA4C,CAAE;CAE5D,MAAM,YAAY,4BAA4B,YAAY,WAAW;CACrE,MAAM;CACN,IAAI;AAEJ,KAAI,kBAAkB,UAAU,CAC9B,cAAa,GAAG,UAAU,4BAA4B,GAAG,WAAW,GAAG;UAC9D,UAAU,WAAW,SAAS,CACvC,cAAa,GAAG,UAAU,+BAA+B,GAAG,WAAW,GAAG;KAE1E,cAAa,GAAG,UAAU,GAAG,uBAAuB,UAAU;AAMhE,mBAAkB,QAAQ,WAFxB,yCAAoC,oBAAoB,GAAG,KAAK,WAAW,KAE1B,WAAW;;;;;;;;;AAUhE,SAAS,eACP,QAAgB,WAChB,WAAmB,YAAoB,YACjC;AACN,KAAI,UAAU,8CAAyC,CAAE;AAKzD,mBAAkB,QAAQ,WAFxB,sCAAiC,6BAA6B,YAAY,WAAW,SAEpC,WAAW;;;;;;;;;;;;AAahE,SAAS,gBACP,QAAgB,WAChB,YACM;AACN,KAAI,UAAU,+CAA0C,CAAE;AAM1D,mBAAkB,QAAQ,WAFxB,uCAAkC,eAFjB,sBAAsB,UAAU,CAEW,KAEX,WAAW;;;;;AAUhE,SAAS,UAAU,WAA6B,YAA6B;AAC3E,QAAO,UAAU,QAAQ,MAAK,WAC5B,OAAO,SAAS,WAAW,qBACvB,OAA6B,KAAK,SAAS,cAC5C,OAAO,GAAG,cAAc,SAAS,CACrC;;;;;;;AAQH,SAAS,kBAAkB,WAAsC;AAC/D,MAAK,MAAM,UAAU,UAAU,SAAS;AACtC,MAAI,OAAO,SAAS,WAAW,kBAAmB;EAElD,MAAM,aAAa,OAAO;AAC1B,MAAI,CAAC,WAAY;AAEjB,OAAK,MAAM,aAAa,YAAY;GAClC,MAAM,OAAQ,UAA4B;AAC1C,OAAI,SAAS,gBAAgB,YAAY,SAAS,gBAAgB,eAAgB;GAGlF,MAAM,OAAQ,UAA4B;AAC1C,OAAI,CAAC,QAAQ,KAAK,WAAW,EAAG;AAOhC,OADiB,KAAK,GACT,UAAU,KACrB,QAAO;;;AAKb,QAAO;;;;;;;AAQT,SAAS,uBAAuB,WAAqC;CACnE,MAAM,aAAa,UAAU;AAC7B,KAAI,CAAC,cAAc,WAAW,WAAW,EACvC,QAAO;AAIT,QAAO,IADY,WAAW,KAAI,UAAS,MAAM,KAAK,KAAK,CACrC,KAAK,KAAK,CAAC;;;;;;;AAYnC,SAAS,wBAAwB,WAAiD;AAChF,QAAO,UAAU,QAAQ,QAAO,WAAU;AACxC,MAAI,OAAO,SAAS,WAAW,iBAAkB,QAAO;AAGxD,MAAI,OAAO,GAAG,cAAc,OAAO,CAAE,QAAO;AAI5C,MAAI,OAAO,GAAG,cAAc,IAAI,IAAI,OAAO,GAAG,cAAc,IAAI,CAAE,QAAO;AAEzE,SAAO;GACP;;;;;;;;;;AAWJ,SAAS,uBAAuB,WAAqC;CACnE,MAAM,SAAS,wBAAwB,UAAU;CACjD,MAAM;AAGN,KAAI,OAAO,WAAW,EACpB,QAAO,UAAU,GAAG;CAItB,MAAM,WAAW,UAAU,gBAAgB;CAE3C,MAAM,cAAwB,EAAE;AAGhC,aAAY,KAAK,iBAAiB,GAAG,GAAG;AAIxC,KAAI,SACF,aAAY,KACV,6DAAwD,8DACD,6BAClC,GAAG,4BAEzB;AAGH,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,YAAY,MAAM,KAAK;AAC7B,cAAY,KACV,8CAAiC,KAAK,UAAU,0DACJ,QAAQ,UAAU,UAAU,UAAU,qBAC7D,GAAG,qEACU,KACnC;;AAGH,QAAO,YAAY,KAAK,IAAI,GAAG,WAAW,GAAG;;;;;;;AAQ/C,SAAS,sBAAsB,WAAqC;CAClE,MAAM,SAAS,wBAAwB,UAAU;CACjD,MAAM,WAAW,UAAU,gBAAgB;CAC3C,MAAM;CACN,MAAM;AAGN,KAAI,OAAO,WAAW,KAAK,CAAC,SAC1B,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,cAAc;AAEzB,KAAI,SACF,OAAM,KACJ,uBAAuB,aAAa,kBACpB,aAAa,+BAG9B;CAGH,IAAI,aAAa;AACjB,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,YAAY,MAAM,KAAK;AAC7B,MAAI,CAAC,WACH,OAAM,KAAK,aAAa;AAE1B,QAAM,KAAK,SAAS,UAAU,QAAQ,GAAG,QAAQ,UAAU,IAAI;AAC/D,eAAa;;AAGf,OAAM,KAAK,YAAY;AACvB,QAAO,MAAM,KAAK,IAAI;;;;;;;;;;;;;;AAmBxB,SAAS,kBACP,QACA,WACA,cACA,YACM;CAON,MAAM,YAAY,IAAI,UANH,IAAI,OACrB,aAAa,MACb,YACA,aACD,CAE0C;AAG3C,WAAU,MAAM;CAEhB,MAAM,SAAS,OAAO,iBAAiB,WAAW,UAAU;AAC5D,KAAI,OACF,WAAU,QAAQ,KAAK,OAA+B"}
1
+ {"version":3,"file":"deep-equals.mjs","names":[],"sources":["../../../src/compiler/transforms/deep-equals.mts"],"sourcesContent":["/**\n * AssemblyScript Compiler Transform: Deep Equality & Stringification for User-Defined Objects\n *\n * Injects three methods into user-defined classes at `afterParse`:\n *\n * 1. `__vitest_assemblyscript_deep_equals` — deep equality comparison for `toEqual()`\n * - If the class defines `@operator(\"==\")`: delegates to `this == other`\n * - If the class defines `.equals()`: delegates to `this.equals(other)`\n * - Otherwise: compares all stored instance fields via the pool's `equals()` function\n *\n * 2. `__vitest_assemblyscript_typename` — returns the runtime class name via `nameof<ClassName>()`\n * - Virtual dispatch ensures correct runtime name even for base-typed variables\n * - Used by stringifyValue() for user-facing output and by RTM type name tracking\n *\n * 3. `__vitest_assemblyscript_stringify` — returns comma-separated field entries for stringification\n * - Always stringifies all stored instance fields regardless of operator==/equals()\n * - Follows super chain via isDefined guard, same pattern as deep equality\n * - Uses @global bridge __vitest_assemblyscript_stringify_value to call stringifyValue()\n * - Threads a `budget` parameter through the generated body for short-form truncation\n *\n * Scoping:\n * - Only user source files (not node_modules, not AS stdlib)\n * - Blanket injection into all user classes (always enabled)\n *\n * Cross-module function availability:\n * - Structural bodies reference @global functions from assembly/compare.ts and assembly/utils.ts\n * which are available in all source files without import\n * - Loaded transitively: user test → vitest-pool-assemblyscript/assembly → compare.ts → utils.ts\n *\n * AST injection:\n * - Method source is generated as a string, then parsed into an AST node using\n * `Parser.parseClassMember()` via a temporary `Source` + `Tokenizer`\n *\n * @see https://www.assemblyscript.org/compiler.html#transforms\n * @see https://github.com/AssemblyScript/assemblyscript/blob/main/src/ast.ts\n */\n\nimport {\n ClassDeclaration,\n DeclarationStatement,\n DecoratorNode,\n FieldDeclaration,\n MethodDeclaration,\n Parser,\n Source,\n Tokenizer,\n} from 'assemblyscript';\nimport { Transform } from 'assemblyscript/transform';\n\nimport { ASTVisitor } from '../../util/ast-visitor.js';\nimport {\n ASSEMBLYSCRIPT_LIB_PREFIX,\n COMPARE_EQUALS_GLOBAL_ALIAS,\n DEEP_EQUALS_INJECTED_METHOD_NAME,\n EQUALITY_RESULT_ENUM_NAME,\n COMPARE_EQUALS_PATH_POP_GLOBAL_ALIAS,\n COMPARE_EQUALS_PATH_PUSH_GLOBAL_ALIAS,\n ESCAPE_TO_DIFF_STRING_GLOBAL_ALIAS,\n STRINGIFY_EXCEEDS_BUDGET_GLOBAL_ALIAS,\n STRINGIFY_INDENT_GLOBAL_ALIAS,\n INTERNAL_PATH_LIB_PREFIX,\n STRINGIFY_INJECTED_METHOD_NAME,\n STRINGIFY_VALUE_GLOBAL_ALIAS,\n TYPENAME_INJECTED_METHOD_NAME,\n ASCommonFlags,\n ASDecoratorKind,\n ASNodeKind,\n ASSourceKind,\n} from '../../types/constants.js';\n\n/**\n * Visitor that finds class declarations and injects deep equality, typename, and stringify methods.\n * Uses ASTVisitor for full recursive traversal (finds classes inside namespaces, etc).\n */\nclass DeepEqualsVisitor extends ASTVisitor {\n constructor(\n private parser: Parser,\n private barrelPath: string,\n ) {\n super();\n }\n\n protected onClassEnter(node: ClassDeclaration): void {\n processClass(this.parser, node, this.barrelPath);\n }\n}\n\n/**\n * AssemblyScript compiler transform that injects deep equality, typename, and stringify methods\n * into user-defined classes\n */\nclass DeepEqualsTransform extends Transform {\n afterParse(parser: Parser): void {\n const sources = (this as Transform).program.sources;\n\n // Find the pool's assembly barrel file — used as the normalizedPath for injected\n // methods so the source map attributes them to pool internals, not user code.\n // The AS compiler requires a real source in the compilation for identifier resolution.\n const barrelPath = `${INTERNAL_PATH_LIB_PREFIX}index.ts`;\n const barrelSource = sources.find((s: Source) => s.normalizedPath === barrelPath);\n if (!barrelSource) {\n // This should never happen — the barrel is always loaded transitively via user imports.\n // If it does, fall back to the class's own source path (incorrect attribution but functional).\n console.warn(`[deep-equals transform] WARNING: Could not find barrel source \"${barrelPath}\" in compilation`);\n }\n\n const resolvedBarrelPath = barrelSource ? barrelPath : '';\n const visitor = new DeepEqualsVisitor(parser, resolvedBarrelPath);\n\n // Filter to user source files only (same scoping as strip-inline transform)\n const userSources = sources.filter((source: Source) =>\n (source.sourceKind === ASSourceKind.User || source.sourceKind === ASSourceKind.UserEntry)\n && !source.normalizedPath.startsWith(ASSEMBLYSCRIPT_LIB_PREFIX)\n );\n\n for (const source of userSources) {\n visitor.visitSource(source);\n }\n }\n}\n\n/**\n * Process a class declaration: inject deep equality, typename, and stringify methods.\n */\nfunction processClass(parser: Parser, classDecl: ClassDeclaration, barrelPath: string): void {\n const className = classDecl.name.text;\n\n // Use the barrel path if available, otherwise fall back to the class's own source path\n const sourcePath = barrelPath || classDecl.range.source.normalizedPath;\n\n // Build the type suffix for generic classes (e.g. \"Pair\" → \"Pair<T>\" or \"Pair<K, V>\")\n const typeSuffix = getTypeParameterSuffix(classDecl);\n\n injectDeepEquals(parser, classDecl, className, typeSuffix, sourcePath);\n injectTypename(parser, classDecl, className, typeSuffix, sourcePath);\n injectStringify(parser, classDecl, sourcePath);\n}\n\n/**\n * Inject the deep equality comparison method into a class.\n *\n * Behavior depends on user-defined equality semantics:\n * - @operator(\"==\") present: delegates to `this == other`\n * - .equals() present: delegates to `this.equals(other)`\n * - Neither: field-by-field structural comparison\n *\n * All methods use a usize parameter for inheritance compatibility — AS treats child methods\n * with the same name as overrides, requiring compatible parameter types. Each body casts\n * the pointer to its own type via changetype.\n */\nfunction injectDeepEquals(\n parser: Parser, classDecl: ClassDeclaration,\n className: string, typeSuffix: string, sourcePath: string,\n): void {\n if (hasMethod(classDecl, DEEP_EQUALS_INJECTED_METHOD_NAME)) return;\n\n const typedCast = `const other = changetype<${className}${typeSuffix}>(__other);`;\n const EQ = EQUALITY_RESULT_ENUM_NAME;\n let methodBody: string;\n\n if (hasOperatorEquals(classDecl)) {\n methodBody = `${typedCast} return (this == other) ? ${EQ}.Equal : ${EQ}.NotEqual;`;\n } else if (hasMethod(classDecl, 'equals')) {\n methodBody = `${typedCast} return this.equals(other) ? ${EQ}.Equal : ${EQ}.NotEqual;`;\n } else {\n methodBody = `${typedCast} ${generateStructuralBody(classDecl)}`;\n }\n\n const methodSource =\n `${DEEP_EQUALS_INJECTED_METHOD_NAME}(__other: usize): ${EQ} { ${methodBody} }`;\n\n injectClassMember(parser, classDecl, methodSource, sourcePath);\n}\n\n/**\n * Inject the typename method into a class.\n *\n * Returns the class's own name via nameof<ClassName>(). No super chain — each class returns\n * its own name. Virtual dispatch ensures the correct runtime class name is returned even\n * when the variable is typed as a base class.\n */\nfunction injectTypename(\n parser: Parser, classDecl: ClassDeclaration,\n className: string, typeSuffix: string, sourcePath: string,\n): void {\n if (hasMethod(classDecl, TYPENAME_INJECTED_METHOD_NAME)) return;\n\n const methodSource =\n `${TYPENAME_INJECTED_METHOD_NAME}(): string { return nameof<${className}${typeSuffix}>(); }`;\n\n injectClassMember(parser, classDecl, methodSource, sourcePath);\n}\n\n/**\n * Inject the stringify method into a class.\n *\n * Returns \"fieldName: value\" entries for all stored instance fields, regardless of\n * operator==/equals() — stringify shows full object state, not equality-relevant\n * fields only. See generateStringifyBody for how budget is threaded through fields.\n */\nfunction injectStringify(\n parser: Parser, classDecl: ClassDeclaration,\n sourcePath: string,\n): void {\n if (hasMethod(classDecl, STRINGIFY_INJECTED_METHOD_NAME)) return;\n\n const methodBody = generateStringifyBody(classDecl);\n const methodSource =\n `${STRINGIFY_INJECTED_METHOD_NAME}(formatForDiff: bool = true, depth: i32 = 0, budget: i32 = -1): string { ${methodBody} }`;\n\n injectClassMember(parser, classDecl, methodSource, sourcePath);\n}\n\n// =============================================================================\n// Detection helpers\n// =============================================================================\n\n/**\n * Check if a class has a specific instance method by name\n */\nfunction hasMethod(classDecl: ClassDeclaration, methodName: string): boolean {\n return classDecl.members.some(member =>\n member.kind === ASNodeKind.MethodDeclaration\n && (member as MethodDeclaration).name.text === methodName\n && member.is(ASCommonFlags.Instance)\n );\n}\n\n/**\n * Check if a class has an @operator(\"==\") decorator on any method.\n * The AS compiler uses DecoratorKind.Operator (2) for @operator and\n * DecoratorKind.OperatorBinary (3) for @operator.binary — check both.\n */\nfunction hasOperatorEquals(classDecl: ClassDeclaration): boolean {\n for (const member of classDecl.members) {\n if (member.kind !== ASNodeKind.MethodDeclaration) continue;\n\n const decorators = member.decorators;\n if (!decorators) continue;\n\n for (const decorator of decorators) {\n const kind = (decorator as DecoratorNode).decoratorKind;\n if (kind !== ASDecoratorKind.Operator && kind !== ASDecoratorKind.OperatorBinary) continue;\n\n // Check if the decorator argument is \"==\"\n const args = (decorator as DecoratorNode).args;\n if (!args || args.length === 0) continue;\n\n // The first argument is a string literal with the operator name.\n // At the AST level, LiteralExpression has a .value property for string literals.\n // The AS type declarations expose it as Expression, but the runtime type is\n // StringLiteralExpression with a .value: string property.\n const firstArg = args[0] as any;\n if (firstArg.value === '==') {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Get the type parameter suffix for a class declaration.\n * Returns empty string for non-generic classes, \"<T>\" for single param,\n * \"<K, V>\" for multiple params, etc.\n */\nfunction getTypeParameterSuffix(classDecl: ClassDeclaration): string {\n const typeParams = classDecl.typeParameters;\n if (!typeParams || typeParams.length === 0) {\n return '';\n }\n\n const paramNames = typeParams.map(param => param.name.text);\n return `<${paramNames.join(', ')}>`;\n}\n\n// =============================================================================\n// Structural body generation\n// =============================================================================\n\n/**\n * Collect stored instance fields from a class declaration.\n * Includes public, private, protected fields.\n * Excludes: static fields, getters, setters, constructors, methods.\n */\nfunction getStoredInstanceFields(classDecl: ClassDeclaration): FieldDeclaration[] {\n return classDecl.members.filter(member => {\n if (member.kind !== ASNodeKind.FieldDeclaration) return false;\n\n // Exclude static fields\n if (member.is(ASCommonFlags.Static)) return false;\n\n // Exclude getters and setters (these are MethodDeclarations in AS,\n // but guard against FieldDeclarations with these flags just in case)\n if (member.is(ASCommonFlags.Get) || member.is(ASCommonFlags.Set)) return false;\n\n return true;\n }) as FieldDeclaration[];\n}\n\n/**\n * Generate the structural comparison body for a class.\n * Delegates all field comparisons to the pool's equals function, which handles\n * primitives, strings, containers, nullables, and nested user types recursively.\n *\n * Uses a shared `__result` variable to capture and propagate EqualityResult from\n * each comparison, so type mismatch information from nested comparisons is preserved.\n */\nfunction generateStructuralBody(classDecl: ClassDeclaration): string {\n const fields = getStoredInstanceFields(classDecl);\n const EQ = EQUALITY_RESULT_ENUM_NAME;\n\n // No fields: always equal (two instances of an empty class are structurally identical)\n if (fields.length === 0) {\n return `return ${EQ}.Equal;`;\n }\n\n // Check if class extends another class — if so, include super comparison\n const hasSuper = classDecl.extendsType !== null;\n\n const comparisons: string[] = [];\n\n // Declare a shared result variable for capturing and propagating EqualityResult\n comparisons.push(`let __result: ${EQ};`);\n\n // Super class comparison: delegate to superclass's deep equality comparison method if it exists.\n // Passes __other (raw usize) since the parent's method also takes usize.\n if (hasSuper) {\n comparisons.push(\n `if (isDefined(super.${DEEP_EQUALS_INJECTED_METHOD_NAME})) { `\n + `__result = super.${DEEP_EQUALS_INJECTED_METHOD_NAME}(__other); `\n + `if (__result != ${EQ}.Equal) return __result; `\n + `}`\n );\n }\n\n for (const field of fields) {\n const fieldName = field.name.text;\n comparisons.push(\n `${COMPARE_EQUALS_PATH_PUSH_GLOBAL_ALIAS}(\".${fieldName}\"); `\n + `__result = ${COMPARE_EQUALS_GLOBAL_ALIAS}(this.${fieldName}, other.${fieldName}); `\n + `if (__result != ${EQ}.Equal) return __result; `\n + `${COMPARE_EQUALS_PATH_POP_GLOBAL_ALIAS}();`\n );\n }\n\n return comparisons.join(' ') + ` return ${EQ}.Equal;`;\n}\n\n/**\n * Generate the stringify body for a class — produces \"fieldName: value\" entries\n * (and an atomic super piece, if any) via the global stringify bridge, with each\n * piece guarded by a shared `truncated` flag so the budget is respected.\n */\nfunction generateStringifyBody(classDecl: ClassDeclaration): string {\n const fields = getStoredInstanceFields(classDecl);\n const hasSuper = classDecl.extendsType !== null;\n\n // No fields and no super: return empty string\n if (fields.length === 0 && !hasSuper) {\n return `return \"\";`;\n }\n\n const parts: string[] = [];\n parts.push(`const sep: string = formatForDiff ? \",\\\\n\" : \", \";`);\n // Field/super lines sit at depth+1; short-form stays single-line so prefix is empty\n parts.push(`const linePrefix: string = formatForDiff ? ${STRINGIFY_INDENT_GLOBAL_ALIAS}(depth + 1) : \"\";`);\n parts.push(`let s = \"\";`);\n parts.push(`let used: i32 = 0;`);\n parts.push(`let truncated: bool = false;`);\n\n // Super is an atomic single piece — keeps at most one truncation marker per nesting level\n if (hasSuper) {\n const totalIncludingSuper = fields.length + 1;\n const superTrailingSepLen = fields.length > 0 ? 'sep.length' : '0';\n parts.push(`if (!truncated) {`);\n parts.push(` if (isDefined(super.${STRINGIFY_INJECTED_METHOD_NAME})) {`);\n // Pass all three args explicitly: AS routes default-arg fills through a @varargs\n // trampoline that virtually dispatches on `this`, so a partial super call resolves\n // back to the subclass override and infinitely recurses\n parts.push(` const superStr: string = super.${STRINGIFY_INJECTED_METHOD_NAME}(formatForDiff, depth, -1);`);\n parts.push(` if (superStr != \"\") {`);\n parts.push(` const truncMarker: string = budget >= 0 ? \"…(${totalIncludingSuper})\" : \"\";`);\n parts.push(` const trailingSepLen: i32 = ${superTrailingSepLen};`);\n parts.push(` if (${STRINGIFY_EXCEEDS_BUDGET_GLOBAL_ALIAS}(used, superStr.length, trailingSepLen, truncMarker.length, budget)) {`);\n parts.push(` s += truncMarker;`);\n parts.push(` truncated = true;`);\n parts.push(` } else {`);\n parts.push(` s += superStr;`);\n parts.push(` used += superStr.length;`);\n if (fields.length > 0) {\n parts.push(` s += sep;`);\n parts.push(` used += sep.length;`);\n }\n parts.push(` }`);\n parts.push(` }`);\n parts.push(` }`);\n parts.push(`}`);\n }\n\n // Each field is guarded by `truncated`; values sit one level deeper (depth + 1)\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i];\n const fieldName = field?.name?.text;\n const isLast = i === fields.length - 1;\n const remainingPieces = fields.length - i; // includes the current field\n parts.push(`if (!truncated) {`);\n parts.push(` const fieldName: string = formatForDiff ? ${ESCAPE_TO_DIFF_STRING_GLOBAL_ALIAS}(\"${fieldName}\") : \"${fieldName}\";`);\n parts.push(` const truncMarker: string = budget >= 0 ? \"…(${remainingPieces})\" : \"\";`);\n parts.push(` const fieldSepLen: i32 = ${isLast ? '0' : 'sep.length'};`);\n parts.push(` const childBudget: i32 = budget < 0 ? -1 : max(0, budget - used - fieldSepLen - truncMarker.length);`);\n parts.push(` const piece: string = \\`\\${linePrefix}\\${fieldName}: \\${${STRINGIFY_VALUE_GLOBAL_ALIAS}(this.${fieldName}, formatForDiff, depth + 1, childBudget)}\\`;`);\n parts.push(` if (${STRINGIFY_EXCEEDS_BUDGET_GLOBAL_ALIAS}(used, piece.length, fieldSepLen, truncMarker.length, budget)) {`);\n parts.push(` s += truncMarker;`);\n parts.push(` truncated = true;`);\n parts.push(` } else {`);\n parts.push(` s += piece;`);\n parts.push(` used += piece.length;`);\n if (!isLast) {\n parts.push(` s += sep;`);\n parts.push(` used += sep.length;`);\n }\n parts.push(` }`);\n parts.push(`}`);\n }\n\n parts.push(`return s;`);\n return parts.join(' ');\n}\n\n// =============================================================================\n// AST injection\n// =============================================================================\n\n/**\n * Parse a method source string and inject it as a member of the given class.\n *\n * Creates a temporary Source and Tokenizer, uses the parser's parseClassMember()\n * to produce a proper AST node, then appends it to the class's members array.\n *\n * The temporary source uses the pool's assembly barrel file (assembly/index.ts) as its\n * normalizedPath instead of the user's source file. This prevents the source map from\n * incorrectly attributing generated code to user source lines. The AS compiler requires\n * the normalizedPath to be a real source in the compilation for identifier resolution\n * (synthetic paths cause assertion failures in maybeCompileEnclosingSource).\n */\nfunction injectClassMember(\n parser: Parser,\n classDecl: ClassDeclaration,\n memberSource: string,\n barrelPath: string,\n): void {\n const tempSource = new Source(\n ASSourceKind.User,\n barrelPath,\n memberSource,\n );\n\n const tokenizer = new Tokenizer(tempSource);\n\n // Advance past the initial token so the parser is positioned correctly\n tokenizer.next();\n\n const member = parser.parseClassMember(tokenizer, classDecl);\n if (member) {\n classDecl.members.push(member as DeclarationStatement);\n }\n}\n\nexport default DeepEqualsTransform;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { ASDecoratorKind, ASSourceKind } from "../../constants-DbxJ3hzg.mjs";
2
- import { ASTVisitor } from "../../ast-visitor-CWEOd3UH.mjs";
1
+ import { ASDecoratorKind, ASSourceKind } from "../../constants-Bq5KNxXJ.mjs";
2
+ import { ASTVisitor } from "../../ast-visitor-w1HMbuJR.mjs";
3
3
  import { Transform } from "assemblyscript/transform";
4
4
 
5
5
  //#region src/compiler/transforms/strip-inline.mts
@@ -1,7 +1,7 @@
1
- import { POOL_ERROR_NAMES } from "./constants-DbxJ3hzg.mjs";
2
- import { createPoolError, debug, throwPoolErrorIfAborted } from "./debug-DtRAL4rM.mjs";
3
- import { toForwardSlash } from "./path-utils-t9OzjXYF.mjs";
4
- import { clearNativeBuildError, hasNativeBuildError, warnASInstrumentationNotLoaded } from "./feature-check-Bje3ntpV.mjs";
1
+ import { POOL_ERROR_NAMES } from "./constants-Bq5KNxXJ.mjs";
2
+ import { createPoolError, debug, parseSourceMap, toForwardSlash } from "./pool-errors-Bn6YaguR.mjs";
3
+ import { getWasmMemoryRequirements } from "./wasm-memory-C8Nkl2Sz.mjs";
4
+ import { clearNativeBuildError, hasNativeBuildError, warnASInstrumentationNotLoaded } from "./feature-check-BJpc4LoO.mjs";
5
5
  import { basename, resolve } from "node:path";
6
6
  import { access, readFile } from "node:fs/promises";
7
7
  import { main } from "assemblyscript/asc";
@@ -15,7 +15,7 @@ import { main } from "assemblyscript/asc";
15
15
  */
16
16
  let nativeAddon;
17
17
  try {
18
- nativeAddon = await import("./addon-interface-CYFXMbK7.mjs");
18
+ nativeAddon = await import("./addon-interface-BaUmn7uC.mjs");
19
19
  clearNativeBuildError();
20
20
  } catch (err) {
21
21
  if (await hasNativeBuildError()) debug(`[Compiler] Native instrumentation addon not loaded (known build failure): ${err?.message ?? String(err)}`);
@@ -28,23 +28,22 @@ setImmediate(async () => {
28
28
  try {
29
29
  await access(STRIP_INLINE_TRANSFORM);
30
30
  } catch {
31
- throw createPoolError(`AS Compiler strip inline transform file not found at "${STRIP_INLINE_TRANSFORM}"`, POOL_ERROR_NAMES.CompilationError);
31
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, `AS Compiler strip inline transform file not found at "${STRIP_INLINE_TRANSFORM}"`);
32
32
  }
33
33
  try {
34
34
  await access(DEEP_EQUALS_TRANSFORM);
35
35
  } catch {
36
- throw createPoolError(`AS Compiler deep equals transform file not found at "${DEEP_EQUALS_TRANSFORM}"`, POOL_ERROR_NAMES.CompilationError);
36
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, `AS Compiler deep equals transform file not found at "${DEEP_EQUALS_TRANSFORM}"`);
37
37
  }
38
38
  });
39
39
  /**
40
40
  * Compile AssemblyScript source code to WASM binary
41
41
  */
42
- async function compileAssemblyScript(filename, options, logModule, logLabel, signal) {
43
- throwPoolErrorIfAborted(signal);
42
+ async function compileAssemblyScript(filename, options, logModule, logLabel) {
44
43
  const compileStart = performance.now();
45
44
  const logPrefix = `[${logModule} ASC] ${logLabel}`;
46
45
  const { shouldInstrument, instrumentationOptions, extraFlags } = options;
47
- if (shouldInstrument && !instrumentationOptions) throw createPoolError("Instrumentation options are required for coverage instrumentation", POOL_ERROR_NAMES.CompilationError);
46
+ if (shouldInstrument && !instrumentationOptions) throw createPoolError(POOL_ERROR_NAMES.CompilationError, "Instrumentation options are required for coverage instrumentation");
48
47
  const stdoutLines = [];
49
48
  const stderrLines = [];
50
49
  let binary;
@@ -89,7 +88,6 @@ async function compileAssemblyScript(filename, options, logModule, logLabel, sig
89
88
  stdout,
90
89
  stderr,
91
90
  writeFile: (name, contents, _baseDir) => {
92
- throwPoolErrorIfAborted(signal);
93
91
  if (name.endsWith(".wasm") && contents instanceof Uint8Array) {
94
92
  binary = contents;
95
93
  debug(`${logPrefix} - Captured binary in memory: "${name}"`);
@@ -119,39 +117,69 @@ async function compileAssemblyScript(filename, options, logModule, logLabel, sig
119
117
  debug(`${logPrefix} - TIMING asc.main: ${(performance.now() - ascStart).toFixed(2)} ms`);
120
118
  if (result.error) {
121
119
  const errorMessage = stderrLines.length > 0 ? `${result.error.message}\n\n${stderrLines.join("")}` : result.error.message;
122
- throw createPoolError(errorMessage, POOL_ERROR_NAMES.CompilationError, errorMessage);
120
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, errorMessage);
123
121
  }
124
- if (!binary) throw createPoolError(stderrLines.length > 0 ? `No WASM binary was generated\n\nAS Compiler output:\n${stderrLines.join("")}` : "No WASM binary was generated", POOL_ERROR_NAMES.CompilationError);
125
- if (!sourceMap) throw createPoolError("Source map not captured from AssemblyScript Compiler", POOL_ERROR_NAMES.CompilationError);
122
+ if (!binary) {
123
+ const errorMessage = stderrLines.length > 0 ? `No WASM binary was generated\n\nAS Compiler output:\n${stderrLines.join("")}` : "No WASM binary was generated";
124
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, errorMessage);
125
+ }
126
+ if (!sourceMap) throw createPoolError(POOL_ERROR_NAMES.CompilationError, "Source map not captured from AssemblyScript Compiler");
126
127
  const cleanBinary = binary;
127
128
  const wasmSourceMap = sourceMap;
128
129
  debug(`${logPrefix} - Compilation successful, clean binary size: ${cleanBinary.length} bytes`);
129
130
  debug(`${logPrefix} - Source map generated, size: ${wasmSourceMap.length * 2} bytes`);
131
+ let compilationBinary = cleanBinary;
132
+ let compilationSourceMap = wasmSourceMap;
133
+ let compilationDebugInfo;
134
+ let compilationIsInstrumented = false;
130
135
  if (options.shouldInstrument && nativeAddon) {
131
- throwPoolErrorIfAborted(signal);
132
136
  const instrumentStart = performance.now();
133
137
  const wasmBuffer = Buffer.from(cleanBinary);
134
138
  const sourceMapBuffer = Buffer.from(wasmSourceMap);
135
139
  const instrumentResult = nativeAddon.instrumentForCoverage(wasmBuffer, sourceMapBuffer, options.instrumentationOptions, logModule, logLabel);
136
140
  const instCount = instrumentResult.debugInfo.instrumentedFunctionCount;
137
- const instrumentEnd = performance.now();
138
141
  debug(`${logPrefix} - TIMING Instrumented ${instCount} functions: ${(performance.now() - instrumentStart).toFixed(2)} ms`);
139
- return {
140
- binary: instrumentResult.instrumentedWasm,
141
- sourceMap: instrumentResult.sourceMap,
142
- debugInfo: instrumentResult.debugInfo,
143
- isInstrumented: true,
144
- compileTiming: instrumentEnd - compileStart
145
- };
142
+ compilationBinary = instrumentResult.instrumentedWasm;
143
+ compilationSourceMap = instrumentResult.sourceMap;
144
+ compilationDebugInfo = instrumentResult.debugInfo;
145
+ compilationIsInstrumented = true;
146
+ }
147
+ let parsedSourceMap;
148
+ let compiledModule;
149
+ let requiredMemory;
150
+ try {
151
+ const s = performance.now();
152
+ parsedSourceMap = parseSourceMap(compilationSourceMap);
153
+ debug(`${logPrefix} - TIMING compileAssemblyScript - parseSourceMap:${(performance.now() - s).toFixed(2)} ms`);
154
+ } catch (error) {
155
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, "Error parsing WASM compilation source map", error, true);
156
+ }
157
+ try {
158
+ const s = performance.now();
159
+ compiledModule = await WebAssembly.compile(compilationBinary);
160
+ debug(`${logPrefix} - TIMING compileAssemblyScript - WebAssembly.compile:${(performance.now() - s).toFixed(2)} ms`);
161
+ } catch (error) {
162
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, "Error running WebAssembly.compile on asc-compiled WASM binary", error, true);
163
+ }
164
+ try {
165
+ const s = performance.now();
166
+ requiredMemory = getWasmMemoryRequirements(compilationBinary);
167
+ debug(`${logPrefix} - TIMING compileAssemblyScript - getWasmMemoryRequirements:${(performance.now() - s).toFixed(2)} ms`);
168
+ debug(`${logPrefix} - Required Memory:`, JSON.stringify(requiredMemory));
169
+ } catch (error) {
170
+ throw createPoolError(POOL_ERROR_NAMES.CompilationError, "Error extracting memory requirements from asc-compiled WASM binary", error, true);
146
171
  }
147
172
  return {
148
- binary: cleanBinary,
149
- sourceMap: wasmSourceMap,
150
- isInstrumented: false,
173
+ filePath: filename,
174
+ sourceMap: parsedSourceMap,
175
+ debugInfo: compilationDebugInfo,
176
+ compiledModule,
177
+ requiredMemory,
178
+ isInstrumented: compilationIsInstrumented,
151
179
  compileTiming: performance.now() - compileStart
152
180
  };
153
181
  }
154
182
 
155
183
  //#endregion
156
184
  export { compileAssemblyScript };
157
- //# sourceMappingURL=compiler-Dqs-qd3I.mjs.map
185
+ //# sourceMappingURL=compiler-CXR5UJId.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-CXR5UJId.mjs","names":["ascMain"],"sources":["../src/compiler/index.ts"],"sourcesContent":["/**\n * AssemblyScript Compiler\n *\n * Handles compilation of AssemblyScript source code to WASM binaries.\n * Manages compiler options, transforms, and in-memory compilation.\n */\n\nimport { main as ascMain } from 'assemblyscript/asc';\nimport { basename, resolve } from 'node:path';\nimport { access, readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { RawSourceMap } from 'source-map';\n\nimport type {\n AssemblyScriptCompilerOptions,\n NativeAddonInterface,\n BinaryDebugInfo,\n WASMModuleMemoryRequirements,\n WASMCompilation\n} from '../types/types.js';\nimport { POOL_ERROR_NAMES } from '../types/constants.js';\nimport { debug } from '../util/debug.js';\nimport { createPoolError } from '../util/pool-errors.js';\nimport { clearNativeBuildError, hasNativeBuildError, warnASInstrumentationNotLoaded } from '../util/feature-check.js';\nimport { toForwardSlash } from '../util/path-utils.js';\nimport { parseSourceMap } from '../wasm-executor/source-maps.js';\nimport { getWasmMemoryRequirements } from '../wasm-executor/wasm-memory.js';\n\nlet nativeAddon: NativeAddonInterface | undefined;\ntry {\n nativeAddon = await import('../instrumentation/addon-interface.js');\n // Addon loaded successfully — clear any stale build error marker (fire and forget)\n clearNativeBuildError();\n} catch (err: any) {\n const knownBuildFailure = await hasNativeBuildError();\n if (knownBuildFailure) {\n // Marker file exists — coverage provider will warn the user, just debug log here\n debug(`[Compiler] Native instrumentation addon not loaded (known build failure): ${err?.message ?? String(err)}`);\n } else {\n // Unexpected failure — no marker file, warn the user\n warnASInstrumentationNotLoaded(err?.message ?? String(err));\n }\n}\n\nconst DEBUG_WRITE_FILES = false;\n\n// Path prefix the AS compiler uses when resolving bare `vitest-pool-assemblyscript/assembly` imports\n// via node_modules. Used to detect self-imports and redirect to local assembly/ dir when running locally in-tree.\nconst POOL_ASSEMBLY_NODE_MODULES_PREFIX = 'node_modules/vitest-pool-assemblyscript/assembly/';\n\n// paths assume that we're running from dist/\nconst STRIP_INLINE_TRANSFORM = resolve(import.meta.dirname, './compiler/transforms/strip-inline.mjs');\nconst DEEP_EQUALS_TRANSFORM = resolve(import.meta.dirname, './compiler/transforms/deep-equals.mjs');\n\nsetImmediate(async () => {\n try {\n await access(STRIP_INLINE_TRANSFORM);\n } catch {\n throw createPoolError(\n POOL_ERROR_NAMES.CompilationError,\n `AS Compiler strip inline transform file not found at \"${STRIP_INLINE_TRANSFORM}\"`,\n );\n }\n\n try {\n await access(DEEP_EQUALS_TRANSFORM);\n } catch {\n throw createPoolError(\n POOL_ERROR_NAMES.CompilationError,\n `AS Compiler deep equals transform file not found at \"${DEEP_EQUALS_TRANSFORM}\"`,\n );\n }\n});\n\n/**\n * Compile AssemblyScript source code to WASM binary\n */\nexport async function compileAssemblyScript(\n filename: string,\n options: AssemblyScriptCompilerOptions,\n logModule: string,\n logLabel: string,\n): Promise<WASMCompilation> {\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 POOL_ERROR_NAMES.CompilationError,\n 'Instrumentation options are required for coverage instrumentation',\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 // Injects deep equality comparison method into user-defined classes for toEqual support\n '--transform', DEEP_EQUALS_TRANSFORM,\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 if (name.endsWith('.wasm') && contents instanceof Uint8Array) {\n binary = contents;\n debug(`${logPrefix} - Captured binary in memory: \"${name}\"`);\n } else if (name.endsWith('.wasm.map') && typeof contents === 'string') {\n debug(`${logPrefix} - Captured source map in memory: \"${name}\"`);\n sourceMap = contents;\n } else {\n debug(`${logPrefix} - WARNING - Captured Unexpected File: \"${name}\" at baseDir: \"${_baseDir}\"`);\n }\n },\n \n // Custom readFile enables in-tree resolution of bare pool assembly imports.\n // When a test file imports 'vitest-pool-assemblyscript/assembly', the AS compiler\n // resolves it to a node_modules path. This works when the package is installed,\n // but fails in-tree (the package isn't in its own node_modules). The fallback\n // redirects these to the local assembly/ directory when the normal path isn't found.\n readFile: async (filename, baseDir): Promise<string | null> => {\n const filePath = resolve(baseDir, filename);\n\n try {\n return await readFile(filePath, { encoding: 'utf-8' });\n } catch {\n // Fallback: when running in-tree, redirect pool assembly imports to local assembly/ dir\n const normalizedFilename = toForwardSlash(filename);\n if (normalizedFilename.startsWith(POOL_ASSEMBLY_NODE_MODULES_PREFIX)) {\n const localSubpath = normalizedFilename.substring(POOL_ASSEMBLY_NODE_MODULES_PREFIX.length);\n const localPath = resolve(baseDir, 'assembly', localSubpath);\n\n try {\n return await readFile(localPath, { encoding: 'utf-8' });\n } catch {\n return null;\n }\n }\n\n return null;\n }\n },\n });\n\n debug(`${logPrefix} - TIMING asc.main: ${(performance.now() - ascStart).toFixed(2)} ms`);\n\n if (result.error) {\n const errorMessage = stderrLines.length > 0\n ? `${result.error.message}\\n\\n${stderrLines.join('')}`\n : result.error.message;\n\n throw createPoolError(\n POOL_ERROR_NAMES.CompilationError,\n errorMessage\n );\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(\n POOL_ERROR_NAMES.CompilationError,\n errorMessage\n );\n }\n\n if (!sourceMap) {\n throw createPoolError(\n POOL_ERROR_NAMES.CompilationError,\n 'Source map not captured from AssemblyScript Compiler'\n );\n }\n\n const cleanBinary: Uint8Array = binary;\n const wasmSourceMap: string = sourceMap;\n\n debug(`${logPrefix} - Compilation successful, clean binary size: ${cleanBinary.length} bytes`);\n debug(`${logPrefix} - Source map generated, size: ${wasmSourceMap.length * 2} bytes`);\n \n if (DEBUG_WRITE_FILES) {\n // Write source map for debugging\n const dir = './debug';\n // TODO - handle non-.ts extensions\n const sourceMapFileName = `${basename(filename, '.ts')}.ts.map`;\n const sourceMapPath = `${dir}/${sourceMapFileName}`;\n\n // Create directory if it doesn't exist\n try {\n await mkdir(dir, { recursive: true });\n } catch {\n // Directory already exists or creation failed, continue\n }\n\n // Format as well-formed JSON\n const formattedSourceMap = JSON.stringify(JSON.parse(wasmSourceMap), null, 2);\n\n writeFile(sourceMapPath, formattedSourceMap, { encoding: 'utf8' });\n debug(`${logPrefix} - Wrote source map to: \"${sourceMapPath}\"`);\n\n // Also write WASM binary for inspection\n const wasmPath = sourceMapPath.replace('.map', '.wasm');\n writeFile(wasmPath, cleanBinary);\n debug(`${logPrefix} - Wrote WASM binary to: \"${wasmPath}\"`);\n }\n\n let compilationBinary: Uint8Array = cleanBinary;\n let compilationSourceMap: string = wasmSourceMap;\n let compilationDebugInfo: BinaryDebugInfo | undefined;\n let compilationIsInstrumented: boolean = false;\n \n // Instrument binary for coverage if requested and available\n if (options.shouldInstrument && nativeAddon) {\n const instrumentStart = performance.now();\n const wasmBuffer = Buffer.from(cleanBinary);\n const sourceMapBuffer = Buffer.from(wasmSourceMap);\n\n const instrumentResult = nativeAddon.instrumentForCoverage(wasmBuffer, sourceMapBuffer, options.instrumentationOptions!, logModule, logLabel);\n const instCount = instrumentResult.debugInfo.instrumentedFunctionCount;\n\n debug(`${logPrefix} - TIMING Instrumented ${instCount} functions: ${(performance.now() - instrumentStart).toFixed(2)} ms`);\n\n compilationBinary = instrumentResult.instrumentedWasm;\n compilationSourceMap = instrumentResult.sourceMap;\n compilationDebugInfo = instrumentResult.debugInfo;\n compilationIsInstrumented = true;\n }\n\n let parsedSourceMap: RawSourceMap;\n let compiledModule: WebAssembly.Module;\n let requiredMemory: WASMModuleMemoryRequirements;\n\n try {\n const s = performance.now();\n parsedSourceMap = parseSourceMap(compilationSourceMap);\n\n debug(`${logPrefix} - TIMING compileAssemblyScript - parseSourceMap:`\n + `${(performance.now() - s).toFixed(2)} ms`\n );\n } catch (error) {\n throw createPoolError(POOL_ERROR_NAMES.CompilationError, 'Error parsing WASM compilation source map', error, true);\n }\n \n try {\n const s = performance.now();\n compiledModule = await WebAssembly.compile(compilationBinary as BufferSource);\n\n debug(`${logPrefix} - TIMING compileAssemblyScript - WebAssembly.compile:`\n + `${(performance.now() - s).toFixed(2)} ms`\n );\n } catch (error) {\n throw createPoolError(POOL_ERROR_NAMES.CompilationError, 'Error running WebAssembly.compile on asc-compiled WASM binary', error, true);\n }\n\n try {\n const s = performance.now();\n requiredMemory = getWasmMemoryRequirements(compilationBinary);\n\n debug(`${logPrefix} - TIMING compileAssemblyScript - getWasmMemoryRequirements:`\n + `${(performance.now() - s).toFixed(2)} ms`\n );\n debug(`${logPrefix} - Required Memory:`, JSON.stringify(requiredMemory));\n } catch (error) {\n throw createPoolError(POOL_ERROR_NAMES.CompilationError, 'Error extracting memory requirements from asc-compiled WASM binary', error, true);\n }\n\n return {\n filePath: filename,\n sourceMap: parsedSourceMap,\n debugInfo: compilationDebugInfo,\n compiledModule,\n requiredMemory,\n isInstrumented: compilationIsInstrumented,\n compileTiming: performance.now() - compileStart,\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { AssemblyScriptPoolOptions, HybridProviderOptions, WasmImportsFactory, WasmImportsFactoryInfo } from "../types-DHVk5iAx.mjs";
1
+ import { AssemblyScriptPoolOptions, HybridProviderOptions, WasmImportsFactory, WasmImportsFactoryInfo } from "../types-CoroKYxB.mjs";
2
2
  import { CoverageV8Options } from "vitest/node";
3
3
  import { ConfigEnv, UserWorkspaceConfig, ViteUserConfig } from "vitest/config";
4
4
 
@@ -1 +1 @@
1
- {"version":3,"file":"index-v3.d.mts","names":[],"sources":["../../src/config/custom-provider-options-v3.ts","../../src/config/config-helpers-v3.ts"],"mappings":";;;;;;;;AAE2C;;;;;;;;;;;;;;;;;;YAuB/B,qBAAA,SAA8B,qBAAA,EAAuB,IAAA,CAAK,iBAAA;IAClE,QAAA;ICOJ;IDJG,oBAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;KCIS,wBAAA,WAAmC,cAAA,IAAkB,CAAA;EAC/D,IAAA;IAEE,WAAA;MACE,cAAA,GAAiB,yBAAA;IAAA;EAAA;AAAA;;;;KAQX,0BAAA,GAA6B,wBAAA,CAAyB,cAAA;;;;KAKtD,iCAAA,GAAoC,wBAAA,CAAyB,mBAAA;;;;;;AALzE;;;;;AAKA;;;;;AA+BA;;;;;;;;;AAGA;;;;;iBAHgB,0BAAA,CACd,MAAA,EAAQ,0BAAA,GACP,0BAAA;AAAA,iBACa,0BAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,0BAAA,IACf,OAAA,CAAQ,0BAAA;AAAA,iBACK,0BAAA,CACd,MAAA,GAAS,GAAA,EAAK,SAAA,KAAc,0BAAA,GAA6B,OAAA,CAAQ,0BAAA,KAC/D,GAAA,EAAK,SAAA,KAAc,0BAAA,GAA6B,OAAA,CAAQ,0BAAA;;;;;;;;;AAF5D;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA;;;;;;iBAAgB,2BAAA,CACd,MAAA,EAAQ,iCAAA,GACP,iCAAA;AAAA,iBACa,2BAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,iCAAA,IACf,OAAA,CAAQ,iCAAA;AAAA,iBACK,2BAAA,CACd,MAAA,GAAS,GAAA,EAAK,SAAA,KAAc,iCAAA,GAAoC,OAAA,CAAQ,iCAAA,KACtE,GAAA,EAAK,SAAA,KAAc,iCAAA,GAAoC,OAAA,CAAQ,iCAAA"}
1
+ {"version":3,"file":"index-v3.d.mts","names":[],"sources":["../../src/config/custom-provider-options-v3.ts","../../src/config/config-helpers-v3.ts"],"mappings":";;;;;;;;AAE2C;;;;;;;;;;;;;;;;;;YAuB/B,qBAAA,SAA8B,qBAAA,EAAuB,IAAA,CAAK,iBAAA;IAClE,QAAA;ICOJ;IDJG,oBAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;KCIS,wBAAA,WAAmC,cAAA,IAAkB,CAAA;EAC/D,IAAA;IACE,WAAA;MACE,cAAA,GAAiB,yBAAA;IAAA;EAAA;AAAA;;;;KAQX,0BAAA,GAA6B,wBAAA,CAAyB,cAAA;;;;KAKtD,iCAAA,GAAoC,wBAAA,CAAyB,mBAAA;;;;;;AALzE;;;;;AAKA;;;;;AA+BA;;;;;;;;;AAGA;;;;;iBAHgB,0BAAA,CACd,MAAA,EAAQ,0BAAA,GACP,0BAAA;AAAA,iBACa,0BAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,0BAAA,IACf,OAAA,CAAQ,0BAAA;AAAA,iBACK,0BAAA,CACd,MAAA,GAAS,GAAA,EAAK,SAAA,KAAc,0BAAA,GAA6B,OAAA,CAAQ,0BAAA,KAC/D,GAAA,EAAK,SAAA,KAAc,0BAAA,GAA6B,OAAA,CAAQ,0BAAA;;;;;;;;;AAF5D;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA;;;;;;iBAAgB,2BAAA,CACd,MAAA,EAAQ,iCAAA,GACP,iCAAA;AAAA,iBACa,2BAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,iCAAA,IACf,OAAA,CAAQ,iCAAA;AAAA,iBACK,2BAAA,CACd,MAAA,GAAS,GAAA,EAAK,SAAA,KAAc,iCAAA,GAAoC,OAAA,CAAQ,iCAAA,KACtE,GAAA,EAAK,SAAA,KAAc,iCAAA,GAAoC,OAAA,CAAQ,iCAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index-v3.mjs","names":[],"sources":["../../src/config/config-helpers-v3.ts"],"sourcesContent":["/**\n * Configuration helpers for vitest-pool-assemblyscript\n *\n * Provides custom type-safe config helpers similar to Cloudflare's vitest-pool-workers\n * to work around TypeScript's ProjectConfig poolOptions type narrowing in Vitest v3.\n */\n\nimport type { ViteUserConfig, UserWorkspaceConfig, ConfigEnv } from 'vitest/config';\n\nimport type { AssemblyScriptPoolOptions } from '../types/types.js';\n\n/**\n * Type for config that may be a value, Promise, or function\n */\ntype AnyConfigExport<T extends ViteUserConfig> =\n | T\n | Promise<T>\n | ((env: ConfigEnv) => T | Promise<T>);\n\n/**\n * AssemblyScript pool configuration with proper typing for poolOptions\n *\n * Use this type with `defineAssemblyScriptConfig` for root-level configs,\n * or `defineAssemblyScriptProject` for project-level configs.\n * \n * Vitest v3's ProjectConfig narrows poolOptions as an inline object type,\n * which cannot be augmented via TypeScript module augmentation. Config helpers\n * use type intersection to add poolOptions.assemblyScript typing.\n *\n * Note: Coverage is NOT included here because it's global-only config in Vitest.\n * Coverage typing comes from the `CustomProviderOptions` augmentation loaded\n * via the `./index-v3.ts` side-effect import.\n */\nexport type AssemblyScriptUserConfig<T extends ViteUserConfig> = T & {\n test?: {\n // pool?: string;\n poolOptions?: {\n assemblyScript?: AssemblyScriptPoolOptions;\n };\n };\n};\n\n/**\n * Root-level config type with AssemblyScript pool support\n */\nexport type AssemblyScriptConfigExport = AssemblyScriptUserConfig<ViteUserConfig>;\n\n/**\n * Project-level config type with AssemblyScript pool support\n */\nexport type AssemblyScriptProjectConfigExport = AssemblyScriptUserConfig<UserWorkspaceConfig>;\n\n/**\n * Define a root-level Vitest config with AssemblyScript pool options.\n *\n * This is a type-safe wrapper that properly types `poolOptions.assemblyScript`\n * for both root and project-level configurations.\n *\n * @example\n * ```ts\n * import { defineAssemblyScriptConfig } from 'vitest-pool-assemblyscript/config';\n *\n * export default defineAssemblyScriptConfig({\n * test: {\n * name: 'assemblyscript-unit-tests',\n * pool: 'vitest-pool-assemblyscript',\n * include: ['test/assembly/**‍/*.as.test.ts'], // example\n * poolOptions: {\n * assemblyScript: { // optional },\n * },\n * coverage: {\n * provider: 'custom',\n * customProviderModule: 'vitest-pool-assemblyscript/coverage',\n * include: ['src/**‍/*.ts'], // example JS/TS sources (v8 provider)\n * assemblyScriptInclude: ['assembly/**‍/*.ts'], // example AS sources\n * assemblyScriptExclude: ['**‍/*.as.test.ts'], // exclude AS test files\n * },\n * },\n * });\n * ```\n */\nexport function defineAssemblyScriptConfig(\n config: AssemblyScriptConfigExport\n): AssemblyScriptConfigExport;\nexport function defineAssemblyScriptConfig(\n config: Promise<AssemblyScriptConfigExport>\n): Promise<AssemblyScriptConfigExport>;\nexport function defineAssemblyScriptConfig(\n config: (env: ConfigEnv) => AssemblyScriptConfigExport | Promise<AssemblyScriptConfigExport>\n): (env: ConfigEnv) => AssemblyScriptConfigExport | Promise<AssemblyScriptConfigExport>;\nexport function defineAssemblyScriptConfig(\n config: AnyConfigExport<AssemblyScriptConfigExport>\n): AnyConfigExport<AssemblyScriptConfigExport> {\n // Pass through - this is just for type safety\n return config;\n}\n\n/**\n * Define a project-level Vitest config with AssemblyScript pool options.\n *\n * Use this when defining AssemblyScript test projects within a workspace.\n *\n * @example\n * ```ts\n * import { defineConfig, defineProject } from 'vitest/config';\n * import { defineAssemblyScriptProject } from 'vitest-pool-assemblyscript/config';\n *\n * export default defineConfig({\n * test: {\n * projects: [\n * defineProject({\n * test: {\n * name: { label: 'typescript-unit-tests', color: 'blue' },\n * }\n * }),\n * defineAssemblyScriptProject({\n * test: {\n * name: { label: 'assemblyscript-unit-tests', color: 'yellow' },\n * pool: 'vitest-pool-assemblyscript',\n * include: ['test/assembly/**‍/*.as.test.ts'], // example\n * poolOptions: {\n * assemblyScript: { // optional },\n * },\n * },\n * }),\n * ],\n * coverage: { // coverage section is global only in vitest\n * provider: 'custom',\n * customProviderModule: 'vitest-pool-assemblyscript/coverage',\n * include: ['src/**‍/*.ts'], // example JS/TS sources (v8 provider)\n * assemblyScriptInclude: ['assembly/**‍/*.ts'], // example AS sources\n * assemblyScriptExclude: ['**‍/*.as.test.ts'], // exclude AS test files\n * },\n * },\n * });\n * ```\n */\nexport function defineAssemblyScriptProject(\n config: AssemblyScriptProjectConfigExport\n): AssemblyScriptProjectConfigExport;\nexport function defineAssemblyScriptProject(\n config: Promise<AssemblyScriptProjectConfigExport>\n): Promise<AssemblyScriptProjectConfigExport>;\nexport function defineAssemblyScriptProject(\n config: (env: ConfigEnv) => AssemblyScriptProjectConfigExport | Promise<AssemblyScriptProjectConfigExport>\n): (env: ConfigEnv) => AssemblyScriptProjectConfigExport | Promise<AssemblyScriptProjectConfigExport>;\nexport function defineAssemblyScriptProject(\n config: AnyConfigExport<AssemblyScriptProjectConfigExport>\n): AnyConfigExport<AssemblyScriptProjectConfigExport> {\n // Pass through - this is just for type safety\n return config;\n}\n"],"mappings":";AA0FA,SAAgB,2BACd,QAC6C;AAE7C,QAAO;;AAoDT,SAAgB,4BACd,QACoD;AAEpD,QAAO"}
1
+ {"version":3,"file":"index-v3.mjs","names":[],"sources":["../../src/config/config-helpers-v3.ts"],"sourcesContent":["/**\n * Configuration helpers for vitest-pool-assemblyscript\n *\n * Provides custom type-safe config helpers similar to Cloudflare's vitest-pool-workers\n * to work around TypeScript's ProjectConfig poolOptions type narrowing in Vitest v3.\n */\n\nimport type { ViteUserConfig, UserWorkspaceConfig, ConfigEnv } from 'vitest/config';\n\nimport type { AssemblyScriptPoolOptions } from '../types/types.js';\n\n/**\n * Type for config that may be a value, Promise, or function\n */\ntype AnyConfigExport<T extends ViteUserConfig> =\n | T\n | Promise<T>\n | ((env: ConfigEnv) => T | Promise<T>);\n\n/**\n * AssemblyScript pool configuration with proper typing for poolOptions\n *\n * Use this type with `defineAssemblyScriptConfig` for root-level configs,\n * or `defineAssemblyScriptProject` for project-level configs.\n * \n * Vitest v3's ProjectConfig narrows poolOptions as an inline object type,\n * which cannot be augmented via TypeScript module augmentation. Config helpers\n * use type intersection to add poolOptions.assemblyScript typing.\n *\n * Note: Coverage is NOT included here because it's global-only config in Vitest.\n * Coverage typing comes from the `CustomProviderOptions` augmentation loaded\n * via the `./index-v3.ts` side-effect import.\n */\nexport type AssemblyScriptUserConfig<T extends ViteUserConfig> = T & {\n test?: {\n poolOptions?: {\n assemblyScript?: AssemblyScriptPoolOptions;\n };\n };\n};\n\n/**\n * Root-level config type with AssemblyScript pool support\n */\nexport type AssemblyScriptConfigExport = AssemblyScriptUserConfig<ViteUserConfig>;\n\n/**\n * Project-level config type with AssemblyScript pool support\n */\nexport type AssemblyScriptProjectConfigExport = AssemblyScriptUserConfig<UserWorkspaceConfig>;\n\n/**\n * Define a root-level Vitest config with AssemblyScript pool options.\n *\n * This is a type-safe wrapper that properly types `poolOptions.assemblyScript`\n * for both root and project-level configurations.\n *\n * @example\n * ```ts\n * import { defineAssemblyScriptConfig } from 'vitest-pool-assemblyscript/config';\n *\n * export default defineAssemblyScriptConfig({\n * test: {\n * name: 'assemblyscript-unit-tests',\n * pool: 'vitest-pool-assemblyscript',\n * include: ['test/assembly/**‍/*.as.test.ts'], // example\n * poolOptions: {\n * assemblyScript: { // optional },\n * },\n * coverage: {\n * provider: 'custom',\n * customProviderModule: 'vitest-pool-assemblyscript/coverage',\n * include: ['src/**‍/*.ts'], // example JS/TS sources (v8 provider)\n * assemblyScriptInclude: ['assembly/**‍/*.ts'], // example AS sources\n * assemblyScriptExclude: ['**‍/*.as.test.ts'], // exclude AS test files\n * },\n * },\n * });\n * ```\n */\nexport function defineAssemblyScriptConfig(\n config: AssemblyScriptConfigExport\n): AssemblyScriptConfigExport;\nexport function defineAssemblyScriptConfig(\n config: Promise<AssemblyScriptConfigExport>\n): Promise<AssemblyScriptConfigExport>;\nexport function defineAssemblyScriptConfig(\n config: (env: ConfigEnv) => AssemblyScriptConfigExport | Promise<AssemblyScriptConfigExport>\n): (env: ConfigEnv) => AssemblyScriptConfigExport | Promise<AssemblyScriptConfigExport>;\nexport function defineAssemblyScriptConfig(\n config: AnyConfigExport<AssemblyScriptConfigExport>\n): AnyConfigExport<AssemblyScriptConfigExport> {\n // Pass through - this is just for type safety\n return config;\n}\n\n/**\n * Define a project-level Vitest config with AssemblyScript pool options.\n *\n * Use this when defining AssemblyScript test projects within a workspace.\n *\n * @example\n * ```ts\n * import { defineConfig, defineProject } from 'vitest/config';\n * import { defineAssemblyScriptProject } from 'vitest-pool-assemblyscript/config';\n *\n * export default defineConfig({\n * test: {\n * projects: [\n * defineProject({\n * test: {\n * name: { label: 'typescript-unit-tests', color: 'blue' },\n * }\n * }),\n * defineAssemblyScriptProject({\n * test: {\n * name: { label: 'assemblyscript-unit-tests', color: 'yellow' },\n * pool: 'vitest-pool-assemblyscript',\n * include: ['test/assembly/**‍/*.as.test.ts'], // example\n * poolOptions: {\n * assemblyScript: { // optional },\n * },\n * },\n * }),\n * ],\n * coverage: { // coverage section is global only in vitest\n * provider: 'custom',\n * customProviderModule: 'vitest-pool-assemblyscript/coverage',\n * include: ['src/**‍/*.ts'], // example JS/TS sources (v8 provider)\n * assemblyScriptInclude: ['assembly/**‍/*.ts'], // example AS sources\n * assemblyScriptExclude: ['**‍/*.as.test.ts'], // exclude AS test files\n * },\n * },\n * });\n * ```\n */\nexport function defineAssemblyScriptProject(\n config: AssemblyScriptProjectConfigExport\n): AssemblyScriptProjectConfigExport;\nexport function defineAssemblyScriptProject(\n config: Promise<AssemblyScriptProjectConfigExport>\n): Promise<AssemblyScriptProjectConfigExport>;\nexport function defineAssemblyScriptProject(\n config: (env: ConfigEnv) => AssemblyScriptProjectConfigExport | Promise<AssemblyScriptProjectConfigExport>\n): (env: ConfigEnv) => AssemblyScriptProjectConfigExport | Promise<AssemblyScriptProjectConfigExport>;\nexport function defineAssemblyScriptProject(\n config: AnyConfigExport<AssemblyScriptProjectConfigExport>\n): AnyConfigExport<AssemblyScriptProjectConfigExport> {\n // Pass through - this is just for type safety\n return config;\n}\n"],"mappings":";AAyFA,SAAgB,2BACd,QAC6C;AAE7C,QAAO;;AAoDT,SAAgB,4BACd,QACoD;AAEpD,QAAO"}
@@ -1,5 +1,5 @@
1
- import { AssemblyScriptPoolOptions, HybridProviderOptions, WasmImportsFactory, WasmImportsFactoryInfo } from "../types-DHVk5iAx.mjs";
2
- import { createAssemblyScriptPool } from "../pool-runner-init-CNpRdA5u.mjs";
1
+ import { AssemblyScriptPoolOptions, HybridProviderOptions, WasmImportsFactory, WasmImportsFactoryInfo } from "../types-CoroKYxB.mjs";
2
+ import { createAssemblyScriptPool } from "../pool-runner-init-CCvnKt5o.mjs";
3
3
 
4
4
  //#region src/config/coverage-options.d.ts
5
5
  /**
@@ -1,9 +1,7 @@
1
- import "../constants-DbxJ3hzg.mjs";
2
- import "../resolve-config-s9gSJSMc.mjs";
3
- import "../debug-DtRAL4rM.mjs";
4
- import "../vitest-file-tasks-D8sOClGX.mjs";
5
- import "../vitest-tasks-BZ24sghI.mjs";
6
- import "../worker-rpc-channel-CZZIxtv5.mjs";
7
- import { createAssemblyScriptPool } from "../pool-runner-init-BqkwQ2tk.mjs";
1
+ import "../constants-Bq5KNxXJ.mjs";
2
+ import "../vitest-file-tasks-vvZzigcF.mjs";
3
+ import "../pool-errors-Bn6YaguR.mjs";
4
+ import "../worker-rpc-channel-CvCrc8aa.mjs";
5
+ import { createAssemblyScriptPool } from "../pool-runner-init-DjRCbiX-.mjs";
8
6
 
9
7
  export { createAssemblyScriptPool };
@@ -31,14 +31,16 @@ const TEST_ERROR_NAMES = {
31
31
  const POOL_ERROR_NAMES = {
32
32
  CompilationError: "CompilationError",
33
33
  WASMInstrumentationError: "WASMInstrumentationError",
34
+ WASMUserImportsError: "WASMUserImportsError",
34
35
  WASMExecutionHarnessError: "WASMExecutionHarnessError",
35
36
  HybridCoverageProviderError: "HybridCoverageProviderError",
36
37
  PoolReportingError: "PoolReportingError",
37
38
  PoolConfigError: "PoolConfigError",
38
- PoolError: "PoolError",
39
39
  PoolSyntaxError: "PoolSyntaxError",
40
+ PoolError: "PoolError",
40
41
  PoolRunAbortedError: "PoolRunAbortedError",
41
42
  WASMExecutionAbortError: "WASMExecutionAbortError",
43
+ WASMExecutionAbortSuccess: "WASMExecutionAbortSuccess",
42
44
  WASMExecutionTimeoutError: "WASMExecutionTimeoutError"
43
45
  };
44
46
  const asRuntime = ascript;
@@ -49,4 +51,4 @@ const ASSourceKind = asRuntime.SourceKind;
49
51
 
50
52
  //#endregion
51
53
  export { ASCommonFlags, ASDecoratorKind, ASNodeKind, ASSourceKind, COVERAGE_PAYLOAD_FORMATS, INTERNAL_PATH_LIB_PREFIX, POOL_ERROR_NAMES, POOL_INTERNAL_PATHS, TEST_ERROR_NAMES };
52
- //# sourceMappingURL=constants-DbxJ3hzg.mjs.map
54
+ //# sourceMappingURL=constants-Bq5KNxXJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-Bq5KNxXJ.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_FLAG = '__as_pool_error__' as const;\n\nexport const AS_POOL_WORKER_MSG_FLAG = '__as_pool__' as const;\n\nexport const AS_POOL_WASM_IMPORTS_MODULE_NAME = '__as_pool_env__' as const;\n\nexport const AS_POOL_WASM_COVERAGE_MEM_IMPORT_NAME = '__coverage_memory' 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\nexport const INTERNAL_PATH_LIB_PREFIX: string = `${ASSEMBLYSCRIPT_LIB_PREFIX}vitest-pool-assemblyscript/assembly/` as const;\n\nexport const INTERNAL_FUNCTION_NAME_SUBSTRING = '__vitest_assemblyscript_' as const;\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/utils.ts',\n 'assembly/test.ts',\n\n // AS compiler source maps these as library paths when running published version\n `${INTERNAL_PATH_LIB_PREFIX}compare.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}describe.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}expect.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}index.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}options.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}stringify.ts`,\n `${INTERNAL_PATH_LIB_PREFIX}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 /** Error importing/creating user imports for WASM environment */\n WASMUserImportsError: 'WASMUserImportsError',\n /** Unexpected WASM execution error */\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 /** User syntax error in `test`/`suite`/`expect` */\n PoolSyntaxError: 'PoolSyntaxError',\n /** Generic AssemblyScript pool error */\n PoolError: 'PoolError',\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 WASMExecutionAbortSuccess: 'WASMExecutionAbortSuccess',\n /** Flow Control: Indicates WASM execution halt because test timeout elapsed */\n WASMExecutionTimeoutError: 'WASMExecutionTimeoutError',\n} as const;\n\n\n// ============================================================================\n// AssemblyScript Deep Equals & Stringify Transform\n// ============================================================================\n\n/** Name of the method injected by the deep-equals compiler transform */\nexport const DEEP_EQUALS_INJECTED_METHOD_NAME = '__vitest_assemblyscript_deep_equals' as const;\n\n/** Name of the method injected by the compiler transform that returns the runtime class name */\nexport const TYPENAME_INJECTED_METHOD_NAME = '__vitest_assemblyscript_typename' as const;\n\n/** Name of the method injected by the compiler transform that returns stringified field contents */\nexport const STRINGIFY_INJECTED_METHOD_NAME = '__vitest_assemblyscript_stringify' as const;\n\n/**\n * Name of the @global enum in assembly/compare.ts that represents deep equality comparison results.\n * Used in transform-generated code to reference enum members (e.g. EqualityResult.Equal).\n */\nexport const EQUALITY_RESULT_ENUM_NAME = '__vitest_assemblyscript_EqualityResult' as const;\n\n/**\n * Export alias for pool's equals() function used by injected deep equal method comparison body.\n */\nexport const COMPARE_EQUALS_GLOBAL_ALIAS = '__vitest_assemblyscript_compare_equals' as const;\n\n/**\n * Global alias for the path push function used by injected deep equality method field comparisons.\n */\nexport const COMPARE_EQUALS_PATH_PUSH_GLOBAL_ALIAS = '__vitest_assemblyscript_compare_equals_path_push' as const;\n\n/**\n * Global alias for the path pop function used by injected deep equality method field comparisons.\n */\nexport const COMPARE_EQUALS_PATH_POP_GLOBAL_ALIAS = '__vitest_assemblyscript_compare_equals_path_pop' as const;\n\n/**\n * Global alias for the stringifyValue() wrapper used by injected stringify method bodies.\n */\nexport const STRINGIFY_VALUE_GLOBAL_ALIAS = '__vitest_assemblyscript_stringify_value' as const;\n\n/**\n * Global alias for the escapeToDiffString() wrapper used by injected stringify method bodies.\n */\nexport const ESCAPE_TO_DIFF_STRING_GLOBAL_ALIAS = '__vitest_assemblyscript_escape_to_diff_string' as const;\n\n/**\n * Global alias for the depth-to-indent helper used by injected stringify method bodies.\n */\nexport const STRINGIFY_INDENT_GLOBAL_ALIAS = '__vitest_assemblyscript_stringify_indent' as const;\n\n/**\n * Global alias for the short-form budget overflow predicate used by injected stringify method bodies.\n */\nexport const STRINGIFY_EXCEEDS_BUDGET_GLOBAL_ALIAS = '__vitest_assemblyscript_stringify_exceeds_budget' as const;\n\n\n// ============================================================================\n// AssemblyScript Compiler Internals\n// ============================================================================\n\n// Original const enum values defined in assemblyscript.generated.d.ts.\n// These are reexported to avoid access issues with `const enum` exports \n// in assemblyscript, because we're using isolatedModules & isolatedDeclarations\n\nimport * as ascript from 'assemblyscript';\nimport type * as AS from 'assemblyscript';\n\ntype NodeKindMap = Record<keyof typeof AS.NodeKind, number>;\ntype CommonFlagsMap = Record<keyof typeof AS.CommonFlags, number>;\ntype DecoratorKindMap = Record<keyof typeof AS.DecoratorKind, number>;\ntype SourceKindMap = Record<keyof typeof AS.SourceKind, number>;\n\nconst asRuntime = ascript as unknown as {\n NodeKind: NodeKindMap;\n CommonFlags: CommonFlagsMap;\n DecoratorKind: DecoratorKindMap;\n SourceKind: SourceKindMap;\n};\n\nexport const ASNodeKind: NodeKindMap = asRuntime.NodeKind;\nexport const ASCommonFlags: CommonFlagsMap = asRuntime.CommonFlags;\nexport const ASDecoratorKind: DecoratorKindMap = asRuntime.DecoratorKind;\nexport const ASSourceKind: SourceKindMap = asRuntime.SourceKind;\n"],"mappings":";;;AAyBA,MAAa,2BAA2B,EACtC,gBAAgB,kBACjB;;AAGD,MAAa,4BAA4B;AAEzC,MAAa,2BAAmC,WAA6B;;AAK7E,MAAa,sBAAgC;CAE3C;CACA;CACA;CACA;CACA;CACA;CACA;CAGA,GAAG,yBAAyB;CAC5B,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,sBAAsB;CAEtB,2BAA2B;CAE3B,6BAA6B;CAE7B,oBAAoB;CAEpB,iBAAiB;CAEjB,iBAAiB;CAEjB,WAAW;CAGX,qBAAqB;CAKrB,yBAAyB;CACzB,2BAA2B;CAE3B,2BAA2B;CAC5B;AA0ED,MAAM,YAAY;AAOlB,MAAa,aAA0B,UAAU;AACjD,MAAa,gBAAgC,UAAU;AACvD,MAAa,kBAAoC,UAAU;AAC3D,MAAa,eAA8B,UAAU"}
@@ -19,4 +19,4 @@ function mergeCoverageData(accumulated, incoming) {
19
19
 
20
20
  //#endregion
21
21
  export { mergeCoverageData };
22
- //# sourceMappingURL=coverage-merge-CBXkpM1O.mjs.map
22
+ //# sourceMappingURL=coverage-merge-0WqdC-dq.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"coverage-merge-CBXkpM1O.mjs","names":[],"sources":["../src/coverage-provider/coverage-merge.ts"],"sourcesContent":["/**\n * Coverage Data Merge Utilities\n *\n * Functions for merging CoverageData objects\n */\n\nimport type { CoverageData } from '../types/types.js';\n\n/**\n * Merge incoming CoverageData into accumulated CoverageData\n *\n * Combines by filepath + position, summing hit counts.\n * Mutates the accumulated object in place.\n *\n * @param accumulated - Accumulated coverage data (mutated)\n * @param incoming - New coverage data to merge in\n */\nexport function mergeCoverageData(\n accumulated: CoverageData,\n incoming: CoverageData\n): void {\n for (const [filePath, positions] of Object.entries(incoming.hitCountsByFileAndPosition)) {\n // Ensure file exists in accumulated\n if (!accumulated.hitCountsByFileAndPosition[filePath]) {\n accumulated.hitCountsByFileAndPosition[filePath] = {};\n }\n\n const accumulatedPositions = accumulated.hitCountsByFileAndPosition[filePath];\n\n for (const [positionKey, hitCount] of Object.entries(positions)) {\n if (accumulatedPositions[positionKey] !== undefined) {\n // Position exists - sum hit counts\n accumulatedPositions[positionKey] += hitCount;\n } else {\n // New position - set hit count\n accumulatedPositions[positionKey] = hitCount;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,kBACd,aACA,UACM;AACN,MAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,SAAS,2BAA2B,EAAE;AAEvF,MAAI,CAAC,YAAY,2BAA2B,UAC1C,aAAY,2BAA2B,YAAY,EAAE;EAGvD,MAAM,uBAAuB,YAAY,2BAA2B;AAEpE,OAAK,MAAM,CAAC,aAAa,aAAa,OAAO,QAAQ,UAAU,CAC7D,KAAI,qBAAqB,iBAAiB,OAExC,sBAAqB,gBAAgB;MAGrC,sBAAqB,eAAe"}
1
+ {"version":3,"file":"coverage-merge-0WqdC-dq.mjs","names":[],"sources":["../src/coverage-provider/coverage-merge.ts"],"sourcesContent":["/**\n * Coverage Data Merge Utilities\n *\n * Functions for merging CoverageData objects\n */\n\nimport type { CoverageData } from '../types/types.js';\n\n/**\n * Merge incoming CoverageData into accumulated CoverageData\n *\n * Combines by filepath + position, summing hit counts.\n * Mutates the accumulated object in place.\n *\n * @param accumulated - Accumulated coverage data (mutated)\n * @param incoming - New coverage data to merge in\n */\nexport function mergeCoverageData(\n accumulated: CoverageData,\n incoming: CoverageData\n): void {\n for (const [filePath, positions] of Object.entries(incoming.hitCountsByFileAndPosition)) {\n // Ensure file exists in accumulated\n if (!accumulated.hitCountsByFileAndPosition[filePath]) {\n accumulated.hitCountsByFileAndPosition[filePath] = {};\n }\n\n const accumulatedPositions = accumulated.hitCountsByFileAndPosition[filePath];\n\n for (const [positionKey, hitCount] of Object.entries(positions)) {\n if (accumulatedPositions[positionKey] !== undefined) {\n // Position exists - sum hit counts\n accumulatedPositions[positionKey] += hitCount;\n } else {\n // New position - set hit count\n accumulatedPositions[positionKey] = hitCount;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,kBACd,aACA,UACM;AACN,MAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,SAAS,2BAA2B,EAAE;AAEvF,MAAI,CAAC,YAAY,2BAA2B,UAC1C,aAAY,2BAA2B,YAAY,EAAE;EAGvD,MAAM,uBAAuB,YAAY,2BAA2B;AAEpE,OAAK,MAAM,CAAC,aAAa,aAAa,OAAO,QAAQ,UAAU,CAC7D,KAAI,qBAAqB,iBAAiB,OAExC,sBAAqB,gBAAgB;MAGrC,sBAAqB,eAAe"}