Preface
Explore the "Three Two Things" behind the browser The introduction of the previous article gave everyone a vague understanding of the composition of the browser:
- What is the browser?
- Browser (chromium) basic architecture
- The main components of the browser
- What is the browser kernel?
- JavaScript (js) engine
- Rendering engine
Today, I will do the rendering module (WebKit) to start learning and discussion.
First of all, as a sequence introduction. I should specifically introduce what content should be included to implement a browser (introduce what content is included in the implementation of chromium
But consider the front-end topic at 160afd01d452da. Just make a simple list without discussing it in detail; if you are interested, you can go on and study by yourself.
Secondly, if everyone is familiar with it, I should focus on the JS engine (V8 event-loop related); but in this section I want to first introduce and discuss the
rendering engine (WebKit). For nothing else, I just like to play~ Because the audience I write this series is still biased towards the front end, so the part that requires code intervention is used here to implement
JavaScript
Rendering engine
Get used to drawing architectural drawings, don't care about ugly details...
From the above figure, you can get the information about the internal analysis and execution process of the rendering engine:
- When the page is accessed, a network request (network) is made to obtain the content of the page; when it hits the cache (cache), it will be read directly from the storage (memory).
- HTMLParser performs html parsing to block by specific identifiers. It can be parsed into several modules of CSS DOM JS.
- CSSParser is also parsing css.
- DOMParser performs DOM structure analysis. (During the construction process, it was found that the JS part was executed 5. If it is an asynchronous request for resources, it will not hinder the analysis).
- The JavaScript part is thrown to the JS engine for parsing. (If the DOM/CSS part is manipulated, it will affect the previous parsing and hinder the parsing at the same time).
- Construct RenderTree by analyzing the content above.
- The analysis is completed and the layout and drawing are performed through renderTree.
- Display the final image on the screen.
Let's discuss the part mentioned above flow me~ gogogo!
Parser analysis
Are there too many words in Parser above? We get an information analysis is a very important part of the rendering engine, so we need to introduce the analysis first.
Parsing a document means turning the document into a meaningful structure, that is, a structure that can be understood and used by the code. The result of parsing is usually a tree of nodes representing the structure of the document, which is called a parse tree or a syntax tree.
Parsing is based on the grammatical rules (the language or format in which the document is written) followed by the document. For example, HTML parsing is carried out on the basis of HTML4/5 specifications. All formats that can be parsed must correspond to a certain grammar (consisting of vocabulary and grammatical rules).
The parsing process is usually divided into two sub-processes: lexical analysis and syntax analysis .
lexical analysis is the process of dividing the input content into a large number of tags. (Segmentation can identify a large number of marked words) grammatical analysis is the process of applying the grammatical rules of the language (what does this language do?).
HTMLParser
HTML parser is to parse HTML tags into a parse tree.
HTML syntax definition:
The vocabulary and grammar of HTML are defined in specifications created by the W3C organization.
DOM
The output "parse tree" of the parser is a tree structure composed of DOM elements and attribute nodes. DOM is the abbreviation of Document Object Model. It is HTML
document, as well as the interface between external content (such as JavaScript) and HTML elements.
The root node of the parse tree is the Document
object.
DOM parsing code indicates (cannot run) First of all, we must understand that the parsing process must be an iterative process:
// 分析标记<>和属性的正则表达式
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[\w-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/,
attr = /([-A-Za-z0-9_]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
function ParserHTML(html){
// 接收参数html
while(html){
// 匹配注释内容
if(html.indexOf("<!--") == 0){
//
}
// 匹配开始标签
if (html.indexOf("<") == 0) {
match = html.match(startTag);
if (match) {
html = html.substring(match[0].length); //匹配截取
//继续迭代
}
}
if(html.indexOf("</") == 0){
//匹配结束标签操作
}
}
}
// 输出示意结构
{
element:"",
parentNode:{},
childrenNode:{},
content:"",
....
}
// 我之前写的找不到了--, 大家可以试着去实现一下。有问题随时沟通 本示例正则可用。
CSSParser
The difference between CSS parsing and HTML is a context-free grammar; it can be parsed by many parsers.
Lexical grammar (vocabulary) is defined by regular expressions for each token:
comment \/\*[^*]*\*+([^/*][^*]*\*+)*\/
num [0-9]+|[0-9]*"."[0-9]+
nonascii [\200-\377]
nmstart [_a-z]|{nonascii}|{escape}
nmchar [_a-z0-9-]|{nonascii}|{escape}
name {nmchar}+
ident {nmstart}{nmchar}*
A parser is automatically created through the CSS grammar file, and a bottom-up shift reduction parser will be created. The CSS file will be parsed into StyleSheet objects, and each object contains CSS rules. The CSS rule object contains selectors and declaration objects, as well as other objects corresponding to CSS syntax. as follows:
RenderTree
While building the DOM tree, the browser will also build another tree structure: the rendering tree. This is a tree composed of visual elements in the order in which they are displayed, and it is also a visual representation of the document. Its role is to allow you to draw content in the correct order.
The WebKits RenderObject class is the base class of all render trees and is defined as follows:
class RenderObject{
virtual void layout(); //布局
virtual void paint(PaintInfo); //绘制
virtual void rect repaintRect(); //重新绘制Rect
Node* node; // DOM节点
RenderStyle* style; // 计算render style
RenderLayer* containgLayer; //render layer
}
The relationship between the rendering tree and the DOM tree
The render tree corresponds to the DOM elements, but not one-to-one. Non-visual DOM elements will not be inserted into the render tree, such as the "head" element. If the display attribute value of the element is "none", it will not be displayed in the render tree (but the element with the visibility attribute value of "hidden" will still be displayed).
An example of multiple render trees is invalid HTML. According to the CSS specification, inline elements can only contain either block elements or inline elements. If there is mixed content, an anonymous block render tree should be created to wrap the inline element.
Some rendering objects correspond to DOM nodes, but their positions in the tree are different from DOM nodes. Floating positioning and absolute positioning elements are like this. They are outside the normal flow, placed elsewhere in the tree, and mapped to the real frame, while the placeholder frame is placed in place.
layout
When the render tree is created, the location and size information is not included. The process of calculating these values is called layout or rearrangement.
HTML uses a flow-based layout model, which means that in most cases, geometric information can be calculated with just one traversal. Elements at the back of the stream usually do not affect the geometric characteristics of the elements at the front, so the layout can traverse the document in the order from left to right and top to bottom. But there are exceptions. For example, the calculation of HTML tables requires more than one traversal (3.5).
The coordinate system is established relative to the root frame, using the upper and left coordinates.
Layout is a recursive process. It starts from the root render tree (corresponding to the <html> element of the HTML document), and then recursively traverses part or all of the frame hierarchy, and calculates geometric information for each render tree that needs to be calculated.
The upper left corner of the root render tree is 0,0
, (consistent with the canvas2D coordinate rules) and its size is the viewport (that is, the visible area of the browser window).
All render trees have a layout
or reflow
method, and each render tree will call the layout
method of its children that need to be laid out.
draw
In the drawing phase, the system traverses the render tree and calls the paint
method of the render tree to display the content of the render tree on the screen. The drawing work is done using the basic components of the user interface.
The order of drawing is actually the order in which the elements enter the stack style context; from back to front. The stacking order of the block render tree is as follows:
- background color
- Background picture
- frame
- Offspring
- contour
For drawing realization, please refer to canvas
( canvas must be learned, always pay attention to some cutting-edge actions), to understand the basic primitive drawing method and process. For example, draw
line
(requires coordinate basic primitive structure, etc.):
At last
Life diary from the previous article: 20210521 It was still happy that day (the circle of friends is still not active). 20210522 is not happy. 20210523 means that today, in general, is going well and has not studied. (Combination of work and rest haha)
then, because some people have always WeChat recently, which programming paradigm should I choose? Which programming paradigm I am using more now? What should I do if it is difficult to maintain the code by myself?... (I have been doing it for a long time The answer should be recorded and provided to everyone) Before the next issue of the JS engine, I will give a brief introduction to the programming paradigm for your reference (expected tomorrow).
Come on! If you have any questions, please leave a message at any time, and you will definitely reply when you see it. Regarding the previous supplementary structure diagram... well, I am a pigeon. I don’t see anyone urged.. too lazy to draw
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。