Kako podesiti pametne telefone i računare. Informativni portal

Pregledači su. Chrome: ulaganje u kvalitet

Vaš pretraživač možda ne podržava funkcije navedene u ovom članku.

ForEach.call(document.querySelectorAll("header .date a"), function(elem, i) ( elem.textContent += " (" + ["author","editor"][i] + ")"; ) );

Predgovor

Ovo je detaljan vodič o unutrašnjem radu WebKit i Gecko sistema je rezultat opsežnog istraživanja izraelskog web programera Talija Garciela. Ona već nekoliko godina prati sve objavljene informacije o tome kako pretraživači rade (vidi odjeljak ) i posvetila je dosta vremena analizi njihovog izvornog koda. Evo šta piše sama Tali:

Kada je IE instaliran na 90% računara, morali ste da se pomirite sa činjenicom da se radi o misterioznoj "crnoj kutiji", ali sada kada više od polovine korisnika bira pretraživače otvorenog koda, vreme je da shvatite šta se krije unutar njih, u milionima redova programski kod u C++...
Tali je rezultate istraživanja objavila na svojoj web stranici, ali vjerujemo da zaslužuju pažnju šire publike, pa ih ovdje objavljujemo uz neke skraćenice.

Web programer koji je upoznat sa unutrašnjim radom pretraživača donosi bolje odluke i razumije zašto treba izabrati jedan ili drugi. Ovo je prilično dugačak dokument, ali preporučujemo vam da ga pročitate što je moguće pažljivije i garantiramo da nećete požaliti. Paul Irish, Chrome Developer Relations

Uvod

Web pretraživači su možda najčešće aplikacije. U ovom tutorijalu objašnjavam kako funkcioniraju. Detaljno ćemo pogledati šta se dešava od trenutka kada upišete google.ru u adresnu traku do Google stranice na ekranu.

Koje pretraživače ćemo razmotriti

Danas postoji pet glavnih pretraživača: Internet Explorer, Firefox, Safari, Chrome i Opera. Primjeri koriste pretraživače otvorenog koda: Firefox, Chrome i Safari (kod je djelomično otvoren). Prema statistici korišćenja pretraživača na StatCounter-u, od avgusta 2011. Firefox, Safari i Chrome pretraživači su instalirani na ukupno 60% uređaja. Stoga pretraživači otvorenog koda danas imaju veoma jaku poziciju.

Osnovne funkcije pretraživača

Glavna svrha pretraživača je da prikaže web resurse. Da biste to učinili, zahtjev se šalje serveru, a rezultat se prikazuje u prozoru pretraživača. Resursi su uglavnom HTML dokumenti, ali mogu biti i PDF datoteke, slike ili drugi sadržaj. Lokacija resursa se određuje korištenjem URI-ja (Uniform Resource Identifier).

Način na koji pretraživač obrađuje i prikazuje HTML datoteke definiran je HTML i CSS specifikacijama. Razvija ih Konzorcij W3C, koji implementira standarde za Internet.
Dugi niz godina pretraživači su ispunjavali samo dio specifikacija, a za njih su kreirana posebna proširenja. Za web programere to je značilo ozbiljne probleme s kompatibilnošću. Većina današnjih pretraživača zadovoljava sve specifikacije u većoj ili manjoj mjeri.

Korisnički interfejsi različitim pretraživačima imaju mnogo toga zajedničkog. Glavni elementi interfejsa pretraživača su navedeni u nastavku.

  • Adresna traka za unos URI-ja
  • Navigacijski gumbi "Nazad" i "Naprijed"
  • Bookmarks
  • Osvježi i zaustavi učitavanje stranice
  • Dugme Početna za odlazak na glavnu stranicu

Čudno, specifikacija koja bi definisala standarde korisnički interfejs pretraživač ne postoji. Moderni interfejsi rezultat su višegodišnje evolucije, kao i činjenice da programeri djelimično kopiraju jedni druge. HTML5 specifikacija ne precizira šta tačno interfejs pretraživača treba da sadrži, ali navodi neke od osnovnih elemenata. To uključuje adresnu traku, statusnu traku i traku sa alatkama. Naravno, postoje i specifične funkcije, kao što je menadžer preuzimanja u Firefoxu.

Struktura najvišeg nivoa

Glavne komponente pretraživača () su navedene u nastavku.

  1. Korisnički interfejs– uključuje adresna traka, dugmad za nazad i naprijed, meni sa oznakama itd. Sadrži sve elemente osim prozora u kojem se prikazuje tražena stranica.
  2. Mehanizam pretraživača– kontrolira interakciju između interfejsa i modula displeja.
  3. Display modul- Odgovoran za prikazivanje traženog sadržaja na ekranu. Na primjer, ako je zatražen HTML dokument, renderer analizira HTML i CSS kod i prikazuje rezultat na ekranu.
  4. Mrežne komponente – dizajnirano za upućivanje mrežnih poziva kao što su HTTP zahtjevi. Njihovo sučelje ne ovisi o vrsti platforme, od kojih svaka ima svoje implementacije.
  5. Izvršni dio korisničkog interfejsa- koristi se za crtanje osnovnih widgeta kao što su prozori i kombinovani okviri. Njegov generički interfejs je takođe nezavisan od tipa platforme. Izvršni dio uvijek primjenjuje metode korisničkog interfejsa određenog operativnog sistema.
  6. JavaScript interpreter– koristi se za raščlanjivanje i izvršavanje JavaScript koda.
  7. Skladište podataka- neophodno za postojanost procesa. Pregledač čuva u HDD podaci razne vrste, Na primjer kolačići. Nova HTML specifikacija (HTML5) definira pojam "web baza podataka": to je potpuna (iako lagana) baza podataka zasnovana na pretraživaču.
Slika . Glavne komponente pretraživača.

Treba napomenuti da Chrome, za razliku od većine pretraživača, koristi više instanci modula za prikaz, po jednu u svakoj kartici, što su zasebni procesi.

Display modul

Kao što naziv govori, modul displeja je odgovoran za prikazivanje traženog sadržaja na ekranu pretraživača.

Podrazumevano je sposoban da prikazuje HTML i XML dokumente, kao i slike. Izrađuju se posebni dodaci (proširenja za pretraživač). mogući prikaz drugi sadržaj kao što su PDF datoteke. Međutim, ovo poglavlje se fokusira na glavne karakteristike: prikazivanje HTML dokumenata i slika formatiranih CSS stilovima.

Moduli za prikaz

Preglednici koji nas zanimaju (Firefox, Chrome i Safari) koriste dva renderera. Firefox koristi Gecko - sopstveni razvoj Mozilla, dok Safari i Chrome koriste WebKit.

WebKit je modul za prikaz otvorenog koda koji je prvobitno razvijen za Linux platforme i prilagođeno od Apple-a za Mac OS i Windows. Detalji možete pronaći na webkit.org.

Osnovna shema rada

Modul displeja protokolom prima sadržaj traženog dokumenta mrežni sloj, obično u komadima od 8 KB.

Šema dalji rad Modul displeja izgleda ovako.

Slika . Šema displej modula.

Renderer analizira HTML dokument i prevodi oznake u čvorove u stablu sadržaja. Informacije o stilu se preuzimaju iz eksternih CSS datoteka i stilskih elemenata. Ove informacije i uputstva za prikaz u HTML datoteci koriste se za kreiranje drugog stabla - .

Sadrži pravokutnike s vizualnim atributima kao što su boja i veličina. Pravokutnici su raspoređeni onim redoslijedom kojim bi trebali biti prikazani na ekranu.

Kada se kreira stablo prikaza, počinju elementi, tokom kojih se svakom čvoru dodeljuju koordinate tačke na ekranu gde treba da se pojavi. Zatim se izvršava , u kojem se čvorovi stabla prikaza uzastopno crtaju koristeći frontend korisničkog sučelja.

Važno je shvatiti da je ovo sekvencijalni proces. Radi praktičnosti korisnika, renderer pokušava prikazati sadržaj što je prije moguće, tako da stablo renderiranja i izgled mogu započeti prije nego što se HTML kod analizira. Neki dijelovi dokumenta se raščlanjuju i prikazuju, dok se drugi prenose samo preko mreže.

Primjeri rada

Slika . Šematski dijagram WebKit modula za renderiranje. Slika . Shema Mozilla Gecko modula za prikaz ().

Kao što možete vidjeti na slikama 3 i 4, WebKit i Gecko koriste različitu terminologiju, ali način na koji rade je gotovo identičan.

U Gecku, stablo vizuelno oblikovanih elemenata naziva se stablo okvira, u kojem je svaki element okvir. WebKit koristi stablo renderiranja koje se sastoji od objekata renderiranja. Postavljanje elemenata u WebKit-u naziva se layout, ili layout (layout), a u Gecko-u - wrapping (reflow). Union DOM čvorovi a vizuelni atributi za kreiranje stabla prikaza nazivaju se privitak u WebKit-u. Mala razlika u Gecko-u koja nema nikakve veze sa semantikom je da postoji još jedan sloj između HTML datoteke i DOM stabla. Zove se ponor sadržaja i koristi se za formiranje DOM elemenata. Razgovarajmo sada o svakoj fazi rada detaljnije.

Parsing: opće informacije

Pošto je raščlanjivanje prekretnica rad modula displeja, razmotrimo ga detaljnije. Počnimo sa kratkim uvodom.

Parsiranje dokumenta znači pretvaranje u čitljivu i izvršnu strukturu. Rezultat raščlanjivanja je tipično stablo čvorova koji predstavljaju strukturu dokumenta. Zove se stablo raščlanjivanja ili jednostavno stablo raščlanjivanja.

Na primjer, raščlanjivanje izraza 2 + 3 - 1 može rezultirati sljedećim stablom:

Slika . Čvor stabla za matematički izraz.

Gramatika

raščlanjivanje radi na bazi određena pravila, koji su određeni jezikom (formatom) dokumenta. Za svaki format postoje gramatička pravila koja se sastoje od vokabulara i sintakse. Oni formiraju tzv. . Prirodni jezici ne prate pravila gramatike bez konteksta, tako da standardne tehnike raščlanjivanja nisu prikladne za njih.

Sintaksički i leksički analizatori

Uz sintaksičku analizu koristi se i leksička analiza.

Leksička analiza je podjela informacija na lekseme ili lekseme. Tokeni čine vokabular određenog jezika i gradivni su blokovi za kreiranje dokumenata. Na prirodnom jeziku, tokeni bi bile sve riječi koje se mogu naći u rječnicima.

Smisao raščlanjivanja je primjena pravila sintakse jezika.

Raščlanjivanje dokumenta obično se izvodi pomoću dvije komponente: leksički analizator, koji analizira ulazni niz znakova u stvarne tokene, i parser, analizirajući strukturu dokumenta prema pravilima sintakse dati jezik i formiranje stabla sintakse. Parser zanemaruje neinformativne znakove kao što su razmaci i prijelomi reda.

Slika . Prijelaz sa izvornog dokumenta na stablo sintakse.

Parsing je iterativni proces. Parser obično traži od leksičke novi token i provjerava da li odgovara jednom od pravila sintakse. Ako se podudaranje može napraviti, token se kreira novi čvor u stablu sintakse, a parser traži sljedeći token.

Ako token ne odgovara nijednom pravilu, parser ga odgađa i traži još tokena. Ovo se nastavlja sve dok se ne pronađe pravilo da se svi tokeni na čekanju podudaraju. Ako se takvo pravilo ne može pronaći, parser izbacuje izuzetak. To znači da dokument sadrži sintaksne greške i ne može se u potpunosti obraditi.

Prevod

Stablo sintakse nije uvijek konačni rezultat. Parsing se često koristi u procesu prevođenja ulaznog dokumenta u željeni format. Kompilacija je primjer. Kompajler koji prevodi izvor u mašinski kod, prvo ga analizira i formira stablo sintakse, a tek onda kreira dokument sa mašinskim kodom na osnovu ovog stabla.

Slika . korake kompilacije.

Primjer raščlanjivanja

Slika 5 prikazuje stablo sintakse izgrađeno na osnovu matematičkog izraza. Hajde da definišemo elementarni matematički jezik i razmotrimo proces raščlanjivanja.

Rječnik: Naš jezik može sadržavati cijele brojeve, znake plus i minus.

Sintaksa

  1. Strukturni elementi jezika su izrazi, operandi i operatori.
  2. Jezik može sadržavati bilo koji broj izraza.
  3. Izraz je niz koji se sastoji od operanda, operatora i drugog operanda.
  4. Operator je token plus ili minus.
  5. Operand je ili cijeli broj token ili izraz.

Uzmite u obzir ulazni niz znakova 2 + 3 - 1.
Prvi element koji odgovara pravilu je 2 (prema pravilu #5, ovo je operand). Drugi takav element je 2 + 3 (sekvenca koja se sastoji od operanda, operatora i drugog operanda definisana je pravilom #3). Naći ćemo sljedeću korespondenciju na samom kraju: niz 2 + 3 - 1 je izraz. Pošto je 2+3 operand, dobijamo niz koji se sastoji od operanda, operatora i drugog operanda, koji odgovara definiciji izraza. Red 2++ ne odgovara pravilima, pa bi se smatrao nevažećim.

Formalna definicija vokabulara i sintakse

Jezik iz gornjeg primjera mogao bi se definirati ovako:

INTEGER:0|* PLUS: + MINUS: - Kao što vidite, cijeli brojevi su definisani regularnim izrazom.

Sintaksa se obično opisuje u BNF formatu. Jezik iz gornjeg primjera može se opisati na sljedeći način:

Izraz:= terminski rad terminski rad:= PLUS | MINUS izraz:= CEO | izraz

Kao što je već spomenuto, jezik se može obraditi koristeći standardne parsere ako je njegova gramatika bez konteksta, odnosno može se u potpunosti izraziti u BNF formatu. Formalna definicija Gramatika bez konteksta može se naći u ovom članku na Wikipediji.

Vrste parsera

Postoje dvije vrste parsera: odozgo prema dolje i odozdo prema gore. Prvi vrše analizu odozgo prema dolje, a drugi odozdo prema gore. Nizvodni parseri analiziraju strukturu vrhunski nivo i potražite podudaranja sa sintaksičkim pravilima. Parseri odozdo prema gore prvo obrađuju ulazni niz znakova i postepeno otkrivaju sintaktička pravila u njemu, počevši od pravila nižeg i završavajući s pravilima višeg nivoa.

Sada da vidimo kako bi ove dvije vrste parsera postupile u našem primjeru.

Parser odozgo prema dolje bi započeo s pravilom najvišeg nivoa i odredio da je 2 + 3 izraz. Tada bi se utvrdilo da je 2 + 3 - 1 također izraz (u procesu definiranja izraza, također se pronalaze podudaranja sa drugim pravilima, ali pravilo najvišeg nivoa se uvijek razmatra prvo).

Uzvodni parser će obraditi niz znakova dok ga ne pronađe odgovarajuće pravilo, koji se može koristiti za zamjenu otkrivenog fragmenta, i tako dalje do kraja sekvence. Izrazi s djelomičnim podudaranjem se postavljaju na parserski stog.

Prilikom pokretanja takvog parsera, ulazni niz znakova se pomiče udesno (zamislite kursor postavljen na početak niza i pomjeren udesno tokom raščlanjivanja) i postepeno se svodi na sintaktička pravila.

Automatsko generiranje parsera

Postoji posebne aplikacije za kreiranje parsera koji se nazivaju generatori. Dovoljno je učitati gramatiku jezika (rečnik i sintaktička pravila) u generator i on će automatski kreirati analizator. Kreiranje parsera zahtijeva duboko razumijevanje kako on funkcionira, a izvođenje ručno nije tako lako, tako da generatori mogu biti prilično korisni.

DOM

Rezultirajuće stablo sintakse sastoji se od DOM elemenata i atributnih čvorova. DOM- objektni model dokument (Document Object Model) - služi za predstavljanje HTML dokumenta i interfejsa HTML elementi vanjski objekti kao što je JavaScript kod.
U korijenu stabla nalazi se objekt Document.

DOM model gotovo identično označavanju. Razmotrite primjer oznake:

Zdravo svijete

DOM stablo za ovu oznaku izgleda ovako: Slika . DOM stablo za oznaku iz primjera.

Pod "stablo sadrži DOM čvorove" podrazumijeva se da se stablo sastoji od elemenata koji implementiraju jedan od DOM interfejsa. Preglednici koriste specifične implementacije koje imaju dodatne atribute za internu upotrebu.

Algoritam raščlanjivanja

Kao što je objašnjeno u prethodnim odjeljcima, HTML kod se ne može raščlaniti korištenjem standardnih nizvodnih ili nizvodnih parsera.

Razlozi za to su navedeni u nastavku.

  1. Jezik ima "poštedni" karakter.
  2. Preglednici imaju ugrađene mehanizme za rukovanje nekim uobičajenim greškama u HTML kodu.
  3. Ciklus raščlanjivanja karakterizira mogućnost ponovnog ulaska. Izvorni dokument se obično ne mijenja tokom raščlanjivanja, međutim, u slučaju HTML-a, oznake skripte koje sadrže document.write mogu dodati nove tokene, tako da se izvorni kod može promijeniti.

Pošto standardni parseri nisu prikladni za HTML, pretraživači kreiraju sopstvene parsere.

Algoritam raščlanjivanja je detaljno opisan u HTML5 specifikaciji. Sastoji se od dvije faze: leksičke analize i konstrukcije stabla.

Tokom leksičke analize, ulazni niz znakova se dijeli na tokene. HTML tokeni uključuju početne i krajnje oznake, kao i imena i vrijednosti atributa.

Leksički analizator pronalazi token, prosljeđuje ga konstruktoru stabla i prelazi na sljedeći znak, tražeći još tokena, do kraja ulaznog niza.

Slika . Koraci u raščlanjivanju HTML koda (izvor: HTML5 specifikacija).

Algoritam leksičke analize

Rezultat algoritma je HTML token. Algoritam je izražen kao automat sa konačnim brojem stanja. U svakom stanju se obrađuje jedan ili više znakova ulaznog niza, na osnovu čega se određuje sljedeće stanje. Zavisi od faze leksičke analize i faze formiranja stabla, odnosno obrada istog karaktera može dovesti do različitih rezultata (različitih stanja) u zavisnosti od trenutnog stanja. Algoritam je dovoljno složen da ga ovdje detaljno opišemo, pa pogledajmo pojednostavljeni primjer koji će nam pomoći da bolje razumijemo kako funkcionira.

Hajde da leksički analiziramo jednostavan HTML kod:

Zdravo svijete

Početno stanje je "podaci". Kada parser naiđe na karakter< , состояние меняется на "otvorena oznaka". Ako se sljedeće naiđe na slovo (a-z), generira se token početne oznake i stanje se mijenja u "ime oznake". Traje sve dok se ne naiđe na znak >. Simboli se dodaju jedan po jedan imenu novog tokena. U našem slučaju se dobija html token.

Kada se pronađe simbol >, token se smatra spremnim i analizator se vraća u stanje "podaci". Tag obrađene na potpuno isti način. Dakle, parser je već generirao html i body oznake i vratio se u stanje "podaci". Pronalaženje slova H u frazi Hello world vodi do generiranja znaka. Isto se dešava i sa ostalim slovima, sve dok analizator ne dođe do simbola< в теге . Za svaki znak fraze Hello world kreira se token.

Analizator se tada vraća u stanje "otvorena oznaka". Detekcija karaktera / dovodi do kreiranja tokena završne oznake i prelaska u stanje "ime oznake". Traje sve dok se ne naiđe na znak >. U ovom trenutku se generiše nova oznaka oznake i analizator se vraća u stanje "podaci". Slijed karaktera obrađen kako je gore opisano.

Slika . Leksička analiza ulaznog niza znakova.

Algoritam izgradnje stabla

Kada se kreira parser, generira se objekt Document. Tokom faze izgradnje, DOM stablo u čijem korijenu se nalazi ovaj objekt se mijenja i dodaju mu se novi elementi. Svaki čvor koji generiše lekser obrađuje konstruktor stabla. Svaki token ima svoj vlastiti DOM element definiran specifikacijom. Elementi se dodaju ne samo u DOM stablo, već i u stog otvorenih elemenata, koji služi za popravljanje pogrešno ugniježđenih ili nezatvorenih oznaka. Algoritam se takođe izražava kao automat sa konačnim brojem stanja, koja se nazivaju "režim umetanja".

Razmotrite korake kreiranja stabla za sljedeći isječak koda:

Zdravo svijete

Na početku faze izgradnje stabla imamo niz tokena dobijenih kao rezultat leksičke analize. Prvo stanje se zove original. Nakon prijema html tokena, stanje se mijenja u "na html", nakon čega se token ponovo obrađuje u ovom stanju. Ovo kreira element HTMLHtmlElement koji se dodaje osnovnom objektu dokumenta.

Stanje se mijenja u "do glave". Parser detektuje token tijela. Iako u našem kodu nema oznake head, element HTMLHeadElement će se automatski kreirati i dodati stablu.

Stanje se mijenja u "unutrašnja glava", zatim dalje "poslije glave". Token tijela se ponovo analizira, HTMLBodyElement se kreira i dodaje stablu, a stanje se mijenja u "unutarnje tijelo".

Sada je red na Hello world string tokene. Pronalaženje prvog vodi do kreiranja i umetanja čvora Text, kojem se zatim dodaju ostali znakovi.

Po prijemu tokena za zatvaranje, stanje se mijenja u "poslije tijela". Kada parser dođe do završne html oznake, stanje se mijenja u "poslije tijela". Kada se primi token za kraj datoteke, raščlanjivanje se završava.

Slika . Izgradnja stabla za HTML kod iz primjera.

Radnje nakon raščlanjivanja

U ovom trenutku, pretraživač označava dokument kao interaktivan i počinje raščlanjivati ​​odgođene skripte koje se moraju izvršiti nakon što se raščlanjivanje dokumenta završi. Stanje dokumenta se tada mijenja u "gotovo" i pokreće se događaj učitavanja.

Pogledajmo nekoliko primjera.
Leksička gramatika (rečnik) je definisana regularnim izrazima za svaki token:

Komentar \/\*[^*]*\*+([^/*][^*]*\*+)*\/ num +|*"."+ nonascii [\200-\377] nmstart [_a -z]|(nonascii)|(escape) nmchar [_a-z0-9-]|(nonascii)|(escape) ime (nmchar)+ ident (nmstart)(nmchar)*

Ident je identifikator koji se koristi kao ime klase. Ime je id element i referencira se pomoću znaka funte (#).

Pravila sintakse su opisana u BNF formatu.

Skup pravila: selektor [ "," S* selektor ]* "(" S* deklaracija [ ";" S* deklaracija ]* ")" S* ; selektor: simple_selector [ selektor kombinatora | S+ [ kombinator? selektor]? ]? ; jednostavan_selektor: ime_elementa [ HASH | razred | attrib | pseudo ]* | [ HASH | razred | attrib | pseudo ]+ ; klasa: "." IDENT ; element_name: IDENT | "*"; atribut: "[" S* IDENT S* [ [ "=" | UKLJUČUJE | DASHMATCH ] S* [ IDENT | STRING ] S* ] "]" ; pseudo: ":" [ IDENT | FUNKCIJA S* ")" ] ; Skup pravila je struktura opisana u nastavku. div.error , a.error ( boja:crvena; font-weight:bold; ) Elementi div.error i a.error su selektori. Važeća pravila ovog skupa su zatvorena u vitičastim zagradama. Formalno, ova struktura je definisana na sledeći način: skup pravila: selektor [ "," S* selektor ]* "(" S* deklaracija [ ";" S* deklaracija ]* ")" S* ; To znači da skup pravila djeluje kao selektor, ili kao višestruki selektori odvojeni zarezima i razmacima (S označava razmak). Skup pravila sadrži jednu ili više deklaracija odvojenih tačkom i zarezom. One su zatvorene u vitičaste zagrade. Definicije pojmova "deklaracija" i "selektor" će biti date u nastavku.

CSS parser u WebKit-u

WebKit koristi generatore za automatsko generiranje CSS parsera. Kao što je već pomenuto, Bison se koristi za kreiranje parsera odozdo prema gore, tokom kojih se niz ulaznih znakova pomera udesno. Firefox koristi top-down parser koji je razvio Mozilla. U oba slučaja, CSS datoteka se analizira u StyleSheet objekte koji sadrže CSS pravila. Objekt CSS pravila sadrži selektor i deklaraciju, kao i druge objekte specifične za CSS gramatiku.

Slika . Parsing CSS.

Obrada naloga za skripte i stilove

Skripte

Web dokumenti slijede sinhroni model. Skripte bi trebale biti raščlanjene i izvršene čim analizator otkrije oznaku

Top Related Articles