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

source-academy / js-slang / 24145129620

08 Apr 2026 03:57PM UTC coverage: 77.155% (+0.06%) from 77.093%
24145129620

Pull #1939

github

web-flow
Merge 9cc941e71 into 440466062
Pull Request #1939: StreamVis drawing arrows

3136 of 4308 branches covered (72.79%)

Branch coverage included in aggregate %.

11 of 11 new or added lines in 1 file covered. (100.0%)

42 existing lines in 4 files now uncovered.

7155 of 9030 relevant lines covered (79.24%)

184687.08 hits per line

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

93.97
/src/createContext.ts
1
// Variable determining chapter of Source is contained in this file.
2

3
import { GLOBAL, JSSLANG_PROPERTIES } from './constants';
4
import { call_with_current_continuation } from './cse-machine/continuations';
5
import Heap from './cse-machine/heap';
6
import { Chapter, Variant, type LanguageOptions } from './langs';
7
import * as list from './stdlib/list';
8
import { list_to_vector } from './stdlib/list';
9
import { listPrelude } from './stdlib/list.prelude';
10
import { localImportPrelude } from './stdlib/localImport.prelude';
11
import * as misc from './stdlib/misc';
12
import * as parser from './stdlib/parser';
13
import * as pylib from './stdlib/pylib';
14
import * as stream from './stdlib/stream';
15
import { streamPrelude } from './stdlib/stream.prelude';
16
import { createTypeEnvironment, tForAll, tVar } from './typeChecker/utils';
17
import type { Context, CustomBuiltIns, Environment, NativeStorage, Value } from './types';
18
import * as operators from './utils/operators';
19
import { stringify } from './utils/stringify';
20

21
export class EnvTree {
22
  private _root: EnvTreeNode | null = null;
4,034✔
23
  private map = new Map<Environment, EnvTreeNode>();
4,034✔
24

25
  get root(): EnvTreeNode | null {
26
    return this._root;
3✔
27
  }
28

29
  public insert(environment: Environment): void {
30
    const tailEnvironment = environment.tail;
458,191✔
31
    if (tailEnvironment === null) {
458,191✔
32
      if (this._root === null) {
3,015!
33
        this._root = new EnvTreeNode(environment, null);
3,015✔
34
        this.map.set(environment, this._root);
3,015✔
35
      }
36
    } else {
37
      const parentNode = this.map.get(tailEnvironment);
455,176✔
38
      if (parentNode) {
455,176!
39
        const childNode = new EnvTreeNode(environment, parentNode);
455,176✔
40
        parentNode.addChild(childNode);
455,176✔
41
        this.map.set(environment, childNode);
455,176✔
42
      }
43
    }
44
  }
45

46
  public getTreeNode(environment: Environment): EnvTreeNode | undefined {
47
    return this.map.get(environment);
5✔
48
  }
49
}
50

51
export class EnvTreeNode {
52
  private _children: EnvTreeNode[] = [];
458,192✔
53

54
  constructor(
55
    readonly environment: Environment,
458,192✔
56
    public parent: EnvTreeNode | null,
458,192✔
57
  ) {}
58

59
  get children(): EnvTreeNode[] {
60
    return this._children;
3✔
61
  }
62

63
  public resetChildren(newChildren: EnvTreeNode[]): void {
64
    this.clearChildren();
1✔
65
    this.addChildren(newChildren);
1✔
66
    newChildren.forEach(c => (c.parent = this));
3✔
67
  }
68

69
  private clearChildren(): void {
70
    this._children = [];
1✔
71
  }
72

73
  private addChildren(newChildren: EnvTreeNode[]): void {
74
    this._children.push(...newChildren);
1✔
75
  }
76

77
  public addChild(newChild: EnvTreeNode): EnvTreeNode {
78
    this._children.push(newChild);
455,177✔
79
    return newChild;
455,177✔
80
  }
81
}
82

83
const createEmptyRuntime = () => ({
3,017✔
84
  break: false,
85
  debuggerOn: true,
86
  isRunning: false,
87
  environmentTree: new EnvTree(),
88
  environments: [],
89
  value: undefined,
90
  nodes: [],
91
  control: null,
92
  stash: null,
93
  objectCount: 0,
94
  envSteps: -1,
95
  envStepsTotal: 0,
96
  breakpointSteps: [],
97
  changepointSteps: [],
98
  streamsPointSteps: [],
99
});
100

101
const createEmptyDebugger = () => ({
3,017✔
102
  observers: { callbacks: Array<() => void>() },
103
  status: false,
104
  state: {
105
    it: (function* (): any {
106
      return;
3,017✔
107
    })(),
108
  },
109
});
110

111
export const createGlobalEnvironment = (): Environment => ({
3,015✔
112
  tail: null,
113
  name: 'global',
114
  head: {},
115
  heap: new Heap(),
116
  id: '-1',
117
});
118

119
const createNativeStorage = (): NativeStorage => ({
3,017✔
120
  builtins: new Map(),
121
  previousProgramsIdentifiers: new Set(),
122
  operators: new Map(Object.entries(operators)),
123
  maxExecTime: JSSLANG_PROPERTIES.maxExecTime,
124
  evaller: null,
125
  loadedModules: {},
126
  loadedModuleTypes: {},
127
});
128

129
export const createEmptyContext = <T>(
63✔
130
  chapter: Chapter,
131
  variant: Variant = Variant.DEFAULT,
3,017✔
132
  languageOptions: LanguageOptions = {},
3,017✔
133
  externalSymbols: string[],
134
  externalContext?: T,
135
): Context<T> => {
136
  return {
3,017✔
137
    chapter,
138
    externalSymbols,
139
    errors: [],
140
    externalContext,
141
    runtime: createEmptyRuntime(),
142
    numberOfOuterEnvironments: 1,
143
    prelude: null,
144
    pendingStreamFnStack: [],
145
    streamLineage: new Map<string, string[]>(),
146
    debugger: createEmptyDebugger(),
147
    nativeStorage: createNativeStorage(),
148
    executionMethod: 'auto',
149
    variant,
150
    languageOptions,
151
    moduleContexts: {},
152
    unTypecheckedCode: [],
153
    typeEnvironment: createTypeEnvironment(chapter),
154
    previousPrograms: [],
155
    shouldIncreaseEvaluationTimeout: false,
156
  };
157
};
158

159
export const ensureGlobalEnvironmentExist = (context: Context) => {
63✔
160
  if (!context.runtime) {
6,026!
UNCOV
161
    context.runtime = createEmptyRuntime();
×
162
  }
163
  if (!context.runtime.environments) {
6,026!
UNCOV
164
    context.runtime.environments = [];
×
165
  }
166
  if (!context.runtime.environmentTree) {
6,026!
UNCOV
167
    context.runtime.environmentTree = new EnvTree();
×
168
  }
169
  if (context.runtime.environments.length === 0) {
6,026✔
170
    const globalEnvironment = createGlobalEnvironment();
3,013✔
171
    context.runtime.environments.push(globalEnvironment);
3,013✔
172
    context.runtime.environmentTree.insert(globalEnvironment);
3,013✔
173
  }
174
};
175

176
export const defineSymbol = (context: Context, name: string, value: Value) => {
63✔
177
  const globalEnvironment = context.runtime.environments[0];
206,475✔
178
  Object.defineProperty(globalEnvironment.head, name, {
206,475✔
179
    value,
180
    writable: false,
181
    enumerable: true,
182
  });
183
  context.nativeStorage.builtins.set(name, value);
206,475✔
184
  const typeEnv = context.typeEnvironment[0];
206,475✔
185
  // if the global type env doesn't already have the imported symbol,
186
  // we set it to a type var T that can typecheck with anything.
187
  if (!typeEnv.declKindMap.has(name)) {
206,475✔
188
    typeEnv.typeMap.set(name, tForAll(tVar('T1')));
20,444✔
189
    typeEnv.declKindMap.set(name, 'const');
20,444✔
190
  }
191
};
192

193
export function defineBuiltin(
194
  context: Context,
195
  name: string, // enforce minArgsNeeded
196
  value: Value,
197
  minArgsNeeded: number,
198
): void;
199
export function defineBuiltin(
200
  context: Context,
201
  name: string,
202
  value: Value,
203
  minArgsNeeded?: number,
204
): void;
205
// Defines a builtin in the given context
206
// If the builtin is a function, wrap it such that its toString hides the implementation
207
export function defineBuiltin(
208
  context: Context,
209
  name: string,
210
  value: Value,
211
  minArgsNeeded: undefined | number = undefined,
206,475✔
212
) {
213
  function extractName(name: string): string {
214
    return name.split('(')[0].trim();
173,832✔
215
  }
216

217
  function extractParameters(name: string): string[] {
218
    // if the function has no () in its name, it has no parameters
219
    if (!name.includes('(')) {
173,832✔
220
      return [];
17✔
221
    }
222
    return name
173,815✔
223
      .split('(')[1]
224
      .split(')')[0]
225
      .split(',')
226
      .map(s => s.trim());
213,944✔
227
  }
228

229
  if (typeof value === 'function') {
206,475✔
230
    const funName = extractName(name);
173,832✔
231
    const funParameters = extractParameters(name);
173,832✔
232
    const repr = `function ${name} {\n\t[implementation hidden]\n}`;
173,832✔
233
    value.toString = () => repr;
173,832✔
234
    value.minArgsNeeded = minArgsNeeded;
173,832✔
235
    value.funName = funName;
173,832✔
236
    value.funParameters = funParameters;
173,832✔
237

238
    defineSymbol(context, funName, value);
173,832✔
239
  } else {
240
    defineSymbol(context, name, value);
32,643✔
241
  }
242
}
243

244
export const importExternalSymbols = (context: Context, externalSymbols: string[]) => {
63✔
245
  ensureGlobalEnvironmentExist(context);
3,013✔
246

247
  externalSymbols.forEach(symbol => {
3,013✔
UNCOV
248
    defineSymbol(context, symbol, GLOBAL[symbol as keyof typeof GLOBAL]);
×
249
  });
250
};
251

252
/**
253
 * Imports builtins from standard and external libraries.
254
 */
255
export const importBuiltins = (context: Context, externalBuiltIns: CustomBuiltIns) => {
63✔
256
  ensureGlobalEnvironmentExist(context);
3,013✔
257
  const rawDisplay = (v: Value, ...s: string[]) =>
3,013✔
258
    externalBuiltIns.rawDisplay(v, s[0], context.externalContext);
38✔
259
  const display = (v: Value, ...s: string[]) => {
3,013✔
260
    if (s.length === 1 && s[0] !== undefined && typeof s[0] !== 'string') {
38✔
261
      throw new TypeError('display expects the second argument to be a string');
1✔
262
    }
263
    return (rawDisplay(stringify(v), s[0]), v);
37✔
264
  };
265
  const displayList = (v: Value, ...s: string[]) => {
3,013✔
266
    if (s.length === 1 && s[0] !== undefined && typeof s[0] !== 'string') {
19✔
267
      throw new TypeError('display_list expects the second argument to be a string');
1✔
268
    }
269
    return list.rawDisplayList(display, v, s[0]);
18✔
270
  };
271
  const prompt = (v: Value) => {
3,013✔
272
    const start = Date.now();
×
273
    const promptResult = externalBuiltIns.prompt(v, '', context.externalContext);
×
274
    context.nativeStorage.maxExecTime += Date.now() - start;
×
UNCOV
275
    return promptResult;
×
276
  };
277
  const alert = (v: Value) => {
3,013✔
278
    const start = Date.now();
2✔
279
    externalBuiltIns.alert(v, '', context.externalContext);
2✔
280
    context.nativeStorage.maxExecTime += Date.now() - start;
2✔
281
  };
282
  const visualiseList = (...v: Value) => {
3,013✔
283
    externalBuiltIns.visualiseList(v, context.externalContext);
3✔
284
    return v[0];
3✔
285
  };
286

287
  if (context.chapter >= 1) {
3,013✔
288
    defineBuiltin(context, 'get_time()', misc.get_time);
2,943✔
289
    defineBuiltin(context, 'display(val, prepend = undefined)', display, 1);
2,943✔
290
    defineBuiltin(context, 'raw_display(str, prepend = undefined)', rawDisplay, 1);
2,943✔
291
    defineBuiltin(context, 'stringify(val, indent = 2, maxLineLength = 80)', stringify, 1);
2,943✔
292
    defineBuiltin(context, 'error(str, prepend = undefined)', misc.error_message, 1);
2,943✔
293
    defineBuiltin(context, 'prompt(str)', prompt);
2,943✔
294
    defineBuiltin(context, 'is_number(val)', misc.is_number);
2,943✔
295
    defineBuiltin(context, 'is_string(val)', misc.is_string);
2,943✔
296
    defineBuiltin(context, 'is_function(val)', misc.is_function);
2,943✔
297
    defineBuiltin(context, 'is_boolean(val)', misc.is_boolean);
2,943✔
298
    defineBuiltin(context, 'is_undefined(val)', misc.is_undefined);
2,943✔
299
    defineBuiltin(context, 'parse_int(str, radix)', misc.parse_int);
2,943✔
300
    defineBuiltin(context, 'char_at(str, index)', misc.char_at);
2,943✔
301
    defineBuiltin(context, 'arity(f)', misc.arity);
2,943✔
302
    defineBuiltin(context, 'undefined', undefined);
2,943✔
303
    defineBuiltin(context, 'NaN', NaN);
2,943✔
304
    defineBuiltin(context, 'Infinity', Infinity);
2,943✔
305
    // Define all Math libraries
306
    const mathLibraryNames = Object.getOwnPropertyNames(Math);
2,943✔
307
    // Short param names for stringified version of math functions
308
    const parameterNames = [...'abcdefghijklmnopqrstuvwxyz'];
2,943✔
309
    for (const name of mathLibraryNames) {
2,943✔
310
      const value = Math[name as keyof typeof Math];
126,549✔
311
      if (typeof value === 'function') {
126,549✔
312
        let paramString: string;
313
        let minArgsNeeded = undefined;
103,005✔
314
        if (name === 'max' || name === 'min') {
103,005✔
315
          paramString = '...values';
5,886✔
316
          minArgsNeeded = 0;
5,886✔
317
        } else {
318
          paramString = parameterNames.slice(0, value.length).join(', ');
97,119✔
319
        }
320
        defineBuiltin(context, `math_${name}(${paramString})`, value, minArgsNeeded);
103,005✔
321
      } else {
322
        defineBuiltin(context, `math_${name}`, value);
23,544✔
323
      }
324
    }
325
  }
326

327
  if (context.chapter >= 2) {
3,013✔
328
    // List library
329
    defineBuiltin(context, 'pair(left, right)', list.pair);
1,590✔
330
    defineBuiltin(context, 'is_pair(val)', list.is_pair);
1,590✔
331
    defineBuiltin(context, 'head(xs)', list.head);
1,590✔
332
    defineBuiltin(context, 'tail(xs)', list.tail);
1,590✔
333
    defineBuiltin(context, 'is_null(val)', list.is_null);
1,590✔
334
    defineBuiltin(context, 'list(...values)', list.list, 0);
1,590✔
335
    defineBuiltin(context, 'draw_data(...xs)', visualiseList, 1);
1,590✔
336
    defineBuiltin(context, 'display_list(val, prepend = undefined)', displayList, 0);
1,590✔
337
    defineBuiltin(context, 'is_list(val)', list.is_list);
1,590✔
338
  }
339

340
  if (context.chapter >= 3) {
3,013✔
341
    defineBuiltin(context, 'set_head(xs, val)', list.set_head);
1,315✔
342
    defineBuiltin(context, 'set_tail(xs, val)', list.set_tail);
1,315✔
343
    defineBuiltin(context, 'array_length(arr)', misc.array_length);
1,315✔
344
    defineBuiltin(context, 'is_array(val)', misc.is_array);
1,315✔
345

346
    // Stream library
347
    defineBuiltin(context, 'stream(...values)', stream.stream, 0);
1,315✔
348
  }
349

350
  if (context.chapter >= 4) {
3,013✔
351
    defineBuiltin(context, 'parse(program_string)', (str: string) =>
1,143✔
352
      parser.parse(str, createContext(context.chapter)),
71✔
353
    );
354
    defineBuiltin(context, 'tokenize(program_string)', (str: string) =>
1,143✔
355
      parser.tokenize(str, createContext(context.chapter)),
3✔
356
    );
357
    defineBuiltin(
1,143✔
358
      context,
359
      'apply_in_underlying_javascript(fun, args)',
360
      (fun: Function, args: Value) => fun.apply(fun, list_to_vector(args)),
5✔
361
    );
362

363
    // Continuations for explicit-control variant
364
    if (context.chapter >= 4) {
1,143!
365
      defineBuiltin(
1,143✔
366
        context,
367
        'call_cc(f)',
368
        context.variant === Variant.EXPLICIT_CONTROL
24!
369
          ? call_with_current_continuation
370
          : (f: any) => {
UNCOV
371
              throw new Error('call_cc is only available in Explicit-Control variant');
×
372
            },
373
      );
374
    }
375
  }
376

377
  if (context.chapter === Chapter.LIBRARY_PARSER) {
3,013✔
378
    defineBuiltin(context, 'is_object(val)', misc.is_object);
308✔
379
    defineBuiltin(context, 'is_NaN(val)', misc.is_NaN);
308✔
380
    defineBuiltin(context, 'has_own_property(obj, prop)', misc.has_own_property);
308✔
381
    defineBuiltin(context, 'alert(val)', alert);
308✔
382
    defineBuiltin(context, 'timed(fun)', (f: Function) =>
308✔
UNCOV
383
      misc.timed(context, f, context.externalContext, externalBuiltIns.rawDisplay),
×
384
    );
385
  }
386

387
  if (context.chapter <= Chapter.PYTHON_1 && context.chapter >= Chapter.PYTHON_1) {
3,013✔
388
    if (context.chapter == Chapter.PYTHON_1) {
45!
389
      // Display
390
      defineBuiltin(context, 'get_time()', misc.get_time);
45✔
391
      defineBuiltin(context, 'print(val)', display, 1);
45✔
392
      defineBuiltin(context, 'raw_print(str)', rawDisplay, 1);
45✔
393
      defineBuiltin(context, 'str(val)', (val: any) => stringify(val, 2, 80), 1);
45✔
394
      defineBuiltin(context, 'error(str)', misc.error_message, 1);
45✔
395
      defineBuiltin(context, 'prompt(str)', prompt);
45✔
396
      defineBuiltin(context, 'is_float(val)', pylib.is_float);
45✔
397
      defineBuiltin(context, 'is_int(val)', pylib.is_int);
45✔
398
      defineBuiltin(context, 'is_string(val)', misc.is_string);
45✔
399
      defineBuiltin(context, 'is_function(val)', misc.is_function);
45✔
400
      defineBuiltin(context, 'is_boolean(val)', misc.is_boolean);
45✔
401
      defineBuiltin(context, 'is_None(val)', list.is_null);
45✔
402
      defineBuiltin(context, 'parse_int(str, radix)', misc.parse_int);
45✔
403
      defineBuiltin(context, 'char_at(str, index)', misc.char_at);
45✔
404
      defineBuiltin(context, 'arity(f)', misc.arity);
45✔
405
      defineBuiltin(context, 'None', null);
45✔
406

407
      // Binary operators
408
      defineBuiltin(context, '__py_adder(x, y)', pylib.__py_adder);
45✔
409
      defineBuiltin(context, '__py_minuser(x, y)', pylib.__py_minuser);
45✔
410
      defineBuiltin(context, '__py_multiplier(x, y)', pylib.__py_multiplier);
45✔
411
      defineBuiltin(context, '__py_divider(x, y)', pylib.__py_divider);
45✔
412
      defineBuiltin(context, '__py_modder(x, y)', pylib.__py_modder);
45✔
413
      defineBuiltin(context, '__py_powerer(x, y)', pylib.__py_powerer);
45✔
414
      defineBuiltin(context, '__py_floorer(x, y)', pylib.__py_floorer);
45✔
415

416
      // Unary operator +
417
      defineBuiltin(context, '__py_unary_plus(x)', pylib.__py_unary_plus);
45✔
418

419
      // Math Library
420
      defineBuiltin(context, 'math_abs(x)', pylib.math_abs);
45✔
421
      defineBuiltin(context, 'math_acos(x)', pylib.math_acos);
45✔
422
      defineBuiltin(context, 'math_acosh(x)', pylib.math_acosh);
45✔
423
      defineBuiltin(context, 'math_asin(x)', pylib.math_asin);
45✔
424
      defineBuiltin(context, 'math_asinh(x)', pylib.math_asinh);
45✔
425
      defineBuiltin(context, 'math_atan(x)', pylib.math_atan);
45✔
426
      defineBuiltin(context, 'math_atan2(x)', pylib.math_atan2);
45✔
427
      defineBuiltin(context, 'math_atanh(x)', pylib.math_atanh);
45✔
428
      defineBuiltin(context, 'math_cbrt(x)', pylib.math_cbrt);
45✔
429
      defineBuiltin(context, 'math_ceil(x)', pylib.math_ceil);
45✔
430
      defineBuiltin(context, 'math_clz32(x)', pylib.math_clz32);
45✔
431
      defineBuiltin(context, 'math_cos(x)', pylib.math_cos);
45✔
432
      defineBuiltin(context, 'math_cosh(x)', pylib.math_cosh);
45✔
433
      defineBuiltin(context, 'math_exp(x)', pylib.math_exp);
45✔
434
      defineBuiltin(context, 'math_expm1(x)', pylib.math_expm1);
45✔
435
      defineBuiltin(context, 'math_floor(x)', pylib.math_floor);
45✔
436
      defineBuiltin(context, 'math_fround(x)', pylib.math_fround);
45✔
437
      defineBuiltin(context, 'math_hypot(...values)', pylib.math_hypot);
45✔
438
      defineBuiltin(context, 'math_imul(x, y)', pylib.math_imul);
45✔
439
      defineBuiltin(context, 'math_log(x)', pylib.math_log);
45✔
440
      defineBuiltin(context, 'math_log1p(x)', pylib.math_log1p);
45✔
441
      defineBuiltin(context, 'math_log2(x)', pylib.math_log2);
45✔
442
      defineBuiltin(context, 'math_log10(x)', pylib.math_log10);
45✔
443
      defineBuiltin(context, 'math_max(...values)', pylib.math_max);
45✔
444
      defineBuiltin(context, 'math_min(...values)', pylib.math_min);
45✔
445
      defineBuiltin(context, 'math_pow(base, exponent)', pylib.math_pow);
45✔
446
      defineBuiltin(context, 'math_random()', pylib.math_random);
45✔
447
      defineBuiltin(context, 'math_round(x)', pylib.math_round);
45✔
448
      defineBuiltin(context, 'math_sign(x)', pylib.math_sign);
45✔
449
      defineBuiltin(context, 'math_sin(x)', pylib.math_sin);
45✔
450
      defineBuiltin(context, 'math_sinh(x)', pylib.math_sinh);
45✔
451
      defineBuiltin(context, 'math_sqrt(x)', pylib.math_sqrt);
45✔
452
      defineBuiltin(context, 'math_tan(x)', pylib.math_tan);
45✔
453
      defineBuiltin(context, 'math_tanh(x)', pylib.math_tanh);
45✔
454
      defineBuiltin(context, 'math_trunc(x)', pylib.math_trunc);
45✔
455

456
      // Math constants
457
      defineBuiltin(context, 'math_e', Math.E);
45✔
458
      defineBuiltin(context, 'math_inf', Infinity);
45✔
459
      defineBuiltin(context, 'math_nan', NaN);
45✔
460
      defineBuiltin(context, 'math_pi', Math.PI);
45✔
461
      defineBuiltin(context, 'math_tau', Math.PI * 2);
45✔
462
    }
463
  }
464
};
465

466
function importPrelude(context: Context) {
467
  let prelude = '';
3,013✔
468
  if (context.chapter >= 2) {
3,013✔
469
    prelude += listPrelude;
1,590✔
470
    prelude += localImportPrelude;
1,590✔
471
  }
472
  if (context.chapter >= 3) {
3,013✔
473
    prelude += streamPrelude;
1,315✔
474
  }
475

476
  if (prelude !== '') {
3,013✔
477
    context.prelude = prelude;
1,590✔
478
  }
479
}
480

481
const defaultBuiltIns: CustomBuiltIns = {
63✔
482
  rawDisplay: misc.rawDisplay,
483
  // See issue #5
484
  prompt: misc.rawDisplay,
485
  // See issue #11
486
  alert: misc.rawDisplay,
487
  visualiseList: (_v: Value) => {
UNCOV
488
    throw new Error('List visualizer is not enabled');
×
489
  },
490
};
491

492
const createContext = <T>(
63✔
493
  chapter: Chapter = Chapter.SOURCE_1,
3,164✔
494
  variant: Variant = Variant.DEFAULT,
3,164✔
495
  languageOptions: LanguageOptions = {},
3,164✔
496
  externalSymbols: string[] = [],
3,164✔
497
  externalContext?: T,
498
  externalBuiltIns: CustomBuiltIns = defaultBuiltIns,
3,164✔
499
): Context => {
500
  if (chapter === Chapter.FULL_JS || chapter === Chapter.FULL_TS) {
3,164✔
501
    // fullJS will include all builtins and preludes of source 4
502
    return {
151✔
503
      ...createContext(
504
        Chapter.SOURCE_4,
505
        variant,
506
        languageOptions,
507
        externalSymbols,
508
        externalContext,
509
        externalBuiltIns,
510
      ),
511
      chapter,
512
    } as Context;
513
  }
514
  const context = createEmptyContext(
3,013✔
515
    chapter,
516
    variant,
517
    languageOptions,
518
    externalSymbols,
519
    externalContext,
520
  );
521

522
  importBuiltins(context, externalBuiltIns);
3,013✔
523
  importPrelude(context);
3,013✔
524
  importExternalSymbols(context, externalSymbols);
3,013✔
525

526
  return context;
3,013✔
527
};
528

529
export default createContext;
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