|
139 | 139 | /// throw `EncodeError.cyclicObject`, which we relay as `NSError`.
|
140 | 140 | @inline(__always)
|
141 | 141 | internal static func bridgeInputForEncode(_ input: Any) -> Any {
|
142 |
| - let seen = NSHashTable<AnyObject>.weakObjects() |
143 |
| - return _bridgeInputForEncode(input, seen: seen) |
| 142 | + var seen = Set<ObjectIdentifier>() |
| 143 | + return _bridgeInputForEncode(input, seen: &seen) |
144 | 144 | }
|
145 | 145 |
|
146 | 146 | @inline(__always)
|
147 |
| - private static func _bridgeInputForEncode(_ input: Any, seen: NSHashTable<AnyObject>) -> Any |
| 147 | + private static func _bridgeInputForEncode(_ input: Any, seen: inout Set<ObjectIdentifier>) |
| 148 | + -> Any |
148 | 149 | {
|
149 | 150 | switch input {
|
150 | 151 | // Strings
|
|
155 | 156 | case let od as OrderedDictionary<String, Any>:
|
156 | 157 | var out = OrderedDictionary<String, Any>()
|
157 | 158 | out.reserveCapacity(od.count)
|
158 |
| - for (k, v) in od { out[k] = _bridgeInputForEncode(v, seen: seen) } |
| 159 | + for (k, v) in od { out[k] = _bridgeInputForEncode(v, seen: &seen) } |
159 | 160 | return out
|
160 | 161 |
|
161 | 162 | // Already ordered Swift dict (NSString keys)
|
162 | 163 | case let od as OrderedDictionary<NSString, Any>:
|
163 | 164 | var out = OrderedDictionary<String, Any>()
|
164 | 165 | out.reserveCapacity(od.count)
|
165 |
| - for (k, v) in od { out[k as String] = _bridgeInputForEncode(v, seen: seen) } |
| 166 | + for (k, v) in od { out[k as String] = _bridgeInputForEncode(v, seen: &seen) } |
166 | 167 | return out
|
167 | 168 |
|
168 | 169 | // NSDictionary → OrderedDictionary<String, Any> (stringify keys)
|
169 | 170 | case let d as NSDictionary:
|
170 | 171 | let obj = d as AnyObject
|
171 |
| - if seen.contains(obj) { |
| 172 | + let id = ObjectIdentifier(obj) |
| 173 | + if seen.contains(id) { |
172 | 174 | // Cycle detected: keep the original reference so the core can report cyclicObject.
|
173 | 175 | return d
|
174 | 176 | }
|
175 |
| - seen.add(obj) |
| 177 | + seen.insert(id) |
176 | 178 |
|
177 | 179 | var out = OrderedDictionary<String, Any>()
|
178 | 180 | out.reserveCapacity(d.count)
|
179 | 181 | d.forEach { (k, v) in
|
180 |
| - out[stringifyKey(k)] = _bridgeInputForEncode(v, seen: seen) |
| 182 | + out[stringifyKey(k)] = _bridgeInputForEncode(v, seen: &seen) |
181 | 183 | }
|
182 | 184 | return out
|
183 | 185 |
|
184 | 186 | // NSArray → [Any]
|
185 | 187 | case let a as NSArray:
|
186 | 188 | let obj = a as AnyObject
|
187 |
| - if seen.contains(obj) { return a } |
188 |
| - seen.add(obj) |
189 |
| - return a.map { _bridgeInputForEncode($0, seen: seen) } |
| 189 | + let id = ObjectIdentifier(obj) |
| 190 | + if seen.contains(id) { return a } |
| 191 | + seen.insert(id) |
| 192 | + return a.map { _bridgeInputForEncode($0, seen: &seen) } |
190 | 193 |
|
191 | 194 | // Plain Swift dict → OrderedDictionary<String, Any>
|
192 | 195 | case let d as [String: Any]:
|
193 | 196 | var out = OrderedDictionary<String, Any>()
|
194 | 197 | out.reserveCapacity(d.count)
|
195 |
| - for (k, v) in d { out[k] = _bridgeInputForEncode(v, seen: seen) } |
| 198 | + for (k, v) in d { out[k] = _bridgeInputForEncode(v, seen: &seen) } |
196 | 199 | return out
|
197 | 200 |
|
198 | 201 | // Plain Swift array
|
199 | 202 | case let a as [Any]:
|
200 |
| - return a.map { _bridgeInputForEncode($0, seen: seen) } |
| 203 | + return a.map { _bridgeInputForEncode($0, seen: &seen) } |
201 | 204 |
|
202 | 205 | // Scalars / everything else
|
203 | 206 | default:
|
|
214 | 217 | /// - **Identity cycles** (returns the original Foundation object when revisiting it)
|
215 | 218 | @inline(__always)
|
216 | 219 | internal static func bridgeUndefinedPreservingOrder(_ v: Any?) -> Any? {
|
217 |
| - let seen = NSHashTable<AnyObject>.weakObjects() |
218 |
| - return _bridgeUndefinedPreservingOrder(v, seen: seen) |
| 220 | + var seen = Set<ObjectIdentifier>() |
| 221 | + return _bridgeUndefinedPreservingOrder(v, seen: &seen) |
219 | 222 | }
|
220 | 223 |
|
221 | 224 | @inline(__always)
|
222 | 225 | internal static func _bridgeUndefinedPreservingOrder(
|
223 |
| - _ v: Any?, seen: NSHashTable<AnyObject> |
224 |
| - ) |
225 |
| - -> Any? |
226 |
| - { |
| 226 | + _ v: Any?, seen: inout Set<ObjectIdentifier> |
| 227 | + ) -> Any? { |
227 | 228 | switch v {
|
228 | 229 | // ObjC sentinel → Swift sentinel
|
229 | 230 | case is UndefinedObjC:
|
|
234 | 235 | var out = OrderedDictionary<String, Any>()
|
235 | 236 | out.reserveCapacity(od.count)
|
236 | 237 | for (k, val) in od {
|
237 |
| - out[k] = _bridgeUndefinedPreservingOrder(val, seen: seen) ?? val |
| 238 | + out[k] = _bridgeUndefinedPreservingOrder(val, seen: &seen) ?? val |
238 | 239 | }
|
239 | 240 | return out
|
240 | 241 |
|
|
243 | 244 | var out = OrderedDictionary<String, Any>()
|
244 | 245 | out.reserveCapacity(od.count)
|
245 | 246 | for (k, val) in od {
|
246 |
| - out[k as String] = _bridgeUndefinedPreservingOrder(val, seen: seen) ?? val |
| 247 | + out[k as String] = _bridgeUndefinedPreservingOrder(val, seen: &seen) ?? val |
247 | 248 | }
|
248 | 249 | return out
|
249 | 250 |
|
250 | 251 | // NSDictionary → OrderedDictionary<String, Any>
|
251 | 252 | case let d as NSDictionary:
|
252 | 253 | let obj = d as AnyObject
|
253 |
| - if seen.contains(obj) { return d } // keep cycles |
254 |
| - seen.add(obj) |
| 254 | + let id = ObjectIdentifier(obj) |
| 255 | + if seen.contains(id) { return d } // keep cycles |
| 256 | + seen.insert(id) |
255 | 257 | var out = OrderedDictionary<String, Any>()
|
256 | 258 | out.reserveCapacity(d.count)
|
257 | 259 | d.forEach { (k, val) in
|
258 |
| - out[stringifyKey(k)] = _bridgeUndefinedPreservingOrder(val, seen: seen) ?? val |
| 260 | + out[stringifyKey(k)] = _bridgeUndefinedPreservingOrder(val, seen: &seen) ?? val |
259 | 261 | }
|
260 | 262 | return out
|
261 | 263 |
|
262 | 264 | // NSArray → [Any]
|
263 | 265 | case let a as NSArray:
|
264 | 266 | let obj = a as AnyObject
|
265 |
| - if seen.contains(obj) { return a } |
266 |
| - seen.add(obj) |
267 |
| - return a.map { _bridgeUndefinedPreservingOrder($0, seen: seen) ?? $0 } |
| 267 | + let id = ObjectIdentifier(obj) |
| 268 | + if seen.contains(id) { return a } |
| 269 | + seen.insert(id) |
| 270 | + return a.map { _bridgeUndefinedPreservingOrder($0, seen: &seen) ?? $0 } |
268 | 271 |
|
269 | 272 | // Plain Swift dict → OrderedDictionary<String, Any>
|
270 | 273 | case let d as [String: Any]:
|
271 | 274 | var out = OrderedDictionary<String, Any>()
|
272 | 275 | out.reserveCapacity(d.count)
|
273 | 276 | for (k, val) in d {
|
274 |
| - out[k] = _bridgeUndefinedPreservingOrder(val, seen: seen) ?? val |
| 277 | + out[k] = _bridgeUndefinedPreservingOrder(val, seen: &seen) ?? val |
275 | 278 | }
|
276 | 279 | return out
|
277 | 280 |
|
278 | 281 | // Plain Swift array
|
279 | 282 | case let a as [Any]:
|
280 |
| - return a.map { _bridgeUndefinedPreservingOrder($0, seen: seen) ?? $0 } |
| 283 | + return a.map { _bridgeUndefinedPreservingOrder($0, seen: &seen) ?? $0 } |
281 | 284 |
|
282 | 285 | // Scalars / everything else
|
283 | 286 | default:
|
|
0 commit comments