risei 1.2.0 → 1.3.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.
@@ -1,79 +1,106 @@
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
- }
1
+ /**/
2
+
3
+ import { TypeIdentifier } from "./TypeIdentifier.js";
4
+ import { Types } from "./Types.js";
5
+
6
+ export class TotalCopier {
7
+ #identifier = new TypeIdentifier();
8
+
9
+ copy(original) /* passed */ {
10
+ return this.recursiveCopy(original);
11
+ }
12
+
13
+ recursiveCopy(original) /* verified */ {
14
+ /* &cruft, factor, possibly abstracting similar code,
15
+ and/or return copy only once, or similar */
16
+
17
+ /* Algorithm: First copied at current level by value if a value, by reference if
18
+ not a value; then recursively replaced at next level, and so on. */
19
+
20
+ let copy;
21
+
22
+ let type = this.#identifier.identify(original);
23
+
24
+ if (type === Types.isArray) {
25
+ copy = [ ];
26
+
27
+ // Traversal construction with recursion.
28
+ for (let item of original) {
29
+ let next = this.recursiveCopy(item);
30
+ copy.push(next);
31
+ }
32
+
33
+ return copy;
34
+ }
35
+
36
+ if (type === Types.isMap) {
37
+ copy = new Map();
38
+
39
+ // Traversal construction with recursion.
40
+ for (let entry of original.entries()) {
41
+ let next = this.recursiveCopy(entry);
42
+ copy.set(next[0], next[1]);
43
+ }
44
+
45
+ return copy;
46
+ }
47
+
48
+ if (type === Types.isSet) {
49
+ copy = new Set();
50
+
51
+ // Traversal construction with recursion.
52
+ for (let value of original.values()) {
53
+ let next = this.recursiveCopy(value);
54
+ copy.add(next);
55
+ }
56
+
57
+ return copy;
58
+ }
59
+
60
+ if (type === Types.isDate) {
61
+ copy = new Date(original);
62
+ return copy;
63
+ }
64
+
65
+ // Actually copying isn't needed (or desirable) here,
66
+ // since should always point to same thing regardless.
67
+ if (type === Types.isClass) {
68
+ copy = original;
69
+ return copy;
70
+ }
71
+
72
+ // The workaround here makes a true independent copy of the
73
+ // original function, regardless of its definition style.
74
+ if (type === Types.isFunction) {
75
+ let passer = [ original ];
76
+ passer = [ ...passer ];
77
+ copy = passer[0];
78
+
79
+ return copy;
80
+ }
81
+
82
+ if (original instanceof Object) {
83
+ // If original has a prototype, it's probably a class instance,
84
+ // so it's constructed, so it includes all methods and accessors.
85
+ let prototype = Object.getPrototypeOf(original);
86
+ copy = prototype !== null ? new prototype.constructor() : { };
87
+
88
+ let keys = Object.keys(original);
89
+
90
+ // Settable properties are added, with recursion.
91
+ for (let key of Object.keys(original)) {
92
+ let next = this.recursiveCopy(original[key]);
93
+ copy[key] = next;
94
+ }
95
+
96
+ return copy;
97
+ }
98
+
99
+ /* &cruft, other object types here */
100
+
101
+ // All object types exhausted, so this is a value,
102
+ // which can be used directly for a copy.
103
+ copy = original;
104
+ return copy;
105
+ }
106
+ }
@@ -1,103 +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
- }
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
+ }