@quenty/nevermore-cli 4.50.0 → 4.50.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.
- package/CHANGELOG.md +6 -0
- package/dist/commands/tools-command/ci-post-test-results.d.ts.map +1 -1
- package/dist/commands/tools-command/ci-post-test-results.js +7 -3
- package/dist/commands/tools-command/ci-post-test-results.js.map +1 -1
- package/dist/utils/batch/changed-packages-utils.d.ts +8 -0
- package/dist/utils/batch/changed-packages-utils.d.ts.map +1 -1
- package/dist/utils/batch/changed-packages-utils.js +9 -11
- package/dist/utils/batch/changed-packages-utils.js.map +1 -1
- package/dist/utils/testing/parsers/annotation-workspace.d.ts +17 -0
- package/dist/utils/testing/parsers/annotation-workspace.d.ts.map +1 -0
- package/dist/utils/testing/parsers/annotation-workspace.js +47 -0
- package/dist/utils/testing/parsers/annotation-workspace.js.map +1 -0
- package/dist/utils/testing/parsers/index.d.ts +0 -1
- package/dist/utils/testing/parsers/index.d.ts.map +1 -1
- package/dist/utils/testing/parsers/index.js +0 -1
- package/dist/utils/testing/parsers/index.js.map +1 -1
- package/dist/utils/testing/parsers/jest-lua-parser.d.ts +14 -29
- package/dist/utils/testing/parsers/jest-lua-parser.d.ts.map +1 -1
- package/dist/utils/testing/parsers/jest-lua-parser.js +85 -100
- package/dist/utils/testing/parsers/jest-lua-parser.js.map +1 -1
- package/dist/utils/testing/parsers/jest-lua-parser.test.js +359 -56
- package/dist/utils/testing/parsers/jest-lua-parser.test.js.map +1 -1
- package/dist/utils/testing/parsers/roblox-path-resolver.d.ts +23 -17
- package/dist/utils/testing/parsers/roblox-path-resolver.d.ts.map +1 -1
- package/dist/utils/testing/parsers/roblox-path-resolver.js +89 -54
- package/dist/utils/testing/parsers/roblox-path-resolver.js.map +1 -1
- package/dist/utils/testing/parsers/roblox-path-resolver.test.js +76 -36
- package/dist/utils/testing/parsers/roblox-path-resolver.test.js.map +1 -1
- package/dist/utils/testing/runner/combined-project-generator.d.ts.map +1 -1
- package/dist/utils/testing/runner/combined-project-generator.js +5 -6
- package/dist/utils/testing/runner/combined-project-generator.js.map +1 -1
- package/dist/utils/testing/runner/test-project-slug.d.ts +11 -0
- package/dist/utils/testing/runner/test-project-slug.d.ts.map +1 -0
- package/dist/utils/testing/runner/test-project-slug.js +11 -0
- package/dist/utils/testing/runner/test-project-slug.js.map +1 -0
- package/package.json +6 -6
- package/src/commands/tools-command/ci-post-test-results.ts +7 -2
- package/src/utils/batch/changed-packages-utils.ts +21 -12
- package/src/utils/testing/parsers/annotation-workspace.ts +74 -0
- package/src/utils/testing/parsers/index.ts +0 -1
- package/src/utils/testing/parsers/jest-lua-parser.test.ts +433 -65
- package/src/utils/testing/parsers/jest-lua-parser.ts +131 -109
- package/src/utils/testing/parsers/roblox-path-resolver.test.ts +144 -61
- package/src/utils/testing/parsers/roblox-path-resolver.ts +117 -56
- package/src/utils/testing/runner/combined-project-generator.ts +9 -13
- package/src/utils/testing/runner/test-project-slug.ts +18 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [4.50.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/nevermore-cli@4.50.0...@quenty/nevermore-cli@4.50.1) (2026-11-02)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **nevermore-cli:** resolve test failure annotations to real files ([#853](https://github.com/Quenty/NevermoreEngine/issues/853)) ([aa52794](https://github.com/Quenty/NevermoreEngine/commit/aa5279471baa0877e72b6ee75d89f722a5dc5505))
|
|
11
|
+
|
|
6
12
|
# [4.50.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/nevermore-cli@4.49.0...@quenty/nevermore-cli@4.50.0) (2026-10-28)
|
|
7
13
|
|
|
8
14
|
### Features
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-post-test-results.d.ts","sourceRoot":"","sources":["../../../src/commands/tools-command/ci-post-test-results.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ci-post-test-results.d.ts","sourceRoot":"","sources":["../../../src/commands/tools-command/ci-post-test-results.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAQtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAkBhE,UAAU,qBAAsB,SAAQ,mBAAmB;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAClD,mBAAmB,EACnB,qBAAqB,CAuFtB,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
2
|
-
import { emitAnnotations, writeAnnotationSummaryAsync, } from '@quenty/cli-output-helpers/reporting';
|
|
2
|
+
import { dedupeDiagnostics, emitAnnotations, writeAnnotationSummaryAsync, } from '@quenty/cli-output-helpers/reporting';
|
|
3
3
|
import { GithubCommentTableReporter, GithubJobSummaryReporter, LoadedStateTracker, createTestCommentConfig, } from '../../utils/testing/reporting/index.js';
|
|
4
4
|
import { parseJestLuaOutput } from '../../utils/testing/parsers/index.js';
|
|
5
5
|
import { tryLoadSourcemapResolver } from '../../utils/sourcemap/index.js';
|
|
6
|
+
import { tryLoadAnnotationWorkspaceAsync } from '../../utils/testing/parsers/annotation-workspace.js';
|
|
6
7
|
/** Create the standard set of GitHub reporters for posting results. */
|
|
7
8
|
function _createGithubReporters(state, concurrency) {
|
|
8
9
|
const config = createTestCommentConfig();
|
|
@@ -56,14 +57,17 @@ export const ciPostTestResultsCommand = {
|
|
|
56
57
|
}
|
|
57
58
|
// Emit test failure annotations
|
|
58
59
|
const sourcemapResolver = tryLoadSourcemapResolver(process.cwd());
|
|
59
|
-
const
|
|
60
|
+
const workspace = await tryLoadAnnotationWorkspaceAsync(process.cwd());
|
|
61
|
+
const parsedDiagnostics = [];
|
|
60
62
|
for (const failure of state.getFailures()) {
|
|
61
63
|
const diagnostics = parseJestLuaOutput(failure.logs, {
|
|
62
64
|
packageName: failure.packageName,
|
|
63
65
|
sourcemapResolver,
|
|
66
|
+
workspace,
|
|
64
67
|
});
|
|
65
|
-
|
|
68
|
+
parsedDiagnostics.push(...diagnostics);
|
|
66
69
|
}
|
|
70
|
+
const allDiagnostics = dedupeDiagnostics(parsedDiagnostics);
|
|
67
71
|
if (allDiagnostics.length > 0) {
|
|
68
72
|
OutputHelper.info(`Found ${allDiagnostics.length} test failure(s). Emitting annotations...`);
|
|
69
73
|
emitAnnotations(allDiagnostics);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-post-test-results.js","sourceRoot":"","sources":["../../../src/commands/tools-command/ci-post-test-results.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAEL,eAAe,EACf,2BAA2B,GAC5B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAGL,0BAA0B,EAC1B,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"ci-post-test-results.js","sourceRoot":"","sources":["../../../src/commands/tools-command/ci-post-test-results.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { DeployTarget, ManifestPlaceInfo } from '@quenty/nevermore-deploy';
|
|
2
|
+
export interface WorkspacePackageInfo {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
}
|
|
2
6
|
export interface TargetPackage {
|
|
3
7
|
name: string;
|
|
4
8
|
path: string;
|
|
@@ -35,6 +39,8 @@ export interface BatchTarget {
|
|
|
35
39
|
* Discover all packages that have a deploy.nevermore.json with the given target.
|
|
36
40
|
*/
|
|
37
41
|
export declare function discoverAllTargetPackagesAsync(targetName: string): Promise<TargetPackage[]>;
|
|
42
|
+
/** Every package in the pnpm workspace, with absolute paths. */
|
|
43
|
+
export declare function listWorkspacePackagesAsync(cwd?: string): Promise<WorkspacePackageInfo[]>;
|
|
38
44
|
/**
|
|
39
45
|
* Discover packages with the given target that have changed since `baseBranch`.
|
|
40
46
|
* Uses pnpm's --filter "...[<base>]" to include transitive dependents.
|
|
@@ -57,4 +63,6 @@ export declare function discoverChangedTestableBatchTargetsAsync(baseBranch: str
|
|
|
57
63
|
* multi-place package produces one per place, with ` - <place.name>` suffix.
|
|
58
64
|
*/
|
|
59
65
|
export declare function flattenToBatchTargets(packages: TargetPackage[]): BatchTarget[];
|
|
66
|
+
/** Keep the packages whose deploy config has `targetName`, with its places. */
|
|
67
|
+
export declare function filterByTargetAsync(packages: WorkspacePackageInfo[], targetName: string): Promise<TargetPackage[]>;
|
|
60
68
|
//# sourceMappingURL=changed-packages-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changed-packages-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/batch/changed-packages-utils.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,iBAAiB,EAKlB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,MAAM,EAAE,YAAY,CAAC;IACrB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,wBAAsB,8BAA8B,CAClD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"changed-packages-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/batch/changed-packages-utils.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,iBAAiB,EAKlB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,MAAM,EAAE,YAAY,CAAC;IACrB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,wBAAsB,8BAA8B,CAClD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,CAE1B;AAED,gEAAgE;AAChE,wBAAsB,0BAA0B,CAC9C,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAOjC;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,CAwB1B;AAED;;;GAGG;AACH,wBAAsB,oCAAoC,IAAI,OAAO,CACnE,WAAW,EAAE,CACd,CAGA;AAED;;;;GAIG;AACH,wBAAsB,wCAAwC,CAC5D,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAGxB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,aAAa,EAAE,GACxB,WAAW,EAAE,CA2Bf;AA6BD,+EAA+E;AAC/E,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,oBAAoB,EAAE,EAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,CAyC1B"}
|
|
@@ -6,15 +6,12 @@ import { loadDeployConfigAsync, resolveDeployConfigPath, resolveDeployTargetPlac
|
|
|
6
6
|
* Discover all packages that have a deploy.nevermore.json with the given target.
|
|
7
7
|
*/
|
|
8
8
|
export async function discoverAllTargetPackagesAsync(targetName) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
]);
|
|
16
|
-
const packages = JSON.parse(stdout);
|
|
17
|
-
return _filterByTargetAsync(packages, targetName);
|
|
9
|
+
return filterByTargetAsync(await listWorkspacePackagesAsync(), targetName);
|
|
10
|
+
}
|
|
11
|
+
/** Every package in the pnpm workspace, with absolute paths. */
|
|
12
|
+
export async function listWorkspacePackagesAsync(cwd) {
|
|
13
|
+
const { stdout } = await execa('pnpm', ['ls', '--json', '-r', '--depth', '-1'], { cwd });
|
|
14
|
+
return JSON.parse(stdout);
|
|
18
15
|
}
|
|
19
16
|
/**
|
|
20
17
|
* Discover packages with the given target that have changed since `baseBranch`.
|
|
@@ -41,7 +38,7 @@ export async function discoverChangedTargetPackagesAsync(baseBranch, targetName)
|
|
|
41
38
|
if (!Array.isArray(packages) || packages.length === 0) {
|
|
42
39
|
return [];
|
|
43
40
|
}
|
|
44
|
-
return
|
|
41
|
+
return filterByTargetAsync(packages, targetName);
|
|
45
42
|
}
|
|
46
43
|
/**
|
|
47
44
|
* Discover all packages that have a deploy.nevermore.json with a "test" target
|
|
@@ -113,7 +110,8 @@ function _requireScriptTemplate(targets) {
|
|
|
113
110
|
}
|
|
114
111
|
return withTemplate;
|
|
115
112
|
}
|
|
116
|
-
|
|
113
|
+
/** Keep the packages whose deploy config has `targetName`, with its places. */
|
|
114
|
+
export async function filterByTargetAsync(packages, targetName) {
|
|
117
115
|
const results = [];
|
|
118
116
|
const skippedNoConfig = [];
|
|
119
117
|
const skippedNoTarget = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changed-packages-utils.js","sourceRoot":"","sources":["../../../src/utils/batch/changed-packages-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAGL,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"changed-packages-utils.js","sourceRoot":"","sources":["../../../src/utils/batch/changed-packages-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface AnnotationWorkspacePackage {
|
|
2
|
+
/** Repo-relative POSIX directory, e.g. `src/player-mock` */
|
|
3
|
+
dir: string;
|
|
4
|
+
/** Rojo project name, which the sourcemap uses */
|
|
5
|
+
projectName?: string;
|
|
6
|
+
/** Instance names the package gets in its test places */
|
|
7
|
+
testSlugs: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface AnnotationWorkspace {
|
|
10
|
+
packagesByName: Map<string, AnnotationWorkspacePackage>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Index the pnpm workspace for mapping test output back to files. Returns
|
|
14
|
+
* `undefined` when the workspace can't be listed.
|
|
15
|
+
*/
|
|
16
|
+
export declare function tryLoadAnnotationWorkspaceAsync(repoRoot: string): Promise<AnnotationWorkspace | undefined>;
|
|
17
|
+
//# sourceMappingURL=annotation-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotation-workspace.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/annotation-workspace.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,0BAA0B;IACzC,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;CACzD;AAED;;;GAGG;AACH,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAmC1C"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { filterByTargetAsync, listWorkspacePackagesAsync, } from '../../batch/changed-packages-utils.js';
|
|
4
|
+
import { findTestProjectSlug, } from '../runner/test-project-slug.js';
|
|
5
|
+
/**
|
|
6
|
+
* Index the pnpm workspace for mapping test output back to files. Returns
|
|
7
|
+
* `undefined` when the workspace can't be listed.
|
|
8
|
+
*/
|
|
9
|
+
export async function tryLoadAnnotationWorkspaceAsync(repoRoot) {
|
|
10
|
+
let packages;
|
|
11
|
+
try {
|
|
12
|
+
packages = await listWorkspacePackagesAsync(repoRoot);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const packagesByName = new Map();
|
|
18
|
+
await Promise.all(packages.map(async (pkg) => {
|
|
19
|
+
const project = await _tryReadJsonAsync(path.join(pkg.path, 'default.project.json'));
|
|
20
|
+
packagesByName.set(pkg.name, {
|
|
21
|
+
dir: path.relative(repoRoot, pkg.path).replace(/\\/g, '/'),
|
|
22
|
+
projectName: project?.name,
|
|
23
|
+
testSlugs: [],
|
|
24
|
+
});
|
|
25
|
+
}));
|
|
26
|
+
for (const testPackage of await filterByTargetAsync(packages, 'test')) {
|
|
27
|
+
const entry = packagesByName.get(testPackage.name);
|
|
28
|
+
if (!entry)
|
|
29
|
+
continue;
|
|
30
|
+
for (const target of testPackage.activeTargets) {
|
|
31
|
+
const project = await _tryReadJsonAsync(path.resolve(testPackage.path, target.project));
|
|
32
|
+
const slug = project && findTestProjectSlug(project);
|
|
33
|
+
if (slug && !entry.testSlugs.includes(slug))
|
|
34
|
+
entry.testSlugs.push(slug);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { packagesByName };
|
|
38
|
+
}
|
|
39
|
+
async function _tryReadJsonAsync(filePath) {
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(await fs.readFile(filePath, 'utf-8'));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=annotation-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotation-workspace.js","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/annotation-workspace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAEL,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AAexC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,QAAgB;IAEhB,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsC,CAAC;IACrE,MAAM,OAAO,CAAC,GAAG,CACf,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,MAAM,iBAAiB,CACrC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAC5C,CAAC;QACF,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE;YAC3B,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;YAC1D,WAAW,EAAE,OAAO,EAAE,IAAI;YAC1B,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;IAEF,KAAK,MAAM,WAAW,IAAI,MAAM,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,iBAAiB,CACrC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAC/C,CAAC;YACF,MAAM,IAAI,GAAG,OAAO,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;YACrD,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAI,QAAgB;IAClD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAM,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,41 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Parser for Jest-lua verbose output (`verbose=true, ci=true`).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* ● ObservableList > add and remove > should track count
|
|
9
|
-
*
|
|
10
|
-
* expect(received).toEqual(expected)
|
|
11
|
-
*
|
|
12
|
-
* Expected: 3
|
|
13
|
-
* Received: 2
|
|
14
|
-
*
|
|
15
|
-
* at ServerScriptService.observablecollection.Shared.ObservableList.spec:45
|
|
16
|
-
* ```
|
|
17
|
-
*
|
|
18
|
-
* 2. **Runtime errors** — `Stack Begin`/`Stack End` blocks:
|
|
19
|
-
* ```
|
|
20
|
-
* Error: attempt to index nil with "Connect"
|
|
21
|
-
* Stack Begin
|
|
22
|
-
* Script 'ServerScriptService.maid.Shared.Maid.spec', Line 23
|
|
23
|
-
* Stack End
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* The parser is intentionally lenient — it extracts what it can, skips what
|
|
27
|
-
* it can't, and never crashes on unexpected input.
|
|
4
|
+
* Emits one diagnostic per `●` failure block and per `Stack Begin`/`Stack End`
|
|
5
|
+
* runtime error, at the innermost frame that resolves to a repo file,
|
|
6
|
+
* preferring the package under test. Diagnostics with no resolvable frame
|
|
7
|
+
* carry no file. Unexpected input is skipped, never thrown on.
|
|
28
8
|
*/
|
|
29
9
|
import { type Diagnostic } from '@quenty/cli-output-helpers/reporting';
|
|
30
10
|
import type { SourcemapResolver } from '../../sourcemap/index.js';
|
|
11
|
+
import type { AnnotationWorkspace } from './annotation-workspace.js';
|
|
12
|
+
export interface JestLuaParseOptions {
|
|
13
|
+
/** npm name of the package under test, e.g. `@quenty/saveslot`. */
|
|
14
|
+
packageName: string;
|
|
15
|
+
sourcemapResolver?: SourcemapResolver;
|
|
16
|
+
workspace?: AnnotationWorkspace;
|
|
17
|
+
/** Repo root that holds the workspace. Defaults to cwd. */
|
|
18
|
+
repoRoot?: string;
|
|
19
|
+
}
|
|
31
20
|
/**
|
|
32
21
|
* Parse Jest-lua verbose output into `Diagnostic[]`.
|
|
33
22
|
*
|
|
34
23
|
* @param raw - Raw test output (may include ANSI codes)
|
|
35
|
-
* @param options.packageName - Package name for fallback path resolution
|
|
36
24
|
*/
|
|
37
|
-
export declare function parseJestLuaOutput(raw: string, options:
|
|
38
|
-
packageName: string;
|
|
39
|
-
sourcemapResolver?: SourcemapResolver;
|
|
40
|
-
}): Diagnostic[];
|
|
25
|
+
export declare function parseJestLuaOutput(raw: string, options: JestLuaParseOptions): Diagnostic[];
|
|
41
26
|
//# sourceMappingURL=jest-lua-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jest-lua-parser.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/jest-lua-parser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"jest-lua-parser.d.ts","sourceRoot":"","sources":["../../../../src/utils/testing/parsers/jest-lua-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAkDrE,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA8DD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,mBAAmB,GAC3B,UAAU,EAAE,CAgKd"}
|
|
@@ -1,47 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Parser for Jest-lua verbose output (`verbose=true, ci=true`).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* ● ObservableList > add and remove > should track count
|
|
9
|
-
*
|
|
10
|
-
* expect(received).toEqual(expected)
|
|
11
|
-
*
|
|
12
|
-
* Expected: 3
|
|
13
|
-
* Received: 2
|
|
14
|
-
*
|
|
15
|
-
* at ServerScriptService.observablecollection.Shared.ObservableList.spec:45
|
|
16
|
-
* ```
|
|
17
|
-
*
|
|
18
|
-
* 2. **Runtime errors** — `Stack Begin`/`Stack End` blocks:
|
|
19
|
-
* ```
|
|
20
|
-
* Error: attempt to index nil with "Connect"
|
|
21
|
-
* Stack Begin
|
|
22
|
-
* Script 'ServerScriptService.maid.Shared.Maid.spec', Line 23
|
|
23
|
-
* Stack End
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* The parser is intentionally lenient — it extracts what it can, skips what
|
|
27
|
-
* it can't, and never crashes on unexpected input.
|
|
4
|
+
* Emits one diagnostic per `●` failure block and per `Stack Begin`/`Stack End`
|
|
5
|
+
* runtime error, at the innermost frame that resolves to a repo file,
|
|
6
|
+
* preferring the package under test. Diagnostics with no resolvable frame
|
|
7
|
+
* carry no file. Unexpected input is skipped, never thrown on.
|
|
28
8
|
*/
|
|
29
9
|
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
30
11
|
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
31
|
-
import {
|
|
32
|
-
/**
|
|
33
|
-
const
|
|
34
|
-
/**
|
|
35
|
-
const
|
|
36
|
-
/**
|
|
37
|
-
const
|
|
38
|
-
/**
|
|
12
|
+
import { tryResolveRobloxSourceFile } from './roblox-path-resolver.js';
|
|
13
|
+
/** `at ServerScriptService.pkg.Path.spec:45`, line optional */
|
|
14
|
+
const AT_FRAME_PATTERN = /^\s+at\s+(\S+?)(?::(\d+))?\s*$/;
|
|
15
|
+
/** `ServerScriptService.pkg.Path:1263 function requireModule`, any service root */
|
|
16
|
+
const BARE_FRAME_PATTERN = /^\s+(\[string "[^"]+"\]|[A-Za-z_][\w-]*(?:\.[^\s:"]+)+):(\d+)(?:\s+function\s+\S+)?\s*$/;
|
|
17
|
+
/** `Script '[string "ServerScriptService.pkg.Path"]', Line 23` */
|
|
18
|
+
const SCRIPT_FRAME_PATTERN = /Script '(.+?)', Line (\d+)/;
|
|
19
|
+
/** `<chunk>:214:` location prefixes inside error messages */
|
|
20
|
+
const MESSAGE_LOCATION_PATTERN = /(\[string "[^"]+"\]|ServerScriptService\.[^\s:"]+):(\d+):/g;
|
|
21
|
+
/** `● TestSuite › nested › test name` */
|
|
39
22
|
const FAILURE_HEADER_PATTERN = /^\s*●\s+(.+)$/;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* Returns the 1-indexed line number, or `undefined` if not found.
|
|
43
|
-
*/
|
|
44
|
-
function _findTestLineInFile(filePath, testName) {
|
|
23
|
+
const TITLE_SEPARATOR_PATTERN = / [›>] /;
|
|
24
|
+
function _findTestLineInFile(filePath, title) {
|
|
45
25
|
let content;
|
|
46
26
|
try {
|
|
47
27
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
@@ -50,54 +30,67 @@ function _findTestLineInFile(filePath, testName) {
|
|
|
50
30
|
return undefined;
|
|
51
31
|
}
|
|
52
32
|
const lines = content.split('\n');
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
33
|
+
const names = title.split(TITLE_SEPARATOR_PATTERN).map((name) => name.trim());
|
|
34
|
+
for (const name of names.reverse()) {
|
|
35
|
+
const index = lines.findIndex((line) => line.includes(`("${name}"`) || line.includes(`('${name}'`));
|
|
36
|
+
if (index !== -1)
|
|
37
|
+
return index + 1;
|
|
58
38
|
}
|
|
59
39
|
return undefined;
|
|
60
40
|
}
|
|
41
|
+
function _parseFrameLine(rawLine) {
|
|
42
|
+
const match = rawLine.match(BARE_FRAME_PATTERN) ?? rawLine.match(AT_FRAME_PATTERN);
|
|
43
|
+
if (!match)
|
|
44
|
+
return undefined;
|
|
45
|
+
return {
|
|
46
|
+
instancePath: match[1],
|
|
47
|
+
line: match[2] ? parseInt(match[2], 10) : undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function _parseMessageLocations(message) {
|
|
51
|
+
return [...message.matchAll(MESSAGE_LOCATION_PATTERN)].map((match) => ({
|
|
52
|
+
instancePath: match[1],
|
|
53
|
+
line: parseInt(match[2], 10),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
function _resolveLocation(frames, options) {
|
|
57
|
+
let fallback;
|
|
58
|
+
for (const frame of frames) {
|
|
59
|
+
const resolved = tryResolveRobloxSourceFile(frame.instancePath, options);
|
|
60
|
+
if (!resolved)
|
|
61
|
+
continue;
|
|
62
|
+
const location = { ...resolved, line: frame.line };
|
|
63
|
+
if (resolved.isPackageUnderTest) {
|
|
64
|
+
return location;
|
|
65
|
+
}
|
|
66
|
+
fallback ??= location;
|
|
67
|
+
}
|
|
68
|
+
return fallback;
|
|
69
|
+
}
|
|
61
70
|
/**
|
|
62
71
|
* Parse Jest-lua verbose output into `Diagnostic[]`.
|
|
63
72
|
*
|
|
64
73
|
* @param raw - Raw test output (may include ANSI codes)
|
|
65
|
-
* @param options.packageName - Package name for fallback path resolution
|
|
66
74
|
*/
|
|
67
75
|
export function parseJestLuaOutput(raw, options) {
|
|
68
76
|
const diagnostics = [];
|
|
69
77
|
const clean = OutputHelper.stripAnsi(raw);
|
|
70
78
|
const lines = clean.split('\n');
|
|
79
|
+
const repoRoot = options.repoRoot ?? process.cwd();
|
|
71
80
|
let state = 0 /* State.IDLE */;
|
|
72
81
|
let failureCtx;
|
|
73
82
|
let stackCtx;
|
|
74
83
|
let lastNonEmptyLine = '';
|
|
75
84
|
function _emitFailure(ctx) {
|
|
76
85
|
const message = ctx.messageLines.join('\n').trim();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
let file;
|
|
82
|
-
let line;
|
|
83
|
-
if (ctx.file) {
|
|
84
|
-
file = resolveRobloxTestPath(ctx.file, options.sourcemapResolver);
|
|
85
|
-
if (ctx.line) {
|
|
86
|
-
line = ctx.line;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
const segments = ctx.title.split(' > ');
|
|
90
|
-
const testName = segments[segments.length - 1].trim();
|
|
91
|
-
line = _findTestLineInFile(file, testName) ?? 1;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
file = `src/${options.packageName}/src`;
|
|
96
|
-
line = 1;
|
|
86
|
+
const location = _resolveLocation([...ctx.frames, ..._parseMessageLocations(message)], options);
|
|
87
|
+
let line = location?.line;
|
|
88
|
+
if (location?.isPackageUnderTest && line === undefined) {
|
|
89
|
+
line = _findTestLineInFile(path.join(repoRoot, location.file), ctx.title);
|
|
97
90
|
}
|
|
98
91
|
diagnostics.push({
|
|
99
|
-
file,
|
|
100
|
-
line,
|
|
92
|
+
...(location ? { file: location.file } : {}),
|
|
93
|
+
...(line !== undefined ? { line } : {}),
|
|
101
94
|
severity: 'error',
|
|
102
95
|
title: ctx.title,
|
|
103
96
|
message: message || 'Test failed',
|
|
@@ -105,20 +98,17 @@ export function parseJestLuaOutput(raw, options) {
|
|
|
105
98
|
});
|
|
106
99
|
}
|
|
107
100
|
function _emitStack(ctx) {
|
|
108
|
-
const
|
|
109
|
-
? resolveRobloxTestPath(ctx.file, options.sourcemapResolver)
|
|
110
|
-
: `src/${options.packageName}/src`;
|
|
111
|
-
const line = ctx.line ?? 1;
|
|
101
|
+
const location = _resolveLocation([...ctx.frames, ..._parseMessageLocations(ctx.errorMessage)], options);
|
|
112
102
|
diagnostics.push({
|
|
113
|
-
file,
|
|
114
|
-
line,
|
|
103
|
+
...(location ? { file: location.file, line: location.line ?? 1 } : {}),
|
|
115
104
|
severity: 'error',
|
|
116
105
|
title: 'Runtime error',
|
|
117
106
|
message: ctx.errorMessage || 'Unknown runtime error',
|
|
118
107
|
source: 'jest-lua',
|
|
119
108
|
});
|
|
120
109
|
}
|
|
121
|
-
for (
|
|
110
|
+
for (let i = 0; i < lines.length; i++) {
|
|
111
|
+
const rawLine = lines[i];
|
|
122
112
|
switch (state) {
|
|
123
113
|
case 0 /* State.IDLE */: {
|
|
124
114
|
const failureMatch = rawLine.match(FAILURE_HEADER_PATTERN);
|
|
@@ -126,6 +116,7 @@ export function parseJestLuaOutput(raw, options) {
|
|
|
126
116
|
failureCtx = {
|
|
127
117
|
title: failureMatch[1].trim(),
|
|
128
118
|
messageLines: [],
|
|
119
|
+
frames: [],
|
|
129
120
|
};
|
|
130
121
|
state = 1 /* State.FAILURE_BLOCK */;
|
|
131
122
|
break;
|
|
@@ -133,6 +124,7 @@ export function parseJestLuaOutput(raw, options) {
|
|
|
133
124
|
if (rawLine.trim() === 'Stack Begin') {
|
|
134
125
|
stackCtx = {
|
|
135
126
|
errorMessage: lastNonEmptyLine,
|
|
127
|
+
frames: [],
|
|
136
128
|
};
|
|
137
129
|
state = 2 /* State.STACK_BLOCK */;
|
|
138
130
|
break;
|
|
@@ -147,30 +139,9 @@ export function parseJestLuaOutput(raw, options) {
|
|
|
147
139
|
state = 0 /* State.IDLE */;
|
|
148
140
|
break;
|
|
149
141
|
}
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
failureCtx.
|
|
153
|
-
failureCtx.line = parseInt(atMatch[2], 10);
|
|
154
|
-
_emitFailure(failureCtx);
|
|
155
|
-
failureCtx = undefined;
|
|
156
|
-
state = 0 /* State.IDLE */;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
const atNoLineMatch = rawLine.match(AT_LOCATION_NO_LINE_PATTERN);
|
|
160
|
-
if (atNoLineMatch) {
|
|
161
|
-
failureCtx.file = atNoLineMatch[1];
|
|
162
|
-
_emitFailure(failureCtx);
|
|
163
|
-
failureCtx = undefined;
|
|
164
|
-
state = 0 /* State.IDLE */;
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
const nextFailure = rawLine.match(FAILURE_HEADER_PATTERN);
|
|
168
|
-
if (nextFailure) {
|
|
169
|
-
_emitFailure(failureCtx);
|
|
170
|
-
failureCtx = {
|
|
171
|
-
title: nextFailure[1].trim(),
|
|
172
|
-
messageLines: [],
|
|
173
|
-
};
|
|
142
|
+
const frame = _parseFrameLine(rawLine);
|
|
143
|
+
if (frame) {
|
|
144
|
+
failureCtx.frames.push(frame);
|
|
174
145
|
break;
|
|
175
146
|
}
|
|
176
147
|
if (rawLine.trim() === 'Stack Begin') {
|
|
@@ -179,12 +150,24 @@ export function parseJestLuaOutput(raw, options) {
|
|
|
179
150
|
errorMessage: failureCtx.messageLines.length > 0
|
|
180
151
|
? failureCtx.messageLines[failureCtx.messageLines.length - 1].trim()
|
|
181
152
|
: failureCtx.title,
|
|
153
|
+
frames: [],
|
|
182
154
|
};
|
|
183
155
|
failureCtx = undefined;
|
|
184
156
|
state = 2 /* State.STACK_BLOCK */;
|
|
185
157
|
break;
|
|
186
158
|
}
|
|
187
|
-
|
|
159
|
+
const endsBlock = FAILURE_HEADER_PATTERN.test(rawLine) ||
|
|
160
|
+
(failureCtx.frames.length > 0 && rawLine.trim() !== '');
|
|
161
|
+
if (endsBlock) {
|
|
162
|
+
_emitFailure(failureCtx);
|
|
163
|
+
failureCtx = undefined;
|
|
164
|
+
state = 0 /* State.IDLE */;
|
|
165
|
+
i--;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
if (failureCtx.frames.length === 0) {
|
|
169
|
+
failureCtx.messageLines.push(rawLine);
|
|
170
|
+
}
|
|
188
171
|
break;
|
|
189
172
|
}
|
|
190
173
|
case 2 /* State.STACK_BLOCK */: {
|
|
@@ -192,10 +175,12 @@ export function parseJestLuaOutput(raw, options) {
|
|
|
192
175
|
state = 0 /* State.IDLE */;
|
|
193
176
|
break;
|
|
194
177
|
}
|
|
195
|
-
const scriptMatch = rawLine.match(
|
|
178
|
+
const scriptMatch = rawLine.match(SCRIPT_FRAME_PATTERN);
|
|
196
179
|
if (scriptMatch) {
|
|
197
|
-
stackCtx.
|
|
198
|
-
|
|
180
|
+
stackCtx.frames.push({
|
|
181
|
+
instancePath: scriptMatch[1],
|
|
182
|
+
line: parseInt(scriptMatch[2], 10),
|
|
183
|
+
});
|
|
199
184
|
break;
|
|
200
185
|
}
|
|
201
186
|
if (rawLine.trim() === 'Stack End') {
|