@molecule/api-ai-tools 1.16.2 → 1.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +197 -136
- package/dist/browser-probe.d.ts.map +1 -1
- package/dist/browser-probe.js +1 -211
- package/dist/source-code.d.ts +17 -0
- package/dist/source-code.d.ts.map +1 -0
- package/dist/source-code.js +214 -0
- package/dist/suite-overlap.d.ts +24 -0
- package/dist/suite-overlap.d.ts.map +1 -1
- package/dist/suite-overlap.js +53 -17
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +3 -7
- package/dist/trace-artifacts.d.ts +6 -0
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +196 -106
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +8 -22
- package/package.json +1 -1
package/dist/browser-probe.js
CHANGED
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
*
|
|
37
37
|
* @module
|
|
38
38
|
*/
|
|
39
|
+
import { codeWithModuleSpecifiers as codeOnly } from './source-code.js';
|
|
39
40
|
/** A `const|let|var <name> = await [qualifier.]chromium|firefox|webkit.launch(` binding. */
|
|
40
41
|
const LAUNCH = /(?<![\w$.])(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=\n]+)?=\s*await\s+(?:([A-Za-z_$][\w$]*)\s*\.\s*)?(chromium|firefox|webkit)\s*\.\s*launch\s*\(/g;
|
|
41
42
|
/** A browser method that does not close the browser, so calling it leaves the handle alive. */
|
|
@@ -57,217 +58,6 @@ const ANY_CLEANUP = /\.\s*(?:close|disconnect|dispose)\s*\(|[A-Za-z_$][\w$]*\s*\
|
|
|
57
58
|
const CLEANUP_HINT = /cleanup|teardown|close|dispose|shutdown|quit/i;
|
|
58
59
|
/** The packages whose `chromium`/`firefox`/`webkit` export really launches a browser. */
|
|
59
60
|
const PLAYWRIGHT_PACKAGE = '(?:playwright-core|playwright|@playwright/test)';
|
|
60
|
-
/** The characters after which a `/` starts a regex literal rather than a division. */
|
|
61
|
-
const REGEX_AFTER = new Set([
|
|
62
|
-
'',
|
|
63
|
-
'(',
|
|
64
|
-
'[',
|
|
65
|
-
'{',
|
|
66
|
-
',',
|
|
67
|
-
';',
|
|
68
|
-
':',
|
|
69
|
-
'=',
|
|
70
|
-
'!',
|
|
71
|
-
'&',
|
|
72
|
-
'|',
|
|
73
|
-
'?',
|
|
74
|
-
'+',
|
|
75
|
-
'-',
|
|
76
|
-
'*',
|
|
77
|
-
'%',
|
|
78
|
-
'^',
|
|
79
|
-
'~',
|
|
80
|
-
'<',
|
|
81
|
-
'>',
|
|
82
|
-
'}',
|
|
83
|
-
]);
|
|
84
|
-
/**
|
|
85
|
-
* A source with every comment and every string, template and regex literal blanked to spaces,
|
|
86
|
-
* preserving offsets and newlines so a match's position still indexes the original source.
|
|
87
|
-
*
|
|
88
|
-
* A launch mentioned in prose is not a launch: a review proved scripts that only PRINT
|
|
89
|
-
* `const browser = await chromium.launch()` — in a string, a comment and a template literal — and
|
|
90
|
-
* a raw substring match refused all of them. Template `${…}` substitutions stay code (a `close()`
|
|
91
|
-
* written there is a real cleanup path), nested braces are tracked so the substitution's end is
|
|
92
|
-
* found, and regex literals are recognised by the token before them so a quote inside a character
|
|
93
|
-
* class cannot blank the rest of the file.
|
|
94
|
-
*
|
|
95
|
-
* @param source - The script's source.
|
|
96
|
-
* @returns The same text with literal/comment spans replaced by spaces.
|
|
97
|
-
*/
|
|
98
|
-
function codeOnly(source) {
|
|
99
|
-
const out = source.split('');
|
|
100
|
-
const blank = (from, to) => {
|
|
101
|
-
for (let i = from; i < to; i++)
|
|
102
|
-
if (out[i] !== '\n')
|
|
103
|
-
out[i] = ' ';
|
|
104
|
-
};
|
|
105
|
-
const stack = [{ mode: 'code', braces: 0 }];
|
|
106
|
-
const top = () => stack[stack.length - 1];
|
|
107
|
-
/** The last non-whitespace CODE character: decides whether a `/` opens a regex. */
|
|
108
|
-
let lastCode = '';
|
|
109
|
-
/** The last identifier word and the word being read — a module specifier follows `from`. */
|
|
110
|
-
let lastWord = '';
|
|
111
|
-
let word = '';
|
|
112
|
-
/** A specifier (`from 'playwright'`, `require('playwright')`) stays readable to provenance. */
|
|
113
|
-
const specifierAhead = () => lastWord === 'from' || lastWord === 'require' || lastWord === 'import';
|
|
114
|
-
let i = 0;
|
|
115
|
-
while (i < source.length) {
|
|
116
|
-
const frame = top();
|
|
117
|
-
const char = source[i] ?? '';
|
|
118
|
-
const next = source[i + 1];
|
|
119
|
-
if (frame.mode === 'code') {
|
|
120
|
-
if (char === '/' && next === '/') {
|
|
121
|
-
stack.push({ mode: 'line' });
|
|
122
|
-
blank(i, i + 2);
|
|
123
|
-
i += 2;
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (char === '/' && next === '*') {
|
|
127
|
-
stack.push({ mode: 'block' });
|
|
128
|
-
blank(i, i + 2);
|
|
129
|
-
i += 2;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (char === "'" || char === '"') {
|
|
133
|
-
stack.push({ mode: 'string', quote: char, keep: specifierAhead() });
|
|
134
|
-
if (!specifierAhead())
|
|
135
|
-
out[i] = ' ';
|
|
136
|
-
i += 1;
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
if (char === '`') {
|
|
140
|
-
stack.push({ mode: 'template' });
|
|
141
|
-
out[i] = ' ';
|
|
142
|
-
i += 1;
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
if (char === '/' && REGEX_AFTER.has(lastCode)) {
|
|
146
|
-
stack.push({ mode: 'regex', inClass: false });
|
|
147
|
-
out[i] = ' ';
|
|
148
|
-
i += 1;
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
if (frame.braces > 0) {
|
|
152
|
-
if (char === '{')
|
|
153
|
-
frame.braces += 1;
|
|
154
|
-
else if (char === '}') {
|
|
155
|
-
frame.braces -= 1;
|
|
156
|
-
if (frame.braces === 0) {
|
|
157
|
-
stack.pop();
|
|
158
|
-
out[i] = ' ';
|
|
159
|
-
i += 1;
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
if (/[\w$]/.test(char))
|
|
165
|
-
word += char;
|
|
166
|
-
else if (word !== '') {
|
|
167
|
-
lastWord = word;
|
|
168
|
-
word = '';
|
|
169
|
-
}
|
|
170
|
-
if (!/\s/.test(char))
|
|
171
|
-
lastCode = char;
|
|
172
|
-
i += 1;
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
if (frame.mode === 'line') {
|
|
176
|
-
if (char === '\n') {
|
|
177
|
-
stack.pop();
|
|
178
|
-
i += 1;
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
out[i] = ' ';
|
|
182
|
-
i += 1;
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
if (frame.mode === 'block') {
|
|
186
|
-
if (char === '*' && next === '/') {
|
|
187
|
-
blank(i, i + 2);
|
|
188
|
-
stack.pop();
|
|
189
|
-
i += 2;
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
if (char !== '\n')
|
|
193
|
-
out[i] = ' ';
|
|
194
|
-
i += 1;
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
if (frame.mode === 'string') {
|
|
198
|
-
if (char === '\\') {
|
|
199
|
-
if (!frame.keep)
|
|
200
|
-
blank(i, i + 2);
|
|
201
|
-
i += 2;
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
if (char === frame.quote) {
|
|
205
|
-
if (!frame.keep)
|
|
206
|
-
out[i] = ' ';
|
|
207
|
-
stack.pop();
|
|
208
|
-
// A string is an operand: the next `/` is division, not a regex.
|
|
209
|
-
lastCode = 'x';
|
|
210
|
-
i += 1;
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if (!frame.keep && char !== '\n')
|
|
214
|
-
out[i] = ' ';
|
|
215
|
-
i += 1;
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
if (frame.mode === 'template') {
|
|
219
|
-
if (char === '\\') {
|
|
220
|
-
blank(i, i + 2);
|
|
221
|
-
i += 2;
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
if (char === '`') {
|
|
225
|
-
out[i] = ' ';
|
|
226
|
-
stack.pop();
|
|
227
|
-
lastCode = 'x';
|
|
228
|
-
i += 1;
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
if (char === '$' && next === '{') {
|
|
232
|
-
// The substitution is code: keep it visible and track its closing brace.
|
|
233
|
-
blank(i, i + 2);
|
|
234
|
-
stack.push({ mode: 'code', braces: 1 });
|
|
235
|
-
lastCode = '{';
|
|
236
|
-
i += 2;
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
if (char !== '\n')
|
|
240
|
-
out[i] = ' ';
|
|
241
|
-
i += 1;
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
// Regex literal: blank it, honour escapes and character classes, then its flags.
|
|
245
|
-
if (char === '\\') {
|
|
246
|
-
blank(i, i + 2);
|
|
247
|
-
i += 2;
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
if (char === '[')
|
|
251
|
-
frame.inClass = true;
|
|
252
|
-
else if (char === ']')
|
|
253
|
-
frame.inClass = false;
|
|
254
|
-
else if (char === '/' && !frame.inClass) {
|
|
255
|
-
out[i] = ' ';
|
|
256
|
-
stack.pop();
|
|
257
|
-
lastCode = 'x';
|
|
258
|
-
i += 1;
|
|
259
|
-
while (i < source.length && /[a-z]/i.test(source[i] ?? '')) {
|
|
260
|
-
out[i] = ' ';
|
|
261
|
-
i += 1;
|
|
262
|
-
}
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
if (char !== '\n')
|
|
266
|
-
out[i] = ' ';
|
|
267
|
-
i += 1;
|
|
268
|
-
}
|
|
269
|
-
return out.join('');
|
|
270
|
-
}
|
|
271
61
|
/**
|
|
272
62
|
* How many `{ … }` blocks are open at one offset of the code-only text.
|
|
273
63
|
*
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Shared lexical masking for source inspection without executing a module. */
|
|
2
|
+
/**
|
|
3
|
+
* A source with every comment and every string, template and regex literal blanked to spaces,
|
|
4
|
+
* preserving offsets and newlines so a match's position still indexes the original source.
|
|
5
|
+
*
|
|
6
|
+
* A launch mentioned in prose is not a launch: a review proved scripts that only PRINT
|
|
7
|
+
* `const browser = await chromium.launch()` — in a string, a comment and a template literal — and
|
|
8
|
+
* a raw substring match refused all of them. Template `${…}` substitutions stay code (a `close()`
|
|
9
|
+
* written there is a real cleanup path), nested braces are tracked so the substitution's end is
|
|
10
|
+
* found, and regex literals are recognised by the token before them so a quote inside a character
|
|
11
|
+
* class cannot blank the rest of the file.
|
|
12
|
+
*
|
|
13
|
+
* @param source - The script's source.
|
|
14
|
+
* @returns The same text with literal/comment spans replaced by spaces.
|
|
15
|
+
*/
|
|
16
|
+
export declare function codeWithModuleSpecifiers(source: string): string;
|
|
17
|
+
//# sourceMappingURL=source-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-code.d.ts","sourceRoot":"","sources":["../src/source-code.ts"],"names":[],"mappings":"AAAA,+EAA+E;AA2B/E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAwK/D"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/** Shared lexical masking for source inspection without executing a module. */
|
|
2
|
+
/** The characters after which a `/` starts a regex literal rather than a division. */
|
|
3
|
+
const REGEX_AFTER = new Set([
|
|
4
|
+
'',
|
|
5
|
+
'(',
|
|
6
|
+
'[',
|
|
7
|
+
'{',
|
|
8
|
+
',',
|
|
9
|
+
';',
|
|
10
|
+
':',
|
|
11
|
+
'=',
|
|
12
|
+
'!',
|
|
13
|
+
'&',
|
|
14
|
+
'|',
|
|
15
|
+
'?',
|
|
16
|
+
'+',
|
|
17
|
+
'-',
|
|
18
|
+
'*',
|
|
19
|
+
'%',
|
|
20
|
+
'^',
|
|
21
|
+
'~',
|
|
22
|
+
'<',
|
|
23
|
+
'>',
|
|
24
|
+
'}',
|
|
25
|
+
]);
|
|
26
|
+
/**
|
|
27
|
+
* A source with every comment and every string, template and regex literal blanked to spaces,
|
|
28
|
+
* preserving offsets and newlines so a match's position still indexes the original source.
|
|
29
|
+
*
|
|
30
|
+
* A launch mentioned in prose is not a launch: a review proved scripts that only PRINT
|
|
31
|
+
* `const browser = await chromium.launch()` — in a string, a comment and a template literal — and
|
|
32
|
+
* a raw substring match refused all of them. Template `${…}` substitutions stay code (a `close()`
|
|
33
|
+
* written there is a real cleanup path), nested braces are tracked so the substitution's end is
|
|
34
|
+
* found, and regex literals are recognised by the token before them so a quote inside a character
|
|
35
|
+
* class cannot blank the rest of the file.
|
|
36
|
+
*
|
|
37
|
+
* @param source - The script's source.
|
|
38
|
+
* @returns The same text with literal/comment spans replaced by spaces.
|
|
39
|
+
*/
|
|
40
|
+
export function codeWithModuleSpecifiers(source) {
|
|
41
|
+
const out = source.split('');
|
|
42
|
+
const blank = (from, to) => {
|
|
43
|
+
for (let i = from; i < to; i++)
|
|
44
|
+
if (out[i] !== '\n')
|
|
45
|
+
out[i] = ' ';
|
|
46
|
+
};
|
|
47
|
+
const stack = [{ mode: 'code', braces: 0 }];
|
|
48
|
+
const top = () => stack[stack.length - 1];
|
|
49
|
+
/** The last non-whitespace CODE character: decides whether a `/` opens a regex. */
|
|
50
|
+
let lastCode = '';
|
|
51
|
+
/** The last identifier word and the word being read — a module specifier follows `from`. */
|
|
52
|
+
let lastWord = '';
|
|
53
|
+
let word = '';
|
|
54
|
+
/** A specifier (`from 'playwright'`, `require('playwright')`) stays readable to provenance. */
|
|
55
|
+
const specifierAhead = () => (lastWord === 'from' && lastCode === 'm') ||
|
|
56
|
+
(lastWord === 'import' && lastCode === 't') ||
|
|
57
|
+
((lastWord === 'require' || lastWord === 'import') && lastCode === '(');
|
|
58
|
+
let i = 0;
|
|
59
|
+
while (i < source.length) {
|
|
60
|
+
const frame = top();
|
|
61
|
+
const char = source[i] ?? '';
|
|
62
|
+
const next = source[i + 1];
|
|
63
|
+
if (frame.mode === 'code') {
|
|
64
|
+
if (char === '/' && next === '/') {
|
|
65
|
+
stack.push({ mode: 'line' });
|
|
66
|
+
blank(i, i + 2);
|
|
67
|
+
i += 2;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (char === '/' && next === '*') {
|
|
71
|
+
stack.push({ mode: 'block' });
|
|
72
|
+
blank(i, i + 2);
|
|
73
|
+
i += 2;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (char === "'" || char === '"') {
|
|
77
|
+
stack.push({ mode: 'string', quote: char, keep: specifierAhead() });
|
|
78
|
+
if (!specifierAhead())
|
|
79
|
+
out[i] = ' ';
|
|
80
|
+
i += 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (char === '`') {
|
|
84
|
+
stack.push({ mode: 'template' });
|
|
85
|
+
out[i] = ' ';
|
|
86
|
+
i += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (char === '/' && REGEX_AFTER.has(lastCode)) {
|
|
90
|
+
stack.push({ mode: 'regex', inClass: false });
|
|
91
|
+
out[i] = ' ';
|
|
92
|
+
i += 1;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (frame.braces > 0) {
|
|
96
|
+
if (char === '{')
|
|
97
|
+
frame.braces += 1;
|
|
98
|
+
else if (char === '}') {
|
|
99
|
+
frame.braces -= 1;
|
|
100
|
+
if (frame.braces === 0) {
|
|
101
|
+
stack.pop();
|
|
102
|
+
out[i] = ' ';
|
|
103
|
+
i += 1;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (/[\w$]/.test(char))
|
|
109
|
+
word += char;
|
|
110
|
+
else if (word !== '') {
|
|
111
|
+
lastWord = word;
|
|
112
|
+
word = '';
|
|
113
|
+
}
|
|
114
|
+
if (!/\s/.test(char))
|
|
115
|
+
lastCode = char;
|
|
116
|
+
i += 1;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (frame.mode === 'line') {
|
|
120
|
+
if (char === '\n') {
|
|
121
|
+
stack.pop();
|
|
122
|
+
i += 1;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
out[i] = ' ';
|
|
126
|
+
i += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (frame.mode === 'block') {
|
|
130
|
+
if (char === '*' && next === '/') {
|
|
131
|
+
blank(i, i + 2);
|
|
132
|
+
stack.pop();
|
|
133
|
+
i += 2;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (char !== '\n')
|
|
137
|
+
out[i] = ' ';
|
|
138
|
+
i += 1;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (frame.mode === 'string') {
|
|
142
|
+
if (char === '\\') {
|
|
143
|
+
if (!frame.keep)
|
|
144
|
+
blank(i, i + 2);
|
|
145
|
+
i += 2;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (char === frame.quote) {
|
|
149
|
+
if (!frame.keep)
|
|
150
|
+
out[i] = ' ';
|
|
151
|
+
stack.pop();
|
|
152
|
+
// A string is an operand: the next `/` is division, not a regex.
|
|
153
|
+
lastCode = 'x';
|
|
154
|
+
i += 1;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (!frame.keep && char !== '\n')
|
|
158
|
+
out[i] = ' ';
|
|
159
|
+
i += 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (frame.mode === 'template') {
|
|
163
|
+
if (char === '\\') {
|
|
164
|
+
blank(i, i + 2);
|
|
165
|
+
i += 2;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (char === '`') {
|
|
169
|
+
out[i] = ' ';
|
|
170
|
+
stack.pop();
|
|
171
|
+
lastCode = 'x';
|
|
172
|
+
i += 1;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (char === '$' && next === '{') {
|
|
176
|
+
// The substitution is code: keep it visible and track its closing brace.
|
|
177
|
+
blank(i, i + 2);
|
|
178
|
+
stack.push({ mode: 'code', braces: 1 });
|
|
179
|
+
lastCode = '{';
|
|
180
|
+
i += 2;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (char !== '\n')
|
|
184
|
+
out[i] = ' ';
|
|
185
|
+
i += 1;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
// Regex literal: blank it, honour escapes and character classes, then its flags.
|
|
189
|
+
if (char === '\\') {
|
|
190
|
+
blank(i, i + 2);
|
|
191
|
+
i += 2;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (char === '[')
|
|
195
|
+
frame.inClass = true;
|
|
196
|
+
else if (char === ']')
|
|
197
|
+
frame.inClass = false;
|
|
198
|
+
else if (char === '/' && !frame.inClass) {
|
|
199
|
+
out[i] = ' ';
|
|
200
|
+
stack.pop();
|
|
201
|
+
lastCode = 'x';
|
|
202
|
+
i += 1;
|
|
203
|
+
while (i < source.length && /[a-z]/i.test(source[i] ?? '')) {
|
|
204
|
+
out[i] = ' ';
|
|
205
|
+
i += 1;
|
|
206
|
+
}
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (char !== '\n')
|
|
210
|
+
out[i] = ' ';
|
|
211
|
+
i += 1;
|
|
212
|
+
}
|
|
213
|
+
return out.join('');
|
|
214
|
+
}
|
package/dist/suite-overlap.d.ts
CHANGED
|
@@ -50,6 +50,14 @@ export declare function withoutHeredocs(command: string): string;
|
|
|
50
50
|
* @returns The target key.
|
|
51
51
|
*/
|
|
52
52
|
export declare function suiteCommandTarget(command: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* The target of the actual Playwright step, including inherited exports. URLs and option names
|
|
55
|
+
* in another program or a quoted title cannot decide whether this step is deployed.
|
|
56
|
+
* @param command - The shell command.
|
|
57
|
+
* @param last - Read the last Playwright invocation, for the background launch rewrite.
|
|
58
|
+
* @returns The comparable target key, or local when no target setting is present.
|
|
59
|
+
*/
|
|
60
|
+
export declare function playwrightCommandTarget(command: string, last?: boolean): string;
|
|
53
61
|
/**
|
|
54
62
|
* Whether a Playwright statement names its own config — the reading {@link withSuiteConfig} and
|
|
55
63
|
* {@link scopedRerunCommand} share, so neither adds a second `--config` to a command that has one.
|
|
@@ -147,6 +155,22 @@ export interface RunEnvSetting {
|
|
|
147
155
|
* @returns The command, or the command unchanged when it already carries every setting.
|
|
148
156
|
*/
|
|
149
157
|
export declare function withRunEnv(command: string, settings?: readonly RunEnvSetting[]): string;
|
|
158
|
+
/**
|
|
159
|
+
* The absolute directory the Playwright statement in a command runs in, or null when the command
|
|
160
|
+
* does not say.
|
|
161
|
+
*
|
|
162
|
+
* The reporter prints a failing test's file relative to the process directory the runner started
|
|
163
|
+
* in (`../fixtures/…` from a run whose suite lives outside its own tree), so the directory has to
|
|
164
|
+
* come from the command itself: `exec_command`'s `cwd` when it was given, then each `cd` before
|
|
165
|
+
* the runner. Only a literal `cd` is followed — a target holding a variable, a glob or `~`
|
|
166
|
+
* resolves nowhere useful, and a guessed absolute path is worse than the relative one the
|
|
167
|
+
* reporter printed.
|
|
168
|
+
*
|
|
169
|
+
* @param command - The shell command.
|
|
170
|
+
* @param cwd - The `cwd` the tool was given, when it was.
|
|
171
|
+
* @returns The absolute directory, or null.
|
|
172
|
+
*/
|
|
173
|
+
export declare function suiteRunDirectory(command: string, cwd?: string | null): string | null;
|
|
150
174
|
/**
|
|
151
175
|
* Resolve literal `./`/`../` Playwright file selections against the runner's own directory.
|
|
152
176
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suite-overlap.d.ts","sourceRoot":"","sources":["../src/suite-overlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAaH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAS1F;AA2VD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,GAAG,GAAE,SAAS,aAAa,EAAO,EAClC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,MAAM,CA2DR;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,aAAa,EAAO,GAAG,MAAM,CAe3F;
|
|
1
|
+
{"version":3,"file":"suite-overlap.d.ts","sourceRoot":"","sources":["../src/suite-overlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAaH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,MAAM,CAwB7E;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAS1F;AA2VD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,GAAG,GAAE,SAAS,aAAa,EAAO,EAClC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,MAAM,CA2DR;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,aAAa,EAAO,GAAG,MAAM,CAe3F;AAQD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAiCrF;AAkND;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAa5F;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,gBAAgB,EACzD,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7B,QAAQ,EAAE,SAAS,CAAC,EAAE,GACrB,CAAC,GAAG,IAAI,CAMV;AAqHD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,MAA4D,CAAA;AAEhG;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7D;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CA2BtF"}
|
package/dist/suite-overlap.js
CHANGED
|
@@ -75,6 +75,31 @@ export function suiteCommandTarget(command) {
|
|
|
75
75
|
}
|
|
76
76
|
return 'local';
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* The target of the actual Playwright step, including inherited exports. URLs and option names
|
|
80
|
+
* in another program or a quoted title cannot decide whether this step is deployed.
|
|
81
|
+
* @param command - The shell command.
|
|
82
|
+
* @param last - Read the last Playwright invocation, for the background launch rewrite.
|
|
83
|
+
* @returns The comparable target key, or local when no target setting is present.
|
|
84
|
+
*/
|
|
85
|
+
export function playwrightCommandTarget(command, last = false) {
|
|
86
|
+
const steps = locatedCommandSegments(command);
|
|
87
|
+
const runners = steps.filter((step) => step.segment?.program === 'playwright' && step.segment.args[0] === 'test');
|
|
88
|
+
const runner = runners.at(last ? -1 : 0);
|
|
89
|
+
if (!runner)
|
|
90
|
+
return suiteCommandTarget(command);
|
|
91
|
+
const inherited = steps
|
|
92
|
+
.slice(0, steps.indexOf(runner))
|
|
93
|
+
.filter((step) => (step.shellScope ?? []).every((scope, i) => scope === runner.shellScope?.[i]) &&
|
|
94
|
+
(step.segment === null || step.segment.program === 'export'));
|
|
95
|
+
const prefix = runner.start !== null && runner.programOffset !== null
|
|
96
|
+
? command.slice(runner.start, runner.programOffset)
|
|
97
|
+
: runner.assignments.join(' ');
|
|
98
|
+
return suiteCommandTarget([
|
|
99
|
+
prefix,
|
|
100
|
+
...inherited.reverse().map((step) => step.segment?.text ?? step.assignments.join(' ')),
|
|
101
|
+
].join('; '));
|
|
102
|
+
}
|
|
78
103
|
/** Whether a Playwright statement already names its own config (`-c`, `--config`, `--config=`). */
|
|
79
104
|
const NAMES_CONFIG = /(?:^|\s)(?:-c|--config)(?:\s+|=)/;
|
|
80
105
|
/**
|
|
@@ -619,29 +644,40 @@ const unquoted = (word) => word.replace(/^['"]|['"]$/g, '');
|
|
|
619
644
|
* @param cwd - The `cwd` the tool was given, when it was.
|
|
620
645
|
* @returns The absolute directory, or null.
|
|
621
646
|
*/
|
|
622
|
-
function suiteRunDirectory(command, cwd) {
|
|
623
|
-
|
|
624
|
-
|
|
647
|
+
export function suiteRunDirectory(command, cwd) {
|
|
648
|
+
const dirs = new Map([
|
|
649
|
+
['', typeof cwd === 'string' && cwd.startsWith('/') ? posix.normalize(cwd) : null],
|
|
650
|
+
]);
|
|
651
|
+
for (const located of locatedCommandSegments(command)) {
|
|
652
|
+
const scope = located.shellScope ?? [];
|
|
653
|
+
const key = scope.join('\0');
|
|
654
|
+
if (!dirs.has(key)) {
|
|
655
|
+
let parent = scope.slice(0, -1);
|
|
656
|
+
while (!dirs.has(parent.join('\0')))
|
|
657
|
+
parent = parent.slice(0, -1);
|
|
658
|
+
dirs.set(key, dirs.get(parent.join('\0')) ?? null);
|
|
659
|
+
}
|
|
660
|
+
const { segment } = located;
|
|
625
661
|
if (segment === null)
|
|
626
662
|
continue;
|
|
627
663
|
if (segment.program === 'cd') {
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
664
|
+
const words = segment.args.map(unquoted);
|
|
665
|
+
while (words[0] === '--' || words[0] === '-L' || words[0] === '-P')
|
|
666
|
+
words.shift();
|
|
667
|
+
const target = words[0] ?? '';
|
|
668
|
+
const dir = dirs.get(key) ?? null;
|
|
669
|
+
dirs.set(key, !target || target.startsWith('-') || target.startsWith('~') || !LITERAL_DIR.test(target)
|
|
670
|
+
? null
|
|
671
|
+
: target.startsWith('/')
|
|
672
|
+
? posix.normalize(target)
|
|
673
|
+
: dir === null
|
|
674
|
+
? null
|
|
675
|
+
: posix.normalize(posix.join(dir, target)));
|
|
640
676
|
}
|
|
641
677
|
if (segment.program === 'playwright' && segment.args[0] === 'test')
|
|
642
|
-
|
|
678
|
+
return dirs.get(key) ?? null;
|
|
643
679
|
}
|
|
644
|
-
return
|
|
680
|
+
return null;
|
|
645
681
|
}
|
|
646
682
|
/** A failure location's path and its `:line[:column]` suffix, split the way Playwright does. */
|
|
647
683
|
const LOCATION_LINE = /^(.*?)(:\d+(?::\d+)?)$/;
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA2B9C,OAAO,EAIL,KAAK,mBAAmB,EAEzB,MAAM,wBAAwB,CAAA;AAsC/B;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,GAAG,KAAK,CAAC,EACnD,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAmB9B;AAuLD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAwdD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAkInE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AA0DlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGtE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA2B9C,OAAO,EAIL,KAAK,mBAAmB,EAEzB,MAAM,wBAAwB,CAAA;AAsC/B;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,GAAG,KAAK,CAAC,EACnD,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAmB9B;AAuLD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAwdD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAkInE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AA0DlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGtE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAypGxF"}
|
package/dist/tools.js
CHANGED
|
@@ -2819,17 +2819,13 @@ export function buildTools(backend, config) {
|
|
|
2819
2819
|
};
|
|
2820
2820
|
}
|
|
2821
2821
|
}
|
|
2822
|
-
//
|
|
2823
|
-
//
|
|
2824
|
-
// tells a swallowed request error from a selector, and X1 xr-molecule-flash-m100 spent the
|
|
2825
|
-
// last minutes of its run hand-writing Chromium probes for what the trace it never wrote
|
|
2826
|
-
// down would have said. The whole rule is that function's; the whole-suite proof run gets it
|
|
2827
|
-
// too, since a trace is retained only for a failing test (m163's proof run left none and the
|
|
2828
|
-
// executor hunted one that did not exist).
|
|
2822
|
+
// Diagnostic runs need readable failure traces. A proof-capable deployed run retains its
|
|
2823
|
+
// own settings; diagnosisTraceCommand owns both decisions and uses the backend's readers.
|
|
2829
2824
|
const traced = await diagnosisTraceCommand({
|
|
2830
2825
|
command: rawCommand,
|
|
2831
2826
|
cwd,
|
|
2832
2827
|
readFile: (path) => backend.readFile(path),
|
|
2828
|
+
readDir: (path) => backend.readDir(path),
|
|
2833
2829
|
});
|
|
2834
2830
|
let command = traced.command;
|
|
2835
2831
|
// A leading `sleep N; <read of a background task's log>` is a hand-rolled poll, and the
|
|
@@ -853,6 +853,11 @@ export declare function suiteRecordsTraces(configText: string): boolean;
|
|
|
853
853
|
export declare function namesNoRetries(command: string): boolean;
|
|
854
854
|
/** The `--trace` flag this platform adds, and the only value it adds it with. */
|
|
855
855
|
export declare const DIAGNOSIS_TRACE_FLAG = "--trace=retain-on-failure";
|
|
856
|
+
/** The backend's existing directory capability, when available. */
|
|
857
|
+
type ReadConfigDirectory = (path: string) => Promise<Array<{
|
|
858
|
+
name: string;
|
|
859
|
+
type: 'file' | 'directory';
|
|
860
|
+
}>>;
|
|
856
861
|
/** A command with the trace flag this platform decided to add, and the sentence to report it in. */
|
|
857
862
|
export interface DiagnosisTraceRewrite {
|
|
858
863
|
/** The command to run. */
|
|
@@ -904,6 +909,7 @@ export declare function diagnosisTraceCommand(args: {
|
|
|
904
909
|
command: string;
|
|
905
910
|
cwd: string;
|
|
906
911
|
readFile: (path: string) => Promise<string>;
|
|
912
|
+
readDir?: ReadConfigDirectory;
|
|
907
913
|
}): Promise<DiagnosisTraceRewrite>;
|
|
908
914
|
export {};
|
|
909
915
|
//# sourceMappingURL=trace-artifacts.d.ts.map
|