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

source-academy / js-slang / 24868044425

24 Apr 2026 01:47AM UTC coverage: 78.522% (+0.1%) from 78.391%
24868044425

push

github

web-flow
Error Handling and Stringify Changes (#1893)

* Modify stringify to prioritize toReplString

* Make the extract declarations helper actually work

* Add ability to change loader for source modules

* Add a new option for controlling how Source modules are loaded

* Improve typing for CSE machine

* Add ability to check if modules are loaded with the wrong Source chapter

* Refactor errors to extend from Error class

* Refactor modules errors

* Refactor parser errors

* Refactor cse machine errors

* Mostly fix error handling in the tracer

* Tidy up generator and explainer implementations for tracer

* Remove unnecessary imports and type guards

* Adjust rttc checks to be type guards instead of returning errors

* Adjust miscellanous error changes

* Add eslint rule for useless constructor

* Fix incorrect ordering for checking exceptionerrors

* Minor changes

* Run format

* Run linting

* Override the message property, but also enable noImplicitOverride to prevent accidental overriding

* Add some documentation to some errors

* Add errors to possible imports for modules

* Update getIds helper

* Minor fix to test case

* Run format

* Allow modules to try and load the context of other modules without crashing

* Fix incorrect stdlib name

* Add some more functions to the stdlib list library

* Change to use GeneralRuntimeError for list

* Revert "Change to use GeneralRuntimeError for list"

This reverts commit 642bd99e6.

* Update src/errors/errors.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Add ability to change manifest and docs importers

* Change how external builtins are defined

* Fix typings and list lib overloads

* Miscellanous changes

* Add the Source equality function to stdlib/misc

* Merge from main branch for tracer

* Add handling for the new importers

* Change errors and made redex a local variable

* Improve tracer typing

* Relocate... (continued)

3125 of 4193 branches covered (74.53%)

Branch coverage included in aggregate %.

899 of 1089 new or added lines in 96 files covered. (82.55%)

21 existing lines in 12 files now uncovered.

7031 of 8741 relevant lines covered (80.44%)

185057.72 hits per line

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

50.57
/src/stdlib/misc.ts
1
import Closure from '../cse-machine/closure';
2
import { GeneralRuntimeError } from '../errors/base';
3
import { InvalidParameterTypeError } from '../errors/rttcErrors';
4
import type { Context, Value } from '../types';
5
import { assertNumberWithinRange } from '../utils/rttc';
6
import { stringify } from '../utils/stringify';
7
import * as list from './list';
8

9
/**
10
 * A function that displays to console.log by default (for a REPL).
11
 *
12
 * @param value the value to be represented and displayed.
13
 * @param externalContext a property of Context that can hold
14
 *   any information required for external use (optional).
15
 */
16
export function rawDisplay(value: Value, str: string, _externalContext: any) {
17
  console.log((str === undefined ? '' : str + ' ') + value.toString());
1!
18
  return value;
1✔
19
}
20

21
export function error_message(value: Value, ...strs: string[]) {
22
  const output = (strs[0] === undefined ? '' : strs[0] + ' ') + stringify(value);
2!
23
  throw new GeneralRuntimeError(`Error: ${output}`);
2✔
24
}
25

26
export function timed(
27
  context: Context,
28
  f: Function,
29
  externalContext: any,
30
  displayBuiltin: (value: Value, str: string, externalContext: any) => Value,
31
) {
32
  return (...args: any[]) => {
×
33
    const start = get_time();
×
34
    const result = f(...args);
×
35
    const diff = get_time() - start;
×
36
    displayBuiltin('Duration: ' + Math.round(diff) + 'ms', '', externalContext);
×
37
    return result;
×
38
  };
39
}
40

41
export function is_number(v: Value) {
42
  return typeof v === 'number';
211✔
43
}
44

45
export function is_undefined(xs: Value) {
46
  return typeof xs === 'undefined';
11✔
47
}
48

49
export function is_string(xs: Value) {
50
  return typeof xs === 'string';
36✔
51
}
52

53
export function is_boolean(xs: Value) {
54
  return typeof xs === 'boolean';
25✔
55
}
56

57
export function is_object(xs: Value) {
58
  return typeof xs === 'object' || is_function(xs);
10✔
59
}
60

61
export function is_function(xs: Value) {
62
  return typeof xs === 'function';
2,340✔
63
}
64

65
export function is_NaN(x: Value) {
66
  return is_number(x) && isNaN(x);
4✔
67
}
68

69
export function has_own_property(obj: Value, p: Value) {
70
  return obj.hasOwnProperty(p);
2✔
71
}
72

73
export function is_array(a: Value) {
74
  return a instanceof Array;
6✔
75
}
76

77
export function array_length(xs: Value[]) {
78
  return xs.length;
25✔
79
}
80

81
/**
82
 * Source version of parseInt. Both arguments are required.
83
 *
84
 * @param str String representation of the integer to be parsed. Required.
85
 * @param radix Base to parse the given `str`. Required.
86
 *
87
 * An error is thrown if `str` is not of type string, or `radix` is not an
88
 * integer within the range 2, 36 inclusive.
89
 */
90
export function parse_int(str: string, radix: number) {
91
  if (typeof str !== 'string') {
12✔
92
    throw new InvalidParameterTypeError('string', str, parse_int.name, 'str');
1✔
93
  }
94

95
  assertNumberWithinRange(radix, parse_int.name, 2, 36, true, 'radix');
11✔
96
  return parseInt(str, radix);
11✔
97
}
98

99
/**
100
 * Returns the character at the given index of the given string. If the `index` is out of bounds,
101
 * returns `undefined`.
102
 */
103
export function char_at(str: string, index: number) {
104
  if (typeof str !== 'string') {
5✔
105
    throw new InvalidParameterTypeError('string', str, char_at.name, 'str');
1✔
106
  }
107

108
  assertNumberWithinRange(index, char_at.name, 0, undefined, true, 'index');
4✔
109

110
  if (index >= str.length) {
4✔
111
    return undefined;
1✔
112
  }
113

114
  return str[index];
1✔
115
}
116

117
/**
118
 * arity returns the number of parameters a given function `f` expects.
119
 *
120
 * @param f Function whose arity is to be found. Required.
121
 *
122
 * An error is thrown if `f` is not a function.
123
 */
124
export function arity(f: Function) {
125
  if (f instanceof Closure) {
46!
126
    const params = f.node.params;
×
127
    const hasVarArgs = params[params.length - 1]?.type === 'RestElement';
×
128
    return hasVarArgs ? params.length - 1 : params.length;
×
129
  } else if (typeof f === 'function') {
46✔
130
    return f.length;
45✔
131
  }
132

133
  throw new InvalidParameterTypeError('function', f, arity.name);
1✔
134
}
135

136
/**
137
 * Gets the current time as returned by `new Date().getTime()`
138
 */
139
export function get_time() {
140
  return new Date().getTime();
25,217,343✔
141
}
142

143
/**
144
 * Compute structural equality for the two provided arguments.
145
 */
146
export function equal(xs: any, ys: any): boolean {
NEW
147
  return list.is_pair(xs)
×
148
    ? list.is_pair(ys) && equal(list.head(xs), list.head(ys)) && equal(list.tail(xs), list.tail(ys))
×
149
    : list.is_null(xs)
×
150
      ? list.is_null(ys)
151
      : is_number(xs)
×
152
        ? is_number(ys) && xs === ys
×
153
        : is_boolean(xs)
×
154
          ? is_boolean(ys) && ((xs && ys) || (!xs && !ys))
×
155
          : is_string(xs)
×
156
            ? is_string(ys) && xs === ys
×
157
            : is_undefined(xs)
×
158
              ? is_undefined(ys)
159
              : is_function(xs)
×
160
                ? // we know now that xs is a function,
161
                  // but we use an if check anyway to make use of the type predicate
162
                  is_function(ys) && xs === ys
×
163
                : false;
164
}
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