Ders 24 / 24
Kaynak Hata Ayıklama
Programı seçilen bir noktada durdurup durumu okumak; kesme noktası türlerinin yanıtladığı sorular, adımlama ve kapsam okuma, üretim çıktısındaki konumun kaynak haritasıyla çözülmesi ve haritanın dağıtımı.
İçindekiler
Buraya kadarki araçlar sonucu ölçtü: hangi kural kazandı, istek ne kadar sürdü, hangi işlev ana iş parçacığını tuttu, hangi nesne bellekte kaldı. Hiçbiri “bu satır çalıştığında değişkenin değeri neydi” sorusunu yanıtlamaz.
Ölçüm listesinin bir satırının neden eksik çizildiği, ancak programı seçilen bir noktada durdurup o andaki durumu okuyarak görülür. Bu ders duraklatma mekanizmasını ve üretim çıktısında durdurulan kodun kaynaktaki karşılığının nasıl bulunduğunu ele alır.
Duraklatmanın Anlamı
Bir kesme noktasına ulaşıldığında ana iş parçacığı durur. Duran şey yalnızca o işlev değildir: sayfanın tamamıdır. Zamanlayıcılar tetiklenmez, olaylar işlenmez, kare üretilmez. Okunan durum, tam olarak o komutun çalışmak üzere olduğu andaki durumdur.
İki sonuç doğar. Birincisi, zamana bağlı davranış duraklatmayla bozulur: bir animasyonun ortasında durup devam edildiğinde geçen süre gerçekte geçmiştir ve süreye dayalı hesaplar sıçrar. Zamanlamayla ilgili sorunlar duraklatarak değil, kayıtla incelenir.
İkincisi, durdurulan noktada okunan değer, yazdırılan değerden güvenilirdir. Kütüğe yazılan bir nesne, konsolda açıldığı anda okunur; bu, yazma anından sonradır ve nesne o arada değişmiş olabilir. Kesme noktası bu belirsizliği ortadan kaldırır.
Kesme Noktası Türleri ve Yanıtladıkları Soru
Kesme noktasının türü, sorulan soruya göre seçilir.
Satır kesme noktası “bu satıra gelindi mi ve o an durum neydi” sorusunu yanıtlar. En temel türdür ve satırın hangi kodda olduğu bilindiğinde kullanılır.
Koşullu kesme noktası aynı satırı yalnızca bir koşul sağlandığında durdurur. Yüz satırlık bir listede yalnızca eksik çizilen satırda durmak için gereklidir; koşulsuz bir kesme noktası burada yüz kez durur ve kullanılamaz hâle gelir.
Kayıt noktası durdurmaz, yalnızca bir ifadenin değerini kütüğe yazar. Kodu değiştirmeden kütük satırı eklemenin yoludur ve bu yüzden sürüm kontrolüne sızacak geçici yazdırma satırlarını ortadan kaldırır.
İstisna kesme noktası “bu hata nereden atıldı” sorusunu yanıtlar ve iki kipi vardır: her istisnada durmak, ya da yalnızca yakalanmayanlarda. Birinci kip, bir hatanın yakalanıp yutulduğu yerleri bulur.
Ağaç değişimi kesme noktası “bu düğümü kim değiştirdi” sorusunu yanıtlar. Öznitelik değişiminde, çocuk ekleme–çıkarmada ya da düğümün kendisinin kaldırılmasında durur. Beklenmedik biçimde kaybolan ya da değişen bir ögenin sorumlusunu bulmanın en kısa yoludur; kodun hangi bölümünde arayacağını bilmek gerekmez.
Olay kesme noktası belirli bir olay türü işlenmeye başladığında durur ve “bu tıklamayı hangi dinleyici karşılıyor” sorusunu yanıtlar. Olay Devri dersinde kurulan yapıda dinleyicinin hedeften uzak bir atada bulunması bu aracı gerekli kılar.
İstek kesme noktası adresi belirli bir örüntüye uyan bir ağ isteği yapıldığında durur ve isteği başlatan çağrı zincirini gösterir.
Adımlama, Kapsam ve Çağrı Yığıtı
Durdurulmuş programda üç görünüm birlikte okunur.
Çağrı yığıtı o noktaya nasıl gelindiğini söyler. Her çerçeve seçilebilir ve seçilen çerçevenin kapsamı okunur; hatalı değerin nereden geldiği yığıtta yukarı çıkılarak bulunur. Eşzamansız sınırlar da yığıta katılır: bir sözün ardından çalışan kodun, sözü başlatan çağrıyla ilişkisi ayrı bir bölüm olarak gösterilir. Bu olmadan yığıt olay döngüsünde başlar ve hiçbir şey anlatmaz.
Kapsam görünümü seçilen çerçevedeki yerel değişkenleri, kapanışta yakalanmış değerleri ve genel kapsamı ayrı ayrı listeler. Kapanış bölümü tanıda özellikle değerlidir: bir değişkenin beklenenden farklı olması, çoğunlukla döngü değişkeninin yakalanma biçiminden gelir.
Adımlama üç kipte yapılır. Üzerinden atlama, bulunulan satırdaki çağrıyı çalıştırır ve sonraki satırda durur. İçine girme, çağrılan işlevin ilk satırında durur. Dışına çıkma, bulunulan işlev dönene kadar çalıştırır ve çağırana geri döner.
Adımlamanın pratik sorunu, yardımcı kodun içine düşmektir: bir olay dinleyicisinin içine girmeye çalışırken araya giren altyapı çerçeveleri adımlamayı dağıtır. Araçlar belirli dosyaların adımlamada yok sayılmasına izin verir; yok sayılan dosyaların çerçeveleri yığıtta gizlenir ve içine girme onları atlar. Kendi kodunda kalmak bu ayarla sağlanır.
Üretim Çıktısında Durmak: Kaynak Haritaları
Dağıtılan betik, yazılan betik değildir: adları kısaltılmış, satırları birleştirilmiş, belki başka bir söz dizimine indirgenmiştir. Bu çıktıda durdurulan bir program, okunamayan tek bir satır gösterir.
Modüller, Araçlar ve Ekosistem kursundaki Kaynak Haritaları dersinde tanımlanan yapı bu boşluğu kapatır: üretilen dosyadaki her konumu özgün dosyadaki bir konuma bağlayan bir eşleme tablosu. Tablo, yerden kazanmak için farklarla ve değişken uzunluklu niceliklerle kodlanır. Çözümü hesaplanabilir bir işlemdir.
// kaynak-haritasi.mjs — VLQ kodlama/cozme ve uretilen konumun kaynaktaki karsiligi const ABECE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; function vlqKodla(sayi) { let deger = sayi < 0 ? (-sayi << 1) | 1 : sayi << 1; // isaret en dusuk bitte let cikti = ""; do { let parca = deger & 0b11111; deger >>>= 5; if (deger > 0) parca |= 0b100000; // devam biti cikti += ABECE[parca]; } while (deger > 0); return cikti; } function vlqCoz(dizgi) { const sayilar = []; let deger = 0, kaydirma = 0; for (const karakter of dizgi) { const parca = ABECE.indexOf(karakter); deger += (parca & 0b11111) << kaydirma; if (parca & 0b100000) { kaydirma += 5; continue; } // devam biti: sonraki karaktere gec sayilar.push(deger & 1 ? -(deger >>> 1) : deger >>> 1); deger = 0; kaydirma = 0; } return sayilar; } // Saltik eslemeler: uretilen dosyadaki konum → kaynaktaki konum const ESLEMELER = [ [ // uretilen satir 0 { uretilenSutun: 0, kaynak: 0, satir: 0, sutun: 0, ad: 0 }, { uretilenSutun: 12, kaynak: 0, satir: 4, sutun: 2, ad: 1 }, { uretilenSutun: 31, kaynak: 0, satir: 5, sutun: 14, ad: null }, ], [ // uretilen satir 1 { uretilenSutun: 0, kaynak: 0, satir: 9, sutun: 0, ad: null }, { uretilenSutun: 8, kaynak: 0, satir: 11, sutun: 4, ad: null }, ], ]; // Saltik eslemeleri fark dizisine cevirip kodlar: alanlar farklarla saklanir. function mappingsUret(eslemeler) { let oncekiKaynak = 0, oncekiSatir = 0, oncekiSutun = 0, oncekiAd = 0; return eslemeler.map((satirEslemeleri) => { let oncekiUretilenSutun = 0; return satirEslemeleri.map((e) => { const alanlar = [e.uretilenSutun - oncekiUretilenSutun, e.kaynak - oncekiKaynak, e.satir - oncekiSatir, e.sutun - oncekiSutun]; if (e.ad !== null) alanlar.push(e.ad - oncekiAd); oncekiUretilenSutun = e.uretilenSutun; oncekiKaynak = e.kaynak; oncekiSatir = e.satir; oncekiSutun = e.sutun; if (e.ad !== null) oncekiAd = e.ad; return alanlar.map(vlqKodla).join(""); }).join(","); }).join(";"); } const harita = { version: 3, file: "olcum.min.js", sources: ["olcum.js"], names: ["olcumleriCiz", "satirKur"], mappings: mappingsUret(ESLEMELER), }; console.log("mappings:", harita.mappings); // Cozme: fark dizisinden saltik konumlara geri don. function mappingsCoz(mappings) { let kaynak = 0, satir = 0, sutun = 0, ad = 0; return mappings.split(";").map((satirMetni) => { let uretilenSutun = 0; if (satirMetni === "") return []; return satirMetni.split(",").map((bolum) => { const a = vlqCoz(bolum); uretilenSutun += a[0]; kaynak += a[1]; satir += a[2]; sutun += a[3]; if (a.length === 5) ad += a[4]; return { uretilenSutun, kaynak, satir, sutun, ad: a.length === 5 ? ad : null }; }); }); } const cozulen = mappingsCoz(harita.mappings); // Uretilen konumdan kaynaga: satirdaki, sutunu gecmeyen SON esleme alinir. function kaynaktaBul(uretilenSatir, uretilenSutun) { const satirEslemeleri = cozulen[uretilenSatir] ?? []; let bulunan = null; for (const e of satirEslemeleri) if (e.uretilenSutun <= uretilenSutun) bulunan = e; if (!bulunan) return null; return { dosya: harita.sources[bulunan.kaynak], satir: bulunan.satir + 1, sutun: bulunan.sutun + 1, ad: bulunan.ad === null ? null : harita.names[bulunan.ad], }; } console.log("\nuretilen konum → kaynaktaki konum"); for (const [s, k] of [[0, 0], [0, 20], [0, 40], [1, 3], [1, 12]]) { const c = kaynaktaBul(s, k); console.log(` olcum.min.js ${s + 1}:${k + 1}`.padEnd(24) + `→ ${c.dosya} ${c.satir}:${c.sutun}` + (c.ad ? ` (${c.ad})` : "")); }
mappings: AAAAA,YAIEC,mBACY;AAId,QAEI uretilen konum → kaynaktaki konum olcum.min.js 1:1 → olcum.js 1:1 (olcumleriCiz) olcum.min.js 1:21 → olcum.js 5:3 (satirKur) olcum.min.js 1:41 → olcum.js 6:15 olcum.min.js 2:4 → olcum.js 10:1 olcum.min.js 2:13 → olcum.js 12:5
Çıktı üç ayrıntıyı görünür kılar.
Birincisi, eşleme tam değildir. Yirmi birinci sütun için tabloda kayıt yoktur; çözüm, o sütunu geçmeyen son eşlemeye düşer. Hata ayıklayıcıda bir kesme noktasının yazıldığı satırdan biraz kayması bundandır: en yakın eşlemeye tutunur.
İkincisi, ad alanı isteğe bağlıdır. Üçüncü eşlemede ad yoktur; kısaltılmış bir değişkenin özgün adı yalnızca eşlemesi ad taşıyorsa geri getirilebilir. Kapsam görünümünde tek harfli adlar görünmeye devam ediyorsa nedeni budur.
Üçüncüsü, kodlama farklara dayanır. Bir bölümün çözülmesi kendinden öncekilere bağlıdır; tablonun ortasından okumaya başlanamaz. Bu, dosyayı küçük tutar ve tam çözümü zorunlu kılar.
Haritanın Dağıtımı
Kaynak haritası ayrı bir dosyadır ve üretilen dosyanın sonundaki bir yorum satırıyla ona bağlanır. Dağıtım kararı üç seçeneğe iner.
Haritayı herkese açık sunmak en kolayıdır ve kaynak kodunu okunabilir kılar. Kapalı kaynak bir uygulamada bu, kodun yayımlanması anlamına gelir.
Haritayı üretmek ama yayımlamamak yaygın orta yoldur: harita hata izleme sistemine yüklenir, sunucudan servis edilmez. Kullanıcının tarayıcısında yığıt izi kısaltılmış hâliyle kalır, geliştirici tarafında çözülmüş hâliyle görünür.
Hiç üretmemek ölçülebilir bir kazanç sağlamaz — harita yalnızca istendiğinde indirilir — ve üretimdeki hataların tanısını olanaksız kılar.
Haritanın kaynak metni kendi içinde taşıyıp taşımayacağı da ayrı bir karardır: taşırsa dosya büyür ama özgün dosyalara ayrıca erişim gerekmez; taşımazsa harita küçüktür ve kaynakların ayrıca sunulması gerekir.
Özet
- Kesme noktası ana iş parçacığını durdurur; zamana bağlı davranış duraklatmayla bozulur, bu yüzden zamanlama sorunları kayıtla incelenir.
- Kesme noktası türü sorulan soruya göre seçilir: satır, koşul, kayıt, istisna, ağaç değişimi, olay ve istek.
- Çağrı yığıtı o noktaya nasıl gelindiğini, kapsam görünümü seçilen çerçevedeki değerleri verir; eşzamansız sınırlar yığıta ayrıca eklenir.
- Adımlama üç kiptir; yardımcı dosyaların yok sayılması adımlamayı kendi kodunda tutar.
- Kaynak haritası, farklarla kodlanmış bir eşleme tablosudur; çözüm en yakın eşlemeye düşer ve ad alanı isteğe bağlıdır.
- Harita dağıtımı, kodun okunabilirliği ile üretim hatalarının tanınabilirliği arasında bir karardır.
Kurs Kapanışı
Bu kurs tarayıcıyı bir çalışma ortamı olarak ele aldı ve dört katmanda kurdu.
Belge ve olaylar katmanında sayfa, program içinden okunup değiştirilebilen bir veri yapısına dönüştü; olayın kökten hedefe ve hedeften köke izlediği tanımlı yol, tek dinleyiciyle çok ögeyi yönetmeyi, tarayıcının varsayılan davranışına müdahale etmeyi ve klavye ile form etkileşimini kurmayı sağladı.
Tarayıcı API’leri katmanı sayfaya kalıcılık, gezinme denetimi, gözlem yeteneği, kareyle uyumlu güncelleme, yerelleştirilmiş biçimleme ve ana iş parçacığını boşaltma olanağı ekledi.
Web bileşenleri ve çevrimdışı katmanı iki bağımsızlık kurdu: arayüz parçasının sayfadan bağımsızlığı — kendi adı, yaşam döngüsü, kapsüllenmiş yapısı ve biçemiyle — ve uygulamanın ağdan bağımsızlığı — araya giren bir çalışan, kaynak başına verilmiş önbellek kararları ve kurulabilir bir kabukla.
Geliştirici araçları katmanı bu üçünün üzerine tanıyı koydu. Her aracın yanıtladığı soru ayrıydı: hangi kural kazandı, istek nereden ve ne kadar sürede karşılandı, ana iş parçacığı nerede tıkandı, hangi nesne bırakılmadı, o satırda değer neydi. Ortak yöntem her seferinde aynıydı — önce soruyu belirlemek, sonra o soruyu yanıtlayan ölçüyü okumak.
Bu kursun kurduğu her şey elle yapılıyordu: düğüm oluşturmak, dinleyici bağlamak, değişikliği ilgili ögeye yazmak, sökerken hepsini geri almak. Ölçüm rozeti bir bileşen oldu, ama panodaki on beş rozetin listeyle eşzamanlı kalması hâlâ elle yazılmış güncelleme koduna bağlı. Liste bir kayıt eklendiğinde hangi düğümlerin değişeceğini kodun kendisi hesaplıyor; bu hesap büyüdükçe hata kaynağına dönüşüyor.
Bir sonraki kurs, M14/K05 · Bileşen Tabanlı Arayüz Geliştirme, bu hesabı tersine çevirir. Arayüz, adım adım nasıl değiştirileceğiyle değil, verili durumda ne olması gerektiğiyle tanımlanır; aradaki farkı bulmak ve ağaca uygulamak altyapının işi olur. Platform yetenekleri ve tanı araçları kurulduğuna göre sıra, bildirimsel arayüz modelinde ve bileşenlerin bileşiminde.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.