Open cisen opened 5 years ago
components\script\dom\event.rs
, dispatch_to_listenerscomponents\script\fetch.rs
, https://fetch.spec.whatwg.org/#fetch-methodcomponents\script\dom\blob.rs
read_file
requestAnimframe的实现原理是什么?
components\script\dom\document.rs
的request_animation_frame
, run_the_animation_frame_callbacks
CallJSNative(cx, native, args);
animation_frame_list
队列run_the_animation_frame_callbacks
遍历该队列,并调用callBack执行rA插入的是JS函数,如何再rust里面调用?
没有实现IdleRequestCallback ?
addeventlistener在哪里?
components\script\dom\eventtarget.rs
的add_event_listener
, remove_event_listener
事件实现类似react的合成事件?
如何知道触发了addeventlistener的event?
components/script/script_thread.rs
起一个死循环,start,轮询侦听事件components/script/script_thread.rs
会起一个循环线程,不断侦听事件handle_msgs
,如果有事件则调用对应事件函components/script/dom/event.rs
的pub fn fire
里面打// Receive at least one message so we don't spinloop.
debug!("Waiting for event.");
let mut event = select! {
recv(self.task_queue.select()) -> msg => {
self.task_queue.take_tasks(msg.unwrap());
let event = self
.task_queue
.recv()
.expect("Spurious wake-up of the event-loop, task-queue has no tasks available");
FromScript(event)
},
recv(self.control_port) -> msg => FromConstellation(msg.unwrap()),
recv(self.timer_event_port) -> msg => FromScheduler(msg.unwrap()),
recv(self.devtools_chan.as_ref().map(|_| &self.devtools_port).unwrap_or(&crossbeam_channel::never())) -> msg
=> FromDevtools(msg.unwrap()),
recv(self.image_cache_port) -> msg => FromImageCache(msg.unwrap()),
};
debug!("Got event.");
同源策略在哪里?
components\net\fetch\cors_cache.rs
,components\net\connector.rs
sw的缓存是如何实现的?
整个浏览器的流程是怎样的?
ports\glutin\main2.rs
的main函数servo::run_content_process
connection_bootstrap
?init_service_workers
, 初始化swUnprivilegedPipelineContent::start_all
LayoutThreadFactory
ScriptThreadFactory
image_cache
ScriptThreadFactory::create
components\script\script_thread.rs
, ScriptThread::start
ScriptThread::handle_msgs
ScriptThread::handle_new_layout
,message::Msg::CreateLayoutThread
LayoutThread::create_layout_thread
LayoutThreadFactory::create
, layout.start()
关键layout.start()
开始渲染layout.start()
, LayoutThread::start
handle_request
, 应该是layout的主线程LayoutThread::handle_request
LayoutThread::handle_request_helper
self.handle_reflow
, self.tick_all_animations
perform_post_style_recalc_layout_passes
perform_post_main_layout_passes
compute_abs_pos_and_build_display_list
let traversal = ComputeStackingRelativePositions {
layout_context: layout_context,
};
traversal.traverse(layout_root);
reflow的机制是怎样的?
components/layout/sequential.rs
的pub fn reflow
函数components\script\dom\window.rs
的很多样式取值前都会调用layout_reflow,再获取值的reflow流程是怎样的?
尺寸和位置计算在哪里?
components\layout
components\script\dom\webidls\Element.webidl
各个element支持的事件列表在哪里?
clientWidth/offsetWidth有何区别?
clientWidth
来自FragmentLocatingFragmentIterator.client_rect
,FragmentLocatingFragmentIterator
只携带了client_rect和node的path,也就是只携带了该节点的尺寸和位置FragmentBorderBoxIterator
继承了FragmentLocatingFragmentIterator
,是最常用带clientWidth的盒子clientWidth如何取值的?
element.ClientWidth
通过node.client_rect()
函数获取client尺寸位置client_rect_query
方法利用RPC获取client_rect_query
获取rect前先reflow,再通过components\layout\query.rs
的node_geometry实现rpc调用components\layout_thread\lib.rs
的respond_to_query_if_necessary
函数,它根据不同查询类型分发不同的调用,比如rect是process_node_geometry_request
process_node_geometry_request
是计算rect的入口,真正重点计算的是iterate_through_flow_tree_fragment_border_boxes
iterate_through_flow_tree_fragment_border_boxes
通过递归查询stacking_relative_position
来获取尺寸和位置的,这是获取rect的关键stacking_relative_position
是来自BlockFlow继承自BaseFlow(基础文档流)为什么client_rect_query
在获取rect要先reflow?
stacking_relative_position
是在哪里更新值的?
components\layout\block.rs
的compute_stacking_relative_position
函数里面:self.base.stacking_relative_position.x = absolute_stacking_relative_position.x
之类的更新这个值何时如何跟新stacking_relative_position的值?
perform_post_style_recalc_layout_passes
perform_post_style_recalc_layout_passes
perform_post_main_layout_passes
compute_abs_pos_and_build_display_list
let traversal = ComputeStackingRelativePositions {
layout_context: layout_context,
};
traversal.traverse(layout_root);
网页开始加载是从哪里开始?
ScriptThreadFactory:create
, script_thread.pre_page_load(new_load, load_data)
什么时候开始parse css和html的?
pre_page_load
, 这是提前的部分let context = ParserContext::new(id, load_data.url);
Constellation::run
的时候执行self.handle_request()
Constellation::handle_request_from_network_listener
ConstellationControlMsg::NavigationResponse
, 调用正在侦听的ipcScriptThread::run
ScriptThread::handle_msgs
handle_msg_from_constellation
ConstellationControlMsg
的中断components\script\script_thread.rs
, ConstellationControlMsg::NavigationResponse
components\script\script_thread.rs
, FetchResponseMsg::ProcessResponse
handle_fetch_metadata
, 调用ctxt.process_response(fetch_metadata);
components\script\dom\servoparser\mod.rs
, FetchResponseListener::process_response
content_type
执行不同的parsehtmlparser的入口在哪里?
components\script\dom\servoparser
利用html5ever
生成token tree就完事了components\script\dom\servoparser\mod.rs
, ServoParser::parse_sync
ServoParser::do_parse_sync
ServoParser::tokenize
match feed(&mut *self.tokenizer.borrow_mut())
根据html/xml/async_html的不同递归调用各种的feed函数,以生成token treecss的parser的入口在哪里?
components\style
components\script\dom\htmlstyleelement.rs
parse_own_css 再利用cssparser
(https://github.com/servo/rust-cssparser)JS的parser的入口在哪里?
css是在哪里跟html融合的?
set_stylesheet
,怎么利用css生成element的clientWidth的?
css是怎么匹配到DOM的?
components\selectors\matching.rs
,matches_simple_selector函数css的匹配入口在哪里?
为什么可用直接使用use ipc_channel
?
比如这种:
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use net_traits::request::RequestBuilder;
use net_traits::request::{Request as NetTraitsRequest, ServiceWorkersMode};
components\servo\lib.rs
文件里面,使用pub use ipc_channel
统一从新导出了所有全局依赖,所以任何模块都可以直接使用use引入
各个模块
依赖模块
编译注意
windows
ubuntu 18.04
./mach bootstrap
安装依赖,不要使用自己安装