From 303bff7361f7478d0bfef5b7a450c5a9f99387ed Mon Sep 17 00:00:00 2001
From: Ufuk Kayserilioglu <ufuk.kayserilioglu@shopify.com>
Date: Tue, 29 Apr 2025 21:45:52 +0300
Subject: [PATCH] Revert the removal of UTF-8 force encoding in JSON loading

I think the removal of the force encoding in https://github.com/rails/spring/pull/719 was a mistake. For example, my shell prompt includes multi-byte UTF-8 characters, and when `Spring::Client::Run#run_command` collects the environment variables using `ENV.to_hash`, the resulting JSON string becomes ASCII-8BIT. This causes issues when the `Spring::Application#serve` tries to load the JSON string and passes it to `JSON.load`. Since `OkJson` expects UTF-8 encoded strings, it raises an error when it encounters the ASCII-8BIT string.

I've added a test case that replicates this issue to ensure that the encoding is handled correctly. The test case creates a JSON string with multi-byte UTF-8 characters as an ASCII-8BIT string and verifies that it can be loaded without raising an error.
---
 lib/spring/json.rb     | 1 +
 test/unit/json_test.rb | 7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/spring/json.rb b/lib/spring/json.rb
index 00f0dca3..c90c251d 100644
--- a/lib/spring/json.rb
+++ b/lib/spring/json.rb
@@ -13,6 +13,7 @@
 module Spring
   module JSON
     def self.load(string)
+      string = string.dup.force_encoding("utf-8") unless string.encoding == Encoding::UTF_8
       OkJson.decode(string)
     end
 
diff --git a/test/unit/json_test.rb b/test/unit/json_test.rb
index b9eecc05..3b5eb0ec 100644
--- a/test/unit/json_test.rb
+++ b/test/unit/json_test.rb
@@ -6,7 +6,12 @@ class JsonTest < ActiveSupport::TestCase
     assert_equal({"unicode_example"=>"©"}, Spring::JSON.load('{"unicode_example": "\u00A9"}'))
   end
 
+  test 'can decode binary strings with valid UTF8 characters' do
+    string = "{\"PS1\":\"\xEF\x90\x98 main \xEE\x9E\x91 v3.4.2\"}".b
+    assert_equal({"PS1"=>" main  v3.4.2"}, Spring::JSON.load(string))
+  end
+
   test 'can encode' do
     assert_equal('{}', Spring::JSON.dump({}))
-  end 
+  end
 end