vitest-pool-assemblyscript 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -13
- package/assembly/compare.ts +469 -76
- package/assembly/expect.ts +160 -67
- package/assembly/index.ts +0 -10
- package/assembly/utils.ts +168 -0
- package/dist/{addon-interface-_pNXcbib.mjs → addon-interface-CYFXMbK7.mjs} +4 -3
- package/dist/addon-interface-CYFXMbK7.mjs.map +1 -0
- package/dist/{ast-visitor-C5gQqWD2.mjs → ast-visitor-CWEOd3UH.mjs} +15 -2
- package/dist/ast-visitor-CWEOd3UH.mjs.map +1 -0
- package/dist/{compile-runner-DOMhsLQE.mjs → compile-runner-BGQhBkBo.mjs} +8 -7
- package/dist/compile-runner-BGQhBkBo.mjs.map +1 -0
- package/dist/compiler/transforms/deep-equals.d.mts +14 -0
- package/dist/compiler/transforms/deep-equals.d.mts.map +1 -0
- package/dist/compiler/transforms/deep-equals.mjs +245 -0
- package/dist/compiler/transforms/deep-equals.mjs.map +1 -0
- package/dist/compiler/transforms/strip-inline.mjs +2 -2
- package/dist/{compiler-CIXpfKq0.mjs → compiler-hUlDr5vL.mjs} +14 -6
- package/dist/compiler-hUlDr5vL.mjs.map +1 -0
- package/dist/config/index-v3.d.mts +33 -3
- package/dist/config/index-v3.d.mts.map +1 -1
- package/dist/config/index-v3.mjs.map +1 -1
- package/dist/config/index.d.mts +29 -4
- package/dist/config/index.d.mts.map +1 -0
- package/dist/config/index.mjs +6 -6
- package/dist/{constants-DuBLuMjt.mjs → constants-DbxJ3hzg.mjs} +10 -97
- package/dist/constants-DbxJ3hzg.mjs.map +1 -0
- package/dist/coverage-provider/index.mjs +30 -10
- package/dist/coverage-provider/index.mjs.map +1 -1
- package/dist/{debug-Cm1VFmaz.mjs → debug-DtRAL4rM.mjs} +38 -4
- package/dist/debug-DtRAL4rM.mjs.map +1 -0
- package/dist/{feature-check-ELxw_Mji.mjs → feature-check-Bje3ntpV.mjs} +2 -2
- package/dist/{feature-check-ELxw_Mji.mjs.map → feature-check-Bje3ntpV.mjs.map} +1 -1
- package/dist/index-internal.d.mts +1 -1
- package/dist/index-internal.d.mts.map +1 -1
- package/dist/index-internal.mjs +4 -4
- package/dist/index-v3.d.mts.map +1 -1
- package/dist/index-v3.mjs +8 -7
- package/dist/index-v3.mjs.map +1 -1
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +6 -6
- package/dist/{load-user-imports-B3Iy_K8k.mjs → load-user-imports-Bx5ZlhSm.mjs} +9 -9
- package/dist/load-user-imports-Bx5ZlhSm.mjs.map +1 -0
- package/dist/{pool-runner-init-BDQtAGwQ.mjs → pool-runner-init-BqkwQ2tk.mjs} +7 -7
- package/dist/pool-runner-init-BqkwQ2tk.mjs.map +1 -0
- package/dist/{pool-runner-init-CvnB0-iN.d.mts → pool-runner-init-CNpRdA5u.d.mts} +2 -2
- package/dist/pool-runner-init-CNpRdA5u.d.mts.map +1 -0
- package/dist/pool-thread/compile-worker-thread.d.mts +1 -1
- package/dist/pool-thread/compile-worker-thread.d.mts.map +1 -1
- package/dist/pool-thread/compile-worker-thread.mjs +10 -13
- package/dist/pool-thread/compile-worker-thread.mjs.map +1 -1
- package/dist/pool-thread/test-worker-thread.d.mts +1 -1
- package/dist/pool-thread/test-worker-thread.d.mts.map +1 -1
- package/dist/pool-thread/test-worker-thread.mjs +8 -11
- package/dist/pool-thread/test-worker-thread.mjs.map +1 -1
- package/dist/pool-thread/v3-tinypool-thread.d.mts +1 -1
- package/dist/pool-thread/v3-tinypool-thread.d.mts.map +1 -1
- package/dist/pool-thread/v3-tinypool-thread.mjs +12 -18
- package/dist/pool-thread/v3-tinypool-thread.mjs.map +1 -1
- package/dist/{resolve-config-DhZ4lOSK.mjs → resolve-config-s9gSJSMc.mjs} +14 -5
- package/dist/resolve-config-s9gSJSMc.mjs.map +1 -0
- package/dist/{test-runner-C4I9VknR.mjs → test-runner-BGqc9uCK.mjs} +4 -4
- package/dist/{test-runner-C4I9VknR.mjs.map → test-runner-BGqc9uCK.mjs.map} +1 -1
- package/dist/{types-D0nprJo1.d.mts → types-DHVk5iAx.d.mts} +17 -11
- package/dist/types-DHVk5iAx.d.mts.map +1 -0
- package/dist/vitest-file-tasks-D8sOClGX.mjs +149 -0
- package/dist/vitest-file-tasks-D8sOClGX.mjs.map +1 -0
- package/dist/{vitest-tasks--ow4pacR.mjs → vitest-tasks-BZ24sghI.mjs} +6 -4
- package/dist/vitest-tasks-BZ24sghI.mjs.map +1 -0
- package/package.json +11 -14
- package/prebuilds/darwin-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/darwin-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/linux-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/linux-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/linux-x64/vitest-pool-assemblyscript.musl.node +0 -0
- package/prebuilds/win32-arm64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/prebuilds/win32-x64/vitest-pool-assemblyscript.glibc.node +0 -0
- package/src/instrumentation/native/addon.cpp +29 -3
- package/dist/addon-interface-_pNXcbib.mjs.map +0 -1
- package/dist/ast-visitor-C5gQqWD2.mjs.map +0 -1
- package/dist/compile-runner-DOMhsLQE.mjs.map +0 -1
- package/dist/compiler-CIXpfKq0.mjs.map +0 -1
- package/dist/constants-DuBLuMjt.mjs.map +0 -1
- package/dist/custom-provider-options-YTk1m7At.d.mts +0 -26
- package/dist/custom-provider-options-YTk1m7At.d.mts.map +0 -1
- package/dist/debug-Cm1VFmaz.mjs.map +0 -1
- package/dist/load-user-imports-B3Iy_K8k.mjs.map +0 -1
- package/dist/pool-runner-init-BDQtAGwQ.mjs.map +0 -1
- package/dist/pool-runner-init-CvnB0-iN.d.mts.map +0 -1
- package/dist/resolve-config-DhZ4lOSK.mjs.map +0 -1
- package/dist/types-D0nprJo1.d.mts.map +0 -1
- package/dist/vitest-file-tasks-Bn9CrWt_.mjs +0 -61
- package/dist/vitest-file-tasks-Bn9CrWt_.mjs.map +0 -1
- package/dist/vitest-tasks--ow4pacR.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ASNodeKind } from "./constants-
|
|
1
|
+
import { ASNodeKind } from "./constants-DbxJ3hzg.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/util/ast-visitor.ts
|
|
4
4
|
/**
|
|
@@ -10,6 +10,7 @@ import { ASNodeKind } from "./constants-DuBLuMjt.mjs";
|
|
|
10
10
|
* - onMethodDeclaration: Called when visiting a method declaration
|
|
11
11
|
* - onVariableDeclaration: Called when visiting a variable declaration
|
|
12
12
|
* - onClassEnter/onClassExit: Called when entering/exiting a class
|
|
13
|
+
* - onNamespaceEnter/onNamespaceExit: Called when entering/exiting a namespace
|
|
13
14
|
*/
|
|
14
15
|
var ASTVisitor = class {
|
|
15
16
|
/**
|
|
@@ -24,6 +25,16 @@ var ASTVisitor = class {
|
|
|
24
25
|
*/
|
|
25
26
|
beforeVisit(_node) {}
|
|
26
27
|
/**
|
|
28
|
+
* Hook called when entering a namespace declaration.
|
|
29
|
+
* Override to track namespace context.
|
|
30
|
+
*/
|
|
31
|
+
onNamespaceEnter(_node) {}
|
|
32
|
+
/**
|
|
33
|
+
* Hook called when exiting a namespace declaration.
|
|
34
|
+
* Override to restore namespace context.
|
|
35
|
+
*/
|
|
36
|
+
onNamespaceExit(_node) {}
|
|
37
|
+
/**
|
|
27
38
|
* Hook called when entering a class declaration.
|
|
28
39
|
* Override to track class context.
|
|
29
40
|
*/
|
|
@@ -289,7 +300,9 @@ var ASTVisitor = class {
|
|
|
289
300
|
}
|
|
290
301
|
case ASNodeKind.NamespaceDeclaration: {
|
|
291
302
|
const decl = node;
|
|
303
|
+
this.onNamespaceEnter(decl);
|
|
292
304
|
for (const member of decl.members) this.visitNode(member);
|
|
305
|
+
this.onNamespaceExit(decl);
|
|
293
306
|
break;
|
|
294
307
|
}
|
|
295
308
|
case ASNodeKind.VariableDeclaration: {
|
|
@@ -307,4 +320,4 @@ var ASTVisitor = class {
|
|
|
307
320
|
|
|
308
321
|
//#endregion
|
|
309
322
|
export { ASTVisitor };
|
|
310
|
-
//# sourceMappingURL=ast-visitor-
|
|
323
|
+
//# sourceMappingURL=ast-visitor-CWEOd3UH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-visitor-CWEOd3UH.mjs","names":[],"sources":["../src/util/ast-visitor.ts"],"sourcesContent":["/**\n * Base AST Visitor for AssemblyScript\n *\n * Provides reusable walking logic for traversing AS AST nodes.\n * Subclasses override hook methods to perform specific tasks.\n *\n * Used by:\n * - ast-parser.ts: Extract function metadata for coverage\n * - strip-inline.mts: Strip @inline decorators\n */\n\nimport {\n Node,\n Source,\n BlockStatement,\n FunctionDeclaration,\n MethodDeclaration,\n ClassDeclaration,\n NamespaceDeclaration,\n VariableStatement,\n VariableDeclaration,\n FunctionExpression,\n ExpressionStatement,\n BinaryExpression,\n PropertyAccessExpression,\n IfStatement,\n WhileStatement,\n DoStatement,\n ForStatement,\n ForOfStatement,\n SwitchStatement,\n SwitchCase,\n TryStatement,\n ThrowStatement,\n ReturnStatement,\n CallExpression,\n NewExpression,\n ParenthesizedExpression,\n TernaryExpression,\n CommaExpression,\n AssertionExpression,\n InstanceOfExpression,\n ElementAccessExpression,\n UnaryPostfixExpression,\n UnaryPrefixExpression,\n ClassExpression,\n ParameterNode,\n EnumDeclaration,\n EnumValueDeclaration,\n FieldDeclaration,\n InterfaceDeclaration,\n VoidStatement,\n} from 'assemblyscript';\n\nimport { ASNodeKind } from '../types/constants.js';\n\n/**\n * Abstract base class for AST visitors.\n *\n * Subclasses override hook methods to perform tasks during traversal:\n * - beforeVisit: Called before visiting each node (e.g., strip decorators)\n * - onFunctionDeclaration: Called when visiting a function declaration\n * - onMethodDeclaration: Called when visiting a method declaration\n * - onVariableDeclaration: Called when visiting a variable declaration\n * - onClassEnter/onClassExit: Called when entering/exiting a class\n * - onNamespaceEnter/onNamespaceExit: Called when entering/exiting a namespace\n */\nexport abstract class ASTVisitor {\n /**\n * Visit all statements in a source file\n */\n visitSource(source: Source): void {\n for (const stmt of source.statements) {\n this.visitNode(stmt);\n }\n }\n\n /**\n * Hook called before visiting each node.\n * Override to perform pre-visit tasks (e.g., stripping decorators).\n */\n protected beforeVisit(_node: Node): void {}\n\n /**\n * Hook called when entering a namespace declaration.\n * Override to track namespace context.\n */\n protected onNamespaceEnter(_node: NamespaceDeclaration): void {}\n\n /**\n * Hook called when exiting a namespace declaration.\n * Override to restore namespace context.\n */\n protected onNamespaceExit(_node: NamespaceDeclaration): void {}\n\n /**\n * Hook called when entering a class declaration.\n * Override to track class context.\n */\n protected onClassEnter(_node: ClassDeclaration): void {}\n\n /**\n * Hook called when exiting a class declaration.\n * Override to restore class context.\n */\n protected onClassExit(_node: ClassDeclaration): void {}\n\n /**\n * Hook called when visiting a function declaration.\n * Override to extract function info or perform other tasks.\n * Return false to skip recursing into the function body.\n */\n protected onFunctionDeclaration(_node: FunctionDeclaration): boolean {\n return true; // Continue recursion by default\n }\n\n /**\n * Hook called when visiting a method declaration.\n * Override to extract method info or perform other tasks.\n * Return false to skip recursing into the method body.\n */\n protected onMethodDeclaration(_node: MethodDeclaration): boolean {\n return true; // Continue recursion by default\n }\n\n /**\n * Hook called when visiting a variable declaration.\n * Override to handle variable declarations (e.g., arrow functions).\n * Return false to skip recursing into the initializer.\n */\n protected onVariableDeclaration(_node: VariableDeclaration): boolean {\n return true; // Continue recursion by default\n }\n\n /**\n * Main visitor dispatch - routes to specific handler based on node kind\n */\n visitNode(node: Node): void {\n // Call pre-visit hook\n this.beforeVisit(node);\n\n // Recurse into children based on node kind\n switch (node.kind) {\n // Type nodes - no children to visit\n case ASNodeKind.NamedType:\n case ASNodeKind.FunctionType:\n case ASNodeKind.TypeName:\n case ASNodeKind.TypeParameter:\n break;\n\n // Parameter - may have default value\n case ASNodeKind.Parameter: {\n const param = node as ParameterNode;\n if (param.initializer) this.visitNode(param.initializer);\n break;\n }\n\n // Simple expressions - no children\n case ASNodeKind.Identifier:\n case ASNodeKind.False:\n case ASNodeKind.Literal:\n case ASNodeKind.Null:\n case ASNodeKind.Omitted:\n case ASNodeKind.Super:\n case ASNodeKind.This:\n case ASNodeKind.True:\n case ASNodeKind.Constructor:\n case ASNodeKind.Compiled:\n break;\n\n // Expressions with children\n case ASNodeKind.Assertion: {\n const expr = node as AssertionExpression;\n this.visitNode(expr.expression);\n break;\n }\n case ASNodeKind.Binary: {\n const expr = node as BinaryExpression;\n this.visitNode(expr.left);\n this.visitNode(expr.right);\n break;\n }\n case ASNodeKind.Call: {\n const expr = node as CallExpression;\n this.visitNode(expr.expression);\n for (const arg of expr.args) this.visitNode(arg);\n break;\n }\n case ASNodeKind.Class: {\n const expr = node as ClassExpression;\n this.visitNode(expr.declaration);\n break;\n }\n case ASNodeKind.Comma: {\n const expr = node as CommaExpression;\n for (const e of expr.expressions) this.visitNode(e);\n break;\n }\n case ASNodeKind.ElementAccess: {\n const expr = node as ElementAccessExpression;\n this.visitNode(expr.expression);\n this.visitNode(expr.elementExpression);\n break;\n }\n case ASNodeKind.Function: {\n const expr = node as FunctionExpression;\n this.visitNode(expr.declaration);\n break;\n }\n case ASNodeKind.InstanceOf: {\n const expr = node as InstanceOfExpression;\n this.visitNode(expr.expression);\n break;\n }\n case ASNodeKind.New: {\n const expr = node as NewExpression;\n for (const arg of expr.args) this.visitNode(arg);\n break;\n }\n case ASNodeKind.Parenthesized: {\n const expr = node as ParenthesizedExpression;\n this.visitNode(expr.expression);\n break;\n }\n case ASNodeKind.PropertyAccess: {\n const expr = node as PropertyAccessExpression;\n this.visitNode(expr.expression);\n break;\n }\n case ASNodeKind.Ternary: {\n const expr = node as TernaryExpression;\n this.visitNode(expr.condition);\n this.visitNode(expr.ifThen);\n this.visitNode(expr.ifElse);\n break;\n }\n case ASNodeKind.UnaryPostfix: {\n const expr = node as UnaryPostfixExpression;\n this.visitNode(expr.operand);\n break;\n }\n case ASNodeKind.UnaryPrefix: {\n const expr = node as UnaryPrefixExpression;\n this.visitNode(expr.operand);\n break;\n }\n\n // Statements with no interesting children\n case ASNodeKind.Break:\n case ASNodeKind.Continue:\n case ASNodeKind.Empty:\n case ASNodeKind.Export:\n case ASNodeKind.ExportDefault:\n case ASNodeKind.ExportImport:\n case ASNodeKind.Import:\n case ASNodeKind.Module:\n break;\n\n // Statements with children\n case ASNodeKind.Block: {\n const stmt = node as BlockStatement;\n for (const s of stmt.statements) this.visitNode(s);\n break;\n }\n case ASNodeKind.Do: {\n const stmt = node as DoStatement;\n this.visitNode(stmt.body);\n this.visitNode(stmt.condition);\n break;\n }\n case ASNodeKind.Expression: {\n const stmt = node as ExpressionStatement;\n this.visitNode(stmt.expression);\n break;\n }\n case ASNodeKind.For: {\n const stmt = node as ForStatement;\n if (stmt.initializer) this.visitNode(stmt.initializer);\n if (stmt.condition) this.visitNode(stmt.condition);\n if (stmt.incrementor) this.visitNode(stmt.incrementor);\n this.visitNode(stmt.body);\n break;\n }\n case ASNodeKind.ForOf: {\n const stmt = node as ForOfStatement;\n this.visitNode(stmt.variable);\n this.visitNode(stmt.iterable);\n this.visitNode(stmt.body);\n break;\n }\n case ASNodeKind.If: {\n const stmt = node as IfStatement;\n this.visitNode(stmt.condition);\n this.visitNode(stmt.ifTrue);\n if (stmt.ifFalse) this.visitNode(stmt.ifFalse);\n break;\n }\n case ASNodeKind.Return: {\n const stmt = node as ReturnStatement;\n if (stmt.value) this.visitNode(stmt.value);\n break;\n }\n case ASNodeKind.Switch: {\n const stmt = node as SwitchStatement;\n this.visitNode(stmt.condition);\n for (const switchCase of stmt.cases) this.visitNode(switchCase);\n break;\n }\n case ASNodeKind.Throw: {\n const stmt = node as ThrowStatement;\n this.visitNode(stmt.value);\n break;\n }\n case ASNodeKind.Try: {\n const stmt = node as TryStatement;\n for (const s of stmt.bodyStatements) this.visitNode(s);\n if (stmt.catchStatements) {\n for (const s of stmt.catchStatements) this.visitNode(s);\n }\n if (stmt.finallyStatements) {\n for (const s of stmt.finallyStatements) this.visitNode(s);\n }\n break;\n }\n case ASNodeKind.Variable: {\n const stmt = node as VariableStatement;\n for (const decl of stmt.declarations) this.visitNode(decl);\n break;\n }\n case ASNodeKind.Void: {\n const stmt = node as VoidStatement;\n this.visitNode(stmt.expression);\n break;\n }\n case ASNodeKind.While: {\n const stmt = node as WhileStatement;\n this.visitNode(stmt.condition);\n this.visitNode(stmt.body);\n break;\n }\n case ASNodeKind.SwitchCase: {\n const stmt = node as SwitchCase;\n if (stmt.label) this.visitNode(stmt.label);\n for (const s of stmt.statements) this.visitNode(s);\n break;\n }\n\n // Declaration statements\n case ASNodeKind.ImportDeclaration:\n case ASNodeKind.TypeDeclaration:\n break;\n\n case ASNodeKind.ClassDeclaration: {\n const decl = node as ClassDeclaration;\n this.onClassEnter(decl);\n for (const member of decl.members) this.visitNode(member);\n this.onClassExit(decl);\n break;\n }\n case ASNodeKind.EnumDeclaration: {\n const decl = node as EnumDeclaration;\n for (const value of decl.values) this.visitNode(value);\n break;\n }\n case ASNodeKind.EnumValueDeclaration: {\n const decl = node as EnumValueDeclaration;\n if (decl.initializer) this.visitNode(decl.initializer);\n break;\n }\n case ASNodeKind.FieldDeclaration: {\n const decl = node as FieldDeclaration;\n if (decl.initializer) this.visitNode(decl.initializer);\n break;\n }\n case ASNodeKind.FunctionDeclaration: {\n const decl = node as FunctionDeclaration;\n const shouldRecurse = this.onFunctionDeclaration(decl);\n if (shouldRecurse && decl.body) this.visitNode(decl.body);\n break;\n }\n case ASNodeKind.InterfaceDeclaration: {\n const decl = node as InterfaceDeclaration;\n for (const member of decl.members) this.visitNode(member);\n break;\n }\n case ASNodeKind.MethodDeclaration: {\n const decl = node as MethodDeclaration;\n const shouldRecurse = this.onMethodDeclaration(decl);\n if (shouldRecurse && decl.body) this.visitNode(decl.body);\n break;\n }\n case ASNodeKind.NamespaceDeclaration: {\n const decl = node as NamespaceDeclaration;\n this.onNamespaceEnter(decl);\n for (const member of decl.members) this.visitNode(member);\n this.onNamespaceExit(decl);\n break;\n }\n case ASNodeKind.VariableDeclaration: {\n const decl = node as VariableDeclaration;\n const shouldRecurse = this.onVariableDeclaration(decl);\n if (shouldRecurse && decl.initializer) this.visitNode(decl.initializer);\n break;\n }\n\n // Special nodes - no action needed\n case ASNodeKind.ExportMember:\n case ASNodeKind.IndexSignature:\n case ASNodeKind.Comment:\n case ASNodeKind.Decorator:\n break;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAmEA,IAAsB,aAAtB,MAAiC;;;;CAI/B,YAAY,QAAsB;AAChC,OAAK,MAAM,QAAQ,OAAO,WACxB,MAAK,UAAU,KAAK;;;;;;CAQxB,AAAU,YAAY,OAAmB;;;;;CAMzC,AAAU,iBAAiB,OAAmC;;;;;CAM9D,AAAU,gBAAgB,OAAmC;;;;;CAM7D,AAAU,aAAa,OAA+B;;;;;CAMtD,AAAU,YAAY,OAA+B;;;;;;CAOrD,AAAU,sBAAsB,OAAqC;AACnE,SAAO;;;;;;;CAQT,AAAU,oBAAoB,OAAmC;AAC/D,SAAO;;;;;;;CAQT,AAAU,sBAAsB,OAAqC;AACnE,SAAO;;;;;CAMT,UAAU,MAAkB;AAE1B,OAAK,YAAY,KAAK;AAGtB,UAAQ,KAAK,MAAb;GAEE,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW,cACd;GAGF,KAAK,WAAW,WAAW;IACzB,MAAM,QAAQ;AACd,QAAI,MAAM,YAAa,MAAK,UAAU,MAAM,YAAY;AACxD;;GAIF,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW,SACd;GAGF,KAAK,WAAW,WAAW;IACzB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B;;GAEF,KAAK,WAAW,QAAQ;IACtB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,KAAK;AACzB,SAAK,UAAU,KAAK,MAAM;AAC1B;;GAEF,KAAK,WAAW,MAAM;IACpB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B,SAAK,MAAM,OAAO,KAAK,KAAM,MAAK,UAAU,IAAI;AAChD;;GAEF,KAAK,WAAW,OAAO;IACrB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,YAAY;AAChC;;GAEF,KAAK,WAAW,OAAO;IACrB,MAAM,OAAO;AACb,SAAK,MAAM,KAAK,KAAK,YAAa,MAAK,UAAU,EAAE;AACnD;;GAEF,KAAK,WAAW,eAAe;IAC7B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B,SAAK,UAAU,KAAK,kBAAkB;AACtC;;GAEF,KAAK,WAAW,UAAU;IACxB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,YAAY;AAChC;;GAEF,KAAK,WAAW,YAAY;IAC1B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B;;GAEF,KAAK,WAAW,KAAK;IACnB,MAAM,OAAO;AACb,SAAK,MAAM,OAAO,KAAK,KAAM,MAAK,UAAU,IAAI;AAChD;;GAEF,KAAK,WAAW,eAAe;IAC7B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B;;GAEF,KAAK,WAAW,gBAAgB;IAC9B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B;;GAEF,KAAK,WAAW,SAAS;IACvB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,UAAU;AAC9B,SAAK,UAAU,KAAK,OAAO;AAC3B,SAAK,UAAU,KAAK,OAAO;AAC3B;;GAEF,KAAK,WAAW,cAAc;IAC5B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,QAAQ;AAC5B;;GAEF,KAAK,WAAW,aAAa;IAC3B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,QAAQ;AAC5B;;GAIF,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW,OACd;GAGF,KAAK,WAAW,OAAO;IACrB,MAAM,OAAO;AACb,SAAK,MAAM,KAAK,KAAK,WAAY,MAAK,UAAU,EAAE;AAClD;;GAEF,KAAK,WAAW,IAAI;IAClB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,KAAK;AACzB,SAAK,UAAU,KAAK,UAAU;AAC9B;;GAEF,KAAK,WAAW,YAAY;IAC1B,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B;;GAEF,KAAK,WAAW,KAAK;IACnB,MAAM,OAAO;AACb,QAAI,KAAK,YAAa,MAAK,UAAU,KAAK,YAAY;AACtD,QAAI,KAAK,UAAW,MAAK,UAAU,KAAK,UAAU;AAClD,QAAI,KAAK,YAAa,MAAK,UAAU,KAAK,YAAY;AACtD,SAAK,UAAU,KAAK,KAAK;AACzB;;GAEF,KAAK,WAAW,OAAO;IACrB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,SAAS;AAC7B,SAAK,UAAU,KAAK,SAAS;AAC7B,SAAK,UAAU,KAAK,KAAK;AACzB;;GAEF,KAAK,WAAW,IAAI;IAClB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,UAAU;AAC9B,SAAK,UAAU,KAAK,OAAO;AAC3B,QAAI,KAAK,QAAS,MAAK,UAAU,KAAK,QAAQ;AAC9C;;GAEF,KAAK,WAAW,QAAQ;IACtB,MAAM,OAAO;AACb,QAAI,KAAK,MAAO,MAAK,UAAU,KAAK,MAAM;AAC1C;;GAEF,KAAK,WAAW,QAAQ;IACtB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,UAAU;AAC9B,SAAK,MAAM,cAAc,KAAK,MAAO,MAAK,UAAU,WAAW;AAC/D;;GAEF,KAAK,WAAW,OAAO;IACrB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,MAAM;AAC1B;;GAEF,KAAK,WAAW,KAAK;IACnB,MAAM,OAAO;AACb,SAAK,MAAM,KAAK,KAAK,eAAgB,MAAK,UAAU,EAAE;AACtD,QAAI,KAAK,gBACP,MAAK,MAAM,KAAK,KAAK,gBAAiB,MAAK,UAAU,EAAE;AAEzD,QAAI,KAAK,kBACP,MAAK,MAAM,KAAK,KAAK,kBAAmB,MAAK,UAAU,EAAE;AAE3D;;GAEF,KAAK,WAAW,UAAU;IACxB,MAAM,OAAO;AACb,SAAK,MAAM,QAAQ,KAAK,aAAc,MAAK,UAAU,KAAK;AAC1D;;GAEF,KAAK,WAAW,MAAM;IACpB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,WAAW;AAC/B;;GAEF,KAAK,WAAW,OAAO;IACrB,MAAM,OAAO;AACb,SAAK,UAAU,KAAK,UAAU;AAC9B,SAAK,UAAU,KAAK,KAAK;AACzB;;GAEF,KAAK,WAAW,YAAY;IAC1B,MAAM,OAAO;AACb,QAAI,KAAK,MAAO,MAAK,UAAU,KAAK,MAAM;AAC1C,SAAK,MAAM,KAAK,KAAK,WAAY,MAAK,UAAU,EAAE;AAClD;;GAIF,KAAK,WAAW;GAChB,KAAK,WAAW,gBACd;GAEF,KAAK,WAAW,kBAAkB;IAChC,MAAM,OAAO;AACb,SAAK,aAAa,KAAK;AACvB,SAAK,MAAM,UAAU,KAAK,QAAS,MAAK,UAAU,OAAO;AACzD,SAAK,YAAY,KAAK;AACtB;;GAEF,KAAK,WAAW,iBAAiB;IAC/B,MAAM,OAAO;AACb,SAAK,MAAM,SAAS,KAAK,OAAQ,MAAK,UAAU,MAAM;AACtD;;GAEF,KAAK,WAAW,sBAAsB;IACpC,MAAM,OAAO;AACb,QAAI,KAAK,YAAa,MAAK,UAAU,KAAK,YAAY;AACtD;;GAEF,KAAK,WAAW,kBAAkB;IAChC,MAAM,OAAO;AACb,QAAI,KAAK,YAAa,MAAK,UAAU,KAAK,YAAY;AACtD;;GAEF,KAAK,WAAW,qBAAqB;IACnC,MAAM,OAAO;AAEb,QADsB,KAAK,sBAAsB,KAAK,IACjC,KAAK,KAAM,MAAK,UAAU,KAAK,KAAK;AACzD;;GAEF,KAAK,WAAW,sBAAsB;IACpC,MAAM,OAAO;AACb,SAAK,MAAM,UAAU,KAAK,QAAS,MAAK,UAAU,OAAO;AACzD;;GAEF,KAAK,WAAW,mBAAmB;IACjC,MAAM,OAAO;AAEb,QADsB,KAAK,oBAAoB,KAAK,IAC/B,KAAK,KAAM,MAAK,UAAU,KAAK,KAAK;AACzD;;GAEF,KAAK,WAAW,sBAAsB;IACpC,MAAM,OAAO;AACb,SAAK,iBAAiB,KAAK;AAC3B,SAAK,MAAM,UAAU,KAAK,QAAS,MAAK,UAAU,OAAO;AACzD,SAAK,gBAAgB,KAAK;AAC1B;;GAEF,KAAK,WAAW,qBAAqB;IACnC,MAAM,OAAO;AAEb,QADsB,KAAK,sBAAsB,KAAK,IACjC,KAAK,YAAa,MAAK,UAAU,KAAK,YAAY;AACvE;;GAIF,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW;GAChB,KAAK,WAAW,UACd"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { INTERNAL_PATH_LIB_PREFIX, POOL_ERROR_NAMES, POOL_INTERNAL_PATHS } from "./constants-
|
|
2
|
-
import { createPoolErrorFromAnyError, debug, getTestErrorFromPoolError } from "./debug-
|
|
1
|
+
import { INTERNAL_PATH_LIB_PREFIX, POOL_ERROR_NAMES, POOL_INTERNAL_PATHS } from "./constants-DbxJ3hzg.mjs";
|
|
2
|
+
import { createPoolErrorFromAnyError, debug, getTestErrorFromPoolError } from "./debug-DtRAL4rM.mjs";
|
|
3
3
|
import { toForwardSlash } from "./path-utils-t9OzjXYF.mjs";
|
|
4
|
-
import { failFile, getFullTaskHierarchy, prepareFileTaskForCollection } from "./vitest-file-tasks-
|
|
5
|
-
import { getTaskLogLabel, getTaskLogPrefix } from "./vitest-tasks
|
|
6
|
-
import { executeWASMDiscovery, flushRpcUpdates, reportFileCollected, reportFileError, reportFileQueued, reportUserConsoleLogs } from "./load-user-imports-
|
|
7
|
-
import { compileAssemblyScript } from "./compiler-
|
|
4
|
+
import { failFile, getFullTaskHierarchy, prepareFileTaskForCollection } from "./vitest-file-tasks-D8sOClGX.mjs";
|
|
5
|
+
import { getTaskLogLabel, getTaskLogPrefix } from "./vitest-tasks-BZ24sghI.mjs";
|
|
6
|
+
import { executeWASMDiscovery, flushRpcUpdates, reportFileCollected, reportFileError, reportFileQueued, reportUserConsoleLogs } from "./load-user-imports-Bx5ZlhSm.mjs";
|
|
7
|
+
import { compileAssemblyScript } from "./compiler-hUlDr5vL.mjs";
|
|
8
8
|
import { basename, relative } from "node:path";
|
|
9
9
|
|
|
10
10
|
//#region src/pool-thread/runner/compile-runner.ts
|
|
@@ -30,6 +30,7 @@ async function runCompileAndDiscover(file, logModule, rpc, poolOptions, projectR
|
|
|
30
30
|
],
|
|
31
31
|
excludedLibraryFilePrefix: "~lib/",
|
|
32
32
|
excludedLibraryFileOverridePrefix: poolOptions._instrumentPoolInternals ? INTERNAL_PATH_LIB_PREFIX : void 0,
|
|
33
|
+
excludedInternalFunctionSubstring: "__vitest_assemblyscript_",
|
|
33
34
|
coverageMemoryPagesMin: poolOptions.coverageMemoryPagesInitial,
|
|
34
35
|
coverageMemoryPagesMax: poolOptions.coverageMemoryPagesMax,
|
|
35
36
|
debug: poolOptions.debugNative
|
|
@@ -81,4 +82,4 @@ async function runCompileAndDiscover(file, logModule, rpc, poolOptions, projectR
|
|
|
81
82
|
|
|
82
83
|
//#endregion
|
|
83
84
|
export { runCompileAndDiscover };
|
|
84
|
-
//# sourceMappingURL=compile-runner-
|
|
85
|
+
//# sourceMappingURL=compile-runner-BGQhBkBo.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-runner-BGQhBkBo.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 { toForwardSlash } from '../../util/path-utils.js';\n\nimport type {\n AssemblyScriptCompilerOptions,\n AssemblyScriptConsoleLog,\n AssemblyScriptConsoleLogHandler,\n InstrumentationOptions,\n ResolvedAssemblyScriptPoolOptions,\n ThreadImports,\n WASMCompilation,\n WorkerRPC,\n} from '../../types/types.js';\nimport {\n ASSEMBLYSCRIPT_LIB_PREFIX,\n INTERNAL_FUNCTION_NAME_SUBSTRING,\n INTERNAL_PATH_LIB_PREFIX,\n POOL_ERROR_NAMES,\n POOL_INTERNAL_PATHS,\n} from '../../types/constants.js';\nimport { executeWASMDiscovery } from '../../wasm-executor/index.js';\nimport { debug } from '../../util/debug.js';\nimport {\n reportFileQueued,\n reportFileCollected,\n reportUserConsoleLogs,\n flushRpcUpdates,\n reportFileError,\n} from '../rpc-reporter.js';\nimport { createPoolErrorFromAnyError, getTestErrorFromPoolError } from '../../util/pool-errors.js';\nimport { compileAssemblyScript } from '../../compiler/index.js';\nimport {\n getTaskLogLabel,\n getTaskLogPrefix,\n} from '../../util/vitest-tasks.js';\nimport {\n failFile,\n getFullTaskHierarchy,\n prepareFileTaskForCollection,\n} from '../../util/vitest-file-tasks.js';\n\nlet threadCompilationCount: number = 0;\n\nexport async function runCompileAndDiscover(\n file: File,\n logModule: string,\n rpc: WorkerRPC,\n poolOptions: ResolvedAssemblyScriptPoolOptions,\n projectRoot: string,\n collectCoverage: boolean,\n relativeUserCoverageExclusions: string[],\n threadImports: ThreadImports,\n diffOptions?: SerializedDiffOptions,\n testNamePattern?: RegExp,\n allowOnly?: boolean,\n): Promise<WASMCompilation | undefined> {\n const base = basename(file.filepath);\n const fileLogPrefix = getTaskLogPrefix(logModule, base, file);\n const fileLogLabel = getTaskLogLabel(base, file);\n\n debug(`${fileLogPrefix} - Beginning runCompileAndDiscover for \"${file.filepath}\" at ${Date.now()}`);\n\n const runStart = performance.now();\n let compilation: WASMCompilation | undefined;\n\n try {\n await reportFileQueued(rpc, file, logModule, fileLogLabel);\n\n const relativeTestFilePath = toForwardSlash(relative(projectRoot, file.filepath));\n const instrumentationOptions: InstrumentationOptions = {\n projectRoot,\n relativeExcludedFiles: [\n relativeTestFilePath,\n ...(poolOptions._instrumentPoolInternals ? [] : POOL_INTERNAL_PATHS),\n ...relativeUserCoverageExclusions,\n ],\n excludedLibraryFilePrefix: ASSEMBLYSCRIPT_LIB_PREFIX,\n excludedLibraryFileOverridePrefix: poolOptions._instrumentPoolInternals ? INTERNAL_PATH_LIB_PREFIX : undefined,\n excludedInternalFunctionSubstring: INTERNAL_FUNCTION_NAME_SUBSTRING,\n coverageMemoryPagesMin: poolOptions.coverageMemoryPagesInitial,\n coverageMemoryPagesMax: poolOptions.coverageMemoryPagesMax,\n debug: poolOptions.debugNative,\n };\n const compilerOptions: AssemblyScriptCompilerOptions = {\n stripInline: poolOptions.stripInline,\n projectRoot: projectRoot,\n shouldInstrument: collectCoverage,\n instrumentationOptions,\n extraFlags: poolOptions.extraCompilerFlags\n };\n\n const { binary, sourceMap, debugInfo, compileTiming } = await compileAssemblyScript(\n file.filepath,\n compilerOptions,\n logModule,\n fileLogLabel\n );\n file.setupDuration = compileTiming;\n threadCompilationCount++;\n\n debug(`${fileLogPrefix} - TIMING compileAssemblyScript total `\n + `(thread comp # ${threadCompilationCount}): ${compileTiming.toFixed(2)} ms`\n );\n \n const logMessages: AssemblyScriptConsoleLog[] = [];\n const handleLog: AssemblyScriptConsoleLogHandler = (msg: string, isError: boolean = false): void => {\n logMessages.push({ msg, time: Date.now(), isError });\n };\n \n const discoverStart = performance.now();\n\n await executeWASMDiscovery(\n binary,\n sourceMap,\n base,\n poolOptions,\n collectCoverage,\n handleLog,\n file,\n logModule,\n threadImports,\n diffOptions\n );\n\n // set skips when using only and/or user test name pattern, skip file task if all tests skipped\n prepareFileTaskForCollection(file, testNamePattern, allowOnly);\n\n file.collectDuration = performance.now() - discoverStart;\n debug(`${fileLogPrefix} - TIMING Discovery Phase: ${file.collectDuration.toFixed(2)} ms`);\n\n // vitest collect - report discovery results\n await Promise.all([\n // Report user console logs\n reportUserConsoleLogs(rpc, logMessages, logModule, base, file),\n\n // Report onCollected with collected and filtered tasks\n reportFileCollected(rpc, file, logModule, fileLogLabel),\n ]);\n\n debug(() => `${fileLogPrefix} - Collected Test Suite Hierarchy:\\n${getFullTaskHierarchy(file)}`);\n\n const totalTime = performance.now() - runStart;\n debug(`${fileLogPrefix} - TIMING Compilation and Discovery: ${totalTime.toFixed(2)} ms`);\n\n compilation = {\n filePath: file.filepath,\n binary,\n sourceMap,\n debugInfo,\n };\n } catch (error) {\n const poolError = createPoolErrorFromAnyError(\n `${fileLogLabel} - runCompileAndDiscover failure in worker`,\n POOL_ERROR_NAMES.WASMExecutionHarnessError,\n error\n );\n const testError = getTestErrorFromPoolError(poolError);\n\n failFile(file, testError, runStart);\n\n await reportFileQueued(rpc, file, logModule, fileLogLabel);\n await reportFileError(rpc, file, logModule, fileLogLabel);\n\n debug(`${fileLogPrefix} - Reported file error`);\n } finally {\n await flushRpcUpdates(rpc);\n debug(`${fileLogPrefix} - runCompileAndDiscover Completed`);\n }\n\n return compilation;\n}\n"],"mappings":";;;;;;;;;;;;;AAgDA,IAAI,yBAAiC;AAErC,eAAsB,sBACpB,MACA,WACA,KACA,aACA,aACA,iBACA,gCACA,eACA,aACA,iBACA,WACsC;CACtC,MAAM,OAAO,SAAS,KAAK,SAAS;CACpC,MAAM,gBAAgB,iBAAiB,WAAW,MAAM,KAAK;CAC7D,MAAM,eAAe,gBAAgB,MAAM,KAAK;AAEhD,OAAM,GAAG,cAAc,0CAA0C,KAAK,SAAS,OAAO,KAAK,KAAK,GAAG;CAEnG,MAAM,WAAW,YAAY,KAAK;CAClC,IAAI;AAEJ,KAAI;AACF,QAAM,iBAAiB,KAAK,MAAM,WAAW,aAAa;EAG1D,MAAM,yBAAiD;GACrD;GACA,uBAAuB;IAHI,eAAe,SAAS,aAAa,KAAK,SAAS,CAAC;IAK7E,GAAI,YAAY,2BAA2B,EAAE,GAAG;IAChD,GAAG;IACJ;GACD;GACA,mCAAmC,YAAY,2BAA2B,2BAA2B;GACrG;GACA,wBAAwB,YAAY;GACpC,wBAAwB,YAAY;GACpC,OAAO,YAAY;GACpB;EACD,MAAM,kBAAiD;GACrD,aAAa,YAAY;GACZ;GACb,kBAAkB;GAClB;GACA,YAAY,YAAY;GACzB;EAED,MAAM,EAAE,QAAQ,WAAW,WAAW,kBAAkB,MAAM,sBAC5D,KAAK,UACL,iBACA,WACA,aACD;AACD,OAAK,gBAAgB;AACrB;AAEA,QAAM,GAAG,cAAc,uDACD,uBAAuB,KAAK,cAAc,QAAQ,EAAE,CAAC,KAC1E;EAED,MAAM,cAA0C,EAAE;EAClD,MAAM,aAA8C,KAAa,UAAmB,UAAgB;AAClG,eAAY,KAAK;IAAE;IAAK,MAAM,KAAK,KAAK;IAAE;IAAS,CAAC;;EAGtD,MAAM,gBAAgB,YAAY,KAAK;AAEvC,QAAM,qBACJ,QACA,WACA,MACA,aACA,iBACA,WACA,MACA,WACA,eACA,YACD;AAGD,+BAA6B,MAAM,iBAAiB,UAAU;AAE9D,OAAK,kBAAkB,YAAY,KAAK,GAAG;AAC3C,QAAM,GAAG,cAAc,6BAA6B,KAAK,gBAAgB,QAAQ,EAAE,CAAC,KAAK;AAGzF,QAAM,QAAQ,IAAI,CAEhB,sBAAsB,KAAK,aAAa,WAAW,MAAM,KAAK,EAG9D,oBAAoB,KAAK,MAAM,WAAW,aAAa,CACxD,CAAC;AAEF,cAAY,GAAG,cAAc,sCAAsC,qBAAqB,KAAK,GAAG;AAGhG,QAAM,GAAG,cAAc,wCADL,YAAY,KAAK,GAAG,UACkC,QAAQ,EAAE,CAAC,KAAK;AAExF,gBAAc;GACZ,UAAU,KAAK;GACf;GACA;GACA;GACD;UACM,OAAO;AAQd,WAAS,MAFS,0BALA,4BAChB,GAAG,aAAa,6CAChB,iBAAiB,2BACjB,MACD,CACqD,EAE5B,SAAS;AAEnC,QAAM,iBAAiB,KAAK,MAAM,WAAW,aAAa;AAC1D,QAAM,gBAAgB,KAAK,MAAM,WAAW,aAAa;AAEzD,QAAM,GAAG,cAAc,wBAAwB;WACvC;AACR,QAAM,gBAAgB,IAAI;AAC1B,QAAM,GAAG,cAAc,oCAAoC;;AAG7D,QAAO"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Parser } from "assemblyscript";
|
|
2
|
+
import { Transform } from "assemblyscript/transform";
|
|
3
|
+
|
|
4
|
+
//#region src/compiler/transforms/deep-equals.d.mts
|
|
5
|
+
/**
|
|
6
|
+
* AssemblyScript compiler transform that injects deep equality, typename, and stringify methods
|
|
7
|
+
* into user-defined classes
|
|
8
|
+
*/
|
|
9
|
+
declare class DeepEqualsTransform extends Transform {
|
|
10
|
+
afterParse(parser: Parser): void;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { DeepEqualsTransform as default };
|
|
14
|
+
//# sourceMappingURL=deep-equals.d.mts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { ASCommonFlags, ASDecoratorKind, ASNodeKind, ASSourceKind, INTERNAL_PATH_LIB_PREFIX } from "../../constants-DbxJ3hzg.mjs";
|
|
2
|
+
import { ASTVisitor } from "../../ast-visitor-CWEOd3UH.mjs";
|
|
3
|
+
import { Source, Tokenizer } from "assemblyscript";
|
|
4
|
+
import { Transform } from "assemblyscript/transform";
|
|
5
|
+
|
|
6
|
+
//#region src/compiler/transforms/deep-equals.mts
|
|
7
|
+
/**
|
|
8
|
+
* AssemblyScript Compiler Transform: Deep Equality & Stringification for User-Defined Objects
|
|
9
|
+
*
|
|
10
|
+
* Injects three methods into user-defined classes at `afterParse`:
|
|
11
|
+
*
|
|
12
|
+
* 1. `__vitest_assemblyscript_deep_equals` — deep equality comparison for `toEqual()`
|
|
13
|
+
* - If the class defines `@operator("==")`: delegates to `this == other`
|
|
14
|
+
* - If the class defines `.equals()`: delegates to `this.equals(other)`
|
|
15
|
+
* - Otherwise: compares all stored instance fields via the pool's `equals()` function
|
|
16
|
+
*
|
|
17
|
+
* 2. `__vitest_assemblyscript_typename` — returns the runtime class name via `nameof<ClassName>()`
|
|
18
|
+
* - Virtual dispatch ensures correct runtime name even for base-typed variables
|
|
19
|
+
* - Used by stringifyValue() for user-facing output and by RTM type name tracking
|
|
20
|
+
*
|
|
21
|
+
* 3. `__vitest_assemblyscript_stringify` — returns comma-separated field entries for stringification
|
|
22
|
+
* - Always stringifies all stored instance fields regardless of operator==/equals()
|
|
23
|
+
* - Follows super chain via isDefined guard, same pattern as deep equality
|
|
24
|
+
* - Uses @global bridge __vitest_assemblyscript_stringify_value to call stringifyValue()
|
|
25
|
+
*
|
|
26
|
+
* Scoping:
|
|
27
|
+
* - Only user source files (not node_modules, not AS stdlib)
|
|
28
|
+
* - Blanket injection into all user classes (always enabled)
|
|
29
|
+
*
|
|
30
|
+
* Cross-module function availability:
|
|
31
|
+
* - Structural bodies reference @global functions from assembly/compare.ts and assembly/utils.ts
|
|
32
|
+
* which are available in all source files without import
|
|
33
|
+
* - Loaded transitively: user test → vitest-pool-assemblyscript/assembly → compare.ts → utils.ts
|
|
34
|
+
*
|
|
35
|
+
* AST injection:
|
|
36
|
+
* - Method source is generated as a string, then parsed into an AST node using
|
|
37
|
+
* `Parser.parseClassMember()` via a temporary `Source` + `Tokenizer`
|
|
38
|
+
*
|
|
39
|
+
* @see https://www.assemblyscript.org/compiler.html#transforms
|
|
40
|
+
* @see https://github.com/AssemblyScript/assemblyscript/blob/main/src/ast.ts
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Visitor that finds class declarations and injects deep equality, typename, and stringify methods.
|
|
44
|
+
* Uses ASTVisitor for full recursive traversal (finds classes inside namespaces, etc).
|
|
45
|
+
*/
|
|
46
|
+
var DeepEqualsVisitor = class extends ASTVisitor {
|
|
47
|
+
constructor(parser, barrelPath) {
|
|
48
|
+
super();
|
|
49
|
+
this.parser = parser;
|
|
50
|
+
this.barrelPath = barrelPath;
|
|
51
|
+
}
|
|
52
|
+
onClassEnter(node) {
|
|
53
|
+
processClass(this.parser, node, this.barrelPath);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* AssemblyScript compiler transform that injects deep equality, typename, and stringify methods
|
|
58
|
+
* into user-defined classes
|
|
59
|
+
*/
|
|
60
|
+
var DeepEqualsTransform = class extends Transform {
|
|
61
|
+
afterParse(parser) {
|
|
62
|
+
const sources = this.program.sources;
|
|
63
|
+
const barrelPath = `${INTERNAL_PATH_LIB_PREFIX}index.ts`;
|
|
64
|
+
const barrelSource = sources.find((s) => s.normalizedPath === barrelPath);
|
|
65
|
+
if (!barrelSource) console.warn(`[deep-equals transform] WARNING: Could not find barrel source "${barrelPath}" in compilation`);
|
|
66
|
+
const visitor = new DeepEqualsVisitor(parser, barrelSource ? barrelPath : "");
|
|
67
|
+
const userSources = sources.filter((source) => (source.sourceKind === ASSourceKind.User || source.sourceKind === ASSourceKind.UserEntry) && !source.normalizedPath.startsWith("~lib/"));
|
|
68
|
+
for (const source of userSources) visitor.visitSource(source);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Process a class declaration: inject deep equality, typename, and stringify methods.
|
|
73
|
+
*/
|
|
74
|
+
function processClass(parser, classDecl, barrelPath) {
|
|
75
|
+
const className = classDecl.name.text;
|
|
76
|
+
const sourcePath = barrelPath || classDecl.range.source.normalizedPath;
|
|
77
|
+
const typeSuffix = getTypeParameterSuffix(classDecl);
|
|
78
|
+
injectDeepEquals(parser, classDecl, className, typeSuffix, sourcePath);
|
|
79
|
+
injectTypename(parser, classDecl, className, typeSuffix, sourcePath);
|
|
80
|
+
injectStringify(parser, classDecl, sourcePath);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Inject the deep equality comparison method into a class.
|
|
84
|
+
*
|
|
85
|
+
* Behavior depends on user-defined equality semantics:
|
|
86
|
+
* - @operator("==") present: delegates to `this == other`
|
|
87
|
+
* - .equals() present: delegates to `this.equals(other)`
|
|
88
|
+
* - Neither: field-by-field structural comparison
|
|
89
|
+
*
|
|
90
|
+
* All methods use a usize parameter for inheritance compatibility — AS treats child methods
|
|
91
|
+
* with the same name as overrides, requiring compatible parameter types. Each body casts
|
|
92
|
+
* the pointer to its own type via changetype.
|
|
93
|
+
*/
|
|
94
|
+
function injectDeepEquals(parser, classDecl, className, typeSuffix, sourcePath) {
|
|
95
|
+
if (hasMethod(classDecl, "__vitest_assemblyscript_deep_equals")) return;
|
|
96
|
+
const typedCast = `const other = changetype<${className}${typeSuffix}>(__other);`;
|
|
97
|
+
const EQ = "__vitest_assemblyscript_EqualityResult";
|
|
98
|
+
let methodBody;
|
|
99
|
+
if (hasOperatorEquals(classDecl)) methodBody = `${typedCast} return (this == other) ? ${EQ}.Equal : ${EQ}.NotEqual;`;
|
|
100
|
+
else if (hasMethod(classDecl, "equals")) methodBody = `${typedCast} return this.equals(other) ? ${EQ}.Equal : ${EQ}.NotEqual;`;
|
|
101
|
+
else methodBody = `${typedCast} ${generateStructuralBody(classDecl)}`;
|
|
102
|
+
injectClassMember(parser, classDecl, `${"__vitest_assemblyscript_deep_equals"}(__other: usize): ${EQ} { ${methodBody} }`, sourcePath);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Inject the typename method into a class.
|
|
106
|
+
*
|
|
107
|
+
* Returns the class's own name via nameof<ClassName>(). No super chain — each class returns
|
|
108
|
+
* its own name. Virtual dispatch ensures the correct runtime class name is returned even
|
|
109
|
+
* when the variable is typed as a base class.
|
|
110
|
+
*/
|
|
111
|
+
function injectTypename(parser, classDecl, className, typeSuffix, sourcePath) {
|
|
112
|
+
if (hasMethod(classDecl, "__vitest_assemblyscript_typename")) return;
|
|
113
|
+
injectClassMember(parser, classDecl, `${"__vitest_assemblyscript_typename"}(): string { return nameof<${className}${typeSuffix}>(); }`, sourcePath);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Inject the stringify method into a class.
|
|
117
|
+
*
|
|
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().
|
|
124
|
+
*/
|
|
125
|
+
function injectStringify(parser, classDecl, sourcePath) {
|
|
126
|
+
if (hasMethod(classDecl, "__vitest_assemblyscript_stringify")) return;
|
|
127
|
+
injectClassMember(parser, classDecl, `${"__vitest_assemblyscript_stringify"}(): string { ${generateStringifyBody(classDecl)} }`, sourcePath);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if a class has a specific instance method by name
|
|
131
|
+
*/
|
|
132
|
+
function hasMethod(classDecl, methodName) {
|
|
133
|
+
return classDecl.members.some((member) => member.kind === ASNodeKind.MethodDeclaration && member.name.text === methodName && member.is(ASCommonFlags.Instance));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check if a class has an @operator("==") decorator on any method.
|
|
137
|
+
* The AS compiler uses DecoratorKind.Operator (2) for @operator and
|
|
138
|
+
* DecoratorKind.OperatorBinary (3) for @operator.binary — check both.
|
|
139
|
+
*/
|
|
140
|
+
function hasOperatorEquals(classDecl) {
|
|
141
|
+
for (const member of classDecl.members) {
|
|
142
|
+
if (member.kind !== ASNodeKind.MethodDeclaration) continue;
|
|
143
|
+
const decorators = member.decorators;
|
|
144
|
+
if (!decorators) continue;
|
|
145
|
+
for (const decorator of decorators) {
|
|
146
|
+
const kind = decorator.decoratorKind;
|
|
147
|
+
if (kind !== ASDecoratorKind.Operator && kind !== ASDecoratorKind.OperatorBinary) continue;
|
|
148
|
+
const args = decorator.args;
|
|
149
|
+
if (!args || args.length === 0) continue;
|
|
150
|
+
if (args[0].value === "==") return true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get the type parameter suffix for a class declaration.
|
|
157
|
+
* Returns empty string for non-generic classes, "<T>" for single param,
|
|
158
|
+
* "<K, V>" for multiple params, etc.
|
|
159
|
+
*/
|
|
160
|
+
function getTypeParameterSuffix(classDecl) {
|
|
161
|
+
const typeParams = classDecl.typeParameters;
|
|
162
|
+
if (!typeParams || typeParams.length === 0) return "";
|
|
163
|
+
return `<${typeParams.map((param) => param.name.text).join(", ")}>`;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Collect stored instance fields from a class declaration.
|
|
167
|
+
* Includes public, private, protected fields.
|
|
168
|
+
* Excludes: static fields, getters, setters, constructors, methods.
|
|
169
|
+
*/
|
|
170
|
+
function getStoredInstanceFields(classDecl) {
|
|
171
|
+
return classDecl.members.filter((member) => {
|
|
172
|
+
if (member.kind !== ASNodeKind.FieldDeclaration) return false;
|
|
173
|
+
if (member.is(ASCommonFlags.Static)) return false;
|
|
174
|
+
if (member.is(ASCommonFlags.Get) || member.is(ASCommonFlags.Set)) return false;
|
|
175
|
+
return true;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Generate the structural comparison body for a class.
|
|
180
|
+
* Delegates all field comparisons to the pool's equals function, which handles
|
|
181
|
+
* primitives, strings, containers, nullables, and nested user types recursively.
|
|
182
|
+
*
|
|
183
|
+
* Uses a shared `__result` variable to capture and propagate EqualityResult from
|
|
184
|
+
* each comparison, so type mismatch information from nested comparisons is preserved.
|
|
185
|
+
*/
|
|
186
|
+
function generateStructuralBody(classDecl) {
|
|
187
|
+
const fields = getStoredInstanceFields(classDecl);
|
|
188
|
+
const EQ = "__vitest_assemblyscript_EqualityResult";
|
|
189
|
+
if (fields.length === 0) return `return ${EQ}.Equal;`;
|
|
190
|
+
const hasSuper = classDecl.extendsType !== null;
|
|
191
|
+
const comparisons = [];
|
|
192
|
+
comparisons.push(`let __result: ${EQ};`);
|
|
193
|
+
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
|
+
for (const field of fields) {
|
|
195
|
+
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"}();`);
|
|
197
|
+
}
|
|
198
|
+
return comparisons.join(" ") + ` return ${EQ}.Equal;`;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
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.
|
|
204
|
+
*/
|
|
205
|
+
function generateStringifyBody(classDecl) {
|
|
206
|
+
const fields = getStoredInstanceFields(classDecl);
|
|
207
|
+
const hasSuper = classDecl.extendsType !== null;
|
|
208
|
+
const SV = "__vitest_assemblyscript_stringify_value";
|
|
209
|
+
const SUPER_METHOD = "__vitest_assemblyscript_stringify";
|
|
210
|
+
if (fields.length === 0 && !hasSuper) return `return "";`;
|
|
211
|
+
const parts = [];
|
|
212
|
+
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;
|
|
220
|
+
}
|
|
221
|
+
parts.push(`return s;`);
|
|
222
|
+
return parts.join(" ");
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Parse a method source string and inject it as a member of the given class.
|
|
226
|
+
*
|
|
227
|
+
* Creates a temporary Source and Tokenizer, uses the parser's parseClassMember()
|
|
228
|
+
* to produce a proper AST node, then appends it to the class's members array.
|
|
229
|
+
*
|
|
230
|
+
* The temporary source uses the pool's assembly barrel file (assembly/index.ts) as its
|
|
231
|
+
* normalizedPath instead of the user's source file. This prevents the source map from
|
|
232
|
+
* incorrectly attributing generated code to user source lines. The AS compiler requires
|
|
233
|
+
* the normalizedPath to be a real source in the compilation for identifier resolution
|
|
234
|
+
* (synthetic paths cause assertion failures in maybeCompileEnclosingSource).
|
|
235
|
+
*/
|
|
236
|
+
function injectClassMember(parser, classDecl, memberSource, barrelPath) {
|
|
237
|
+
const tokenizer = new Tokenizer(new Source(ASSourceKind.User, barrelPath, memberSource));
|
|
238
|
+
tokenizer.next();
|
|
239
|
+
const member = parser.parseClassMember(tokenizer, classDecl);
|
|
240
|
+
if (member) classDecl.members.push(member);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
//#endregion
|
|
244
|
+
export { DeepEqualsTransform as default };
|
|
245
|
+
//# sourceMappingURL=deep-equals.mjs.map
|
|
@@ -0,0 +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":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ASDecoratorKind, ASSourceKind } from "../../constants-
|
|
2
|
-
import { ASTVisitor } from "../../ast-visitor-
|
|
1
|
+
import { ASDecoratorKind, ASSourceKind } from "../../constants-DbxJ3hzg.mjs";
|
|
2
|
+
import { ASTVisitor } from "../../ast-visitor-CWEOd3UH.mjs";
|
|
3
3
|
import { Transform } from "assemblyscript/transform";
|
|
4
4
|
|
|
5
5
|
//#region src/compiler/transforms/strip-inline.mts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { POOL_ERROR_NAMES } from "./constants-
|
|
2
|
-
import { createPoolError, debug, throwPoolErrorIfAborted } from "./debug-
|
|
3
|
-
import { clearNativeBuildError, hasNativeBuildError, warnASInstrumentationNotLoaded } from "./feature-check-
|
|
1
|
+
import { POOL_ERROR_NAMES } from "./constants-DbxJ3hzg.mjs";
|
|
2
|
+
import { createPoolError, debug, throwPoolErrorIfAborted } from "./debug-DtRAL4rM.mjs";
|
|
3
|
+
import { clearNativeBuildError, hasNativeBuildError, warnASInstrumentationNotLoaded } from "./feature-check-Bje3ntpV.mjs";
|
|
4
4
|
import { basename, resolve } from "node:path";
|
|
5
5
|
import { access, readFile } from "node:fs/promises";
|
|
6
6
|
import { main } from "assemblyscript/asc";
|
|
@@ -14,7 +14,7 @@ import { main } from "assemblyscript/asc";
|
|
|
14
14
|
*/
|
|
15
15
|
let nativeAddon;
|
|
16
16
|
try {
|
|
17
|
-
nativeAddon = await import("./addon-interface-
|
|
17
|
+
nativeAddon = await import("./addon-interface-CYFXMbK7.mjs");
|
|
18
18
|
clearNativeBuildError();
|
|
19
19
|
} catch (err) {
|
|
20
20
|
if (await hasNativeBuildError()) debug(`[Compiler] Native instrumentation addon not loaded (known build failure): ${err?.message ?? String(err)}`);
|
|
@@ -22,12 +22,18 @@ try {
|
|
|
22
22
|
}
|
|
23
23
|
const POOL_ASSEMBLY_NODE_MODULES_PREFIX = "node_modules/vitest-pool-assemblyscript/assembly/";
|
|
24
24
|
const STRIP_INLINE_TRANSFORM = resolve(import.meta.dirname, "./compiler/transforms/strip-inline.mjs");
|
|
25
|
+
const DEEP_EQUALS_TRANSFORM = resolve(import.meta.dirname, "./compiler/transforms/deep-equals.mjs");
|
|
25
26
|
setImmediate(async () => {
|
|
26
27
|
try {
|
|
27
28
|
await access(STRIP_INLINE_TRANSFORM);
|
|
28
29
|
} catch {
|
|
29
30
|
throw createPoolError(`AS Compiler strip inline transform file not found at "${STRIP_INLINE_TRANSFORM}"`, POOL_ERROR_NAMES.CompilationError);
|
|
30
31
|
}
|
|
32
|
+
try {
|
|
33
|
+
await access(DEEP_EQUALS_TRANSFORM);
|
|
34
|
+
} catch {
|
|
35
|
+
throw createPoolError(`AS Compiler deep equals transform file not found at "${DEEP_EQUALS_TRANSFORM}"`, POOL_ERROR_NAMES.CompilationError);
|
|
36
|
+
}
|
|
31
37
|
});
|
|
32
38
|
/**
|
|
33
39
|
* Compile AssemblyScript source code to WASM binary
|
|
@@ -69,7 +75,9 @@ async function compileAssemblyScript(filename, options, logModule, logLabel, sig
|
|
|
69
75
|
"--sourceMap",
|
|
70
76
|
"--exportStart",
|
|
71
77
|
"_start",
|
|
72
|
-
"--exportTable"
|
|
78
|
+
"--exportTable",
|
|
79
|
+
"--transform",
|
|
80
|
+
DEEP_EQUALS_TRANSFORM
|
|
73
81
|
];
|
|
74
82
|
if (options.stripInline === true) {
|
|
75
83
|
compilerFlags.push("--transform", STRIP_INLINE_TRANSFORM);
|
|
@@ -144,4 +152,4 @@ async function compileAssemblyScript(filename, options, logModule, logLabel, sig
|
|
|
144
152
|
|
|
145
153
|
//#endregion
|
|
146
154
|
export { compileAssemblyScript };
|
|
147
|
-
//# sourceMappingURL=compiler-
|
|
155
|
+
//# sourceMappingURL=compiler-hUlDr5vL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler-hUlDr5vL.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';\n\nimport type {\n AssemblyScriptCompilerResult,\n AssemblyScriptCompilerOptions,\n NativeAddonInterface\n} from '../types/types.js';\nimport { POOL_ERROR_NAMES } from '../types/constants.js';\nimport { debug } from '../util/debug.js';\nimport { createPoolError, throwPoolErrorIfAborted } from '../util/pool-errors.js';\nimport { clearNativeBuildError, hasNativeBuildError, warnASInstrumentationNotLoaded } from '../util/feature-check.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 `AS Compiler strip inline transform file not found at \"${STRIP_INLINE_TRANSFORM}\"`,\n POOL_ERROR_NAMES.CompilationError\n );\n }\n\n try {\n await access(DEEP_EQUALS_TRANSFORM);\n } catch {\n throw createPoolError(\n `AS Compiler deep equals transform file not found at \"${DEEP_EQUALS_TRANSFORM}\"`,\n POOL_ERROR_NAMES.CompilationError\n );\n }\n});\n\n/**\n * Compile AssemblyScript source code to WASM binary\n */\nexport async function compileAssemblyScript(\n filename: string,\n options: AssemblyScriptCompilerOptions,\n logModule: string,\n logLabel: string,\n signal?: AbortSignal\n): Promise<AssemblyScriptCompilerResult> {\n throwPoolErrorIfAborted(signal);\n\n const compileStart = performance.now();\n const logPrefix = `[${logModule} ASC] ${logLabel}`;\n\n const { shouldInstrument, instrumentationOptions, extraFlags } = options;\n\n if (shouldInstrument && !instrumentationOptions) {\n throw createPoolError(\n 'Instrumentation options are required for coverage instrumentation',\n POOL_ERROR_NAMES.CompilationError\n );\n }\n\n const stdoutLines: string[] = [];\n const stderrLines: string[] = [];\n let binary: Uint8Array | undefined;\n let sourceMap: string | undefined;\n\n // Use full path as entry file so AS compiler can resolve relative imports\n const entryFile = filename;\n // Use simple output name to avoid AS compiler prepending it to source map paths\n const outputFile = 'output.wasm';\n\n debug(`${logPrefix} - Compiling: \"${filename}\"`);\n\n // Capture stdout/stderr (for potential error reporting)\n const stdout = {\n write: (text: string) => {\n stdoutLines.push(text);\n return true;\n }\n };\n\n const stderr = {\n write: (text: string) => {\n stderrLines.push(text);\n return true;\n }\n };\n\n // Build compiler flags\n const compilerFlags = [\n entryFile,\n\n // overrideable, though not recommended\n '--optimizeLevel', '0', // No optimization for easier debugging\n '--shrinkLevel', '0', // No shrink\n '--runtime', 'stub', // stub runtime (no GC)\n\n ...(extraFlags || []),\n\n // non-overrideable\n '--outFile', outputFile,\n '--importMemory', // Import memory from JS (enables imports during WASM start)\n '--debug', // Include debug info\n '--sourceMap', // Generate source maps for error reporting\n '--exportStart', '_start', // Export start function for explicit initialization control\n '--exportTable', // Export function table for direct test execution\n\n // 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 throwPoolErrorIfAborted(signal);\n\n if (name.endsWith('.wasm') && contents instanceof Uint8Array) {\n binary = contents;\n debug(`${logPrefix} - Captured binary in memory: \"${name}\"`);\n } else if (name.endsWith('.wasm.map') && typeof contents === 'string') {\n debug(`${logPrefix} - Captured source map in memory: \"${name}\"`);\n sourceMap = contents;\n } else {\n debug(`${logPrefix} - WARNING - Captured Unexpected File: \"${name}\" at baseDir: \"${_baseDir}\"`);\n }\n },\n \n // Custom readFile enables in-tree resolution of bare pool assembly imports.\n // When a test file imports 'vitest-pool-assemblyscript/assembly', the AS compiler\n // resolves it to a node_modules path. This works when the package is installed,\n // but fails in-tree (the package isn't in its own node_modules). The fallback\n // redirects these to the local assembly/ directory when the normal path isn't found.\n readFile: async (filename, baseDir): Promise<string | null> => {\n const filePath = resolve(baseDir, filename);\n\n try {\n return await readFile(filePath, { encoding: 'utf-8' });\n } catch {\n // Fallback: when running in-tree, redirect pool assembly imports to local assembly/ dir\n if (filename.startsWith(POOL_ASSEMBLY_NODE_MODULES_PREFIX)) {\n const localSubpath = filename.substring(POOL_ASSEMBLY_NODE_MODULES_PREFIX.length);\n const localPath = resolve(baseDir, 'assembly', localSubpath);\n\n try {\n return await readFile(localPath, { encoding: 'utf-8' });\n } catch {\n return null;\n }\n }\n\n return null;\n }\n },\n });\n\n debug(`${logPrefix} - TIMING asc.main: ${(performance.now() - ascStart).toFixed(2)} ms`);\n\n if (result.error) {\n const errorMessage = stderrLines.length > 0\n ? `${result.error.message}\\n\\n${stderrLines.join('')}`\n : result.error.message;\n\n throw createPoolError(errorMessage, POOL_ERROR_NAMES.CompilationError, errorMessage);\n }\n\n if (!binary) {\n const errorMessage = stderrLines.length > 0\n ? `No WASM binary was generated\\n\\nAS Compiler output:\\n${stderrLines.join('')}`\n : 'No WASM binary was generated';\n\n throw createPoolError(errorMessage, POOL_ERROR_NAMES.CompilationError);\n }\n\n if (!sourceMap) {\n throw createPoolError('Source map not captured from AssemblyScript Compiler', POOL_ERROR_NAMES.CompilationError);\n }\n\n const cleanBinary: Uint8Array = binary;\n const wasmSourceMap: string = sourceMap;\n\n debug(`${logPrefix} - Compilation successful, clean binary size: ${cleanBinary.length} bytes`);\n debug(`${logPrefix} - Source map generated, size: ${wasmSourceMap.length * 2} bytes`);\n \n if (DEBUG_WRITE_FILES) {\n // Write source map for debugging\n const dir = './debug';\n // TODO - handle non-.ts extensions\n const sourceMapFileName = `${basename(filename, '.ts')}.ts.map`;\n const sourceMapPath = `${dir}/${sourceMapFileName}`;\n\n // Create directory if it doesn't exist\n try {\n await mkdir(dir, { recursive: true });\n } catch {\n // Directory already exists or creation failed, continue\n }\n\n // Format as well-formed JSON\n const formattedSourceMap = JSON.stringify(JSON.parse(wasmSourceMap), null, 2);\n\n writeFile(sourceMapPath, formattedSourceMap, { encoding: 'utf8' });\n debug(`${logPrefix} - Wrote source map to: \"${sourceMapPath}\"`);\n\n // Also write WASM binary for inspection\n const wasmPath = sourceMapPath.replace('.map', '.wasm');\n writeFile(wasmPath, cleanBinary);\n debug(`${logPrefix} - Wrote WASM binary to: \"${wasmPath}\"`);\n }\n\n // Instrument binary for coverage if requested and available\n if (options.shouldInstrument && nativeAddon) {\n throwPoolErrorIfAborted(signal);\n\n const instrumentStart = performance.now();\n const wasmBuffer = Buffer.from(cleanBinary);\n const sourceMapBuffer = Buffer.from(wasmSourceMap);\n\n const instrumentResult = nativeAddon.instrumentForCoverage(wasmBuffer, sourceMapBuffer, options.instrumentationOptions!, logModule, logLabel);\n const instCount = instrumentResult.debugInfo.instrumentedFunctionCount;\n\n const instrumentEnd = performance.now();\n debug(`${logPrefix} - TIMING Instrumented ${instCount} functions: ${(performance.now() - instrumentStart).toFixed(2)} ms`);\n\n return {\n binary: instrumentResult.instrumentedWasm,\n sourceMap: instrumentResult.sourceMap,\n debugInfo: instrumentResult.debugInfo,\n isInstrumented: true,\n compileTiming: instrumentEnd - compileStart,\n };\n }\n\n // No instrumentation requested\n return {\n binary: cleanBinary,\n sourceMap: wasmSourceMap,\n isInstrumented: false,\n compileTiming: performance.now() - compileStart,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,36 @@
|
|
|
1
|
-
import { AssemblyScriptPoolOptions, WasmImportsFactory, WasmImportsFactoryInfo } from "../types-
|
|
2
|
-
import "
|
|
1
|
+
import { AssemblyScriptPoolOptions, HybridProviderOptions, WasmImportsFactory, WasmImportsFactoryInfo } from "../types-DHVk5iAx.mjs";
|
|
2
|
+
import { CoverageV8Options } from "vitest/node";
|
|
3
3
|
import { ConfigEnv, UserWorkspaceConfig, ViteUserConfig } from "vitest/config";
|
|
4
4
|
|
|
5
|
+
//#region src/config/custom-provider-options-v3.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Module augmentation for vitest 3.x — augments `CustomProviderOptions`.
|
|
8
|
+
*
|
|
9
|
+
* In v3, `CoverageOptions` is a generic type alias and cannot be augmented
|
|
10
|
+
* via TypeScript declaration merging (a type alias and an interface with the
|
|
11
|
+
* same name in the same scope produces `Duplicate identifier`). The only
|
|
12
|
+
* augmentation point that's an interface in both v3 and v4 is
|
|
13
|
+
* `CustomProviderOptions`, so the v3 entry uses that.
|
|
14
|
+
*
|
|
15
|
+
* v3's native `CustomProviderOptions` is also very narrow (only fields with
|
|
16
|
+
* defaults plus `customProviderModule`), so this augmentation widens it via
|
|
17
|
+
* `Omit<CoverageV8Options, 'provider'>` to give v3 users full coverage
|
|
18
|
+
* configuration typing alongside the AssemblyScript-specific fields from
|
|
19
|
+
* `HybridProviderOptions`.
|
|
20
|
+
*
|
|
21
|
+
* Loaded as a side-effect import from `./index-v3.ts` (the v3 config entry
|
|
22
|
+
* point) so it only takes effect for users who explicitly import the v3
|
|
23
|
+
* entry. v4 users get the equivalent typing from `./coverage-options.ts`,
|
|
24
|
+
* which augments `CoverageOptions` directly.
|
|
25
|
+
*/
|
|
26
|
+
declare module "vitest/node" {
|
|
27
|
+
interface CustomProviderOptions extends HybridProviderOptions, Omit<CoverageV8Options, "provider"> {
|
|
28
|
+
provider: "custom";
|
|
29
|
+
/** Name of the module or path to a file to load the custom provider from */
|
|
30
|
+
customProviderModule: string;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
5
34
|
//#region src/config/config-helpers-v3.d.ts
|
|
6
35
|
/**
|
|
7
36
|
* AssemblyScript pool configuration with proper typing for poolOptions
|
|
@@ -14,7 +43,8 @@ import { ConfigEnv, UserWorkspaceConfig, ViteUserConfig } from "vitest/config";
|
|
|
14
43
|
* use type intersection to add poolOptions.assemblyScript typing.
|
|
15
44
|
*
|
|
16
45
|
* Note: Coverage is NOT included here because it's global-only config in Vitest.
|
|
17
|
-
* Coverage typing comes from the CustomProviderOptions augmentation
|
|
46
|
+
* Coverage typing comes from the `CustomProviderOptions` augmentation loaded
|
|
47
|
+
* via the `./index-v3.ts` side-effect import.
|
|
18
48
|
*/
|
|
19
49
|
type AssemblyScriptUserConfig<T extends ViteUserConfig> = T & {
|
|
20
50
|
test?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-v3.d.mts","names":[],"sources":["../../src/config/config-helpers-v3.ts"],"mappings":";;;;;;;;;;;;;;;;;;
|
|
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"}
|