From a8763247c02ca3264cb6efa0991a4fcd67ec43a6 Mon Sep 17 00:00:00 2001 From: hippi345 <13539685+hippi345@users.noreply.github.com> Date: Thu, 15 Oct 2026 03:35:56 +0000 Subject: [PATCH] Fix decoder state restoration after decoding child The decoder's decode(_:pathComponent:) method was incorrectly saving the incoming value parameter instead of the decoder's currentValue before decoding a child. This caused the parent context to be lost after child decoding completed. Changed to save and restore currentValue, ensuring the decoder's state is properly maintained across nested decode operations. Fixes #3 --- Sources/Library/Serialization/Decoder.swift | 2 +- Sources/Tests/DecoderStateTests.swift | 27 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Sources/Tests/DecoderStateTests.swift diff --git a/Sources/Library/Serialization/Decoder.swift b/Sources/Library/Serialization/Decoder.swift index 81beba4..30a8b9c 100644 --- a/Sources/Library/Serialization/Decoder.swift +++ b/Sources/Library/Serialization/Decoder.swift @@ -30,7 +30,7 @@ extension XCJSON { let oldPath = currentPath; defer { currentPath = oldPath } - let oldCurrentValue = value; defer { + let oldCurrentValue = currentValue; defer { currentValue = oldCurrentValue } let newPath = AbsolutePath(parent: oldPath, component: pathComponent) diff --git a/Sources/Tests/DecoderStateTests.swift b/Sources/Tests/DecoderStateTests.swift new file mode 100644 index 0000000..c987c8b --- /dev/null +++ b/Sources/Tests/DecoderStateTests.swift @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// Copyright © 2026 Apple Inc. and the xcode-project-format project authors +// +// Licensed under Apache License v2.0 with Runtime Library Exception +// SPDX-License-Identifier: Apache-2.0 WITH Swift-exception +// +//===----------------------------------------------------------------------===// + +import Foundation +import Testing +import XcodeProjectFormat + +private struct ParentValueProbe: XCJSON.Decodable { + init(with coder: XCJSON.Decoder) throws { + let container = try coder.openKeyedContainer() + let _: String = try container.decode("name") + + #expect(coder.currentNodeType == .object) + _ = try coder.openKeyedContainer() + } +} + +@Test func restoresParentValueAfterDecodingChild() throws { + let _: ParentValueProbe = try XCJSON.Decoder.decode( + data: Data(#"{"name":"App"}"#.utf8) + ) +}