📄 document.cpp
字号:
int elapsed = elapsedTime(); m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold; // We'll want to schedule the timer to fire at the minimum layout threshold. return max(0, cLayoutScheduleThreshold - elapsed);}int Document::elapsedTime() const{ return static_cast<int>((currentTime() - m_startTime) * 1000);}void Document::write(const SegmentedString& text, Document* ownerDocument){#ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("Beginning a document.write at %d\n", elapsedTime());#endif if (!m_tokenizer) { open(ownerDocument); ASSERT(m_tokenizer); if (!m_tokenizer) return; UChar documentPrefix[] = { '<', 'h', 't', 'm', 'l', '>' }; m_tokenizer->write(SegmentedString(documentPrefix, sizeof(documentPrefix) / sizeof(documentPrefix[0])), false); } m_tokenizer->write(text, false);#ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("Ending a document.write at %d\n", elapsedTime());#endif }void Document::write(const String& text, Document* ownerDocument){ write(SegmentedString(text), ownerDocument);}void Document::writeln(const String& text, Document* ownerDocument){ write(text, ownerDocument); write("\n", ownerDocument);}void Document::finishParsing(){#ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("Received all data at %d\n", elapsedTime());#endif // Let the tokenizer go through as much data as it can. There will be three possible outcomes after // finish() is called: // (1) All remaining data is parsed, document isn't loaded yet // (2) All remaining data is parsed, document is loaded, tokenizer gets deleted // (3) Data is still remaining to be parsed. if (m_tokenizer) m_tokenizer->finish();}void Document::clear(){ delete m_tokenizer; m_tokenizer = 0; removeChildren(); size_t size = m_windowEventListeners.size(); for (size_t i = 0; i < size; ++i) m_windowEventListeners[i]->setRemoved(true); m_windowEventListeners.clear();}const KURL& Document::virtualURL() const{ return m_url;}KURL Document::virtualCompleteURL(const String& url) const{ return completeURL(url);}void Document::setURL(const KURL& url){ const KURL& newURL = url.isEmpty() ? blankURL() : url; if (newURL == m_url) return; m_url = newURL; m_documentURI = m_url.string(); updateBaseURL();}void Document::setBaseElementURL(const KURL& baseElementURL){ m_baseElementURL = baseElementURL; updateBaseURL();}void Document::updateBaseURL(){ // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 HTML], the base URI is computed using // first the value of the href attribute of the HTML BASE element if any, and the value of the documentURI attribute // from the Document interface otherwise. if (m_baseElementURL.isEmpty()) { // The documentURI attribute is an arbitrary string. DOM 3 Core does not specify how it should be resolved, // so we use a null base URL. m_baseURL = KURL(KURL(), documentURI()); } else m_baseURL = m_baseElementURL; if (!m_baseURL.isValid()) m_baseURL = KURL(); if (m_elemSheet) m_elemSheet->setHref(m_baseURL.string()); if (m_mappedElementSheet) m_mappedElementSheet->setHref(m_baseURL.string());}String Document::userAgent(const KURL& url) const{ return frame() ? frame()->loader()->userAgent(url) : String();}void Document::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet){ m_sheet = CSSStyleSheet::create(this, url, charset); m_sheet->parseString(sheet->sheetText()); updateStyleSelector();}#if FRAME_LOADS_USER_STYLESHEETvoid Document::setUserStyleSheet(const String& sheet){ if (m_usersheet != sheet) { m_usersheet = sheet; updateStyleSelector(); }}#endifString Document::userStyleSheet() const{#if FRAME_LOADS_USER_STYLESHEET return m_usersheet;#else Page* page = this->page(); if (!page) return String(); return page->userStyleSheet();#endif}CSSStyleSheet* Document::elementSheet(){ if (!m_elemSheet) m_elemSheet = CSSStyleSheet::create(this, m_baseURL.string()); return m_elemSheet.get();}CSSStyleSheet* Document::mappedElementSheet(){ if (!m_mappedElementSheet) m_mappedElementSheet = CSSStyleSheet::create(this, m_baseURL.string()); return m_mappedElementSheet.get();}static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event){ // Search is inclusive of start for (Node* n = start; n; n = n->traverseNextNode()) if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex) return n; return 0;}static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event){ // Search is inclusive of start for (Node* n = start; n; n = n->traversePreviousNode()) if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex) return n; return 0;}static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event){ // Search is inclusive of start int winningTabIndex = SHRT_MAX + 1; Node* winner = 0; for (Node* n = start; n; n = n->traverseNextNode()) if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) { winner = n; winningTabIndex = n->tabIndex(); } return winner;}static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event){ // Search is inclusive of start int winningTabIndex = 0; Node* winner = 0; for (Node* n = start; n; n = n->traversePreviousNode()) if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) { winner = n; winningTabIndex = n->tabIndex(); } return winner;}Node* Document::nextFocusableNode(Node* start, KeyboardEvent* event){ if (start) { // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order if (start->tabIndex() < 0) { for (Node* n = start->traverseNextNode(); n; n = n->traverseNextNode()) if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0) return n; } // First try to find a node with the same tabindex as start that comes after start in the document. if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event)) return winner; if (start->tabIndex() == 0) // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order. return 0; } // Look for the first node in the document that: // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and // 2) comes first in the document, if there's a tie. if (Node* winner = nextNodeWithGreaterTabIndex(this, start ? start->tabIndex() : 0, event)) return winner; // There are no nodes with a tabindex greater than start's tabindex, // so find the first node with a tabindex of 0. return nextNodeWithExactTabIndex(this, 0, event);}Node* Document::previousFocusableNode(Node* start, KeyboardEvent* event){ Node* last; for (last = this; last->lastChild(); last = last->lastChild()) ; // Empty loop. // First try to find the last node in the document that comes before start and has the same tabindex as start. // If start is null, find the last node in the document with a tabindex of 0. Node* startingNode; int startingTabIndex; if (start) { startingNode = start->traversePreviousNode(); startingTabIndex = start->tabIndex(); } else { startingNode = last; startingTabIndex = 0; } // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order if (startingTabIndex < 0) { for (Node* n = startingNode; n; n = n->traversePreviousNode()) if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0) return n; } if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event)) return winner; // There are no nodes before start with the same tabindex as start, so look for a node that: // 1) has the highest non-zero tabindex (that is less than start's tabindex), and // 2) comes last in the document, if there's a tie. startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : SHRT_MAX; return previousNodeWithLowerTabIndex(last, startingTabIndex, event);}int Document::nodeAbsIndex(Node *node){ ASSERT(node->document() == this); int absIndex = 0; for (Node *n = node; n && n != this; n = n->traversePreviousNode()) absIndex++; return absIndex;}Node *Document::nodeWithAbsIndex(int absIndex){ Node *n = this; for (int i = 0; n && (i < absIndex); i++) { n = n->traverseNextNode(); } return n;}void Document::processHttpEquiv(const String &equiv, const String &content){ ASSERT(!equiv.isNull() && !content.isNull()); Frame *frame = this->frame(); if (equalIgnoringCase(equiv, "default-style")) { // The preferred style set has been overridden as per section // 14.3.2 of the HTML4.0 specification. We need to update the // sheet used variable and then update our style selector. // For more info, see the test at: // http://www.hixie.ch/tests/evil/css/import/main/preferred.html // -dwh m_selectedStylesheetSet = content; m_preferredStylesheetSet = content; updateStyleSelector(); } else if (equalIgnoringCase(equiv, "refresh")) { double delay; String url; if (frame && parseHTTPRefresh(content, true, delay, url)) { if (url.isEmpty()) url = frame->loader()->url().string(); else url = completeURL(url).string(); frame->loader()->scheduleHTTPRedirection(delay, url); } } else if (equalIgnoringCase(equiv, "set-cookie")) { // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....> if (isHTMLDocument()) static_cast<HTMLDocument*>(this)->setCookie(content); } else if (equalIgnoringCase(equiv, "content-language")) setContentLanguage(content); else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) parseDNSPrefetchControlHeader(content);}MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event){ ASSERT(!renderer() || renderer()->isRenderView()); if (!renderer()) return MouseEventWithHitTestResults(event, HitTestResult(IntPoint())); HitTestResult result(documentPoint); renderView()->layer()->hitTest(request, result); if (!request.readOnly()) updateRendering(); return MouseEventWithHitTestResults(event, result);}// DOM Section 1.1.1bool Document::childTypeAllowed(NodeType type){ switch (type) { case ATTRIBUTE_NODE: case CDATA_SECTION_NODE: case DOCUMENT_FRAGMENT_NODE: case DOCUMENT_NODE: case ENTITY_NODE: case ENTITY_REFERENCE_NODE: case NOTATION_NODE: case TEXT_NODE: case XPATH_NAMESPACE_NODE: return false; case COMMENT_NODE: case PROCESSING_INSTRUCTION_NODE: return true; case DOCUMENT_TYPE_NODE: case ELEMENT_NODE: // Documents may contain no more than one of each of these. // (One Element and one DocumentType.) for (Node* c = firstChild(); c; c = c->nextSibling()) if (c->nodeType() == type) return false; return true; } return false;}bool Document::canReplaceChild(Node* newChild, Node* oldChild){ if (!oldChild) // ContainerNode::replaceChild will raise a NOT_FOUND_ERR. return true; if (oldChild->nodeType() == newChild->nodeType()) return true; int numDoctypes = 0; int numElements = 0; // First, check how many doctypes and elements we have, not counting // the child we're about to remove. for (Node* c = firstChild(); c; c = c->nextSibling()) { if (c == oldChild) continue; switch (c->nodeType()) { case DOCUMENT_TYPE_NODE: numDoctypes++; break; case ELEMENT_NODE: numElements++; break; default: break; } } // Then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -