URL:     https://linuxfr.org/users/n_e/journaux/unicode-ndjson-et-bug-subtil
Title:   Unicode, NDJSON et bug subtil
Authors: n_e
Date:    2026-10-19T21:34:24+02:00
Tags:    
Score:   6


Bonjour Nal,

Pendant des années, j'ai utilisé le code suivant pour parser des fichiers NDJSON (un format de fichier qui contient un document JSON par ligne) en node.js :

```js
import { stdin } from "node:process";
import readline from "node:readline/promises";

const rl = readline.createInterface(stdin);

for await (const l of rl) {
  const data = JSON.parse(l);
}
```
Cependant il a un bug, saurez-vous le trouver ?

# La reproduction

Le bug est exhibé lorsqu'on passe le texte généré ainsi au programme ci-dessus :

```js
console.log(JSON.stringify("a\u2028b")); // Affiche le texte "a b" dans le terminal
```

# Le bug

[U+2028](https://www.compart.com/fr/unicode/U+2028) est un caractère nommé "séparateur de lignes". C'est un caractère qui est autorisé dans les chaînes de caractères JSON, et qui est considéré comme un séparateur de lignes par readline.

Par conséquence le JSON `"a\u2028b"` (où `\u2028` désigne le caractère dont on parle, pas la séquence d'échappement qui le produit) est découpé par readline en `"a` et `b"` qui sont du JSON invalide.

# Les caractères U+2028 et U+2029

Unicode a introduit deux caractères, U+2028 (Séparateur de lignes) et U+2029 (Séparateur de paragraphes), que le consortium [a recommandé d'utiliser](https://www.unicode.org/standard/reports/tr13/tr13-5.html) à la place des caractères issus de ascii (\n et \r\n selon la plateforme) qui ne distingue pas s'il s'agit d'un retour à la ligne au sein d'un paragraphe ou un nouveau paragraphe.

Aujourd'hui ces caractères ne semblent pas gérés : dans vim et dans le terminal ils sont affichés comme des espaces, et Visual Studio Code produit l'avertissement suivant :

> The file 'u2028.txt' contains one or more unusual line terminator characters, like Line Separator (LS) or Paragraph Separator (PS).

> It is recommended to remove them from the file. 

# Les specs

Concernant les caractères autorisés dans une chaîne de caractères JSON, tout est autorisé sauf les caractères de contrôle ascii (dont notamment \n), le caractère \ et les guillemets fermants, qui doivent être échappés.

Concernant le readline de Node.js, le comportement n'est [pas documenté](https://nodejs.org/docs/latest-v24.x/api/readline.html#event-line) (la doc ne mentionne que \n et \r\n), mais le problème a [été introduit](https://github.com/nodejs/node/pull/57591) dans Node 24.0.0, malheureusement sans explication, et alors que la tendance semblait davantage être à ne plus utiliser ces caractères.
