📄 document.cpp
字号:
m_renderArena = new RenderArena(); // Create the rendering tree setRenderer(new (m_renderArena) RenderView(this, view()));#if USE(ACCELERATED_COMPOSITING) renderView()->didMoveOnscreen();#endif if (!m_styleSelector) { bool matchAuthorAndUserStyles = true; if (Settings* docSettings = settings()) matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled(); m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles); } recalcStyle(Force); RenderObject* render = renderer(); setRenderer(0); ContainerNode::attach(); setRenderer(render);}void Document::detach(){ ASSERT(attached()); ASSERT(!m_inPageCache); clearAXObjectCache(); stopActiveDOMObjects(); RenderObject* render = renderer(); // Send out documentWillBecomeInactive() notifications to registered elements, // in order to stop media elements documentWillBecomeInactive(); // indicate destruction mode, i.e. attached() but renderer == 0 setRenderer(0); // Empty out these lists as a performance optimization, since detaching // all the individual render objects will cause all the RenderImage // objects to remove themselves from the lists. m_imageLoadEventDispatchSoonList.clear(); m_imageLoadEventDispatchingList.clear(); m_hoverNode = 0; m_focusedNode = 0; m_activeNode = 0; ContainerNode::detach(); if (render) render->destroy(); // This is required, as our Frame might delete itself as soon as it detaches // us. However, this violates Node::detach() symantics, as it's never // possible to re-attach. Eventually Document::detach() should be renamed // or this call made explicit in each of the callers of Document::detach(). clearFramePointer(); if (m_renderArena) { delete m_renderArena; m_renderArena = 0; }}void Document::clearFramePointer(){ m_frame = 0;}void Document::removeAllEventListenersFromAllNodes(){ size_t size = m_windowEventListeners.size(); for (size_t i = 0; i < size; ++i) m_windowEventListeners[i]->setRemoved(true); m_windowEventListeners.clear(); removeAllDisconnectedNodeEventListeners(); for (Node* node = this; node; node = node->traverseNextNode()) node->removeAllEventListeners();}void Document::registerDisconnectedNodeWithEventListeners(Node* node){ m_disconnectedNodesWithEventListeners.add(node);}void Document::unregisterDisconnectedNodeWithEventListeners(Node* node){ m_disconnectedNodesWithEventListeners.remove(node);}void Document::removeAllDisconnectedNodeEventListeners(){ HashSet<Node*>::iterator end = m_disconnectedNodesWithEventListeners.end(); for (HashSet<Node*>::iterator i = m_disconnectedNodesWithEventListeners.begin(); i != end; ++i) (*i)->removeAllEventListeners(); m_disconnectedNodesWithEventListeners.clear();}RenderView* Document::renderView() const{ return toRenderView(renderer());}void Document::clearAXObjectCache(){ // clear cache in top document if (m_axObjectCache) { delete m_axObjectCache; m_axObjectCache = 0; return; } // ask the top-level document to clear its cache Document* doc = topDocument(); if (doc != this) doc->clearAXObjectCache();}AXObjectCache* Document::axObjectCache() const{ // The only document that actually has a AXObjectCache is the top-level // document. This is because we need to be able to get from any WebCoreAXObject // to any other WebCoreAXObject on the same page. Using a single cache allows // lookups across nested webareas (i.e. multiple documents). if (m_axObjectCache) { // return already known top-level cache if (!ownerElement()) return m_axObjectCache; // In some pages with frames, the cache is created before the sub-webarea is // inserted into the tree. Here, we catch that case and just toss the old // cache and start over. // NOTE: This recovery may no longer be needed. I have been unable to trigger // it again. See rdar://5794454 // FIXME: Can this be fixed when inserting the subframe instead of now? // FIXME: If this function was called to get the cache in order to remove // an AXObject, we are now deleting the cache as a whole and returning a // new empty cache that does not contain the AXObject! That should actually // be OK. I am concerned about other cases like this where accessing the // cache blows away the AXObject being operated on. delete m_axObjectCache; m_axObjectCache = 0; } // ask the top-level document for its cache Document* doc = topDocument(); if (doc != this) return doc->axObjectCache(); // this is the top-level document, so install a new cache m_axObjectCache = new AXObjectCache; return m_axObjectCache;}void Document::setVisuallyOrdered(){ visuallyOrdered = true; if (renderer()) renderer()->style()->setVisuallyOrdered(true);}Tokenizer* Document::createTokenizer(){ // FIXME: this should probably pass the frame instead return new XMLTokenizer(this, view());}void Document::open(Document* ownerDocument){ if (ownerDocument) { setURL(ownerDocument->url()); m_cookieURL = ownerDocument->cookieURL(); ScriptExecutionContext::setSecurityOrigin(ownerDocument->securityOrigin()); } if (m_frame) { if (m_frame->loader()->isLoadingMainResource() || (tokenizer() && tokenizer()->executingScript())) return; if (m_frame->loader()->state() == FrameStateProvisional) m_frame->loader()->stopAllLoaders(); } implicitOpen(); if (m_frame) m_frame->loader()->didExplicitOpen();}void Document::cancelParsing(){ if (m_tokenizer) { // We have to clear the tokenizer to avoid possibly triggering // the onload handler when closing as a side effect of a cancel-style // change, such as opening a new document or closing the window while // still parsing delete m_tokenizer; m_tokenizer = 0; close(); }}void Document::implicitOpen(){ cancelParsing(); clear(); m_tokenizer = createTokenizer(); setParsing(true);}HTMLElement* Document::body() const{ Node* de = documentElement(); if (!de) return 0; // try to prefer a FRAMESET element over BODY Node* body = 0; for (Node* i = de->firstChild(); i; i = i->nextSibling()) { if (i->hasTagName(framesetTag)) return static_cast<HTMLElement*>(i); if (i->hasTagName(bodyTag) && !body) body = i; } return static_cast<HTMLElement*>(body);}void Document::setBody(PassRefPtr<HTMLElement> newBody, ExceptionCode& ec){ if (!newBody || !documentElement()) { ec = HIERARCHY_REQUEST_ERR; return; } HTMLElement* b = body(); if (!b) documentElement()->appendChild(newBody, ec); else documentElement()->replaceChild(newBody, b, ec);}HTMLHeadElement* Document::head(){ Node* de = documentElement(); if (!de) return 0; for (Node* e = de->firstChild(); e; e = e->nextSibling()) if (e->hasTagName(headTag)) return static_cast<HTMLHeadElement*>(e); return 0;}void Document::close(){ Frame* frame = this->frame(); if (frame) { // This code calls implicitClose() if all loading has completed. FrameLoader* frameLoader = frame->loader(); frameLoader->endIfNotLoadingMainResource(); frameLoader->checkCompleted(); } else { // Because we have no frame, we don't know if all loading has completed, // so we just call implicitClose() immediately. FIXME: This might fire // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>. implicitClose(); }}void Document::implicitClose(){ // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached. if (m_inStyleRecalc) { m_closeAfterStyleRecalc = true; return; } bool wasLocationChangePending = frame() && frame()->loader()->isScheduledLocationChangePending(); bool doload = !parsing() && m_tokenizer && !m_processingLoadEvent && !wasLocationChangePending; if (!doload) return; m_processingLoadEvent = true; m_wellFormed = m_tokenizer && m_tokenizer->wellFormed(); // We have to clear the tokenizer, in case someone document.write()s from the // onLoad event handler, as in Radar 3206524. delete m_tokenizer; m_tokenizer = 0; // Parser should have picked up all preloads by now m_docLoader->clearPreloads(); // Create a body element if we don't already have one. See Radar 3758785. if (!this->body() && isHTMLDocument()) { if (Node* documentElement = this->documentElement()) { ExceptionCode ec = 0; documentElement->appendChild(new HTMLBodyElement(bodyTag, this), ec); ASSERT(!ec); } } // FIXME: We kick off the icon loader when the Document is done parsing. // There are earlier opportunities we could start it: // -When the <head> finishes parsing // -When any new HTMLLinkElement is inserted into the document // But those add a dynamic component to the favicon that has UI // ramifications, and we need to decide what is the Right Thing To Do(tm) Frame* f = frame(); if (f) f->loader()->startIconLoader(); // Resume the animations (or start them) if (f) f->animation()->resumeAnimations(this); dispatchImageLoadEventsNow(); this->dispatchWindowEvent(eventNames().loadEvent, false, false); if (f) f->loader()->handledOnloadEvents();#ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("onload fired at %d\n", elapsedTime());#endif m_processingLoadEvent = false; // An event handler may have removed the frame if (!frame()) return; // Make sure both the initial layout and reflow happen after the onload // fires. This will improve onload scores, and other browsers do it. // If they wanna cheat, we can too. -dwh if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) { // Just bail out. Before or during the onload we were shifted to another page. // The old i-Bench suite does this. When this happens don't bother painting or laying out. view()->unscheduleRelayout(); return; } frame()->loader()->checkCallImplicitClose(); // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe // that has been sized already. Otherwise, our view size would be incorrect, so doing any // layout/painting now would be pointless. if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) { updateRendering(); // Always do a layout after loading if needed. if (view() && renderer() && (!renderer()->firstChild() || renderer()->needsLayout())) view()->layout(); // Paint immediately after the document is ready. We do this to ensure that any timers set by the // onload don't have a chance to fire before we would have painted. To avoid over-flushing we only // worry about this for the top-level document. For platforms that use native widgets for ScrollViews, this // call does nothing (Mac, wx). // FIXME: This causes a timing issue with the dispatchDidFinishLoad delegate callback on Mac, so think // before enabling it, even if Mac becomes viewless later. // See <rdar://problem/5092361> if (view() && !ownerElement()) view()->hostWindow()->paint(); }#if PLATFORM(MAC) if (f && renderer() && this == topDocument() && AXObjectCache::accessibilityEnabled()) axObjectCache()->postNotificationToElement(renderer(), "AXLoadComplete");#endif#if ENABLE(SVG) // FIXME: Officially, time 0 is when the outermost <svg> receives its // SVGLoad event, but we don't implement those yet. This is close enough // for now. In some cases we should have fired earlier. if (svgExtensions()) accessSVGExtensions()->startAnimations();#endif}void Document::setParsing(bool b){ m_bParsing = b; if (!m_bParsing && view()) view()->scheduleRelayout();#ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement() && !m_bParsing) printf("Parsing finished at %d\n", elapsedTime());#endif}bool Document::shouldScheduleLayout(){ // This function will only be called when FrameView thinks a layout is needed. // This enforces a couple extra rules. // // (a) Only schedule a layout once the stylesheets are loaded. // (b) Only schedule layout once we have a body element. return haveStylesheetsLoaded() && body() || (documentElement() && !documentElement()->hasTagName(htmlTag));}int Document::minimumLayoutDelay(){ if (m_overMinimumLayoutThreshold) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -