@@ -38,16 +38,23 @@ export interface BaseParserContextOptions extends PluginAccessOptions {
38
38
refs ?: Map < unknown , number > ;
39
39
}
40
40
41
- interface FreshReference {
42
- type : 'fresh' ;
41
+ interface FreshNode {
42
+ type : 0 ;
43
43
value : number ;
44
44
}
45
45
46
- interface CachedReference {
47
- type : 'cached' ;
48
- value : SerovalIndexedValueNode | SerovalReferenceNode ;
46
+ interface IndexedNode {
47
+ type : 1 ;
48
+ value : SerovalIndexedValueNode ;
49
49
}
50
50
51
+ interface ReferencedNode {
52
+ type : 2 ;
53
+ value : SerovalReferenceNode ;
54
+ }
55
+
56
+ type ObjectNode = FreshNode | IndexedNode | ReferencedNode ;
57
+
51
58
export abstract class BaseParserContext implements PluginAccessOptions {
52
59
abstract readonly mode : SerovalMode ;
53
60
@@ -73,78 +80,72 @@ export abstract class BaseParserContext implements PluginAccessOptions {
73
80
return this . marked . has ( id ) ;
74
81
}
75
82
76
- protected getReference < T > ( current : T ) : FreshReference | CachedReference {
83
+ protected getIndexedValue < T > ( current : T ) : FreshNode | IndexedNode {
77
84
const registeredID = this . refs . get ( current ) ;
78
85
if ( registeredID != null ) {
79
86
this . markRef ( registeredID ) ;
80
87
return {
81
- type : 'cached' ,
88
+ type : 1 ,
82
89
value : createIndexedValueNode ( registeredID ) ,
83
90
} ;
84
91
}
85
92
const id = this . refs . size ;
86
93
this . refs . set ( current , id ) ;
94
+ return {
95
+ type : 0 ,
96
+ value : id ,
97
+ } ;
98
+ }
99
+
100
+ protected getReference < T > ( current : T ) : ObjectNode {
101
+ const indexed = this . getIndexedValue ( current ) ;
102
+ if ( indexed . type === 1 ) {
103
+ return indexed ;
104
+ }
87
105
if ( hasReferenceID ( current ) ) {
88
106
return {
89
- type : 'cached' ,
90
- value : createReferenceNode ( id , current ) ,
107
+ type : 2 ,
108
+ value : createReferenceNode ( indexed . value , current ) ,
91
109
} ;
92
110
}
93
- return {
94
- type : 'fresh' ,
95
- value : id ,
96
- } ;
111
+ return indexed ;
97
112
}
98
113
99
114
protected getStrictReference < T > ( current : T ) : SerovalIndexedValueNode | SerovalReferenceNode {
100
- const registeredID = this . refs . get ( current ) ;
101
- if ( registeredID != null ) {
102
- this . markRef ( registeredID ) ;
103
- return createIndexedValueNode ( registeredID ) ;
115
+ assert ( hasReferenceID ( current ) , new Error ( 'Cannot serialize ' + typeof current + ' without reference ID.' ) ) ;
116
+ const result = this . getIndexedValue ( current ) ;
117
+ if ( result . type === 1 ) {
118
+ return result . value ;
104
119
}
105
- const id = this . refs . size ;
106
- this . refs . set ( current , id ) ;
107
- return createReferenceNode ( id , current ) ;
120
+ return createReferenceNode ( result . value , current ) ;
108
121
}
109
122
110
123
// eslint-disable-next-line @typescript-eslint/ban-types
111
124
protected parseFunction ( current : Function ) : SerovalNode {
112
- assert ( hasReferenceID ( current ) , new Error ( 'Cannot serialize function without reference ID.' ) ) ;
113
125
return this . getStrictReference ( current ) ;
114
126
}
115
127
116
128
protected parseWKSymbol (
117
129
current : symbol ,
118
130
) : SerovalIndexedValueNode | SerovalWKSymbolNode | SerovalReferenceNode {
119
- const registeredID = this . refs . get ( current ) ;
120
- if ( registeredID != null ) {
121
- this . markRef ( registeredID ) ;
122
- return createIndexedValueNode ( registeredID ) ;
123
- }
124
- const isValid = current in INV_SYMBOL_REF ;
125
- assert ( current in INV_SYMBOL_REF || hasReferenceID ( current ) , new Error ( 'Cannot serialize symbol without reference ID.' ) ) ;
126
- const id = this . refs . size ;
127
- this . refs . set ( current , id ) ;
128
- if ( isValid ) {
129
- return createWKSymbolNode ( id , current as WellKnownSymbols ) ;
131
+ const ref = this . getReference ( current ) ;
132
+ if ( ref . type !== 0 ) {
133
+ return ref . value ;
130
134
}
131
- return createReferenceNode ( id , current ) ;
135
+ assert ( current in INV_SYMBOL_REF , new Error ( 'Cannot serialized unsupported symbol.' ) ) ;
136
+ return createWKSymbolNode ( ref . value , current as WellKnownSymbols ) ;
132
137
}
133
138
134
139
protected parseSpecialReference (
135
140
ref : SpecialReference ,
136
141
) : SerovalIndexedValueNode | SerovalSpecialReferenceNode {
137
- const specialRef = SPECIAL_REFS [ ref ] ;
138
- const registeredID = this . refs . get ( specialRef ) ;
139
- if ( registeredID != null ) {
140
- this . markRef ( registeredID ) ;
141
- return createIndexedValueNode ( registeredID ) ;
142
+ const result = this . getIndexedValue ( SPECIAL_REFS [ ref ] ) ;
143
+ if ( result . type === 1 ) {
144
+ return result . value ;
142
145
}
143
- const id = this . refs . size ;
144
- this . refs . set ( specialRef , id ) ;
145
146
return {
146
147
t : SerovalNodeType . SpecialReference ,
147
- i : id ,
148
+ i : result . value ,
148
149
s : ref ,
149
150
l : undefined ,
150
151
c : undefined ,
@@ -159,16 +160,13 @@ export abstract class BaseParserContext implements PluginAccessOptions {
159
160
}
160
161
161
162
protected parseIteratorFactory ( ) : SerovalIndexedValueNode | SerovalIteratorFactoryNode {
162
- const registeredID = this . refs . get ( ITERATOR ) ;
163
- if ( registeredID != null ) {
164
- this . markRef ( registeredID ) ;
165
- return createIndexedValueNode ( registeredID ) ;
163
+ const result = this . getIndexedValue ( ITERATOR ) ;
164
+ if ( result . type === 1 ) {
165
+ return result . value ;
166
166
}
167
- const id = this . refs . size ;
168
- this . refs . set ( ITERATOR , id ) ;
169
167
return {
170
168
t : SerovalNodeType . IteratorFactory ,
171
- i : id ,
169
+ i : result . value ,
172
170
s : undefined ,
173
171
l : undefined ,
174
172
c : undefined ,
@@ -183,16 +181,13 @@ export abstract class BaseParserContext implements PluginAccessOptions {
183
181
}
184
182
185
183
protected parseAsyncIteratorFactory ( ) : SerovalIndexedValueNode | SerovalAsyncIteratorFactoryNode {
186
- const registeredID = this . refs . get ( ASYNC_ITERATOR ) ;
187
- if ( registeredID != null ) {
188
- this . markRef ( registeredID ) ;
189
- return createIndexedValueNode ( registeredID ) ;
184
+ const result = this . getIndexedValue ( ASYNC_ITERATOR ) ;
185
+ if ( result . type === 1 ) {
186
+ return result . value ;
190
187
}
191
- const id = this . refs . size ;
192
- this . refs . set ( ASYNC_ITERATOR , id ) ;
193
188
return {
194
189
t : SerovalNodeType . AsyncIteratorFactory ,
195
- i : id ,
190
+ i : result . value ,
196
191
s : undefined ,
197
192
l : undefined ,
198
193
c : undefined ,
0 commit comments