Bun parle le WebKit Inspector Protocol, vous pouvez donc déboguer votre code avec un débogueur interactif. À titre de démonstration, considérons le serveur web simple suivant.
Débogage JavaScript et TypeScript
Bun.serve({
fetch(req) {
console.log(req.url);
return new Response("Bonjour le monde !");
},
});--inspect
Pour activer le débogage lors de l'exécution de code avec Bun, utilisez l'option --inspect. Cela démarre automatiquement un serveur WebSocket sur un port disponible qui peut être utilisé pour inspecter le processus Bun en cours d'exécution.
bun --inspect server.ts------------------ Bun Inspector ------------------
Écoute sur :
ws://localhost:6499/0tqxs9exrgrm
Inspecter dans le navigateur :
https://debug.bun.sh/#localhost:6499/0tqxs9exrgrm
------------------ Bun Inspector --------------------inspect-brk
L'option --inspect-brk se comporte identiquement à --inspect, sauf qu'elle injecte automatiquement un point d'arrêt à la première ligne du script exécuté. Ceci est utile pour déboguer les scripts qui s'exécutent rapidement et se terminent immédiatement.
--inspect-wait
L'option --inspect-wait se comporte identiquement à --inspect, sauf que le code ne s'exécutera pas tant qu'un débogueur ne s'est pas attaché au processus en cours d'exécution.
Définir un port ou une URL pour le débogueur
Quelle que soit l'option que vous utilisez, vous pouvez éventuellement spécifier un numéro de port, un préfixe d'URL, ou les deux.
bun --inspect=4000 server.ts
bun --inspect=localhost:4000 server.ts
bun --inspect=localhost:4000/prefix server.tsDébogueurs
Divers outils de débogage peuvent se connecter à ce serveur pour fournir une expérience de débogage interactive.
debug.bun.sh
Bun héberge un débogueur basé sur le web sur debug.bun.sh. C'est une version modifiée de l'interface Web Inspector de WebKit, qui sera familière aux utilisateurs de Safari.
Ouvrez l'URL debug.bun.sh fournie dans votre navigateur pour démarrer une session de débogage. À partir de cette interface, vous pourrez voir le code source du fichier en cours d'exécution, définir des points d'arrêt et exécuter du code avec la console intégrée.
Définissons un point d'arrêt. Accédez à l'onglet Sources ; vous devriez voir le code vu précédemment. Cliquez sur le numéro de ligne 3 pour définir un point d'arrêt sur notre instruction console.log(req.url).
Ensuite, visitez http://localhost:3000 dans votre navigateur web. Cela enverra une requête HTTP à notre serveur web localhost. Il semblera que la page ne se charge pas. Pourquoi ? Parce que le programme a mis en pause l'exécution au point d'arrêt que nous avons défini plus tôt.
Notez comment l'interface utilisateur a changé.
À ce stade, il y a beaucoup de choses que nous pouvons faire pour inspecter l'environnement d'exécution actuel. Nous pouvons utiliser la console en bas pour exécuter du code arbitraire dans le contexte du programme, avec un accès complet aux variables dans la portée au niveau de notre point d'arrêt.
Sur le côté droit du volet Sources, nous pouvons voir toutes les variables locales actuellement dans la portée, et explorer pour voir leurs propriétés et méthodes. Ici, nous inspectons la variable req.
En haut à gauche du volet Sources, nous pouvons contrôler l'exécution du programme.
Voici un aide-mémoire expliquant les fonctions des boutons de contrôle de flux.
- Continuer l'exécution du script — continuer à exécuter le programme jusqu'au prochain point d'arrêt ou exception.
- Step over — Le programme continuera à la ligne suivante.
- Step into — Si l'instruction actuelle contient un appel de fonction, le débogueur "entrera" dans la fonction appelée.
- Step out — Si l'instruction actuelle est un appel de fonction, le débogueur terminera l'exécution de l'appel, puis "sortira" de la fonction vers l'emplacement où elle a été appelée.
Débogueur Visual Studio Code
La prise en charge expérimentale du débogage des scripts Bun est disponible dans Visual Studio Code. Pour l'utiliser, vous devrez installer l'extension Bun VSCode.
Débogage des requêtes réseau
La variable d'environnement BUN_CONFIG_VERBOSE_FETCH vous permet de journaliser automatiquement les requêtes réseau effectuées avec fetch() ou node:http.
| Valeur | Description |
|---|---|
curl | Affiche les requêtes sous forme de commandes curl. |
true | Affiche les informations de requête et réponse |
false | N'affiche rien. Par défaut |
Afficher les requêtes fetch et node:http sous forme de commandes curl
Bun prend également en charge l'affichage des requêtes réseau fetch() et node:http sous forme de commandes curl en définissant la variable d'environnement BUN_CONFIG_VERBOSE_FETCH sur curl. Cela affiche la requête fetch sous forme de commande curl sur une seule ligne pour vous permettre de copier-coller dans votre terminal pour répliquer la requête.
process.env.BUN_CONFIG_VERBOSE_FETCH = "curl";
await fetch("https://example.com", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ foo: "bar" }),
});[fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.3.3" -H "Accept: */*" -H "Host: example.com" -H "Accept-Encoding: gzip, deflate, br" --compressed -H "Content-Length: 13" --data-raw "{\"foo\":\"bar\"}"
[fetch] > HTTP/1.1 POST https://example.com/
[fetch] > content-type: application/json
[fetch] > Connection: keep-alive
[fetch] > User-Agent: Bun/1.3.3
[fetch] > Accept: */*
[fetch] > Host: example.com
[fetch] > Accept-Encoding: gzip, deflate, br
[fetch] > Content-Length: 13
[fetch] < 200 OK
[fetch] < Accept-Ranges: bytes
[fetch] < Cache-Control: max-age=604800
[fetch] < Content-Type: text/html; charset=UTF-8
[fetch] < Date: Tue, 18 Jun 2024 05:12:07 GMT
[fetch] < Etag: "3147526947"
[fetch] < Expires: Tue, 25 Jun 2024 05:12:07 GMT
[fetch] < Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
[fetch] < Server: EOS (vny/044F)
[fetch] < Content-Length: 1256Les lignes avec [fetch] > sont la requête depuis votre code local, et les lignes avec [fetch] < sont la réponse du serveur distant.
La variable d'environnement BUN_CONFIG_VERBOSE_FETCH est prise en charge à la fois dans les requêtes fetch() et node:http, donc cela devrait simplement fonctionner.
Pour afficher sans la commande curl, définissez BUN_CONFIG_VERBOSE_FETCH sur true.
process.env.BUN_CONFIG_VERBOSE_FETCH = "true";
await fetch("https://example.com", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ foo: "bar" }),
});[fetch] > HTTP/1.1 POST https://example.com/
[fetch] > content-type: application/json
[fetch] > Connection: keep-alive
[fetch] > User-Agent: Bun/1.3.3
[fetch] > Accept: */*
[fetch] > Host: example.com
[fetch] > Accept-Encoding: gzip, deflate, br
[fetch] > Content-Length: 13
[fetch] < 200 OK
[fetch] < Accept-Ranges: bytes
[fetch] < Cache-Control: max-age=604800
[fetch] < Content-Type: text/html; charset=UTF-8
[fetch] < Date: Tue, 18 Jun 2024 05:12:07 GMT
[fetch] < Etag: "3147526947"
[fetch] < Expires: Tue, 25 Jun 2024 05:12:07 GMT
[fetch] < Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
[fetch] < Server: EOS (vny/044F)
[fetch] < Content-Length: 1256Stacktraces et sourcemaps
Bun transpile chaque fichier, ce qui pourrait laisser penser que les stack traces que vous voyez dans la console pointeraient inutilement vers la sortie transpilée. Pour résoudre ce problème, Bun génère et sert automatiquement des fichiers sourcemap pour chaque fichier qu'il transpile. Lorsque vous voyez une stack trace dans la console, vous pouvez cliquer sur le chemin du fichier et être dirigé vers le code source original, même s'il a été écrit en TypeScript ou JSX, ou a subi une autre transformation.
Bun charge automatiquement les sourcemaps à la fois lors de l'exécution lors de la transpilation de fichiers à la demande, et lors de l'utilisation de bun build pour précompiler des fichiers à l'avance.
Aperçu du code source avec coloration syntaxique
Pour aider au débogage, Bun affiche automatiquement un petit aperçu du code source lorsqu'une exception ou un rejet non géré se produit. Vous pouvez simuler ce comportement en appelant Bun.inspect(error) :
// Créer une erreur
const err = new Error("Quelque chose s'est mal passé");
console.log(Bun.inspect(err, { colors: true }));Cela affiche un aperçu avec coloration syntaxique du code source où l'erreur s'est produite, ainsi que le message d'erreur et la stack trace.
1 | // Créer une erreur
2 | const err = new Error("Quelque chose s'est mal passé");
^
error: Quelque chose s'est mal passé
at file.js:2:13Stack Traces V8
Bun utilise JavaScriptCore comme moteur, mais une grande partie de l'écosystème Node.js et npm attend V8. Les moteurs JavaScript diffèrent dans le formatage de error.stack. Bun vise à être un remplacement direct pour Node.js, et cela signifie que c'est notre travail de nous assurer que même si le moteur est différent, les stack traces sont aussi similaires que possible.
C'est pourquoi lorsque vous journalisez error.stack dans Bun, le formatage de error.stack est le même que dans le moteur V8 de Node.js. Ceci est particulièrement utile lorsque vous utilisez des bibliothèques qui attendent des stack traces V8.
API de Stack Trace V8
Bun implémente l'API de Stack Trace V8, qui est un ensemble de fonctions qui vous permettent de manipuler les stack traces.
Error.prepareStackTrace
La fonction Error.prepareStackTrace est une fonction globale qui vous permet de personnaliser la sortie de la stack trace. Cette fonction est appelée avec l'objet d'erreur et un tableau d'objets CallSite et vous permet de retourner une stack trace personnalisée.
Error.prepareStackTrace = (err, stack) => {
return stack.map(callSite => {
return callSite.getFileName();
});
};
const err = new Error("Quelque chose s'est mal passé");
console.log(err.stack);
// [ "error.js" ]L'objet CallSite dispose des méthodes suivantes :
| Méthode | Retourne |
|---|---|
getThis | Valeur this de l'appel de fonction |
getTypeName | typeof this |
getFunction | objet fonction |
getFunctionName | nom de la fonction sous forme de chaîne |
getMethodName | nom de la méthode sous forme de chaîne |
getFileName | nom du fichier ou URL |
getLineNumber | numéro de ligne |
getColumnNumber | numéro de colonne |
getEvalOrigin | undefined |
getScriptNameOrSourceURL | URL source |
isToplevel | retourne true si la fonction est dans la portée globale |
isEval | retourne true si la fonction est un appel eval |
isNative | retourne true si la fonction est native |
isConstructor | retourne true si la fonction est un constructeur |
isAsync | retourne true si la fonction est async |
isPromiseAll | Pas encore implémenté. |
getPromiseIndex | Pas encore implémenté. |
toString | retourne une représentation en chaîne du site d'appel |
Dans certains cas, l'objet Function peut avoir déjà été garbage collecté, donc certaines de ces méthodes peuvent retourner undefined.
Error.captureStackTrace(error, startFn)
La fonction Error.captureStackTrace vous permet de capturer une stack trace à un point spécifique de votre code, plutôt qu'au point où l'erreur a été lancée.
Cela peut être utile lorsque vous avez des callbacks ou du code asynchrone qui rend difficile la détermination de l'origine d'une erreur. Le 2ème argument de Error.captureStackTrace est la fonction où vous voulez que la stack trace commence.
Par exemple, le code ci-dessous fera pointer err.stack vers le code appelant fn(), même si l'erreur a été lancée dans myInner.
const fn = () => {
function myInner() {
throw err;
}
try {
myInner();
} catch (err) {
console.log(err.stack);
console.log("");
console.log("-- captureStackTrace --");
console.log("");
Error.captureStackTrace(err, fn);
console.log(err.stack);
}
};
fn();Error: ici !
at myInner (file.js:4:15)
at fn (file.js:8:5)
at module code (file.js:17:1)
at moduleEvaluation (native)
at moduleEvaluation (native)
at <anonymous> (native)
-- captureStackTrace --
Error: ici !
at module code (file.js:17:1)
at moduleEvaluation (native)
at moduleEvaluation (native)
at <anonymous> (native)