#include "HTMLNames.h"
#include "XMLNames.h"
#include "bindings/v8/ExceptionState.h"
-#include "bindings/v8/ScriptController.h"
#include "bindings/v8/ScriptEventListener.h"
-#include "core/css/CSSParser.h"
+#include "core/css/CSSMarkup.h"
#include "core/css/CSSValuePool.h"
#include "core/css/StylePropertySet.h"
#include "core/dom/DocumentFragment.h"
#include "core/events/EventListener.h"
#include "core/events/KeyboardEvent.h"
#include "core/events/ThreadLocalEventNames.h"
+#include "core/frame/Settings.h"
#include "core/html/HTMLBRElement.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLTemplateElement.h"
#include "core/html/HTMLTextFormControlElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
-#include "core/loader/FrameLoader.h"
-#include "core/frame/Frame.h"
-#include "core/page/Settings.h"
-#include "core/rendering/RenderWordBreak.h"
-#include "platform/graphics/TextRunIterator.h"
+#include "core/rendering/RenderObject.h"
#include "platform/text/BidiResolver.h"
+#include "platform/text/BidiTextRun.h"
+#include "platform/text/TextRunIterator.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/CString.h"
Element::collectStyleForPresentationAttribute(name, value, style);
}
-AtomicString HTMLElement::eventNameForAttributeName(const QualifiedName& attrName) const
+const AtomicString& HTMLElement::eventNameForAttributeName(const QualifiedName& attrName)
{
if (!attrName.namespaceURI().isNull())
- return AtomicString();
+ return nullAtom;
typedef HashMap<AtomicString, AtomicString> StringToStringMap;
DEFINE_STATIC_LOCAL(StringToStringMap, attributeNameToEventNameMap, ());
attributeNameToEventNameMap.set(onprogressAttr.localName(), EventTypeNames::progress);
attributeNameToEventNameMap.set(onratechangeAttr.localName(), EventTypeNames::ratechange);
attributeNameToEventNameMap.set(onresetAttr.localName(), EventTypeNames::reset);
+ attributeNameToEventNameMap.set(onresizeAttr.localName(), EventTypeNames::resize);
attributeNameToEventNameMap.set(onseekedAttr.localName(), EventTypeNames::seeked);
attributeNameToEventNameMap.set(onseekingAttr.localName(), EventTypeNames::seeking);
attributeNameToEventNameMap.set(onselectAttr.localName(), EventTypeNames::select);
setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
}
} else {
- AtomicString eventName = eventNameForAttributeName(name);
+ const AtomicString& eventName = eventNameForAttributeName(name);
if (!eventName.isNull())
setAttributeEventListener(eventName, createAttributeEventListener(this, name, value));
}
}
-PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionState& es)
+PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionState& exceptionState)
{
RefPtr<DocumentFragment> fragment = DocumentFragment::create(document());
unsigned int i, length = text.length();
break;
}
- fragment->appendChild(Text::create(document(), text.substring(start, i - start)), es);
- if (es.hadException())
+ fragment->appendChild(Text::create(document(), text.substring(start, i - start)), exceptionState);
+ if (exceptionState.hadException())
return 0;
if (c == '\r' || c == '\n') {
- fragment->appendChild(HTMLBRElement::create(document()), es);
- if (es.hadException())
+ fragment->appendChild(HTMLBRElement::create(document()), exceptionState);
+ if (exceptionState.hadException())
return 0;
// Make sure \r\n doesn't result in two line breaks.
if (c == '\r' && i + 1 < length && text[i + 1] == '\n')
return fragment;
}
-void HTMLElement::setInnerText(const String& text, ExceptionState& es)
+void HTMLElement::setInnerText(const String& text, ExceptionState& exceptionState)
{
if (ieForbidsInsertHTML()) {
- es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+ exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
return;
}
if (hasLocalName(colTag) || hasLocalName(colgroupTag) || hasLocalName(framesetTag) ||
hasLocalName(headTag) || hasLocalName(htmlTag) || hasLocalName(tableTag) ||
hasLocalName(tbodyTag) || hasLocalName(tfootTag) || hasLocalName(theadTag) ||
hasLocalName(trTag)) {
- es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+ exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
return;
}
removeChildren();
return;
}
- replaceChildrenWithText(this, text, es);
+ replaceChildrenWithText(this, text, exceptionState);
return;
}
RenderObject* r = renderer();
if (r && r->style()->preserveNewline()) {
if (!text.contains('\r')) {
- replaceChildrenWithText(this, text, es);
+ replaceChildrenWithText(this, text, exceptionState);
return;
}
String textWithConsistentLineBreaks = text;
textWithConsistentLineBreaks.replace("\r\n", "\n");
textWithConsistentLineBreaks.replace('\r', '\n');
- replaceChildrenWithText(this, textWithConsistentLineBreaks, es);
+ replaceChildrenWithText(this, textWithConsistentLineBreaks, exceptionState);
return;
}
// Add text nodes and <br> elements.
- RefPtr<DocumentFragment> fragment = textToFragment(text, es);
- if (!es.hadException())
- replaceChildrenWithFragment(this, fragment.release(), es);
+ RefPtr<DocumentFragment> fragment = textToFragment(text, exceptionState);
+ if (!exceptionState.hadException())
+ replaceChildrenWithFragment(this, fragment.release(), exceptionState);
}
-void HTMLElement::setOuterText(const String &text, ExceptionState& es)
+void HTMLElement::setOuterText(const String &text, ExceptionState& exceptionState)
{
if (ieForbidsInsertHTML()) {
- es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+ exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
return;
}
if (hasLocalName(colTag) || hasLocalName(colgroupTag) || hasLocalName(framesetTag) ||
hasLocalName(headTag) || hasLocalName(htmlTag) || hasLocalName(tableTag) ||
hasLocalName(tbodyTag) || hasLocalName(tfootTag) || hasLocalName(theadTag) ||
hasLocalName(trTag)) {
- es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+ exceptionState.throwDOMException(NoModificationAllowedError, "The '" + localName() + "' element does not support text insertion.");
return;
}
ContainerNode* parent = parentNode();
if (!parent) {
- es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
+ exceptionState.throwDOMException(NoModificationAllowedError, "The element has no parent.");
return;
}
// Convert text to fragment with <br> tags instead of linebreaks if needed.
if (text.contains('\r') || text.contains('\n'))
- newChild = textToFragment(text, es);
+ newChild = textToFragment(text, exceptionState);
else
newChild = Text::create(document(), text);
+ // textToFragment might cause mutation events.
if (!this || !parentNode())
- es.throwUninformativeAndGenericDOMException(HierarchyRequestError);
- if (es.hadException())
- return;
- parent->replaceChild(newChild.release(), this, es);
-
- RefPtr<Node> node = next ? next->previousSibling() : 0;
- if (!es.hadException() && node && node->isTextNode())
- mergeWithNextTextNode(node.release(), es);
-
- if (!es.hadException() && prev && prev->isTextNode())
- mergeWithNextTextNode(prev.release(), es);
-}
-
-Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, ExceptionState& es)
-{
- // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
- // a document fragment is created and the elements appended in the correct order. This document
- // fragment isn't returned anywhere.
- //
- // This is impossible for us to implement as the DOM tree does not allow for such structures,
- // Opera also appears to disallow such usage.
-
- if (equalIgnoringCase(where, "beforeBegin")) {
- if (ContainerNode* parent = this->parentNode()) {
- parent->insertBefore(newChild, this, es);
- if (!es.hadException())
- return newChild;
- }
- return 0;
- }
-
- if (equalIgnoringCase(where, "afterBegin")) {
- insertBefore(newChild, firstChild(), es);
- return es.hadException() ? 0 : newChild;
- }
-
- if (equalIgnoringCase(where, "beforeEnd")) {
- appendChild(newChild, es);
- return es.hadException() ? 0 : newChild;
- }
-
- if (equalIgnoringCase(where, "afterEnd")) {
- if (ContainerNode* parent = this->parentNode()) {
- parent->insertBefore(newChild, nextSibling(), es);
- if (!es.hadException())
- return newChild;
- }
- return 0;
- }
-
- // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
- es.throwUninformativeAndGenericDOMException(NotSupportedError);
- return 0;
-}
-
-Element* HTMLElement::insertAdjacentElement(const String& where, Element* newChild, ExceptionState& es)
-{
- if (!newChild) {
- // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative.
- es.throwUninformativeAndGenericDOMException(TypeMismatchError);
- return 0;
- }
-
- Node* returnValue = insertAdjacent(where, newChild, es);
- return toElement(returnValue);
-}
-
-// Step 3 of http://www.whatwg.org/specs/web-apps/current-work/multipage/apis-in-html-documents.html#insertadjacenthtml()
-static Element* contextElementForInsertion(const String& where, Element* element, ExceptionState& es)
-{
- if (equalIgnoringCase(where, "beforeBegin") || equalIgnoringCase(where, "afterEnd")) {
- ContainerNode* parent = element->parentNode();
- if (parent && !parent->isElementNode()) {
- es.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
- return 0;
- }
- return toElement(parent);
- }
- if (equalIgnoringCase(where, "afterBegin") || equalIgnoringCase(where, "beforeEnd"))
- return element;
- es.throwUninformativeAndGenericDOMException(SyntaxError);
- return 0;
-}
+ exceptionState.throwDOMException(HierarchyRequestError, "The element has no parent.");
-void HTMLElement::insertAdjacentHTML(const String& where, const String& markup, ExceptionState& es)
-{
- RefPtr<Element> contextElement = contextElementForInsertion(where, this, es);
- if (!contextElement)
+ if (exceptionState.hadException())
return;
- RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, contextElement.get(), AllowScriptingContent, "insertAdjacentHTML", es);
- if (!fragment)
- return;
- insertAdjacent(where, fragment.get(), es);
-}
+ parent->replaceChild(newChild.release(), this, exceptionState);
-void HTMLElement::insertAdjacentText(const String& where, const String& text, ExceptionState& es)
-{
- RefPtr<Text> textNode = document().createTextNode(text);
- insertAdjacent(where, textNode.get(), es);
+ RefPtr<Node> node = next ? next->previousSibling() : 0;
+ if (!exceptionState.hadException() && node && node->isTextNode())
+ mergeWithNextTextNode(node.release(), exceptionState);
+
+ if (!exceptionState.hadException() && prev && prev->isTextNode())
+ mergeWithNextTextNode(prev.release(), exceptionState);
}
void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStylePropertySet* style)
return "inherit";
}
-void HTMLElement::setContentEditable(const String& enabled, ExceptionState& es)
+void HTMLElement::setContentEditable(const String& enabled, ExceptionState& exceptionState)
{
if (equalIgnoringCase(enabled, "true"))
setAttribute(contenteditableAttr, "true");
else if (equalIgnoringCase(enabled, "inherit"))
removeAttribute(contenteditableAttr);
else
- es.throwUninformativeAndGenericDOMException(SyntaxError);
+ exceptionState.throwDOMException(SyntaxError, "The value provided ('" + enabled + "') is not one of 'true', 'false', 'plaintext-only', or 'inherit'.");
}
bool HTMLElement::draggable() const
void HTMLElement::click()
{
- dispatchSimulatedClick(0, SendNoEvents, DoNotShowPressedLook);
+ dispatchSimulatedClick(0, SendNoEvents);
}
void HTMLElement::accessKeyAction(bool sendMouseEvents)
String HTMLElement::title() const
{
- return getAttribute(titleAttr);
+ return fastGetAttribute(titleAttr);
}
short HTMLElement::tabIndex() const
void HTMLElement::setTabIndex(int value)
{
- setAttribute(tabindexAttr, String::number(value));
+ setIntegralAttribute(tabindexAttr, value);
}
TranslateAttributeMode HTMLElement::translateAttributeMode() const
setAttribute(translateAttr, enable ? "yes" : "no");
}
-bool HTMLElement::rendererIsNeeded(const RenderStyle& style)
-{
- if (hasLocalName(noscriptTag)) {
- Frame* frame = document().frame();
- if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript))
- return false;
- } else if (hasLocalName(noembedTag)) {
- Frame* frame = document().frame();
- if (frame && frame->loader().allowPlugins(NotAboutToInstantiatePlugin))
- return false;
- }
- return Element::rendererIsNeeded(style);
-}
-
-RenderObject* HTMLElement::createRenderer(RenderStyle* style)
-{
- if (hasLocalName(wbrTag))
- return new RenderWordBreak(this);
- return RenderObject::createObject(this, style);
-}
-
HTMLFormElement* HTMLElement::findFormAncestor() const
{
for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
return 0;
}
-HTMLFormElement* HTMLElement::virtualForm() const
-{
- return findFormAncestor();
-}
-
static inline bool elementAffectsDirectionality(const Node* node)
{
return node->isHTMLElement() && (node->hasTagName(bdiTag) || toHTMLElement(node)->hasAttribute(dirAttr));
if (elementAffectsDirectionality(node)) {
if (node == lastNode)
return;
- node = NodeTraversal::nextSkippingChildren(node, firstNode);
+ node = NodeTraversal::nextSkippingChildren(*node, firstNode);
continue;
}
node->setSelfOrAncestorHasDirAutoAttribute(flag);
if (node == lastNode)
return;
- node = NodeTraversal::next(node, firstNode);
+ node = NodeTraversal::next(*node, firstNode);
}
}
return directionality();
}
-static TextDirection determineDirectionality(const String& value, bool& hasStrongDirectionality)
-{
- TextRun run(value);
- BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
- bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
- bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
- return bidiResolver.determineParagraphDirectionality(&hasStrongDirectionality);
-}
-
TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) const
{
if (hasTagName(inputTag)) {
// Skip bdi, script, style and text form controls.
if (equalIgnoringCase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag)
|| (node->isElementNode() && toElement(node)->isTextFormControl())) {
- node = NodeTraversal::nextSkippingChildren(node, this);
+ node = NodeTraversal::nextSkippingChildren(*node, this);
continue;
}
if (node->isElementNode()) {
AtomicString dirAttributeValue = toElement(node)->fastGetAttribute(dirAttr);
if (isValidDirAttribute(dirAttributeValue)) {
- node = NodeTraversal::nextSkippingChildren(node, this);
+ node = NodeTraversal::nextSkippingChildren(*node, this);
continue;
}
}
return textDirection;
}
}
- node = NodeTraversal::next(node, this);
+ node = NodeTraversal::next(*node, this);
}
if (strongDirectionalityTextNode)
*strongDirectionalityTextNode = 0;
Element* elementToAdjust = this;
for (; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) {
if (elementAffectsDirectionality(elementToAdjust)) {
- elementToAdjust->setNeedsStyleRecalc();
+ elementToAdjust->setNeedsStyleRecalc(SubtreeStyleChange);
return;
}
}
TextDirection textDirection = directionality(&strongDirectionalityTextNode);
setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode);
if (renderer() && renderer()->style() && renderer()->style()->direction() != textDirection)
- setNeedsStyleRecalc();
+ setNeedsStyleRecalc(SubtreeStyleChange);
}
void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeChange, int childCountDelta)
{
if (document().renderer() && childCountDelta < 0) {
- Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(beforeChange) : 0;
- for (int counter = 0; node && counter < childCountDelta; counter++, node = NodeTraversal::nextSkippingChildren(node)) {
+ Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(*beforeChange) : 0;
+ for (int counter = 0; node && counter < childCountDelta; counter++, node = NodeTraversal::nextSkippingChildren(*node)) {
if (elementAffectsDirectionality(node))
continue;
if (!selfOrAncestorHasDirAutoAttribute())
return;
- Node* oldMarkedNode = beforeChange ? NodeTraversal::nextSkippingChildren(beforeChange) : 0;
+ Node* oldMarkedNode = beforeChange ? NodeTraversal::nextSkippingChildren(*beforeChange) : 0;
while (oldMarkedNode && elementAffectsDirectionality(oldMarkedNode))
- oldMarkedNode = NodeTraversal::nextSkippingChildren(oldMarkedNode, this);
+ oldMarkedNode = NodeTraversal::nextSkippingChildren(*oldMarkedNode, this);
if (oldMarkedNode)
setHasDirAutoFlagRecursively(oldMarkedNode, false);
return;
// If the string is a named CSS color or a 3/6-digit hex color, use that.
- Color parsedColor(colorString);
- if (!parsedColor.isValid())
+ Color parsedColor;
+ if (!parsedColor.setFromString(colorString))
parsedColor.setRGB(parseColorStringWithCrazyLegacyRules(colorString));
style->setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb()));