Skip to content

Commit bab4bc8

Browse files
committed
feat(napi/parser): add type annotations to parse-raw-worker test (#15998)
1 parent 791d632 commit bab4bc8

File tree

1 file changed

+88
-38
lines changed

1 file changed

+88
-38
lines changed

napi/parser/test/parse-raw-worker.ts

Lines changed: 88 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,22 @@ import {
2222
TS_ESTREE_DIR_PATH,
2323
} from './parse-raw-common.ts';
2424
import { makeUnitsFromTest } from './typescript-make-units-from-test.ts';
25+
import type { Node, ParserOptions } from '../src-js/index.js';
2526

2627
const { hasOwn } = Object,
2728
{ isArray } = Array;
2829

30+
interface ExtendedParserOptions extends ParserOptions {
31+
experimentalRawTransfer?: boolean;
32+
experimentalParent?: boolean;
33+
experimentalLazy?: boolean;
34+
}
35+
36+
type TestCaseProps = string | { filename: string; sourceText: string };
37+
2938
// Run test case and return whether it passes.
3039
// This is the entry point when run as a worker.
31-
export default async function (data) {
40+
export default async function (data: { type: number; props: TestCaseProps }): Promise<boolean> {
3241
try {
3342
await runCase(data, simpleExpect);
3443
return true;
@@ -40,35 +49,43 @@ export default async function (data) {
4049
// Run test case with specified `expect` implementation.
4150
// If test fails, will throw an error.
4251
// Can be called from main thread.
43-
export async function runCase({ type, props }, expect) {
52+
export async function runCase(
53+
{ type, props }: { type: number; props: TestCaseProps },
54+
expect: ExpectFunction,
55+
): Promise<void> {
4456
const rangeParent = (type & TEST_TYPE_RANGE_PARENT) !== 0,
4557
lazy = (type & TEST_TYPE_LAZY) !== 0,
4658
pretty = (type & TEST_TYPE_PRETTY) !== 0;
4759
type &= TEST_TYPE_MAIN_MASK;
4860

4961
switch (type) {
5062
case TEST_TYPE_TEST262:
51-
await runTest262Case(props, rangeParent, lazy, expect);
63+
await runTest262Case(props as string, rangeParent, lazy, expect);
5264
break;
5365
case TEST_TYPE_JSX:
54-
await runJsxCase(props, rangeParent, lazy, expect);
66+
await runJsxCase(props as string, rangeParent, lazy, expect);
5567
break;
5668
case TEST_TYPE_TS:
57-
await runTsCase(props, rangeParent, lazy, expect);
69+
await runTsCase(props as string, rangeParent, lazy, expect);
5870
break;
5971
case TEST_TYPE_FIXTURE:
60-
await runFixture(props, rangeParent, lazy, pretty, expect);
72+
await runFixture(props as string, rangeParent, lazy, pretty, expect);
6173
break;
6274
case TEST_TYPE_INLINE_FIXTURE:
63-
await runInlineFixture(props, rangeParent, lazy, pretty, expect);
75+
await runInlineFixture(props as { filename: string; sourceText: string }, rangeParent, lazy, pretty, expect);
6476
break;
6577
default:
6678
throw new Error('Unexpected test type');
6779
}
6880
}
6981

7082
// Run Test262 test case
71-
async function runTest262Case(path, rangeParent, lazy, expect) {
83+
async function runTest262Case(
84+
path: string,
85+
rangeParent: boolean,
86+
lazy: boolean,
87+
expect: ExpectFunction,
88+
): Promise<void> {
7289
const filename = basename(path);
7390
const [sourceText, acornJson] = await Promise.all([
7491
readFile(pathJoin(TEST262_DIR_PATH, path), 'utf8'),
@@ -93,7 +110,12 @@ async function runTest262Case(path, rangeParent, lazy, expect) {
93110
}
94111

95112
// Run JSX test case
96-
async function runJsxCase(filename, rangeParent, lazy, expect) {
113+
async function runJsxCase(
114+
filename: string,
115+
rangeParent: boolean,
116+
lazy: boolean,
117+
expect: ExpectFunction,
118+
): Promise<void> {
97119
const sourcePath = pathJoin(JSX_DIR_PATH, filename),
98120
jsonPath = sourcePath.slice(0, -1) + 'on'; // `.jsx` -> `.json`
99121
const [sourceText, acornJson] = await Promise.all([readFile(sourcePath, 'utf8'), readFile(jsonPath, 'utf8')]);
@@ -120,7 +142,7 @@ const TS_CASE_HEADER = '__ESTREE_TEST__:PASS:\n```json\n';
120142
const TS_CASE_FOOTER = '\n```\n';
121143
const TS_CASE_FOOTER_LEN = TS_CASE_FOOTER.length;
122144

123-
async function runTsCase(path, rangeParent, lazy, expect) {
145+
async function runTsCase(path: string, rangeParent: boolean, lazy: boolean, expect: ExpectFunction): Promise<void> {
124146
const tsPath = path.slice(0, -3); // Trim off `.md`
125147
let [sourceText, casesJson] = await Promise.all([
126148
readFile(pathJoin(TS_DIR_PATH, tsPath), 'utf8'),
@@ -140,7 +162,7 @@ async function runTsCase(path, rangeParent, lazy, expect) {
140162
for (let i = 0; i < tests.length; i++) {
141163
const { name: filename, content: code, sourceType } = tests[i];
142164

143-
const options = {
165+
const options: ExtendedParserOptions = {
144166
sourceType: sourceType.module ? 'module' : 'unambiguous',
145167
astType: 'ts',
146168
preserveParens: false,
@@ -156,8 +178,7 @@ async function runTsCase(path, rangeParent, lazy, expect) {
156178
continue;
157179
}
158180

159-
// @ts-ignore
160-
const { program, errors } = parseSync(filename, code, options);
181+
const { program, errors } = parseSync(filename, code, options as ParserOptions);
161182
const oxcJson = stringifyAcornTest262Style(program);
162183

163184
const estreeJson = estreeJsons[i];
@@ -168,8 +189,7 @@ async function runTsCase(path, rangeParent, lazy, expect) {
168189
// Fall back to comparing to AST parsed via JSON transfer.
169190
// We can fail to match the TS-ESLint snapshots where there are syntax errors,
170191
// because our parser is not recoverable.
171-
// @ts-ignore
172-
const standard = parseSync(filename, code, { ...options, experimentalRawTransfer: false });
192+
const standard = parseSync(filename, code, { ...options, experimentalRawTransfer: false } as ParserOptions);
173193
const standardJson = stringifyAcornTest262Style(standard.program);
174194
const errorsStandard = standard.errors;
175195

@@ -183,7 +203,13 @@ async function runTsCase(path, rangeParent, lazy, expect) {
183203
}
184204

185205
// Test raw transfer output matches standard (via JSON) output for a fixture file
186-
async function runFixture(path, rangeParent, lazy, pretty, expect) {
206+
async function runFixture(
207+
path: string,
208+
rangeParent: boolean,
209+
lazy: boolean,
210+
pretty: boolean,
211+
expect: ExpectFunction,
212+
): Promise<void> {
187213
const filename = basename(path);
188214
const sourceText = await readFile(pathJoin(ROOT_DIR_PATH, path), 'utf8');
189215

@@ -197,7 +223,13 @@ async function runFixture(path, rangeParent, lazy, pretty, expect) {
197223
}
198224

199225
// Test raw transfer output matches standard (via JSON) output for a fixture, with provided source text
200-
async function runInlineFixture({ filename, sourceText }, rangeParent, lazy, pretty, expect) {
226+
async function runInlineFixture(
227+
{ filename, sourceText }: { filename: string; sourceText: string },
228+
rangeParent: boolean,
229+
lazy: boolean,
230+
pretty: boolean,
231+
expect: ExpectFunction,
232+
): Promise<void> {
201233
if (rangeParent) {
202234
testRangeParent(filename, sourceText, null, expect);
203235
} else if (lazy) {
@@ -208,17 +240,21 @@ async function runInlineFixture({ filename, sourceText }, rangeParent, lazy, pre
208240
}
209241

210242
// Test `range` and `parent` fields are correct on all AST nodes.
211-
function testRangeParent(filename, sourceText, options, expect) {
212-
// @ts-ignore
243+
function testRangeParent(
244+
filename: string,
245+
sourceText: string,
246+
options: ExtendedParserOptions | null,
247+
expect: ExpectFunction,
248+
): void {
213249
const ret = parseSync(filename, sourceText, {
214250
...options,
215251
range: true,
216252
experimentalRawTransfer: true,
217253
experimentalParent: true,
218-
});
254+
} as ParserOptions);
219255

220-
let parent = null;
221-
function walk(node) {
256+
let parent: any = null;
257+
function walk(node: null | Node[] | Node): void {
222258
if (node === null || typeof node !== 'object') return;
223259

224260
if (isArray(node)) {
@@ -260,21 +296,25 @@ function testRangeParent(filename, sourceText, options, expect) {
260296

261297
// Test lazy deserialization does not throw an error.
262298
// We don't test the correctness of the output.
263-
function testLazy(filename, sourceText, options) {
264-
// @ts-ignore
299+
function testLazy(filename: string, sourceText: string, options: ExtendedParserOptions | null): void {
265300
const ret = parseSync(filename, sourceText, {
266301
...options,
267302
experimentalRawTransfer: false,
268303
experimentalLazy: true,
269-
});
304+
} as ParserOptions);
270305
JSON.stringify(ret.program);
271306
JSON.stringify(ret.comments);
272307
JSON.stringify(ret.errors);
273308
JSON.stringify(ret.module);
274309
}
275310

276311
// Assert raw transfer output matches standard (via JSON) output
277-
function assertRawAndStandardMatch(filename, sourceText, pretty, expect) {
312+
function assertRawAndStandardMatch(
313+
filename: string,
314+
sourceText: string,
315+
pretty: boolean,
316+
expect: ExpectFunction,
317+
): void {
278318
const retStandard = parseSync(filename, sourceText);
279319
const {
280320
program: programStandard,
@@ -290,8 +330,7 @@ function assertRawAndStandardMatch(filename, sourceText, pretty, expect) {
290330
moveStartAndEndToLast(moduleStandard.staticExports, true);
291331
moveStartAndEndToLast(moduleStandard.dynamicImports, false);
292332

293-
// @ts-ignore
294-
const retRaw = parseSync(filename, sourceText, { experimentalRawTransfer: true });
333+
const retRaw = parseSync(filename, sourceText, { experimentalRawTransfer: true } as ParserOptions);
295334
const { program: programRaw, comments: commentsRaw } = retRaw;
296335
// Remove `null` values, to match what NAPI-RS does
297336
const moduleRaw = removeNullProperties(retRaw.module);
@@ -309,14 +348,17 @@ function assertRawAndStandardMatch(filename, sourceText, pretty, expect) {
309348
expect(jsonRaw).toEqual(jsonStandard);
310349
}
311350

312-
function moveStartAndEndToLast(arr, reorderEntries) {
351+
function moveStartAndEndToLast<T extends { entries?: any[]; start: number; end: number }>(
352+
arr: T[],
353+
reorderEntries: boolean,
354+
): void {
313355
for (const obj of arr) {
314356
const { start, end } = obj;
315357
delete obj.start;
316358
delete obj.end;
317359
obj.start = start;
318360
obj.end = end;
319-
if (reorderEntries) moveStartAndEndToLast(obj.entries, false);
361+
if (reorderEntries && obj.entries) moveStartAndEndToLast(obj.entries, false);
320362
}
321363
}
322364

@@ -329,14 +371,14 @@ function moveStartAndEndToLast(arr, reorderEntries) {
329371
// }
330372
// ```
331373
// For speed, extract `sourceType` with a slice, rather than parsing the JSON.
332-
function getSourceTypeFromJSON(json) {
374+
function getSourceTypeFromJSON(json: string): 'script' | 'module' {
333375
const index = json.lastIndexOf('"sourceType": "');
334-
return json.slice(index + 15, index + 21);
376+
return json.slice(index + 15, index + 21) as 'script' | 'module';
335377
}
336378

337379
// Stringify to JSON, replacing values which are invalid in JSON.
338380
// If `pretty === true`, JSON is pretty-printed.
339-
function stringify(obj, pretty) {
381+
function stringify(obj: any, pretty: boolean): string {
340382
return JSON.stringify(
341383
obj,
342384
(_key, value) => {
@@ -354,7 +396,7 @@ function stringify(obj, pretty) {
354396
const INFINITY_PLACEHOLDER = '__INFINITY__INFINITY__INFINITY__';
355397
const INFINITY_REGEXP = new RegExp(`"${INFINITY_PLACEHOLDER}"`, 'g');
356398

357-
function stringifyAcornTest262Style(obj) {
399+
function stringifyAcornTest262Style(obj: any): string {
358400
let containsInfinity = false;
359401
const json = JSON.stringify(
360402
obj,
@@ -373,16 +415,24 @@ function stringifyAcornTest262Style(obj) {
373415
}
374416

375417
// Remove `null` values, to match what NAPI-RS does
376-
function removeNullProperties(obj) {
418+
function removeNullProperties(obj: any): any {
377419
return JSON.parse(JSON.stringify(obj, (_key, value) => (value === null ? undefined : value)));
378420
}
379421

422+
// Type for expect function
423+
interface ExpectFunction {
424+
(value: any): {
425+
toEqual: (expected: any) => void;
426+
toBe: (expected: any) => void;
427+
};
428+
}
429+
380430
// Very simple `expect` implementation.
381431
// Only supports `expect(x).toEqual(y)` and `expect(x).toBe(y)`, and both use only a simple `===` comparison.
382432
// Therefore, only works for primitive values e.g. strings.
383-
function simpleExpect(value) {
384-
const toBe = (expected) => {
433+
const simpleExpect: ExpectFunction = (value: any) => {
434+
const toBe = (expected: any): void => {
385435
if (value !== expected) throw new Error('Mismatch');
386436
};
387437
return { toEqual: toBe, toBe };
388-
}
438+
};

0 commit comments

Comments
 (0)