O Bun fala o Protocolo WebKit Inspector, então você pode depurar seu código com um depurador interativo. Para fins de demonstração, considere o seguinte servidor web simples.
Depurando JavaScript e TypeScript
Bun.serve({
fetch(req) {
console.log(req.url);
return new Response("Hello, world!");
},
});--inspect
Para habilitar a depuração ao executar código com Bun, use a flag --inspect. Isso inicia automaticamente um servidor WebSocket em uma porta disponível que pode ser usado para introspecção do processo Bun em execução.
bun --inspect server.ts------------------ Bun Inspector ------------------
Listening at:
ws://localhost:6499/0tqxs9exrgrm
Inspect in browser:
https://debug.bun.sh/#localhost:6499/0tqxs9exrgrm
------------------ Bun Inspector --------------------inspect-brk
A flag --inspect-brk se comporta identicamente à --inspect, exceto que injeta automaticamente um breakpoint na primeira linha do script executado. Isso é útil para depurar scripts que são executados rapidamente e saem imediatamente.
--inspect-wait
A flag --inspect-wait se comporta identicamente à --inspect, exceto que o código não será executado até que um depurador tenha sido anexado ao processo em execução.
Definindo uma porta ou URL para o depurador
Independentemente de qual flag você usar, você pode opcionalmente especificar um número de porta, prefixo de URL ou ambos.
bun --inspect=4000 server.ts
bun --inspect=localhost:4000 server.ts
bun --inspect=localhost:4000/prefix server.tsDepuradores
Várias ferramentas de depuração podem se conectar a este servidor para fornecer uma experiência de depuração interativa.
debug.bun.sh
O Bun hospeda um depurador baseado na web em debug.bun.sh. É uma versão modificada da Interface Web Inspector do WebKit, que será familiar para usuários do Safari.
Abra a URL debug.bun.sh fornecida no seu navegador para iniciar uma sessão de depuração. A partir desta interface, você poderá visualizar o código fonte do arquivo em execução, visualizar e definir breakpoints e executar código com o console embutido.
Vamos definir um breakpoint. Navegue até a aba Sources; você deve ver o código visto anteriormente. Clique no número da linha 3 para definir um breakpoint na nossa instrução console.log(req.url).
Depois visite http://localhost:3000 no seu navegador. Isso enviará uma requisição HTTP para nosso servidor web localhost. Parecerá que a página não está carregando. Por quê? Porque o programa pausou a execução no breakpoint que definimos anteriormente.
Note como a UI mudou.
Neste ponto, há muito que podemos fazer para introspecção do ambiente de execução atual. Podemos usar o console na parte inferior para executar código arbitrário no contexto do programa, com acesso total às variáveis no escopo no nosso breakpoint.
No lado direito do painel Sources, podemos ver todas as variáveis locais atualmente no escopo e explorar para ver suas propriedades e métodos. Aqui, estamos inspecionando a variável req.
No canto superior esquerdo do painel Sources, podemos controlar a execução do programa.
Aqui está um guia explicando as funções dos botões de controle de fluxo.
- Continuar execução do script — continua executando o programa até o próximo breakpoint ou exceção.
- Step over — O programa continuará para a próxima linha.
- Step into — Se a instrução atual contiver uma chamada de função, o depurador "entrará" na função chamada.
- Step out — Se a instrução atual for uma chamada de função, o depurador terminará de executar a chamada e "sairá" da função para o local onde foi chamada.
Depurador do Visual Studio Code
Suporte experimental para depuração de scripts Bun está disponível no Visual Studio Code. Para usá-lo, você precisará instalar a extensão Bun VSCode.
Depurando Requisições de Rede
A variável de ambiente BUN_CONFIG_VERBOSE_FETCH permite registrar requisições de rede feitas com fetch() ou node:http automaticamente.
| Valor | Descrição |
|---|---|
curl | Imprime requisições como comandos curl. |
true | Imprime informações de requisição e resposta |
false | Não imprime nada. Padrão |
Imprimir requisições fetch e node:http como comandos curl
O Bun também suporta imprimir requisições de rede fetch() e node:http como comandos curl definindo a variável de ambiente BUN_CONFIG_VERBOSE_FETCH para curl. Isso imprime a requisição fetch como um comando curl de linha única para permitir copiar e colar no seu terminal para replicar a requisição.
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: 1256As linhas com [fetch] > são a requisição do seu código local e as linhas com [fetch] < são a resposta do servidor remoto.
A variável de ambiente BUN_CONFIG_VERBOSE_FETCH é suportada tanto em requisições fetch() quanto node:http, então deve funcionar automaticamente.
Para imprimir sem o comando curl, defina BUN_CONFIG_VERBOSE_FETCH para 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 e sourcemaps
O Bun transpila todos os arquivos, o que soa como se significasse que os stack traces que você vê no console apontariam inutilmente para a saída transpilada. Para resolver isso, o Bun gera e serve automaticamente sourcemaps para cada arquivo que transpila. Quando você vê um stack trace no console, pode clicar no caminho do arquivo e ser levado ao código fonte original, mesmo que tenha sido escrito em TypeScript ou JSX ou tenha alguma outra transformação aplicada.
O Bun carrega automaticamente sourcemaps tanto em tempo de execução ao transpilar arquivos sob demanda quanto ao usar bun build para pré-compilar arquivos com antecedência.
Visualização de código fonte com syntax-highlighting
Para ajudar na depuração, o Bun imprime automaticamente uma pequena visualização de código fonte quando ocorre uma exceção ou rejeição não tratada. Você pode simular este comportamento chamando Bun.inspect(error):
// Cria um erro
const err = new Error("Something went wrong");
console.log(Bun.inspect(err, { colors: true }));Isso imprime uma visualização com syntax-highlighting do código fonte onde ocorreu o erro, junto com a mensagem de erro e stack trace.
1 | // Create an error
2 | const err = new Error("Something went wrong");
^
error: Something went wrong
at file.js:2:13V8 Stack Traces
O Bun usa JavaScriptCore como seu engine, mas grande parte do ecossistema Node.js e npm espera V8. Engines JavaScript diferem na formatação de error.stack. O Bun pretende ser um drop-in replacement para Node.js, e isso significa que é nosso trabalho garantir que, embora o engine seja diferente, os stack traces sejam o mais similares possível.
É por isso que quando você registra error.stack no Bun, a formatação de error.stack é a mesma que no engine V8 do Node.js. Isso é especialmente útil quando você está usando bibliotecas que esperam stack traces V8.
V8 Stack Trace API
O Bun implementa a V8 Stack Trace API, que é um conjunto de funções que permitem manipular stack traces.
Error.prepareStackTrace
A função Error.prepareStackTrace é uma função global que permite personalizar a saída do stack trace. Esta função é chamada com o objeto de erro e um array de objetos CallSite e permite retornar um stack trace personalizado.
Error.prepareStackTrace = (err, stack) => {
return stack.map(callSite => {
return callSite.getFileName();
});
};
const err = new Error("Something went wrong");
console.log(err.stack);
// [ "error.js" ]O objeto CallSite tem os seguintes métodos:
| Método | Retorna |
|---|---|
getThis | Valor this da chamada de função |
getTypeName | typeof this |
getFunction | objeto da função |
getFunctionName | nome da função como string |
getMethodName | nome do método como string |
getFileName | nome do arquivo ou URL |
getLineNumber | número da linha |
getColumnNumber | número da coluna |
getEvalOrigin | undefined |
getScriptNameOrSourceURL | URL da fonte |
isToplevel | retorna true se a função está no escopo global |
isEval | retorna true se a função é uma chamada eval |
isNative | retorna true se a função é nativa |
isConstructor | retorna true se a função é um construtor |
isAsync | retorna true se a função é async |
isPromiseAll | Ainda não implementado. |
getPromiseIndex | Ainda não implementado. |
toString | retorna uma representação em string do call site |
Em alguns casos, o objeto Function pode já ter sido garbage collected, então alguns destes métodos podem retornar undefined.
Error.captureStackTrace(error, startFn)
A função Error.captureStackTrace permite capturar um stack trace em um ponto específico do seu código, em vez do ponto onde o erro foi lançado.
Isso pode ser útil quando você tem callbacks ou código assíncrono que torna difícil determinar onde um erro se originou. O segundo argumento para Error.captureStackTrace é a função onde você quer que o stack trace comece.
Por exemplo, o código abaixo fará err.stack apontar para o código chamando fn(), mesmo que o erro tenha sido lançado em 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: here!
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: here!
at module code (file.js:17:1)
at moduleEvaluation (native)
at moduleEvaluation (native)
at <anonymous> (native)