risei 1.0.4 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +236 -339
  2. package/index.js +8 -8
  3. package/package.json +23 -9
  4. package/{public/javascript → system}/ASpoofingFixture.js +1 -1
  5. package/{public/javascript → system}/ChosenTestFinder.js +4 -3
  6. package/{public/javascript → system}/SpoofClassMethodsFixture.js +38 -22
  7. package/system/SpoofObjectMethodsFixture.js +58 -0
  8. package/{public/javascript → system}/SpoofTuple.js +14 -1
  9. package/{public/javascript → system}/TerminalReporter.js +249 -222
  10. package/system/TestFrame.js +187 -0
  11. package/system/TestFrameChooser.js +54 -0
  12. package/system/TestFrames.js +232 -0
  13. package/system/TestResult.js +187 -0
  14. package/system/TestRunner.js +280 -0
  15. package/system/TestStages.js +278 -0
  16. package/{public/javascript → system}/TestTuple.js +132 -13
  17. package/{public/javascript → system}/TotalComparer.js +12 -0
  18. package/system/TotalCopier.js +79 -0
  19. package/system/TotalDisplayer.js +143 -0
  20. package/system/TypeAnalyzer.js +103 -0
  21. package/system/TypeIdentifier.js +70 -0
  22. package/system/Types.js +17 -0
  23. package/tests/other-tests/ASpoofingFixture.tests.js +242 -0
  24. package/tests/other-tests/SpoofClassesFixture.tests.js +130 -0
  25. package/tests/other-tests/SpoofObjectsFixture.tests.js +95 -0
  26. package/tests/other-tests/SpoofTuple.tests.js +93 -0
  27. package/tests/other-tests/TotalComparer.tests.js +920 -0
  28. package/tests/other-tests/package.json +7 -0
  29. package/tests/risei-tests/ASpoofingFixtureTests.rt.js +51 -0
  30. package/tests/risei-tests/MomentTests.rt.js +103 -0
  31. package/tests/risei-tests/SpoofTupleTests.rt.js +274 -0
  32. package/tests/risei-tests/TestFrameChooserTests.rt.js +74 -0
  33. package/tests/risei-tests/TestFrameTests.rt.js +84 -0
  34. package/tests/risei-tests/TestStagesTests.rt.js +99 -0
  35. package/tests/risei-tests/TestTupleTests.rt.js +140 -0
  36. package/tests/risei-tests/TotalComparerTests.rt.js +184 -0
  37. package/tests/risei-tests/TotalCopierTests.rt.js +74 -0
  38. package/tests/risei-tests/TotalDisplayerTests.rt.js +186 -0
  39. package/tests/risei-tests/TypeAnalyzerTests.rt.js +29 -0
  40. package/tests/risei-tests/TypeIdentifierTests.rt.js +44 -0
  41. package/tests/self-tests/SelfTests.outward-rt.js +583 -0
  42. package/tests/target-objects/CompositionModel.js +38 -0
  43. package/tests/target-objects/ConditionalThrowModel.js +11 -0
  44. package/tests/target-objects/CountModel.js +46 -0
  45. package/tests/target-objects/DomModel.js +37 -0
  46. package/tests/target-objects/MixedContents.js +33 -0
  47. package/tests/target-objects/MutationModel.js +27 -0
  48. package/tests/target-objects/ObjectCompositionModel.js +34 -0
  49. package/tests/target-objects/PolySpoofableInner.js +30 -0
  50. package/tests/target-objects/PolySpoofableOuter.js +52 -0
  51. package/tests/target-objects/PropertiesModel.js +47 -0
  52. package/tests/target-objects/Returner.js +9 -0
  53. package/tests/target-objects/SearchModel.js +25 -0
  54. package/tests/target-objects/SortModel.js +91 -0
  55. package/tests/target-objects/SpoofCaller.js +24 -0
  56. package/tests/target-objects/Spoofable.js +36 -0
  57. package/tests/target-objects/SpoofableArgsCaller.js +33 -0
  58. package/tests/target-objects/StateModel.js +34 -0
  59. package/tests/target-objects/StaticModel.js +17 -0
  60. package/tests/target-objects/TestableModel.js +47 -0
  61. package/tests/topic-tests/TopicTests.outward-rt.js +354 -0
  62. package/public/javascript/SpoofObjectMethodsFixture.js +0 -52
  63. package/public/javascript/TestResult.js +0 -338
  64. package/public/javascript/TestRunner.js +0 -476
  65. /package/{public/javascript → system}/AComparer.js +0 -0
  66. /package/{public/javascript → system}/ATestCaller.js +0 -0
  67. /package/{public/javascript → system}/ATestFinder.js +0 -0
  68. /package/{public/javascript → system}/ATestFixture.js +0 -0
  69. /package/{public/javascript → system}/ATestReporter.js +0 -0
  70. /package/{public/javascript → system}/ATestSource.js +0 -0
  71. /package/{public/javascript → system}/ClassTestGroup.js +0 -0
  72. /package/{public/javascript → system}/LocalCaller.js +0 -0
  73. /package/{public/javascript → system}/MethodTestGroup.js +0 -0
  74. /package/{public/javascript → system}/Moment.js +0 -0
  75. /package/{public/javascript → system}/Risei.js +0 -0
  76. /package/{public/javascript → system}/TestFinder.js +0 -0
  77. /package/{public/javascript → system}/TestGroup.js +0 -0
  78. /package/{public/javascript → system}/TestSummary.js +0 -0
@@ -1,8 +1,23 @@
1
1
  /**/
2
2
 
3
+ import { TypeAnalyzer } from "./TypeAnalyzer.js";
4
+
3
5
  /* Defines what is found in a test-definition tuple (TDT). Actual TDTs don't need to be instances of this class. */
4
6
 
5
7
  export class TestTuple {
8
+ // region Definitions
9
+
10
+ static staticName = "static";
11
+ static throwName = "throw";
12
+ static constructorName = "constructor";
13
+ static nonceLocalCallableName = "localCallable";
14
+ static dotOperator = ".";
15
+ static colonOperator = ":";
16
+ static parensOperator = "()";
17
+ static operatorsRegExp = /\.|:|\(\)/g;
18
+
19
+ // endregion Definitions
20
+
6
21
  // region Static fields
7
22
 
8
23
  static longsByShort = new Map([
@@ -11,6 +26,7 @@ export class TestTuple {
11
26
  [ "with", "initors" ],
12
27
  [ "of", "method" ],
13
28
  [ "plus", "spoofed" ],
29
+ [ "amid", "settables" ],
14
30
  [ "in", "inputs" ],
15
31
  [ "out", "output" ],
16
32
  [ "from", "source" ],
@@ -21,6 +37,12 @@ export class TestTuple {
21
37
 
22
38
  // region Private fields
23
39
 
40
+ #typeAnalyzer;
41
+
42
+ // endregion Private fields
43
+
44
+ // region Fields
45
+
24
46
  /* These longer names match the constructor-arg names.
25
47
  The short-name properties use the same fields. */
26
48
 
@@ -29,12 +51,25 @@ export class TestTuple {
29
51
  initors;
30
52
  method;
31
53
  spoofed;
54
+ settables;
32
55
  inputs;
33
56
  output;
34
57
  source;
35
58
  factors;
59
+
60
+ /* &cruft, possibly drop defaults when properties settable in tests */
61
+ // These fields are not part of collapse-forward system:
62
+ // Local copies of args; local test targets; outcome fields.
63
+ localInitors = [ ];
64
+ localInputs = [ ];
36
65
 
37
- // endregion Private fields
66
+ localTarget;
67
+ localMethod;
68
+
69
+ actual;
70
+ thrown;
71
+
72
+ // endregion Fields
38
73
 
39
74
  // region Properties
40
75
 
@@ -81,6 +116,15 @@ export class TestTuple {
81
116
  set plus(value) {
82
117
  this.spoofed = value;
83
118
  }
119
+
120
+ /* &cruft, rename this .amid property pair */
121
+ get amid() {
122
+ return this.settables;
123
+ }
124
+
125
+ set amid(value) {
126
+ this.settables = value;
127
+ }
84
128
 
85
129
  get in() {
86
130
  return this.inputs;
@@ -116,7 +160,7 @@ export class TestTuple {
116
160
 
117
161
  // endregion Test definition, short names
118
162
 
119
- // region Tuple state
163
+ // region Tuple state and dependencies
120
164
 
121
165
  get isRunnable() {
122
166
  let isRunnable
@@ -130,7 +174,71 @@ export class TestTuple {
130
174
  return isRunnable;
131
175
  }
132
176
 
133
- // endregion Tuple state
177
+ get isInstanceTest() /* passed */ {
178
+ return !this.isStaticTest || this.isConstructorTest;
179
+ }
180
+
181
+ get isStaticTest() /* passed */ {
182
+ let does = this.andStringContains(TestTuple.staticName);
183
+ return does;
184
+ }
185
+
186
+ get isThrowTest() /* passed */ {
187
+ let is = this.andStringContains(TestTuple.throwName);
188
+ return is;
189
+ }
190
+
191
+ /* Needed externally, and dependency
192
+ of all .and-based properties. */
193
+ andStringContains(keyword) /* passed */ {
194
+ let doesContain
195
+ = typeof this.and === "string"
196
+ && this.and.includes(keyword);
197
+
198
+ return doesContain;
199
+ }
200
+
201
+ get isConstructorTest() /* passed */ {
202
+ let plainTarget = TestTuple.plainNameOf(this.of);
203
+ return plainTarget === TestTuple.constructorName;
204
+ }
205
+
206
+ get isMethodTest() /* passed */ {
207
+ return !this.isPropertyTest;
208
+ }
209
+
210
+ get isPropertyTest() /* passed */ {
211
+ let plainName = TestTuple.plainNameOf(this.of);
212
+
213
+ let isPropertyTest
214
+ = this.of.startsWith(TestTuple.dotOperator)
215
+ || this.of.endsWith(TestTuple.colonOperator)
216
+ || this.#typeAnalyzer.memberIsProperty(plainName);
217
+
218
+ return isPropertyTest;
219
+ }
220
+
221
+ get isRetrievalTest() /* passed */ {
222
+ // Falsy code elements never are a retrieval.
223
+ if (!this.from) {
224
+ return false;
225
+ }
226
+
227
+ // If a (non-falsy) string, must be a retrieval.
228
+ if (typeof this.from === "string") {
229
+ return true;
230
+ }
231
+
232
+ // If a function, is a retrieval.
233
+ if (this.from instanceof Function) {
234
+ return true;
235
+ }
236
+
237
+ // Anything else is not a retrieval.
238
+ return false;
239
+ }
240
+
241
+ // endregion Tuple state and dependencies
134
242
 
135
243
  // endregion Properties
136
244
 
@@ -138,16 +246,19 @@ export class TestTuple {
138
246
 
139
247
  /* Constructor can't use param names like `for`, because when not .-prefixed, they are keywords. */
140
248
 
141
- constructor(nature, type, spoofed, initors, method, inputs, output, source, factors) {
142
- this.nature = nature;
143
- this.type = type;
144
- this.spoofed = spoofed;
145
- this.initors = initors;
146
- this.method = method;
147
- this.inputs = inputs;
148
- this.output = output;
149
- this.source = source;
150
- this.factors = factors;
249
+ constructor(nature, type, spoofed, initors, settables, method, inputs, output, source, factors) {
250
+ this.nature = nature; // .for
251
+ this.type = type; // .on
252
+ this.spoofed = spoofed; // .plus
253
+ this.initors = initors; // .with
254
+ this.settables = settables; // .amid
255
+ this.method = method; // .of
256
+ this.inputs = inputs; // .in
257
+ this.output = output; // .out
258
+ this.source = source; // .from
259
+ this.factors = factors; // .and
260
+
261
+ this.#typeAnalyzer = new TypeAnalyzer(this.type);
151
262
  }
152
263
 
153
264
  static fromNonceTuples(nonces) {
@@ -241,4 +352,12 @@ export class TestTuple {
241
352
 
242
353
  // endregion Initing, including constructor()
243
354
 
355
+ // region Other statics
356
+
357
+ static plainNameOf(name) /* passed */ {
358
+ let plain = name.replaceAll(TestTuple.operatorsRegExp, "");
359
+ return plain;
360
+ }
361
+
362
+ // endregion Other statics
244
363
  }
@@ -36,6 +36,10 @@ export class TotalComparer extends AComparer {
36
36
  return this.#compareFunctions(expected, actual);
37
37
  }
38
38
 
39
+ if (expected instanceof Date) {
40
+ return this.#compareDates(expected, actual);
41
+ }
42
+
39
43
  if (expected instanceof Object) {
40
44
  /* Traverse / recurse to leaves. */
41
45
  return this.#recurseOverObjects(expected, actual);
@@ -223,6 +227,14 @@ export class TotalComparer extends AComparer {
223
227
  return expectedCode === actualCode;
224
228
  }
225
229
 
230
+ #compareDates(expected, actual) /* verified */ {
231
+ if (!(actual instanceof Date)) {
232
+ return false;
233
+ }
234
+
235
+ return expected.valueOf() === actual.valueOf();
236
+ }
237
+
226
238
  // endregion Dependencies of compare()
227
239
 
228
240
  }
@@ -0,0 +1,79 @@
1
+ /**/
2
+
3
+ export class TotalCopier {
4
+ copy(original) /* passed */ {
5
+ return this.recursiveCopy(original);
6
+ }
7
+
8
+ recursiveCopy(original) /* verified */ {
9
+ /* &cruft, factor, possibly abstracting similar code,
10
+ and/or return copy only once, or similar */
11
+
12
+ /* Algorithm: First copied at current level by value if a value, by reference if
13
+ not a value; then recursively replaced at next level, and so on. */
14
+
15
+ let copy;
16
+
17
+ if (Array.isArray(original)) {
18
+ copy = [ ];
19
+
20
+ // Traversal construction with recursion.
21
+ for (let item of original) {
22
+ let next = this.recursiveCopy(item);
23
+ copy.push(next);
24
+ }
25
+
26
+ return copy;
27
+ }
28
+
29
+ if (original instanceof Map) {
30
+ copy = new Map();
31
+
32
+ // Traversal construction with recursion.
33
+ for (let entry of original.entries()) {
34
+ let next = this.recursiveCopy(entry);
35
+ copy.set(next[0], next[1]);
36
+ }
37
+
38
+ return copy;
39
+ }
40
+
41
+ if (original instanceof Set) {
42
+ copy = new Set();
43
+
44
+ // Traversal construction with recursion.
45
+ for (let value of original.values()) {
46
+ let next = this.recursiveCopy(value);
47
+ copy.add(next);
48
+ }
49
+
50
+ return copy;
51
+ }
52
+
53
+ if (original instanceof Date) {
54
+ copy = new Date(original);
55
+ return copy;
56
+ }
57
+
58
+ if (original instanceof Object) {
59
+ copy = { };
60
+
61
+ let keys = Object.keys(original);
62
+
63
+ // Traversal construction with recursion.
64
+ for (let key of Object.keys(original)) {
65
+ let next = this.recursiveCopy(original[key]);
66
+ copy[key] = next;
67
+ }
68
+
69
+ return copy;
70
+ }
71
+
72
+ /* &cruft, other object types here */
73
+
74
+ // All object types exhausted, so this is a value,
75
+ // which can be used directly for a copy.
76
+ copy = original;
77
+ return copy;
78
+ }
79
+ }
@@ -0,0 +1,143 @@
1
+ /**/
2
+
3
+ import { TypeIdentifier } from "./TypeIdentifier.js";
4
+ import { Types } from "./Types.js";
5
+
6
+ export class TotalDisplayer {
7
+ #identifier;
8
+
9
+ constructor() /* verified */ {
10
+ this.#identifier = new TypeIdentifier();
11
+ }
12
+
13
+ display(value) /* passed */ {
14
+ let typeId = this.#identifier.identify(value);
15
+
16
+ switch (typeId) {
17
+ case Types.isValue: return this.displayValue(value);
18
+ case Types.isString: return this.displayString(value);
19
+ case Types.isArray: return this.displayArray(value);
20
+ case Types.isMap: return this.displayMap(value);
21
+ case Types.isSet: return this.displaySet(value);
22
+ case Types.isClass: return this.displayClass(value);
23
+ case Types.isFunction: return this.displayFunction(value);
24
+ case Types.isObject: return this.displayObject(value);
25
+ case Types.isDate: return this.displayValue(value);
26
+ case Types.isUndefined: return this.displayUndefined(value);
27
+ case Types.isNull: return this.displayNull(value);
28
+ }
29
+ }
30
+
31
+ // region Displaying different types
32
+
33
+ /* Plain values (numbers, booleans) and Dates
34
+ are handled together using JS defaults. */
35
+ displayValue(value) /* passed */ {
36
+ return `${ value }`;
37
+ }
38
+
39
+ displayString(value) /* passed */ {
40
+ return `"${ value }"`;
41
+ }
42
+
43
+ displayArray(value) /* passed */ {
44
+ // Cross-recursion.
45
+ let outputs = value
46
+ .map(x => this.display(x));
47
+
48
+ // Brackets around, commas between.
49
+ let output = `[${ outputs.join(",") }]`;
50
+
51
+ // And back to caller.
52
+ return output;
53
+ }
54
+
55
+ displayMap(value) /* passed */ {
56
+ // Array used for clearer display.
57
+ let items = [ ];
58
+
59
+ // Each key-value pair is handled individually.
60
+ for (let key of value.keys()) {
61
+ let item = value.get(key);
62
+
63
+ // Cross-recursion.
64
+ items.push(`${ this.display(key) }:${ this.display(item) }`);
65
+ }
66
+
67
+ // Key-value pairs are all listed together.
68
+ let output = `Map{${ items.join(",") }}`;
69
+ return output;
70
+ }
71
+
72
+ displaySet(value) /* passed */ {
73
+ // Array used for clearer display.
74
+ let items = [ ];
75
+
76
+ // Each element is handled individually.
77
+ for (let item of value) {
78
+ // Cross-recursion for styling values.
79
+ let display = `${ this.display(item) }`;
80
+ items.push(display);
81
+ }
82
+
83
+ // Items are all listed together.
84
+ let output = `Set{${ items.join(",") }}`;
85
+ return output;
86
+ }
87
+
88
+ displayClass(value) /* passed */ {
89
+ // Class definitions have a .name.
90
+ let output = value.name;
91
+ return output;
92
+ }
93
+
94
+ displayFunction(value) /* passed */ {
95
+ // toString() lists the definition, including code.
96
+ let output = value.toString();
97
+
98
+ // Most whitespace is eliminated for readability.
99
+ output = output.replace(/(\r\n?)/g, "");
100
+ output = output.replace(/\s{2,}/g, " ");
101
+
102
+ // Back to caller.
103
+ return output;
104
+ }
105
+
106
+ displayObject(value) /* passed */ {
107
+ // Use toString() text if it's meaningful.
108
+ let asString = value.toString();
109
+
110
+ if (asString !== "[object Object]") {
111
+ return asString;
112
+ }
113
+
114
+ // If toString() not meaningful, list members.
115
+ let items = [ ];
116
+
117
+ // Each property of the object is handled individually.
118
+ for (let p in value) {
119
+ // Cross-recursion.
120
+ let item = this.display(value[p]);
121
+ items.push(`${ p }:${ item }`);
122
+ }
123
+
124
+ // Properties are all listed together.
125
+ let output = `{ ${ items.join(", ") } }`;
126
+
127
+ // If empty, internal empty space reduced.
128
+ output = output !== "{ }" ? output : "{ }";
129
+
130
+ // Back to caller.
131
+ return output;
132
+ }
133
+
134
+ displayUndefined(value) /* passed */ {
135
+ return "undefined";
136
+ }
137
+
138
+ displayNull(value) /* passed */ {
139
+ return "null";
140
+ }
141
+
142
+ // endregion Displaying different types
143
+ }
@@ -0,0 +1,103 @@
1
+ /**/
2
+
3
+ /* Used to analyze classes / members of classes being tested. */
4
+
5
+ export class TypeAnalyzer {
6
+ // region Definitions
7
+
8
+ static constructorName = "constructor";
9
+ static getName = "get";
10
+ static setName = "set";
11
+
12
+ // endregion Definitions
13
+
14
+ // region Fields
15
+
16
+ #type;
17
+
18
+ // endregion Fields
19
+
20
+ constructor(type) {
21
+ this.#type = type;
22
+ }
23
+
24
+ /* Returns true if instance or static member is a property (value or accessor). Returns false if member is a method. */
25
+ memberIsProperty(name) /* passed */ {
26
+ // Constructor is never a property and is irregular,
27
+ // so other type-analysis code can't handle it.
28
+ if (name === TypeAnalyzer.constructorName) {
29
+ return false;
30
+ }
31
+
32
+ // Static methods and properties (value or accessor) are on type.
33
+ if (name in this.#type) {
34
+ return this.#staticMemberIsProperty(this.#type, name);
35
+ }
36
+
37
+ // Methods and accessor properties are on prototype.
38
+ if (name in this.#type.prototype) {
39
+ return this.#instanceMemberIsProperty(this.#type.prototype, name);
40
+ }
41
+
42
+ // Instance value properties are not on type or prototype.
43
+ return true;
44
+ }
45
+
46
+ // region Dependencies of memberIsProperty()
47
+
48
+ /* Algorithm specialized with function check for static members. */
49
+ #staticMemberIsProperty(type, name) {
50
+ let descriptor = Object.getOwnPropertyDescriptor(type, name);
51
+
52
+ // If on type and has accessors, it's a static accessor property.
53
+ if (this.#doesHaveAccessorProps(descriptor)) {
54
+ return true;
55
+ }
56
+
57
+ // If on type and has non-Function .value, it's a static value property.
58
+ if (this.#doesNotHaveFunctionValue(descriptor)) {
59
+ return true;
60
+ }
61
+
62
+ // If on type but not a static property, it's a static method.
63
+ return false;
64
+ }
65
+
66
+ /* Algorithm specialized for instance members, no function check. */
67
+ #instanceMemberIsProperty(prototype, name) {
68
+ let descriptor = Object.getOwnPropertyDescriptor(prototype, name);
69
+
70
+ // If on prototype and has accessors, it's an accessor property.
71
+ if (this.#doesHaveAccessorProps(descriptor)) {
72
+ return true;
73
+ }
74
+
75
+ // If on prototype but not an accessor property, it's a method.
76
+ return false;
77
+ }
78
+
79
+ // region Internally reused dependencies of other memberIsProperty() dependencies
80
+
81
+ #doesHaveAccessorProps(descriptor) /* verified */ {
82
+ // Accessor properties have one or both of these in descriptor.
83
+ if (TypeAnalyzer.getName in descriptor || TypeAnalyzer.setName in descriptor) {
84
+ return true;
85
+ }
86
+
87
+ return false;
88
+ }
89
+
90
+ #doesNotHaveFunctionValue(descriptor) /* verified */ {
91
+ // Simple inverter of other method for readability.
92
+ return !this.#doesHaveFunctionValue(descriptor);
93
+ }
94
+
95
+ #doesHaveFunctionValue(descriptor) /* verified */ {
96
+ // If no member, .value of undefined.
97
+ return descriptor.value instanceof Function;
98
+ }
99
+
100
+ // endregion Internally reused dependencies of other memberIsProperty() dependencies
101
+
102
+ // endregion Dependencies of memberIsProperty()
103
+ }
@@ -0,0 +1,70 @@
1
+ /**/
2
+
3
+ import { Types } from "./Types.js";
4
+
5
+ export class TypeIdentifier {
6
+ identify(value) /* passed */ {
7
+ // Basis for most top branching.
8
+ let rawType = typeof value;
9
+
10
+ // Array, Map, Set, Date, null, and actual
11
+ // objects are all "object" to JavaScript.
12
+ if (rawType === "object") {
13
+ if (Array.isArray(value)) {
14
+ return Types.isArray;
15
+ }
16
+
17
+ if (value instanceof Map) {
18
+ return Types.isMap;
19
+ }
20
+
21
+ if (value instanceof Set) {
22
+ return Types.isSet;
23
+ }
24
+
25
+ if (value instanceof Date) {
26
+ return Types.isDate;
27
+ }
28
+
29
+ if (value === null) {
30
+ return Types.isNull;
31
+ }
32
+
33
+ return Types.isObject;
34
+ }
35
+
36
+ // Functions and classes are both "function" to Javascript.
37
+ if (rawType === "function") {
38
+ // Functions can be anonymous.
39
+ if (!value.name) {
40
+ return Types.isFunction;
41
+ }
42
+
43
+ // Classes all start with this syntax
44
+ // in their defs (never with `export`).
45
+ let classSyntax = `class ${ value.name }`;
46
+
47
+ let definition = value.toString();
48
+
49
+ if (definition.startsWith(classSyntax)) {
50
+ return Types.isClass;
51
+ }
52
+
53
+ // Function but not class is a named function.
54
+ return Types.isFunction;
55
+ }
56
+
57
+ // Strings may be handled specially.
58
+ if (typeof value === "string") {
59
+ return Types.isString;
60
+ }
61
+
62
+ // Undefined is different from the rest.
63
+ if (value === undefined) {
64
+ return Types.isUndefined;
65
+ }
66
+
67
+ // Non-string values all handled the same.
68
+ return Types.isValue;
69
+ }
70
+ }
@@ -0,0 +1,17 @@
1
+ /**/
2
+
3
+ export class Types {
4
+ /* This class is essentially an enum. */
5
+
6
+ static isValue = "value";
7
+ static isString = "string";
8
+ static isArray = "array";
9
+ static isObject = "object";
10
+ static isMap = "map";
11
+ static isSet = "set";
12
+ static isFunction = "function";
13
+ static isClass = "class";
14
+ static isDate = "date";
15
+ static isUndefined = "undefined";
16
+ static isNull = "null";
17
+ }