• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / js-slang / 27589703017

16 Jun 2026 02:20AM UTC coverage: 78.585% (+0.06%) from 78.53%
27589703017

Pull #1995

github

web-flow
Merge 0f4f207ac into aacfa664e
Pull Request #1995: Operators Fix

3155 of 4228 branches covered (74.62%)

Branch coverage included in aggregate %.

98 of 117 new or added lines in 18 files covered. (83.76%)

88 existing lines in 15 files now uncovered.

7061 of 8772 relevant lines covered (80.49%)

181758.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/modules/preprocessor/index.ts
1
import type es from 'estree';
2
// import * as TypedES from '../../typeChecker/tsESTree'
3

4
import type { IOptions } from '../..';
5
import { Variant } from '../../langs';
6
import type { Context, RecursivePartial } from '../../types';
7
import loadSourceModules, { loadSourceModuleTypes } from '../loader';
8
import type { FileGetter } from '../moduleTypes';
9
import analyzeImportsAndExports from './analyzer';
10
import defaultBundler, { type Bundler } from './bundler';
11
import parseProgramsAndConstructImportGraph from './linker';
12

13
export type PreprocessResult =
14
  | {
15
      ok: true;
16
      program: es.Program;
17
      files: Record<string, string>;
18
      verboseErrors: boolean;
19
    }
20
  | {
21
      ok: false;
22
      verboseErrors: boolean;
23
    };
24

25
/**
26
 * Preprocesses file imports and returns a transformed Abstract Syntax Tree (AST).
27
 * If an error is encountered at any point, returns `undefined` to signify that an
28
 * error occurred. Details of the error can be found inside `context.errors`.
29
 *
30
 * The preprocessing works by transforming each imported file into a function whose
31
 * parameters are other files (results of transformed functions) and return value
32
 * is a pair where the head is the default export or null, and the tail is a list
33
 * of pairs that map from exported names to identifiers.
34
 *
35
 * See https://github.com/source-academy/js-slang/wiki/Local-Module-Import-&-Export
36
 * for more information.
37
 *
38
 * @param files              An object mapping absolute file paths to file content.
39
 * @param entrypointFilePath The absolute path of the entrypoint file.
40
 * @param context            The information associated with the program evaluation.
41
 */
42
export default async function preprocessFileImports(
43
  files: FileGetter,
44
  entrypointFilePath: string,
45
  context: Context,
46
  options: RecursivePartial<IOptions> = {},
1,155✔
47
  bundler: Bundler = defaultBundler,
1,155✔
48
): Promise<PreprocessResult> {
49
  const importOptions = options?.importOptions;
1,155✔
50

51
  if (context.variant === Variant.TYPED) {
1,155✔
52
    // Load typed source modules into context first to ensure that the type checker has access to all types.
53
    // TODO: This is a temporary solution, and we should consider a better way to handle this.
54
    try {
3✔
55
      await loadSourceModuleTypes(
3✔
56
        new Set<string>(['rune', 'curve']),
57
        context,
58
        importOptions?.sourceBundleImporter,
59
      );
60
    } catch (error) {
UNCOV
61
      context.errors.push(error);
×
62
      return {
×
63
        ok: false,
64
        verboseErrors: false,
65
      };
66
    }
67
  }
68

69
  // Parse all files into ASTs and build the import graph.
70
  const linkerResult = await parseProgramsAndConstructImportGraph(
1,155✔
71
    files,
72
    entrypointFilePath,
73
    context,
74
    importOptions,
75
    !!options?.shouldAddFileName,
76
  );
77
  // Return if there are errors while parsing.
78
  if (!linkerResult.ok) {
1,155✔
79
    return linkerResult;
159✔
80
  }
81

82
  const { programs, topoOrder, sourceModulesToImport } = linkerResult;
996✔
83

84
  try {
996✔
85
    await loadSourceModules(sourceModulesToImport, context, importOptions);
996✔
86
    // Run type checking on the programs after loading the source modules and their types.
87
    const linkerResult = await parseProgramsAndConstructImportGraph(
996✔
88
      files,
89
      entrypointFilePath,
90
      context,
91
      importOptions,
92
      !!options?.shouldAddFileName,
93
    );
94
    // Return 'undefined' if there are errors while parsing.
95
    if (!linkerResult.ok) {
996!
UNCOV
96
      return linkerResult;
×
97
    }
98

99
    analyzeImportsAndExports(programs, entrypointFilePath, topoOrder, context, importOptions);
996✔
100

101
    const program = bundler(programs, entrypointFilePath, topoOrder, context);
996✔
102
    return {
996✔
103
      ok: true,
104
      program,
105
      files: linkerResult.files,
106
      verboseErrors: linkerResult.verboseErrors,
107
    };
108
  } catch (error) {
109
    context.errors.push(error);
2✔
110
    return {
2✔
111
      ok: false,
112
      verboseErrors: linkerResult.verboseErrors,
113
    };
114
  }
115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc