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

source-academy / js-slang / 13616034401

02 Mar 2025 01:44PM UTC coverage: 81.131% (-0.5%) from 81.652%
13616034401

Pull #1739

github

web-flow
Merge 990642701 into a50f7dcef
Pull Request #1739: Typed modules

3580 of 4791 branches covered (74.72%)

Branch coverage included in aggregate %.

56 of 84 new or added lines in 4 files covered. (66.67%)

231 existing lines in 11 files now uncovered.

11198 of 13424 relevant lines covered (83.42%)

125405.78 hits per line

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

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

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

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

24
/**
25
 * Preprocesses file imports and returns a transformed Abstract Syntax Tree (AST).
26
 * If an error is encountered at any point, returns `undefined` to signify that an
27
 * error occurred. Details of the error can be found inside `context.errors`.
28
 *
29
 * The preprocessing works by transforming each imported file into a function whose
30
 * parameters are other files (results of transformed functions) and return value
31
 * is a pair where the head is the default export or null, and the tail is a list
32
 * of pairs that map from exported names to identifiers.
33
 *
34
 * See https://github.com/source-academy/js-slang/wiki/Local-Module-Import-&-Export
35
 * for more information.
36
 *
37
 * @param files              An object mapping absolute file paths to file content.
38
 * @param entrypointFilePath The absolute path of the entrypoint file.
39
 * @param context            The information associated with the program evaluation.
40
 */
41
const preprocessFileImports = async (
59✔
42
  files: FileGetter,
43
  entrypointFilePath: string,
44
  context: Context,
45
  options: RecursivePartial<IOptions> = {},
7✔
46
  bundler: Bundler = defaultBundler
1,955✔
47
): Promise<PreprocessResult> => {
48
  if (context.variant === Variant.TYPED) {
1,955!
49
    // Load typed source modules into context first to ensure that the type checker has access to all types.
50
    // TODO: This is a temporary solution, and we should consider a better way to handle this.
NEW
51
    try {
×
NEW
52
      await loadSourceModuleTypes(new Set<string>(['rune', 'curve']), context)
×
53
    } catch (error) {
NEW
54
      context.errors.push(error)
×
NEW
55
      return {
×
56
        ok: false,
57
        verboseErrors: false
58
      }
59
    }
60
  }
61

62
  // Parse all files into ASTs and build the import graph.
63
  const linkerResult = await parseProgramsAndConstructImportGraph(
1,955✔
64
    files,
65
    entrypointFilePath,
66
    context,
67
    options?.importOptions,
68
    !!options?.shouldAddFileName
69
  )
70
  // Return 'undefined' if there are errors while parsing.
71
  if (!linkerResult.ok) {
1,955✔
72
    return linkerResult
220✔
73
  }
74

75
  const { programs, topoOrder, sourceModulesToImport } = linkerResult
1,735✔
76

77
  try {
1,735✔
78
    await loadSourceModules(sourceModulesToImport, context, options.importOptions?.loadTabs ?? true)
1,735✔
79
    // Run type checking on the programs after loading the source modules and their types.
80
    const linkerResult = await parseProgramsAndConstructImportGraph(
1,735✔
81
      files,
82
      entrypointFilePath,
83
      context,
84
      options?.importOptions,
85
      !!options?.shouldAddFileName
86
    )
87
    // Return 'undefined' if there are errors while parsing.
88
    if (!linkerResult.ok) {
1,735!
NEW
89
      return linkerResult
×
90
    }
91

92
    analyzeImportsAndExports(
1,735✔
93
      programs,
94
      entrypointFilePath,
95
      topoOrder,
96
      context,
97
      options?.importOptions
98
    )
99
  } catch (error) {
100
    context.errors.push(error)
×
101
    return {
×
102
      ok: false,
103
      verboseErrors: linkerResult.verboseErrors
104
    }
105
  }
106

107
  const program = bundler(programs, entrypointFilePath, topoOrder, context)
1,735✔
108
  return {
1,735✔
109
    ok: true,
110
    program,
111
    files: linkerResult.files,
112
    verboseErrors: linkerResult.verboseErrors
113
  }
114
}
115

116
export default preprocessFileImports
59✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc