> Now the function would rather insert an escape character before the character code so that the result is still readable and valid UTF-8/UTF-16 code:
> JSON.stringify('\uD83D');
> // '"\\ud83d"'
I’m inclined to consider this a misfeature, unbreaking something that I’m glad was broken and should have remained broken.
Unpaired surrogates are (to simplify terminology a little) basically invalid Unicode. On the web platform, the only situation where unpaired surrogates should be encountered is as a transient state on user input, on platforms that send non-BMP characters through in two pieces (which is most browsers on Windows). Beyond that, nothing should ever deal in unpaired surrogates, because they will make things blow up and your life miserable.
Unpaired surrogates cannot be represented in UTF-8, or in well-formed UTF-16 (and that’s where JavaScript did the annoyingly bad thing that we’re paying for decades later, going with UTF-16 and not requiring well-formedness). Hence I’d quibble with the description of the result as “valid UTF-8/UTF-16 code”. (Sure, the actual JSON byte stream will be valid, but it contains an escaped string that is not valid.) U+FFFD REPLACEMENT CHARACTER was at least as valid, arguably more valid.
Various JSON parsers will choke on such strings, as observed in what I’d consider the canonical JSON spec: https://tools.ietf.org/html/rfc7159#section-8.2.
In the I-JSON restricted subset, which is what I’d say everything should actually limit itself to, such strings are disallowed and will cause parse failure: https://tools.ietf.org/html/rfc7493#section-2.1.