summaryrefslogtreecommitdiffstats
path: root/WebCore/html
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html')
-rw-r--r--WebCore/html/HTMLAppletElement.cpp20
-rw-r--r--WebCore/html/HTMLAppletElement.h6
-rw-r--r--WebCore/html/HTMLAreaElement.cpp15
-rw-r--r--WebCore/html/HTMLAreaElement.h9
-rw-r--r--WebCore/html/HTMLAttributeNames.in1
-rw-r--r--WebCore/html/HTMLBaseFontElement.cpp10
-rw-r--r--WebCore/html/HTMLBaseFontElement.h3
-rw-r--r--WebCore/html/HTMLBaseFontElement.idl2
-rw-r--r--WebCore/html/HTMLButtonElement.cpp17
-rw-r--r--WebCore/html/HTMLButtonElement.h4
-rw-r--r--WebCore/html/HTMLCanvasElement.cpp16
-rw-r--r--WebCore/html/HTMLCanvasElement.h3
-rw-r--r--WebCore/html/HTMLDListElement.cpp10
-rw-r--r--WebCore/html/HTMLDListElement.h3
-rw-r--r--WebCore/html/HTMLDirectoryElement.cpp17
-rw-r--r--WebCore/html/HTMLDirectoryElement.h7
-rw-r--r--WebCore/html/HTMLDivElement.cpp10
-rw-r--r--WebCore/html/HTMLDivElement.h3
-rw-r--r--WebCore/html/HTMLDocumentParser.cpp73
-rw-r--r--WebCore/html/HTMLDocumentParser.h12
-rw-r--r--WebCore/html/HTMLElement.cpp1
-rw-r--r--WebCore/html/HTMLElementStack.cpp379
-rw-r--r--WebCore/html/HTMLElementStack.h123
-rw-r--r--WebCore/html/HTMLElementsAllInOne.cpp2
-rw-r--r--WebCore/html/HTMLEntityParser.cpp8
-rw-r--r--WebCore/html/HTMLFontElement.cpp30
-rw-r--r--WebCore/html/HTMLFontElement.h9
-rw-r--r--WebCore/html/HTMLFormControlElement.cpp22
-rw-r--r--WebCore/html/HTMLFormControlElement.h7
-rw-r--r--WebCore/html/HTMLFormElement.cpp20
-rw-r--r--WebCore/html/HTMLFormElement.h4
-rw-r--r--WebCore/html/HTMLFormattingElementList.cpp135
-rw-r--r--WebCore/html/HTMLFormattingElementList.h89
-rw-r--r--WebCore/html/HTMLFrameElement.cpp7
-rw-r--r--WebCore/html/HTMLFrameElement.h1
-rw-r--r--WebCore/html/HTMLFrameElement.idl2
-rw-r--r--WebCore/html/HTMLFrameSetElement.cpp20
-rw-r--r--WebCore/html/HTMLFrameSetElement.h6
-rw-r--r--WebCore/html/HTMLHRElement.cpp40
-rw-r--r--WebCore/html/HTMLHRElement.h12
-rw-r--r--WebCore/html/HTMLHeadElement.cpp10
-rw-r--r--WebCore/html/HTMLHeadElement.h3
-rw-r--r--WebCore/html/HTMLHeadingElement.cpp10
-rw-r--r--WebCore/html/HTMLHeadingElement.h3
-rw-r--r--WebCore/html/HTMLHtmlElement.cpp10
-rw-r--r--WebCore/html/HTMLHtmlElement.h3
-rw-r--r--WebCore/html/HTMLIFrameElement.idl2
-rw-r--r--WebCore/html/HTMLImageElement.cpp52
-rw-r--r--WebCore/html/HTMLImageElement.h15
-rw-r--r--WebCore/html/HTMLInputElement.cpp57
-rw-r--r--WebCore/html/HTMLInputElement.h15
-rw-r--r--WebCore/html/HTMLInputStream.h15
-rw-r--r--WebCore/html/HTMLIsIndexElement.cpp10
-rw-r--r--WebCore/html/HTMLIsIndexElement.h3
-rw-r--r--WebCore/html/HTMLKeygenElement.cpp4
-rw-r--r--WebCore/html/HTMLLIElement.cpp20
-rw-r--r--WebCore/html/HTMLLIElement.h6
-rw-r--r--WebCore/html/HTMLLabelElement.cpp20
-rw-r--r--WebCore/html/HTMLLabelElement.h6
-rw-r--r--WebCore/html/HTMLLegendElement.cpp20
-rw-r--r--WebCore/html/HTMLLegendElement.h6
-rw-r--r--WebCore/html/HTMLLinkElement.cpp70
-rw-r--r--WebCore/html/HTMLLinkElement.h20
-rw-r--r--WebCore/html/HTMLMapElement.cpp10
-rw-r--r--WebCore/html/HTMLMapElement.h3
-rw-r--r--WebCore/html/HTMLMenuElement.cpp10
-rw-r--r--WebCore/html/HTMLMenuElement.h3
-rw-r--r--WebCore/html/HTMLMetaElement.cpp25
-rw-r--r--WebCore/html/HTMLMetaElement.h8
-rw-r--r--WebCore/html/HTMLModElement.cpp20
-rw-r--r--WebCore/html/HTMLModElement.h6
-rw-r--r--WebCore/html/HTMLOListElement.cpp20
-rw-r--r--WebCore/html/HTMLOListElement.h6
-rw-r--r--WebCore/html/HTMLObjectElement.cpp30
-rw-r--r--WebCore/html/HTMLObjectElement.h9
-rw-r--r--WebCore/html/HTMLOptGroupElement.cpp10
-rw-r--r--WebCore/html/HTMLOptGroupElement.h3
-rw-r--r--WebCore/html/HTMLOptionElement.cpp5
-rw-r--r--WebCore/html/HTMLOptionElement.h1
-rw-r--r--WebCore/html/HTMLParagraphElement.cpp10
-rw-r--r--WebCore/html/HTMLParagraphElement.h3
-rw-r--r--WebCore/html/HTMLParamElement.cpp30
-rw-r--r--WebCore/html/HTMLParamElement.h9
-rw-r--r--WebCore/html/HTMLPlugInElement.cpp35
-rw-r--r--WebCore/html/HTMLPlugInElement.h6
-rw-r--r--WebCore/html/HTMLPreElement.cpp20
-rw-r--r--WebCore/html/HTMLPreElement.h6
-rw-r--r--WebCore/html/HTMLQuoteElement.cpp10
-rw-r--r--WebCore/html/HTMLQuoteElement.h3
-rw-r--r--WebCore/html/HTMLScriptElement.cpp69
-rw-r--r--WebCore/html/HTMLScriptElement.h19
-rw-r--r--WebCore/html/HTMLScriptRunner.cpp93
-rw-r--r--WebCore/html/HTMLScriptRunner.h44
-rw-r--r--WebCore/html/HTMLScriptRunnerHost.h2
-rw-r--r--WebCore/html/HTMLSelectElement.cpp2
-rw-r--r--WebCore/html/HTMLSelectElement.idl47
-rw-r--r--WebCore/html/HTMLStyleElement.cpp30
-rw-r--r--WebCore/html/HTMLStyleElement.h14
-rw-r--r--WebCore/html/HTMLStyleElement.idl2
-rw-r--r--WebCore/html/HTMLTableCaptionElement.cpp10
-rw-r--r--WebCore/html/HTMLTableCaptionElement.h3
-rw-r--r--WebCore/html/HTMLTableCellElement.cpp100
-rw-r--r--WebCore/html/HTMLTableCellElement.h33
-rw-r--r--WebCore/html/HTMLTableCellElement.idl2
-rw-r--r--WebCore/html/HTMLTableColElement.cpp45
-rw-r--r--WebCore/html/HTMLTableColElement.h14
-rw-r--r--WebCore/html/HTMLTableElement.cpp86
-rw-r--r--WebCore/html/HTMLTableElement.h26
-rw-r--r--WebCore/html/HTMLTableRowElement.cpp58
-rw-r--r--WebCore/html/HTMLTableRowElement.h17
-rw-r--r--WebCore/html/HTMLTableSectionElement.cpp6
-rw-r--r--WebCore/html/HTMLTableSectionElement.h2
-rw-r--r--WebCore/html/HTMLTagNames.in2
-rw-r--r--WebCore/html/HTMLTextAreaElement.cpp10
-rw-r--r--WebCore/html/HTMLTextAreaElement.h3
-rw-r--r--WebCore/html/HTMLTextAreaElement.idl8
-rw-r--r--WebCore/html/HTMLToken.h25
-rw-r--r--WebCore/html/HTMLTokenizer.cpp733
-rw-r--r--WebCore/html/HTMLTokenizer.h31
-rw-r--r--WebCore/html/HTMLTreeBuilder.cpp1674
-rw-r--r--WebCore/html/HTMLTreeBuilder.h103
-rw-r--r--WebCore/html/HTMLUListElement.cpp20
-rw-r--r--WebCore/html/HTMLUListElement.h6
-rw-r--r--WebCore/html/HTMLUListElement.idl2
-rw-r--r--WebCore/html/HTMLVideoElement.cpp15
-rw-r--r--WebCore/html/HTMLVideoElement.h3
-rw-r--r--WebCore/html/HTMLViewSourceDocument.cpp22
-rw-r--r--WebCore/html/LegacyHTMLDocumentParser.cpp34
-rw-r--r--WebCore/html/LegacyHTMLDocumentParser.h16
-rw-r--r--WebCore/html/LegacyHTMLTreeBuilder.cpp39
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.cpp55
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.h5
-rw-r--r--WebCore/html/canvas/CheckedInt.h527
-rw-r--r--WebCore/html/canvas/WebGLBuffer.cpp66
-rw-r--r--WebCore/html/canvas/WebGLBuffer.h16
-rw-r--r--WebCore/html/canvas/WebGLGetInfo.cpp16
-rw-r--r--WebCore/html/canvas/WebGLGetInfo.h4
-rw-r--r--WebCore/html/canvas/WebGLProgram.cpp14
-rw-r--r--WebCore/html/canvas/WebGLProgram.h14
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.cpp1137
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.h101
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.idl4
-rw-r--r--WebCore/html/canvas/WebGLShader.cpp1
-rw-r--r--WebCore/html/canvas/WebGLShader.h4
144 files changed, 4444 insertions, 2829 deletions
diff --git a/WebCore/html/HTMLAppletElement.cpp b/WebCore/html/HTMLAppletElement.cpp
index 537d615..d6b7c5a 100644
--- a/WebCore/html/HTMLAppletElement.cpp
+++ b/WebCore/html/HTMLAppletElement.cpp
@@ -168,24 +168,4 @@ void HTMLAppletElement::finishParsingChildren()
renderer()->setNeedsLayout(true); // This will cause it to create its widget & the Java applet
}
-String HTMLAppletElement::hspace() const
-{
- return getAttribute(hspaceAttr);
-}
-
-void HTMLAppletElement::setHspace(const String &value)
-{
- setAttribute(hspaceAttr, value);
-}
-
-String HTMLAppletElement::vspace() const
-{
- return getAttribute(vspaceAttr);
-}
-
-void HTMLAppletElement::setVspace(const String &value)
-{
- setAttribute(vspaceAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLAppletElement.h b/WebCore/html/HTMLAppletElement.h
index 1e11b44..e0e4ec9 100644
--- a/WebCore/html/HTMLAppletElement.h
+++ b/WebCore/html/HTMLAppletElement.h
@@ -31,12 +31,6 @@ class HTMLAppletElement : public HTMLPlugInElement {
public:
static PassRefPtr<HTMLAppletElement> create(const QualifiedName&, Document*);
- String hspace() const;
- void setHspace(const String&);
-
- String vspace() const;
- void setVspace(const String&);
-
private:
HTMLAppletElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLAreaElement.cpp b/WebCore/html/HTMLAreaElement.cpp
index c907f83..2d714ba 100644
--- a/WebCore/html/HTMLAreaElement.cpp
+++ b/WebCore/html/HTMLAreaElement.cpp
@@ -163,21 +163,6 @@ Path HTMLAreaElement::getRegion(const IntSize& size) const
return path;
}
-KURL HTMLAreaElement::href() const
-{
- return document()->completeURL(getAttribute(hrefAttr));
-}
-
-bool HTMLAreaElement::noHref() const
-{
- return !getAttribute(nohrefAttr).isNull();
-}
-
-void HTMLAreaElement::setNoHref(bool noHref)
-{
- setAttribute(nohrefAttr, noHref ? "" : 0);
-}
-
HTMLImageElement* HTMLAreaElement::imageElement() const
{
Node* mapElement = parent();
diff --git a/WebCore/html/HTMLAreaElement.h b/WebCore/html/HTMLAreaElement.h
index e6e087f..ce711b2 100644
--- a/WebCore/html/HTMLAreaElement.h
+++ b/WebCore/html/HTMLAreaElement.h
@@ -43,15 +43,10 @@ public:
IntRect getRect(RenderObject*) const;
Path getPath(RenderObject*) const;
-
- // Convenience method to get the parent map's image.
+
+ // The parent map's image.
HTMLImageElement* imageElement() const;
- KURL href() const;
-
- bool noHref() const;
- void setNoHref(bool);
-
private:
HTMLAreaElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLAttributeNames.in b/WebCore/html/HTMLAttributeNames.in
index b45ba9e..36770e2 100644
--- a/WebCore/html/HTMLAttributeNames.in
+++ b/WebCore/html/HTMLAttributeNames.in
@@ -145,6 +145,7 @@ onbeforecopy
onbeforecut
onbeforeload
onbeforepaste
+onbeforeprocess
onbeforeunload
onblur
oncanplay
diff --git a/WebCore/html/HTMLBaseFontElement.cpp b/WebCore/html/HTMLBaseFontElement.cpp
index 39a5591..2ab681e 100644
--- a/WebCore/html/HTMLBaseFontElement.cpp
+++ b/WebCore/html/HTMLBaseFontElement.cpp
@@ -40,14 +40,4 @@ PassRefPtr<HTMLBaseFontElement> HTMLBaseFontElement::create(const QualifiedName&
return adoptRef(new HTMLBaseFontElement(tagName, document));
}
-int HTMLBaseFontElement::size() const
-{
- return getAttribute(sizeAttr).toInt();
-}
-
-void HTMLBaseFontElement::setSize(int value)
-{
- setAttribute(sizeAttr, String::number(value));
-}
-
}
diff --git a/WebCore/html/HTMLBaseFontElement.h b/WebCore/html/HTMLBaseFontElement.h
index 82f9a32..5651a61 100644
--- a/WebCore/html/HTMLBaseFontElement.h
+++ b/WebCore/html/HTMLBaseFontElement.h
@@ -31,9 +31,6 @@ class HTMLBaseFontElement : public HTMLElement {
public:
static PassRefPtr<HTMLBaseFontElement> create(const QualifiedName&, Document*);
- int size() const;
- void setSize(int);
-
private:
HTMLBaseFontElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLBaseFontElement.idl b/WebCore/html/HTMLBaseFontElement.idl
index a0ac127..95bc92c 100644
--- a/WebCore/html/HTMLBaseFontElement.idl
+++ b/WebCore/html/HTMLBaseFontElement.idl
@@ -23,7 +23,7 @@ module html {
attribute [Reflect] DOMString color;
attribute [Reflect] DOMString face;
#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
- attribute [ConvertToString] DOMString size; // this changed to a long, but our existing API is a string
+ attribute [Reflect] DOMString size; // this changed to a long, but our existing API is a string
#else
attribute [Reflect] long size;
#endif
diff --git a/WebCore/html/HTMLButtonElement.cpp b/WebCore/html/HTMLButtonElement.cpp
index 9f2cc9d..b4c8ec0 100644
--- a/WebCore/html/HTMLButtonElement.cpp
+++ b/WebCore/html/HTMLButtonElement.cpp
@@ -164,30 +164,15 @@ bool HTMLButtonElement::appendFormData(FormDataList& formData, bool)
}
void HTMLButtonElement::accessKeyAction(bool sendToAnyElement)
-{
+{
focus();
// send the mouse button events iff the caller specified sendToAnyElement
dispatchSimulatedClick(0, sendToAnyElement);
}
-String HTMLButtonElement::accessKey() const
-{
- return getAttribute(accesskeyAttr);
-}
-
-void HTMLButtonElement::setAccessKey(const String &value)
-{
- setAttribute(accesskeyAttr, value);
-}
-
String HTMLButtonElement::value() const
{
return getAttribute(valueAttr);
}
-void HTMLButtonElement::setValue(const String &value)
-{
- setAttribute(valueAttr, value);
-}
-
} // namespace
diff --git a/WebCore/html/HTMLButtonElement.h b/WebCore/html/HTMLButtonElement.h
index aefb27a..888c0a8 100644
--- a/WebCore/html/HTMLButtonElement.h
+++ b/WebCore/html/HTMLButtonElement.h
@@ -32,11 +32,7 @@ class HTMLButtonElement : public HTMLFormControlElement {
public:
static PassRefPtr<HTMLButtonElement> create(const QualifiedName&, Document*, HTMLFormElement*);
- String accessKey() const;
- void setAccessKey(const String&);
-
String value() const;
- void setValue(const String&);
private:
HTMLButtonElement(const QualifiedName& tagName, Document*, HTMLFormElement*);
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index c1bf8ec..f8baf20 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -209,10 +210,10 @@ void HTMLCanvasElement::reset()
bool ok;
int w = getAttribute(widthAttr).toInt(&ok);
- if (!ok)
+ if (!ok || w < 0)
w = DefaultWidth;
int h = getAttribute(heightAttr).toInt(&ok);
- if (!ok)
+ if (!ok || h < 0)
h = DefaultHeight;
IntSize oldSize = size();
@@ -278,4 +279,15 @@ bool HTMLCanvasElement::is3D() const
}
#endif
+void HTMLCanvasElement::recalcStyle(StyleChange change)
+{
+ HTMLElement::recalcStyle(change);
+
+ // Update font if needed.
+ if (change == Force && m_context && m_context->is2d()) {
+ CanvasRenderingContext2D* ctx = static_cast<CanvasRenderingContext2D*>(m_context.get());
+ ctx->updateFont();
+ }
+}
+
}
diff --git a/WebCore/html/HTMLCanvasElement.h b/WebCore/html/HTMLCanvasElement.h
index ebd9378..1337b87 100644
--- a/WebCore/html/HTMLCanvasElement.h
+++ b/WebCore/html/HTMLCanvasElement.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -117,6 +118,8 @@ private:
virtual void parseMappedAttribute(Attribute*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+ virtual void recalcStyle(StyleChange);
+
void reset();
bool m_rendererIsCanvas;
diff --git a/WebCore/html/HTMLDListElement.cpp b/WebCore/html/HTMLDListElement.cpp
index 1a9d5a2..cc9fabb 100644
--- a/WebCore/html/HTMLDListElement.cpp
+++ b/WebCore/html/HTMLDListElement.cpp
@@ -40,14 +40,4 @@ PassRefPtr<HTMLDListElement> HTMLDListElement::create(const QualifiedName& tagNa
return adoptRef(new HTMLDListElement(tagName, document));
}
-bool HTMLDListElement::compact() const
-{
- return !getAttribute(compactAttr).isNull();
-}
-
-void HTMLDListElement::setCompact(bool b)
-{
- setAttribute(compactAttr, b ? "" : 0);
-}
-
}
diff --git a/WebCore/html/HTMLDListElement.h b/WebCore/html/HTMLDListElement.h
index 906109e..260aa42 100644
--- a/WebCore/html/HTMLDListElement.h
+++ b/WebCore/html/HTMLDListElement.h
@@ -31,9 +31,6 @@ class HTMLDListElement : public HTMLElement {
public:
static PassRefPtr<HTMLDListElement> create(const QualifiedName&, Document*);
- bool compact() const;
- void setCompact(bool);
-
private:
HTMLDListElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLDirectoryElement.cpp b/WebCore/html/HTMLDirectoryElement.cpp
index 173969c..64cbef8 100644
--- a/WebCore/html/HTMLDirectoryElement.cpp
+++ b/WebCore/html/HTMLDirectoryElement.cpp
@@ -1,6 +1,7 @@
-/**
+/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,6 +19,7 @@
* Boston, MA 02110-1301, USA.
*
*/
+
#include "config.h"
#include "HTMLDirectoryElement.h"
@@ -27,20 +29,15 @@ namespace WebCore {
using namespace HTMLNames;
-HTMLDirectoryElement::HTMLDirectoryElement(const QualifiedName& tagName, Document* doc)
- : HTMLElement(tagName, doc)
+inline HTMLDirectoryElement::HTMLDirectoryElement(const QualifiedName& tagName, Document* document)
+ : HTMLElement(tagName, document)
{
ASSERT(hasTagName(dirTag));
}
-bool HTMLDirectoryElement::compact() const
-{
- return !getAttribute(compactAttr).isNull();
-}
-
-void HTMLDirectoryElement::setCompact(bool b)
+PassRefPtr<HTMLDirectoryElement> HTMLDirectoryElement::create(const QualifiedName& tagName, Document* document)
{
- setAttribute(compactAttr, b ? "" : 0);
+ return adoptRef(new HTMLDirectoryElement(tagName, document));
}
}
diff --git a/WebCore/html/HTMLDirectoryElement.h b/WebCore/html/HTMLDirectoryElement.h
index eead141..0e440d4 100644
--- a/WebCore/html/HTMLDirectoryElement.h
+++ b/WebCore/html/HTMLDirectoryElement.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,13 +29,13 @@ namespace WebCore {
class HTMLDirectoryElement : public HTMLElement {
public:
+ static PassRefPtr<HTMLDirectoryElement> create(const QualifiedName& tagName, Document*);
+
+private:
HTMLDirectoryElement(const QualifiedName&, Document*);
virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; }
virtual int tagPriority() const { return 5; }
-
- bool compact() const;
- void setCompact(bool);
};
} //namespace
diff --git a/WebCore/html/HTMLDivElement.cpp b/WebCore/html/HTMLDivElement.cpp
index f35b25b..ca2a914 100644
--- a/WebCore/html/HTMLDivElement.cpp
+++ b/WebCore/html/HTMLDivElement.cpp
@@ -73,14 +73,4 @@ void HTMLDivElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-String HTMLDivElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLDivElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLDivElement.h b/WebCore/html/HTMLDivElement.h
index aa60275..30eddf3 100644
--- a/WebCore/html/HTMLDivElement.h
+++ b/WebCore/html/HTMLDivElement.h
@@ -32,9 +32,6 @@ public:
static PassRefPtr<HTMLDivElement> create(Document*);
static PassRefPtr<HTMLDivElement> create(const QualifiedName&, Document*);
- String align() const;
- void setAlign(const String&);
-
protected:
HTMLDivElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLDocumentParser.cpp b/WebCore/html/HTMLDocumentParser.cpp
index 31977fe..55facbf 100644
--- a/WebCore/html/HTMLDocumentParser.cpp
+++ b/WebCore/html/HTMLDocumentParser.cpp
@@ -70,7 +70,7 @@ private:
} // namespace
HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors)
- : DocumentParser(document)
+ : ScriptableDocumentParser(document)
, m_tokenizer(new HTMLTokenizer)
, m_scriptRunner(new HTMLScriptRunner(document, this))
, m_treeBuilder(new HTMLTreeBuilder(m_tokenizer.get(), document, reportErrors))
@@ -84,7 +84,7 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
// FIXME: Member variables should be grouped into self-initializing structs to
// minimize code duplication between these constructors.
HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
- : DocumentParser(fragment->document())
+ : ScriptableDocumentParser(fragment->document())
, m_tokenizer(new HTMLTokenizer)
, m_treeBuilder(new HTMLTreeBuilder(m_tokenizer.get(), fragment, scriptingPermission))
, m_endWasDelayed(false)
@@ -217,23 +217,44 @@ void HTMLDocumentParser::didPumpLexer()
#endif
}
-void HTMLDocumentParser::write(const SegmentedString& source, bool isFromNetwork)
+void HTMLDocumentParser::insert(const SegmentedString& source)
{
if (m_parserStopped)
return;
+<<<<<<< HEAD
#ifdef ANDROID_INSTRUMENT
android::TimeCounter::start(android::TimeCounter::ParsingTimeCounter);
#endif
NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
+=======
+ {
+ NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
+
+ SegmentedString excludedLineNumberSource(source);
+ excludedLineNumberSource.setExcludeLineNumbers();
+ m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource);
+ pumpTokenizerIfPossible(ForceSynchronous);
+ }
+
+ endIfDelayed();
+}
+
+void HTMLDocumentParser::append(const SegmentedString& source)
+{
+ if (m_parserStopped)
+ return;
+
+ {
+ NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
+>>>>>>> webkit.org at r62496
- if (isFromNetwork) {
m_input.appendToEnd(source);
if (m_preloadScanner)
m_preloadScanner->appendToEnd(source);
if (m_writeNestingLevel > 1) {
- // We've gotten data off the network in a nested call to write().
+ // We've gotten data off the network in a nested write.
// We don't want to consume any more of the input stream now. Do
// not worry. We'll consume this data in a less-nested write().
#ifdef ANDROID_INSTRUMENT
@@ -241,10 +262,10 @@ void HTMLDocumentParser::write(const SegmentedString& source, bool isFromNetwork
#endif
return;
}
- } else
- m_input.insertAtCurrentInsertionPoint(source);
- pumpTokenizerIfPossible(isFromNetwork ? AllowYield : ForceSynchronous);
+ pumpTokenizerIfPossible(AllowYield);
+ }
+
endIfDelayed();
#ifdef ANDROID_INSTRUMENT
android::TimeCounter::record(android::TimeCounter::ParsingTimeCounter, __FUNCTION__);
@@ -267,7 +288,7 @@ void HTMLDocumentParser::attemptToEnd()
// finish() indicates we will not receive any more data. If we are waiting on
// an external script to load, we can't finish parsing quite yet.
- if (inWrite() || isWaitingForScripts() || inScriptExecution() || isScheduledForResume()) {
+ if (shouldDelayEnd()) {
m_endWasDelayed = true;
return;
}
@@ -276,9 +297,7 @@ void HTMLDocumentParser::attemptToEnd()
void HTMLDocumentParser::endIfDelayed()
{
- // We don't check inWrite() here since inWrite() will be true if this was
- // called from write().
- if (!m_endWasDelayed || isWaitingForScripts() || inScriptExecution() || isScheduledForResume())
+ if (!m_endWasDelayed || shouldDelayEnd())
return;
m_endWasDelayed = false;
@@ -287,15 +306,17 @@ void HTMLDocumentParser::endIfDelayed()
void HTMLDocumentParser::finish()
{
- // We're not going to get any more data off the network, so we close the
- // input stream to indicate EOF.
- m_input.close();
+ // We're not going to get any more data off the network, so we tell the
+ // input stream we've reached the end of file. finish() can be called more
+ // than once, if the first time does not call end().
+ if (!m_input.haveSeenEndOfFile())
+ m_input.markEndOfFile();
attemptToEnd();
}
bool HTMLDocumentParser::finishWasCalled()
{
- return m_input.isClosed();
+ return m_input.haveSeenEndOfFile();
}
// This function is virtual and just for the DocumentParser interface.
@@ -338,13 +359,15 @@ void HTMLDocumentParser::resumeParsingAfterScriptExecution()
ASSERT(!m_treeBuilder->isPaused());
pumpTokenizerIfPossible(AllowYield);
-
- // The document already finished parsing we were just waiting on scripts when finished() was called.
endIfDelayed();
}
void HTMLDocumentParser::watchForLoad(CachedResource* cachedScript)
{
+ ASSERT(!cachedScript->isLoaded());
+ // addClient would call notifyFinished if the load were complete.
+ // Callers do not expect to be re-entered from this call, so they should
+ // not an already-loaded CachedResource.
cachedScript->addClient(this);
}
@@ -355,22 +378,14 @@ void HTMLDocumentParser::stopWatchingForLoad(CachedResource* cachedScript)
bool HTMLDocumentParser::shouldLoadExternalScriptFromSrc(const AtomicString& srcValue)
{
- if (!m_XSSAuditor)
+ if (!xssAuditor())
return true;
- return m_XSSAuditor->canLoadExternalScriptFromSrc(srcValue);
+ return xssAuditor()->canLoadExternalScriptFromSrc(srcValue);
}
void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource)
{
ASSERT(m_scriptRunner);
- // Ignore calls unless we have a script blocking the parser waiting
- // for its own load. Otherwise this may be a load callback from
- // CachedResource::addClient because the script was already in the cache.
- // HTMLScriptRunner may not be ready to handle running that script yet.
- if (!m_scriptRunner->hasScriptsWaitingForLoad()) {
- ASSERT(m_scriptRunner->inScriptExecution());
- return;
- }
ASSERT(!inScriptExecution());
ASSERT(m_treeBuilder->isPaused());
// Note: We only ever wait on one script at a time, so we always know this
@@ -411,7 +426,7 @@ ScriptController* HTMLDocumentParser::script() const
void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
{
HTMLDocumentParser parser(fragment, scriptingPermission);
- parser.write(source, false);
+ parser.insert(source); // Use insert() so that the parser will not yield.
parser.finish();
ASSERT(!parser.processingData()); // Make sure we're done. <rdar://problem/3963151>
}
diff --git a/WebCore/html/HTMLDocumentParser.h b/WebCore/html/HTMLDocumentParser.h
index c2e752f..b2a65ca 100644
--- a/WebCore/html/HTMLDocumentParser.h
+++ b/WebCore/html/HTMLDocumentParser.h
@@ -28,11 +28,11 @@
#include "CachedResourceClient.h"
#include "FragmentScriptingPermission.h"
+#include "HTMLInputStream.h"
#include "HTMLScriptRunnerHost.h"
#include "HTMLToken.h"
-#include "HTMLInputStream.h"
+#include "ScriptableDocumentParser.h"
#include "SegmentedString.h"
-#include "DocumentParser.h"
#include "Timer.h"
#include <wtf/OwnPtr.h>
@@ -50,7 +50,7 @@ class LegacyHTMLTreeBuilder;
class ScriptController;
class ScriptSourceCode;
-class HTMLDocumentParser : public DocumentParser, HTMLScriptRunnerHost, CachedResourceClient {
+class HTMLDocumentParser : public ScriptableDocumentParser, HTMLScriptRunnerHost, CachedResourceClient {
public:
// FIXME: These constructors should be made private and replaced by create() methods.
HTMLDocumentParser(HTMLDocument*, bool reportErrors);
@@ -64,8 +64,8 @@ public:
private:
// DocumentParser
- virtual void begin();
- virtual void write(const SegmentedString&, bool isFromNetwork);
+ virtual void insert(const SegmentedString&);
+ virtual void append(const SegmentedString&);
virtual void finish();
virtual bool finishWasCalled();
virtual bool processingData() const;
@@ -101,6 +101,7 @@ private:
bool runScriptsForPausedTreeBuilder();
void resumeParsingAfterScriptExecution();
+ void begin();
void attemptToEnd();
void endIfDelayed();
void end();
@@ -108,6 +109,7 @@ private:
bool isScheduledForResume() const;
bool inScriptExecution() const;
bool inWrite() const { return m_writeNestingLevel > 0; }
+ bool shouldDelayEnd() const { return inWrite() || isWaitingForScripts() || inScriptExecution() || isScheduledForResume(); }
ScriptController* script() const;
diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp
index 0726977..8985407 100644
--- a/WebCore/html/HTMLElement.cpp
+++ b/WebCore/html/HTMLElement.cpp
@@ -858,6 +858,7 @@ static HashSet<AtomicStringImpl*>* inlineTagList()
tagList.add(rubyTag.localName().impl());
tagList.add(progressTag.localName().impl());
tagList.add(meterTag.localName().impl());
+ tagList.add(markTag.localName().impl());
}
return &tagList;
}
diff --git a/WebCore/html/HTMLElementStack.cpp b/WebCore/html/HTMLElementStack.cpp
new file mode 100644
index 0000000..2f1b792
--- /dev/null
+++ b/WebCore/html/HTMLElementStack.cpp
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTMLElementStack.h"
+
+#include "Element.h"
+#include "HTMLNames.h"
+#include <wtf/PassOwnPtr.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+namespace {
+
+inline bool isScopeMarker(Element* element)
+{
+ return element->hasTagName(appletTag)
+ || element->hasTagName(buttonTag)
+ || element->hasTagName(captionTag)
+#if ENABLE(SVG_FOREIGN_OBJECT)
+ || element->hasTagName(SVGNames::foreignObjectTag)
+#endif
+ || element->hasTagName(htmlTag)
+ || element->hasTagName(marqueeTag)
+ || element->hasTagName(objectTag)
+ || element->hasTagName(tableTag)
+ || element->hasTagName(tdTag)
+ || element->hasTagName(thTag);
+}
+
+inline bool isListItemScopeMarker(Element* element)
+{
+ return isScopeMarker(element)
+ || element->hasTagName(olTag)
+ || element->hasTagName(ulTag);
+}
+inline bool isTableScopeMarker(Element* element)
+{
+ return element->hasTagName(tableTag)
+ || element->hasTagName(htmlTag);
+}
+
+inline bool isTableBodyScopeMarker(Element* element)
+{
+ return element->hasTagName(tbodyTag)
+ || element->hasTagName(tfootTag)
+ || element->hasTagName(theadTag)
+ || element->hasTagName(htmlTag);
+}
+
+}
+
+HTMLElementStack::ElementRecord::ElementRecord(PassRefPtr<Element> element, PassOwnPtr<ElementRecord> next)
+ : m_element(element)
+ , m_next(next)
+{
+ ASSERT(m_element);
+}
+
+HTMLElementStack::ElementRecord::~ElementRecord()
+{
+}
+
+void HTMLElementStack::ElementRecord::replaceElement(PassRefPtr<Element> element)
+{
+ ASSERT(element);
+ // FIXME: Should this call finishParsingChildren?
+ m_element = element;
+}
+
+bool HTMLElementStack::ElementRecord::isAbove(ElementRecord* other) const
+{
+ for (ElementRecord* below = next(); below; below = below->next()) {
+ if (below == other)
+ return true;
+ }
+ return false;
+}
+
+HTMLElementStack::HTMLElementStack()
+ : m_htmlElement(0)
+ , m_headElement(0)
+ , m_bodyElement(0)
+{
+}
+
+HTMLElementStack::~HTMLElementStack()
+{
+}
+
+void HTMLElementStack::popHTMLHeadElement()
+{
+ ASSERT(top() == m_headElement);
+ m_headElement = 0;
+ popCommon();
+}
+
+void HTMLElementStack::popHTMLBodyElement()
+{
+ ASSERT(top() == m_bodyElement);
+ m_bodyElement = 0;
+ popCommon();
+}
+
+void HTMLElementStack::pop()
+{
+ ASSERT(!top()->hasTagName(HTMLNames::headTag));
+ popCommon();
+}
+
+void HTMLElementStack::popUntil(const AtomicString& tagName)
+{
+ while (!top()->hasLocalName(tagName)) {
+ // pop() will ASSERT at <body> if callers fail to check that there is an
+ // element with localName |tagName| on the stack of open elements.
+ pop();
+ }
+}
+
+void HTMLElementStack::popUntil(Element* element)
+{
+ while (top() != element)
+ pop();
+}
+
+void HTMLElementStack::popUntilTableScopeMarker()
+{
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-context
+ while (!isTableScopeMarker(top()))
+ pop();
+}
+
+void HTMLElementStack::popUntilTableBodyScopeMarker()
+{
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-body-context
+ while (!isTableBodyScopeMarker(top()))
+ pop();
+}
+
+void HTMLElementStack::pushHTMLHtmlElement(PassRefPtr<Element> element)
+{
+ ASSERT(!m_top); // <html> should always be the bottom of the stack.
+ ASSERT(element->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!m_htmlElement);
+ m_htmlElement = element.get();
+ pushCommon(element);
+}
+
+void HTMLElementStack::pushHTMLHeadElement(PassRefPtr<Element> element)
+{
+ ASSERT(element->hasTagName(HTMLNames::headTag));
+ ASSERT(!m_headElement);
+ m_headElement = element.get();
+ pushCommon(element);
+}
+
+void HTMLElementStack::pushHTMLBodyElement(PassRefPtr<Element> element)
+{
+ ASSERT(element->hasTagName(HTMLNames::bodyTag));
+ ASSERT(!m_bodyElement);
+ m_bodyElement = element.get();
+ pushCommon(element);
+}
+
+void HTMLElementStack::push(PassRefPtr<Element> element)
+{
+ ASSERT(!element->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!element->hasTagName(HTMLNames::headTag));
+ ASSERT(!element->hasTagName(HTMLNames::bodyTag));
+ ASSERT(m_htmlElement);
+ pushCommon(element);
+}
+
+void HTMLElementStack::insertAbove(PassRefPtr<Element> element, ElementRecord* recordBelow)
+{
+ ASSERT(element);
+ ASSERT(recordBelow);
+ ASSERT(m_top);
+ ASSERT(!element->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!element->hasTagName(HTMLNames::headTag));
+ ASSERT(!element->hasTagName(HTMLNames::bodyTag));
+ ASSERT(m_htmlElement);
+ if (recordBelow == m_top) {
+ push(element);
+ return;
+ }
+
+ for (ElementRecord* recordAbove = m_top.get(); recordAbove; recordAbove = recordAbove->next()) {
+ if (recordAbove->next() != recordBelow)
+ continue;
+
+ recordAbove->setNext(new ElementRecord(element, recordAbove->releaseNext()));
+ recordAbove->next()->element()->beginParsingChildren();
+ return;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+HTMLElementStack::ElementRecord* HTMLElementStack::topRecord() const
+{
+ return m_top.get();
+}
+
+Element* HTMLElementStack::top() const
+{
+ return m_top->element();
+}
+
+Element* HTMLElementStack::bottom() const
+{
+ return htmlElement();
+}
+
+void HTMLElementStack::removeHTMLHeadElement(Element* element)
+{
+ ASSERT(m_headElement == element);
+ if (m_top->element() == element) {
+ popHTMLHeadElement();
+ return;
+ }
+ m_headElement = 0;
+ removeNonTopCommon(element);
+}
+
+void HTMLElementStack::remove(Element* element)
+{
+ ASSERT(!element->hasTagName(HTMLNames::headTag));
+ if (m_top->element() == element) {
+ pop();
+ return;
+ }
+ removeNonTopCommon(element);
+}
+
+HTMLElementStack::ElementRecord* HTMLElementStack::find(Element* element) const
+{
+ for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) {
+ if (pos->element() == element)
+ return pos;
+ }
+ return 0;
+}
+
+HTMLElementStack::ElementRecord* HTMLElementStack::topmost(const AtomicString& tagName) const
+{
+ for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) {
+ if (pos->element()->hasLocalName(tagName))
+ return pos;
+ }
+ return 0;
+}
+
+bool HTMLElementStack::contains(Element* element) const
+{
+ return !!find(element);
+}
+
+template <bool isMarker(Element*)>
+bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& targetTag)
+{
+ for (HTMLElementStack::ElementRecord* pos = top; pos; pos = pos->next()) {
+ Element* element = pos->element();
+ if (element->hasLocalName(targetTag))
+ return true;
+ if (isMarker(element))
+ return false;
+ }
+ ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker.
+ return false;
+}
+
+bool HTMLElementStack::inScope(Element* targetElement) const
+{
+ for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) {
+ Element* element = pos->element();
+ if (element == targetElement)
+ return true;
+ if (isScopeMarker(element))
+ return false;
+ }
+ ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker.
+ return false;
+}
+
+bool HTMLElementStack::inScope(const AtomicString& targetTag) const
+{
+ return inScopeCommon<isScopeMarker>(m_top.get(), targetTag);
+}
+
+bool HTMLElementStack::inListItemScope(const AtomicString& targetTag) const
+{
+ return inScopeCommon<isListItemScopeMarker>(m_top.get(), targetTag);
+}
+
+bool HTMLElementStack::inTableScope(const AtomicString& targetTag) const
+{
+ return inScopeCommon<isTableScopeMarker>(m_top.get(), targetTag);
+}
+
+Element* HTMLElementStack::htmlElement() const
+{
+ ASSERT(m_htmlElement);
+ return m_htmlElement;
+}
+
+Element* HTMLElementStack::headElement() const
+{
+ ASSERT(m_headElement);
+ return m_headElement;
+}
+
+Element* HTMLElementStack::bodyElement() const
+{
+ ASSERT(m_bodyElement);
+ return m_bodyElement;
+}
+
+void HTMLElementStack::pushCommon(PassRefPtr<Element> element)
+{
+ ASSERT(m_htmlElement);
+ m_top.set(new ElementRecord(element, m_top.release()));
+ top()->beginParsingChildren();
+}
+
+void HTMLElementStack::popCommon()
+{
+ ASSERT(!top()->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!top()->hasTagName(HTMLNames::headTag) || !m_headElement);
+ ASSERT(!top()->hasTagName(HTMLNames::bodyTag) || !m_bodyElement);
+ top()->finishParsingChildren();
+ m_top = m_top->releaseNext();
+}
+
+void HTMLElementStack::removeNonTopCommon(Element* element)
+{
+ ASSERT(!element->hasTagName(HTMLNames::htmlTag));
+ ASSERT(!element->hasTagName(HTMLNames::bodyTag));
+ ASSERT(top() != element);
+ for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) {
+ if (pos->next()->element() == element) {
+ // FIXME: Is it OK to call finishParsingChildren()
+ // when the children aren't actually finished?
+ element->finishParsingChildren();
+ pos->setNext(pos->next()->releaseNext());
+ return;
+ }
+ }
+ ASSERT_NOT_REACHED();
+}
+
+}
diff --git a/WebCore/html/HTMLElementStack.h b/WebCore/html/HTMLElementStack.h
new file mode 100644
index 0000000..efc3fd8
--- /dev/null
+++ b/WebCore/html/HTMLElementStack.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTMLElementStack_h
+#define HTMLElementStack_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class AtomicString;
+class Element;
+
+// NOTE: The HTML5 spec uses a backwards (grows downward) stack. We're using
+// more standard (grows upwards) stack terminology here.
+class HTMLElementStack : public Noncopyable {
+public:
+ HTMLElementStack();
+ ~HTMLElementStack();
+
+ class ElementRecord : public Noncopyable {
+ public:
+ ~ElementRecord(); // Public for ~PassOwnPtr()
+
+ Element* element() const { return m_element.get(); }
+ void replaceElement(PassRefPtr<Element>);
+
+ bool isAbove(ElementRecord*) const;
+
+ ElementRecord* next() const { return m_next.get(); }
+
+ private:
+ friend class HTMLElementStack;
+
+ ElementRecord(PassRefPtr<Element>, PassOwnPtr<ElementRecord>);
+
+ PassOwnPtr<ElementRecord> releaseNext() { return m_next.release(); }
+ void setNext(PassOwnPtr<ElementRecord> next) { m_next = next; }
+
+ RefPtr<Element> m_element;
+ OwnPtr<ElementRecord> m_next;
+ };
+
+ Element* top() const;
+ ElementRecord* topRecord() const;
+ Element* bottom() const;
+ ElementRecord* find(Element*) const;
+ ElementRecord* topmost(const AtomicString& tagName) const;
+
+ void insertAbove(PassRefPtr<Element>, ElementRecord*);
+
+ void push(PassRefPtr<Element>);
+ void pushHTMLHtmlElement(PassRefPtr<Element>);
+ void pushHTMLHeadElement(PassRefPtr<Element>);
+ void pushHTMLBodyElement(PassRefPtr<Element>);
+
+ void pop();
+ void popUntil(const AtomicString& tagName);
+ void popUntil(Element*);
+ void popUntilTableScopeMarker(); // "clear the stack back to a table context" in the spec.
+ void popUntilTableBodyScopeMarker(); // "clear the stack back to a table body context" in the spec.
+ void popHTMLHeadElement();
+ void popHTMLBodyElement();
+
+ void remove(Element*);
+ void removeHTMLHeadElement(Element*);
+
+ bool contains(Element*) const;
+
+ bool inScope(Element*) const;
+ bool inScope(const AtomicString& tagName) const;
+ bool inListItemScope(const AtomicString& tagName) const;
+ bool inTableScope(const AtomicString& tagName) const;
+
+ Element* htmlElement() const;
+ Element* headElement() const;
+ Element* bodyElement() const;
+
+private:
+ void pushCommon(PassRefPtr<Element>);
+ void popCommon();
+ void removeNonTopCommon(Element*);
+
+ OwnPtr<ElementRecord> m_top;
+
+ // We remember <html>, <head> and <body> as they are pushed. Their
+ // ElementRecords keep them alive. <html> is never popped.
+ // FIXME: We don't currently require type-specific information about
+ // these elements so we haven't yet bothered to plumb the types all the
+ // way down through createElement, etc.
+ Element* m_htmlElement;
+ Element* m_headElement;
+ Element* m_bodyElement;
+};
+
+} // namespace WebCore
+
+#endif // HTMLElementStack_h
diff --git a/WebCore/html/HTMLElementsAllInOne.cpp b/WebCore/html/HTMLElementsAllInOne.cpp
index f19addf..8411188 100644
--- a/WebCore/html/HTMLElementsAllInOne.cpp
+++ b/WebCore/html/HTMLElementsAllInOne.cpp
@@ -46,6 +46,7 @@
#include "HTMLDataGridCellElement.cpp"
#include "HTMLDataGridColElement.cpp"
#include "HTMLDataGridRowElement.cpp"
+#include "HTMLDataListElement.cpp"
#include "HTMLDListElement.cpp"
#include "HTMLDirectoryElement.cpp"
#include "HTMLDivElement.cpp"
@@ -79,6 +80,7 @@
#include "HTMLMetaElement.cpp"
#include "HTMLMeterElement.cpp"
#include "HTMLModElement.cpp"
+#include "HTMLNoScriptElement.cpp"
#include "HTMLOListElement.cpp"
#include "HTMLObjectElement.cpp"
#include "HTMLOptGroupElement.cpp"
diff --git a/WebCore/html/HTMLEntityParser.cpp b/WebCore/html/HTMLEntityParser.cpp
index 3d8d48d..84b2006 100644
--- a/WebCore/html/HTMLEntityParser.cpp
+++ b/WebCore/html/HTMLEntityParser.cpp
@@ -217,6 +217,14 @@ unsigned consumeHTMLEntity(SegmentedString& source, bool& notEnoughCharacters, U
// if the lookhead character is '='.
if (additionalAllowedCharacter && cc == '=')
break;
+ // Some entities require a terminating semicolon, whereas other
+ // entities do not. The HTML5 spec has a giant list:
+ //
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html#named-character-references
+ //
+ // However, the list seems to boil down to this branch:
+ if (entity->code > 255)
+ break;
return entity->code;
}
break;
diff --git a/WebCore/html/HTMLFontElement.cpp b/WebCore/html/HTMLFontElement.cpp
index 74320de..81ae415 100644
--- a/WebCore/html/HTMLFontElement.cpp
+++ b/WebCore/html/HTMLFontElement.cpp
@@ -149,34 +149,4 @@ void HTMLFontElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-String HTMLFontElement::color() const
-{
- return getAttribute(colorAttr);
-}
-
-void HTMLFontElement::setColor(const String& value)
-{
- setAttribute(colorAttr, value);
-}
-
-String HTMLFontElement::face() const
-{
- return getAttribute(faceAttr);
-}
-
-void HTMLFontElement::setFace(const String& value)
-{
- setAttribute(faceAttr, value);
-}
-
-String HTMLFontElement::size() const
-{
- return getAttribute(sizeAttr);
-}
-
-void HTMLFontElement::setSize(const String& value)
-{
- setAttribute(sizeAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLFontElement.h b/WebCore/html/HTMLFontElement.h
index cdf7143..f96a50b 100644
--- a/WebCore/html/HTMLFontElement.h
+++ b/WebCore/html/HTMLFontElement.h
@@ -32,15 +32,6 @@ class HTMLFontElement : public HTMLElement {
public:
static PassRefPtr<HTMLFontElement> create(const QualifiedName&, Document*);
- String color() const;
- void setColor(const String&);
-
- String face() const;
- void setFace(const String&);
-
- String size() const;
- void setSize(const String&);
-
static bool cssValueFromFontSizeNumber(const String&, int&);
private:
diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp
index 0b1c55a..5103bfa 100644
--- a/WebCore/html/HTMLFormControlElement.cpp
+++ b/WebCore/html/HTMLFormControlElement.cpp
@@ -81,11 +81,6 @@ bool HTMLFormControlElement::formNoValidate() const
return !getAttribute(formnovalidateAttr).isNull();
}
-void HTMLFormControlElement::setFormNoValidate(bool formnovalidate)
-{
- setAttribute(formnovalidateAttr, formnovalidate ? "" : 0);
-}
-
ValidityState* HTMLFormControlElement::validity()
{
if (!m_validityState)
@@ -196,7 +191,7 @@ const AtomicString& HTMLFormControlElement::formControlName() const
return name.isNull() ? emptyAtom : name;
}
-void HTMLFormControlElement::setName(const AtomicString &value)
+void HTMLFormControlElement::setName(const AtomicString& value)
{
setAttribute(nameAttr, value);
}
@@ -211,31 +206,16 @@ void HTMLFormControlElement::setDisabled(bool b)
setAttribute(disabledAttr, b ? "" : 0);
}
-void HTMLFormControlElement::setReadOnly(bool b)
-{
- setAttribute(readonlyAttr, b ? "" : 0);
-}
-
bool HTMLFormControlElement::autofocus() const
{
return hasAttribute(autofocusAttr);
}
-void HTMLFormControlElement::setAutofocus(bool b)
-{
- setAttribute(autofocusAttr, b ? "" : 0);
-}
-
bool HTMLFormControlElement::required() const
{
return m_required;
}
-void HTMLFormControlElement::setRequired(bool b)
-{
- setAttribute(requiredAttr, b ? "" : 0);
-}
-
static void updateFromElementCallback(Node* node)
{
ASSERT_ARG(node, node->isElementNode());
diff --git a/WebCore/html/HTMLFormControlElement.h b/WebCore/html/HTMLFormControlElement.h
index 87f6376..02ea4e7 100644
--- a/WebCore/html/HTMLFormControlElement.h
+++ b/WebCore/html/HTMLFormControlElement.h
@@ -44,7 +44,6 @@ public:
ValidityState* validity();
bool formNoValidate() const;
- void setFormNoValidate(bool);
virtual void reset() { }
@@ -59,14 +58,10 @@ public:
virtual bool isFocusable() const;
virtual bool isEnumeratable() const { return false; }
- void setReadOnly(bool);
-
- // Determines whether or not a control will be automatically focused
+ // Determines whether or not a control will be automatically focused.
virtual bool autofocus() const;
- void setAutofocus(bool);
bool required() const;
- void setRequired(bool);
const AtomicString& type() const { return formControlType(); }
const AtomicString& name() const { return formControlName(); }
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index 9d58934..2eface2 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -524,26 +524,11 @@ String HTMLFormElement::name() const
return getAttribute(nameAttr);
}
-void HTMLFormElement::setName(const String &value)
-{
- setAttribute(nameAttr, value);
-}
-
bool HTMLFormElement::noValidate() const
{
return !getAttribute(novalidateAttr).isNull();
}
-void HTMLFormElement::setNoValidate(bool novalidate)
-{
- setAttribute(novalidateAttr, novalidate ? "" : 0);
-}
-
-void HTMLFormElement::setAcceptCharset(const String &value)
-{
- setAttribute(accept_charsetAttr, value);
-}
-
String HTMLFormElement::action() const
{
return getAttribute(actionAttr);
@@ -574,11 +559,6 @@ String HTMLFormElement::target() const
return getAttribute(targetAttr);
}
-void HTMLFormElement::setTarget(const String &value)
-{
- setAttribute(targetAttr, value);
-}
-
HTMLFormControlElement* HTMLFormElement::defaultButton() const
{
for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
diff --git a/WebCore/html/HTMLFormElement.h b/WebCore/html/HTMLFormElement.h
index b19ff07..a2a5897 100644
--- a/WebCore/html/HTMLFormElement.h
+++ b/WebCore/html/HTMLFormElement.h
@@ -85,13 +85,10 @@ public:
bool formWouldHaveSecureSubmission(const String& url);
String name() const;
- void setName(const String&);
bool noValidate() const;
- void setNoValidate(bool);
String acceptCharset() const { return m_formDataBuilder.acceptCharset(); }
- void setAcceptCharset(const String&);
String action() const;
void setAction(const String&);
@@ -100,7 +97,6 @@ public:
void setMethod(const String&);
virtual String target() const;
- void setTarget(const String&);
HTMLFormControlElement* defaultButton() const;
diff --git a/WebCore/html/HTMLFormattingElementList.cpp b/WebCore/html/HTMLFormattingElementList.cpp
new file mode 100644
index 0000000..0198261
--- /dev/null
+++ b/WebCore/html/HTMLFormattingElementList.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTMLFormattingElementList.h"
+
+#include "Element.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+HTMLFormattingElementList::Entry::Entry(Element* element)
+ : m_element(element)
+{
+ ASSERT(element);
+}
+
+HTMLFormattingElementList::Entry::Entry(MarkerEntryType)
+{
+}
+
+HTMLFormattingElementList::Entry::~Entry()
+{
+}
+
+bool HTMLFormattingElementList::Entry::isMarker() const
+{
+ return !m_element;
+}
+
+Element* HTMLFormattingElementList::Entry::element() const
+{
+ // The fact that !m_element == isMarker() is an implementation detail
+ // callers should check isMarker() before calling element().
+ ASSERT(m_element);
+ return m_element.get();
+}
+
+void HTMLFormattingElementList::Entry::replaceElement(PassRefPtr<Element> element)
+{
+ ASSERT(m_element); // Once a marker, always a marker.
+ m_element = element;
+}
+
+bool HTMLFormattingElementList::Entry::operator==(const Entry& other) const
+{
+ return element() == other.element();
+}
+
+bool HTMLFormattingElementList::Entry::operator!=(const Entry& other) const
+{
+ return element() != other.element();
+}
+
+HTMLFormattingElementList::HTMLFormattingElementList()
+{
+}
+
+HTMLFormattingElementList::~HTMLFormattingElementList()
+{
+}
+
+Element* HTMLFormattingElementList::closestElementInScopeWithName(const AtomicString& targetName)
+{
+ for (unsigned i = 1; i <= m_entries.size(); ++i) {
+ const Entry& entry = m_entries[m_entries.size() - i];
+ if (entry.isMarker())
+ return 0;
+ if (entry.element()->hasLocalName(targetName))
+ return entry.element();
+ }
+ return 0;
+}
+
+bool HTMLFormattingElementList::contains(Element* element)
+{
+ return !!find(element);
+}
+
+HTMLFormattingElementList::Entry* HTMLFormattingElementList::find(Element* element)
+{
+ size_t index = m_entries.find(element);
+ if (index != notFound) {
+ // This is somewhat of a hack, and is why this method can't be const.
+ return &m_entries[index];
+ }
+ return 0;
+}
+
+void HTMLFormattingElementList::append(Element* element)
+{
+ m_entries.append(element);
+}
+
+void HTMLFormattingElementList::remove(Element* element)
+{
+ size_t index = m_entries.find(element);
+ if (index != notFound)
+ m_entries.remove(index);
+}
+
+void HTMLFormattingElementList::appendMarker()
+{
+ m_entries.append(Entry::MarkerEntry);
+}
+
+void HTMLFormattingElementList::clearToLastMarker()
+{
+ while (m_entries.size() && !m_entries.last().isMarker())
+ m_entries.removeLast();
+}
+
+}
diff --git a/WebCore/html/HTMLFormattingElementList.h b/WebCore/html/HTMLFormattingElementList.h
new file mode 100644
index 0000000..da30f75
--- /dev/null
+++ b/WebCore/html/HTMLFormattingElementList.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 Google, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTMLFormattingElementList_h
+#define HTMLFormattingElementList_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AtomicString;
+class Element;
+
+// This may end up merged into HTMLElementStack.
+class HTMLFormattingElementList : public Noncopyable {
+public:
+ HTMLFormattingElementList();
+ ~HTMLFormattingElementList();
+
+ // Ideally Entry would be private, but HTMLTreeBuilder has to coordinate
+ // between the HTMLFormattingElementList and HTMLElementStack and needs
+ // access to Entry::isMarker() and Entry::replaceElement() to do so.
+ class Entry {
+ public:
+ Entry(Element*);
+ enum MarkerEntryType { MarkerEntry };
+ Entry(MarkerEntryType);
+ ~Entry();
+
+ bool isMarker() const;
+
+ Element* element() const;
+ void replaceElement(PassRefPtr<Element>);
+
+ // Needed for use with Vector.
+ bool operator==(const Entry&) const;
+ bool operator!=(const Entry&) const;
+
+ private:
+ RefPtr<Element> m_element;
+ };
+
+ bool isEmpty() const { return !size(); }
+ size_t size() const { return m_entries.size(); }
+
+ Element* closestElementInScopeWithName(const AtomicString&);
+
+ Entry* find(Element*);
+ bool contains(Element*);
+ void append(Element*);
+ void remove(Element*);
+
+ void appendMarker();
+ void clearToLastMarker();
+
+ const Entry& operator[](size_t i) const { return m_entries[i]; }
+ Entry& operator[](size_t i) { return m_entries[i]; }
+
+private:
+ Vector<Entry> m_entries;
+};
+
+}
+
+#endif // HTMLFormattingElementList_h
diff --git a/WebCore/html/HTMLFrameElement.cpp b/WebCore/html/HTMLFrameElement.cpp
index 3ccc87f..71c8f3f 100644
--- a/WebCore/html/HTMLFrameElement.cpp
+++ b/WebCore/html/HTMLFrameElement.cpp
@@ -91,15 +91,8 @@ void HTMLFrameElement::parseMappedAttribute(Attribute* attr)
// FIXME: If we are already attached, this has no effect.
// FIXME: Since this does not check attr->isNull(), it can
// never reset m_noResize to false if the attribute is removed.
- // FIXME: There seems to be no code that looks at this
- // value and prevents resizing.
} else
HTMLFrameElementBase::parseMappedAttribute(attr);
}
-void HTMLFrameElement::setNoResize(bool noResize)
-{
- setAttribute(noresizeAttr, noResize ? "" : 0);
-}
-
} // namespace WebCore
diff --git a/WebCore/html/HTMLFrameElement.h b/WebCore/html/HTMLFrameElement.h
index 20f298e..3b1b5ad 100644
--- a/WebCore/html/HTMLFrameElement.h
+++ b/WebCore/html/HTMLFrameElement.h
@@ -35,7 +35,6 @@ public:
bool hasFrameBorder() const { return m_frameBorder; }
bool noResize() const { return m_noResize; }
- void setNoResize(bool);
private:
HTMLFrameElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLFrameElement.idl b/WebCore/html/HTMLFrameElement.idl
index 8f618c6..f1451f5 100644
--- a/WebCore/html/HTMLFrameElement.idl
+++ b/WebCore/html/HTMLFrameElement.idl
@@ -29,7 +29,7 @@ module html {
attribute [Reflect] DOMString name;
attribute [Reflect] boolean noResize;
attribute [Reflect] DOMString scrolling;
- attribute [ReflectURL, CustomSetter] DOMString src;
+ attribute [ReflectURL] DOMString src;
// Introduced in DOM Level 2:
readonly attribute [CheckFrameSecurity] Document contentDocument;
diff --git a/WebCore/html/HTMLFrameSetElement.cpp b/WebCore/html/HTMLFrameSetElement.cpp
index 7be3fdd..1b38a1d 100644
--- a/WebCore/html/HTMLFrameSetElement.cpp
+++ b/WebCore/html/HTMLFrameSetElement.cpp
@@ -216,24 +216,4 @@ void HTMLFrameSetElement::recalcStyle(StyleChange ch)
HTMLElement::recalcStyle(ch);
}
-String HTMLFrameSetElement::cols() const
-{
- return getAttribute(colsAttr);
-}
-
-void HTMLFrameSetElement::setCols(const String &value)
-{
- setAttribute(colsAttr, value);
-}
-
-String HTMLFrameSetElement::rows() const
-{
- return getAttribute(rowsAttr);
-}
-
-void HTMLFrameSetElement::setRows(const String &value)
-{
- setAttribute(rowsAttr, value);
-}
-
} // namespace WebCore
diff --git a/WebCore/html/HTMLFrameSetElement.h b/WebCore/html/HTMLFrameSetElement.h
index accfbf8..a79793d 100644
--- a/WebCore/html/HTMLFrameSetElement.h
+++ b/WebCore/html/HTMLFrameSetElement.h
@@ -42,12 +42,6 @@ public:
bool hasBorderColor() const { return m_borderColorSet; }
- String cols() const;
- void setCols(const String&);
-
- String rows() const;
- void setRows(const String&);
-
const Length* rowLengths() const { return m_rowLengths.get(); }
const Length* colLengths() const { return m_colLengths.get(); }
diff --git a/WebCore/html/HTMLHRElement.cpp b/WebCore/html/HTMLHRElement.cpp
index c4ab28f..44aa052 100644
--- a/WebCore/html/HTMLHRElement.cpp
+++ b/WebCore/html/HTMLHRElement.cpp
@@ -106,44 +106,4 @@ void HTMLHRElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-String HTMLHRElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLHRElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
-bool HTMLHRElement::noShade() const
-{
- return !getAttribute(noshadeAttr).isNull();
-}
-
-void HTMLHRElement::setNoShade(bool noShade)
-{
- setAttribute(noshadeAttr, noShade ? "" : 0);
-}
-
-String HTMLHRElement::size() const
-{
- return getAttribute(sizeAttr);
-}
-
-void HTMLHRElement::setSize(const String &value)
-{
- setAttribute(sizeAttr, value);
-}
-
-String HTMLHRElement::width() const
-{
- return getAttribute(widthAttr);
-}
-
-void HTMLHRElement::setWidth(const String &value)
-{
- setAttribute(widthAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLHRElement.h b/WebCore/html/HTMLHRElement.h
index ea10c88..3cfaabf 100644
--- a/WebCore/html/HTMLHRElement.h
+++ b/WebCore/html/HTMLHRElement.h
@@ -31,18 +31,6 @@ class HTMLHRElement : public HTMLElement {
public:
static PassRefPtr<HTMLHRElement> create(Document*);
static PassRefPtr<HTMLHRElement> create(const QualifiedName&, Document*);
-
- String align() const;
- void setAlign(const String&);
-
- bool noShade() const;
- void setNoShade(bool);
-
- String size() const;
- void setSize(const String&);
-
- String width() const;
- void setWidth(const String&);
private:
HTMLHRElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLHeadElement.cpp b/WebCore/html/HTMLHeadElement.cpp
index 0fb7a47..c57cc2f 100644
--- a/WebCore/html/HTMLHeadElement.cpp
+++ b/WebCore/html/HTMLHeadElement.cpp
@@ -47,16 +47,6 @@ PassRefPtr<HTMLHeadElement> HTMLHeadElement::create(const QualifiedName& tagName
return adoptRef(new HTMLHeadElement(tagName, document));
}
-String HTMLHeadElement::profile() const
-{
- return getAttribute(profileAttr);
-}
-
-void HTMLHeadElement::setProfile(const String &value)
-{
- setAttribute(profileAttr, value);
-}
-
bool HTMLHeadElement::childAllowed(Node* newChild)
{
// Do not allow non-whitespace text nodes in the head
diff --git a/WebCore/html/HTMLHeadElement.h b/WebCore/html/HTMLHeadElement.h
index a91f5f8..c7cfc00 100644
--- a/WebCore/html/HTMLHeadElement.h
+++ b/WebCore/html/HTMLHeadElement.h
@@ -33,9 +33,6 @@ public:
static PassRefPtr<HTMLHeadElement> create(Document*);
static PassRefPtr<HTMLHeadElement> create(const QualifiedName&, Document*);
- String profile() const;
- void setProfile(const String&);
-
virtual int tagPriority() const { return 10; }
private:
diff --git a/WebCore/html/HTMLHeadingElement.cpp b/WebCore/html/HTMLHeadingElement.cpp
index 484dea6..e2a0f73 100644
--- a/WebCore/html/HTMLHeadingElement.cpp
+++ b/WebCore/html/HTMLHeadingElement.cpp
@@ -49,14 +49,4 @@ bool HTMLHeadingElement::checkDTD(const Node* newChild)
return inEitherTagList(newChild);
}
-String HTMLHeadingElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLHeadingElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLHeadingElement.h b/WebCore/html/HTMLHeadingElement.h
index e783360..575a05c 100644
--- a/WebCore/html/HTMLHeadingElement.h
+++ b/WebCore/html/HTMLHeadingElement.h
@@ -31,9 +31,6 @@ class HTMLHeadingElement : public HTMLElement {
public:
static PassRefPtr<HTMLHeadingElement> create(const QualifiedName&, Document*);
- String align() const;
- void setAlign(const String&);
-
private:
HTMLHeadingElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLHtmlElement.cpp b/WebCore/html/HTMLHtmlElement.cpp
index 46913a1..93edf6c 100644
--- a/WebCore/html/HTMLHtmlElement.cpp
+++ b/WebCore/html/HTMLHtmlElement.cpp
@@ -50,16 +50,6 @@ PassRefPtr<HTMLHtmlElement> HTMLHtmlElement::create(const QualifiedName& tagName
return adoptRef(new HTMLHtmlElement(tagName, document));
}
-String HTMLHtmlElement::version() const
-{
- return getAttribute(versionAttr);
-}
-
-void HTMLHtmlElement::setVersion(const String &value)
-{
- setAttribute(versionAttr, value);
-}
-
bool HTMLHtmlElement::checkDTD(const Node* newChild)
{
return newChild->hasTagName(headTag) || newChild->hasTagName(bodyTag) ||
diff --git a/WebCore/html/HTMLHtmlElement.h b/WebCore/html/HTMLHtmlElement.h
index ed04703..34879ed 100644
--- a/WebCore/html/HTMLHtmlElement.h
+++ b/WebCore/html/HTMLHtmlElement.h
@@ -33,9 +33,6 @@ public:
static PassRefPtr<HTMLHtmlElement> create(Document*);
static PassRefPtr<HTMLHtmlElement> create(const QualifiedName&, Document*);
- String version() const;
- void setVersion(const String&);
-
private:
HTMLHtmlElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLIFrameElement.idl b/WebCore/html/HTMLIFrameElement.idl
index 86abaf5..b21263e 100644
--- a/WebCore/html/HTMLIFrameElement.idl
+++ b/WebCore/html/HTMLIFrameElement.idl
@@ -30,7 +30,7 @@ module html {
attribute [Reflect] DOMString name;
attribute [Reflect] DOMString sandbox;
attribute [Reflect] DOMString scrolling;
- attribute [CustomSetter, Reflect] DOMString src;
+ attribute [Reflect] DOMString src;
attribute [Reflect] DOMString width;
// Introduced in DOM Level 2:
diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp
index 5d5923d..82eeab1 100644
--- a/WebCore/html/HTMLImageElement.cpp
+++ b/WebCore/html/HTMLImageElement.cpp
@@ -342,47 +342,6 @@ void HTMLImageElement::setHeight(int value)
setAttribute(heightAttr, String::number(value));
}
-int HTMLImageElement::hspace() const
-{
- // ### return actual value
- return getAttribute(hspaceAttr).toInt();
-}
-
-void HTMLImageElement::setHspace(int value)
-{
- setAttribute(hspaceAttr, String::number(value));
-}
-
-bool HTMLImageElement::isMap() const
-{
- return !getAttribute(ismapAttr).isNull();
-}
-
-void HTMLImageElement::setIsMap(bool isMap)
-{
- setAttribute(ismapAttr, isMap ? "" : 0);
-}
-
-KURL HTMLImageElement::longDesc() const
-{
- return document()->completeURL(getAttribute(longdescAttr));
-}
-
-void HTMLImageElement::setLongDesc(const String& value)
-{
- setAttribute(longdescAttr, value);
-}
-
-KURL HTMLImageElement::lowsrc() const
-{
- return document()->completeURL(getAttribute(lowsrcAttr));
-}
-
-void HTMLImageElement::setLowsrc(const String& value)
-{
- setAttribute(lowsrcAttr, value);
-}
-
KURL HTMLImageElement::src() const
{
return document()->completeURL(getAttribute(srcAttr));
@@ -393,17 +352,6 @@ void HTMLImageElement::setSrc(const String& value)
setAttribute(srcAttr, value);
}
-int HTMLImageElement::vspace() const
-{
- // ### return actual vspace
- return getAttribute(vspaceAttr).toInt();
-}
-
-void HTMLImageElement::setVspace(int value)
-{
- setAttribute(vspaceAttr, String::number(value));
-}
-
void HTMLImageElement::setWidth(int value)
{
setAttribute(widthAttr, String::number(value));
diff --git a/WebCore/html/HTMLImageElement.h b/WebCore/html/HTMLImageElement.h
index 62d315c..2b29570 100644
--- a/WebCore/html/HTMLImageElement.h
+++ b/WebCore/html/HTMLImageElement.h
@@ -62,24 +62,9 @@ public:
void setHeight(int);
- int hspace() const;
- void setHspace(int);
-
- bool isMap() const;
- void setIsMap(bool);
-
- KURL longDesc() const;
- void setLongDesc(const String&);
-
- KURL lowsrc() const;
- void setLowsrc(const String&);
-
KURL src() const;
void setSrc(const String&);
- int vspace() const;
- void setVspace(int);
-
void setWidth(int);
int x() const;
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index 5e27449..d6136d8 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -2427,11 +2427,6 @@ bool HTMLInputElement::defaultChecked() const
return !getAttribute(checkedAttr).isNull();
}
-void HTMLInputElement::setDefaultChecked(bool defaultChecked)
-{
- setAttribute(checkedAttr, defaultChecked ? "" : 0);
-}
-
void HTMLInputElement::setDefaultName(const AtomicString& name)
{
m_data.setName(name);
@@ -2442,41 +2437,11 @@ String HTMLInputElement::accept() const
return getAttribute(acceptAttr);
}
-void HTMLInputElement::setAccept(const String &value)
-{
- setAttribute(acceptAttr, value);
-}
-
-String HTMLInputElement::accessKey() const
-{
- return getAttribute(accesskeyAttr);
-}
-
-void HTMLInputElement::setAccessKey(const String &value)
-{
- setAttribute(accesskeyAttr, value);
-}
-
-String HTMLInputElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLInputElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
String HTMLInputElement::alt() const
{
return getAttribute(altAttr);
}
-void HTMLInputElement::setAlt(const String &value)
-{
- setAttribute(altAttr, value);
-}
-
int HTMLInputElement::maxLength() const
{
return m_data.maxLength();
@@ -2495,11 +2460,6 @@ bool HTMLInputElement::multiple() const
return !getAttribute(multipleAttr).isNull();
}
-void HTMLInputElement::setMultiple(bool multiple)
-{
- setAttribute(multipleAttr, multiple ? "" : 0);
-}
-
void HTMLInputElement::setSize(unsigned size)
{
setAttribute(sizeAttr, String::number(size));
@@ -2510,21 +2470,6 @@ KURL HTMLInputElement::src() const
return document()->completeURL(getAttribute(srcAttr));
}
-void HTMLInputElement::setSrc(const String &value)
-{
- setAttribute(srcAttr, value);
-}
-
-String HTMLInputElement::useMap() const
-{
- return getAttribute(usemapAttr);
-}
-
-void HTMLInputElement::setUseMap(const String &value)
-{
- setAttribute(usemapAttr, value);
-}
-
void HTMLInputElement::setAutofilled(bool b)
{
if (b == m_autofilled)
@@ -2730,6 +2675,7 @@ bool HTMLInputElement::parseToDateComponents(InputType type, const String& formS
}
#if ENABLE(DATALIST)
+
HTMLElement* HTMLInputElement::list() const
{
return dataList();
@@ -2794,6 +2740,7 @@ HTMLOptionElement* HTMLInputElement::selectedOption() const
}
return 0;
}
+
#endif // ENABLE(DATALIST)
void HTMLInputElement::stepUpFromRenderer(int n)
diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h
index 5bcf01f..6791fa2 100644
--- a/WebCore/html/HTMLInputElement.h
+++ b/WebCore/html/HTMLInputElement.h
@@ -162,35 +162,20 @@ public:
void setDefaultValue(const String&);
bool defaultChecked() const;
- void setDefaultChecked(bool);
void setDefaultName(const AtomicString&);
String accept() const;
- void setAccept(const String&);
-
- String accessKey() const;
- void setAccessKey(const String&);
-
- String align() const;
- void setAlign(const String&);
-
String alt() const;
- void setAlt(const String&);
void setSize(unsigned);
KURL src() const;
- void setSrc(const String&);
int maxLength() const;
void setMaxLength(int, ExceptionCode&);
bool multiple() const;
- void setMultiple(bool);
-
- String useMap() const;
- void setUseMap(const String&);
virtual bool isAutofilled() const { return m_autofilled; }
void setAutofilled(bool value = true);
diff --git a/WebCore/html/HTMLInputStream.h b/WebCore/html/HTMLInputStream.h
index 9620388..d7c1c9c 100644
--- a/WebCore/html/HTMLInputStream.h
+++ b/WebCore/html/HTMLInputStream.h
@@ -64,8 +64,19 @@ public:
m_first.append(string);
}
- void close() { m_last->close(); }
- bool isClosed() { return m_last->isClosed(); }
+ void markEndOfFile()
+ {
+ // FIXME: This should use InputStreamPreprocessor::endOfFileMarker
+ // once InputStreamPreprocessor is split off into its own header.
+ static const UChar endOfFileMarker = 0;
+ m_last->append(SegmentedString(String(&endOfFileMarker, 1)));
+ m_last->close();
+ }
+
+ bool haveSeenEndOfFile()
+ {
+ return m_last->isClosed();
+ }
SegmentedString& current() { return m_first; }
diff --git a/WebCore/html/HTMLIsIndexElement.cpp b/WebCore/html/HTMLIsIndexElement.cpp
index dce67f6..a23a353 100644
--- a/WebCore/html/HTMLIsIndexElement.cpp
+++ b/WebCore/html/HTMLIsIndexElement.cpp
@@ -61,14 +61,4 @@ void HTMLIsIndexElement::parseMappedAttribute(Attribute* attr)
HTMLFormControlElement::parseMappedAttribute(attr);
}
-String HTMLIsIndexElement::prompt() const
-{
- return getAttribute(promptAttr);
-}
-
-void HTMLIsIndexElement::setPrompt(const String &value)
-{
- setAttribute(promptAttr, value);
-}
-
} // namespace
diff --git a/WebCore/html/HTMLIsIndexElement.h b/WebCore/html/HTMLIsIndexElement.h
index 528f3e2..8c33d71 100644
--- a/WebCore/html/HTMLIsIndexElement.h
+++ b/WebCore/html/HTMLIsIndexElement.h
@@ -33,9 +33,6 @@ public:
static PassRefPtr<HTMLIsIndexElement> create(Document*, HTMLFormElement*);
static PassRefPtr<HTMLIsIndexElement> create(const QualifiedName&, Document*, HTMLFormElement*);
- String prompt() const;
- void setPrompt(const String&);
-
private:
HTMLIsIndexElement(const QualifiedName&, Document*, HTMLFormElement*);
diff --git a/WebCore/html/HTMLKeygenElement.cpp b/WebCore/html/HTMLKeygenElement.cpp
index 74b3a0f..5185f51 100644
--- a/WebCore/html/HTMLKeygenElement.cpp
+++ b/WebCore/html/HTMLKeygenElement.cpp
@@ -50,8 +50,8 @@ inline HTMLKeygenElement::HTMLKeygenElement(const QualifiedName& tagName, Docume
getSupportedKeySizes(keys);
for (size_t i = 0; i < keys.size(); ++i) {
RefPtr<HTMLOptionElement> option = HTMLOptionElement::create(document, this->form());
- addChild(option);
- option->addChild(Text::create(document, keys[i]));
+ legacyParserAddChild(option);
+ option->legacyParserAddChild(Text::create(document, keys[i]));
}
}
diff --git a/WebCore/html/HTMLLIElement.cpp b/WebCore/html/HTMLLIElement.cpp
index ae96cc3..9abea9f 100644
--- a/WebCore/html/HTMLLIElement.cpp
+++ b/WebCore/html/HTMLLIElement.cpp
@@ -116,24 +116,4 @@ void HTMLLIElement::attach()
}
}
-String HTMLLIElement::type() const
-{
- return getAttribute(typeAttr);
-}
-
-void HTMLLIElement::setType(const String& value)
-{
- setAttribute(typeAttr, value);
-}
-
-int HTMLLIElement::value() const
-{
- return getAttribute(valueAttr).toInt();
-}
-
-void HTMLLIElement::setValue(int value)
-{
- setAttribute(valueAttr, String::number(value));
-}
-
}
diff --git a/WebCore/html/HTMLLIElement.h b/WebCore/html/HTMLLIElement.h
index 5ce00f2..418f7a4 100644
--- a/WebCore/html/HTMLLIElement.h
+++ b/WebCore/html/HTMLLIElement.h
@@ -32,12 +32,6 @@ public:
static PassRefPtr<HTMLLIElement> create(Document*);
static PassRefPtr<HTMLLIElement> create(const QualifiedName&, Document*);
- String type() const;
- void setType(const String&);
-
- int value() const;
- void setValue(int);
-
private:
HTMLLIElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLLabelElement.cpp b/WebCore/html/HTMLLabelElement.cpp
index 6b3069a..1e44e2a 100644
--- a/WebCore/html/HTMLLabelElement.cpp
+++ b/WebCore/html/HTMLLabelElement.cpp
@@ -154,26 +154,6 @@ void HTMLLabelElement::accessKeyAction(bool sendToAnyElement)
HTMLElement::accessKeyAction(sendToAnyElement);
}
-String HTMLLabelElement::accessKey() const
-{
- return getAttribute(accesskeyAttr);
-}
-
-void HTMLLabelElement::setAccessKey(const String &value)
-{
- setAttribute(accesskeyAttr, value);
-}
-
-String HTMLLabelElement::htmlFor() const
-{
- return getAttribute(forAttr);
-}
-
-void HTMLLabelElement::setHtmlFor(const String &value)
-{
- setAttribute(forAttr, value);
-}
-
void HTMLLabelElement::parseMappedAttribute(Attribute* attribute)
{
if (attribute->name() == forAttr) {
diff --git a/WebCore/html/HTMLLabelElement.h b/WebCore/html/HTMLLabelElement.h
index 759ffcd..7964ade 100644
--- a/WebCore/html/HTMLLabelElement.h
+++ b/WebCore/html/HTMLLabelElement.h
@@ -35,12 +35,6 @@ public:
HTMLFormControlElement* control();
- String accessKey() const;
- void setAccessKey(const String&);
-
- String htmlFor() const;
- void setHtmlFor(const String&);
-
private:
HTMLLabelElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLLegendElement.cpp b/WebCore/html/HTMLLegendElement.cpp
index 4249fb1..acc4a59 100644
--- a/WebCore/html/HTMLLegendElement.cpp
+++ b/WebCore/html/HTMLLegendElement.cpp
@@ -54,26 +54,6 @@ const AtomicString& HTMLLegendElement::formControlType() const
return legend;
}
-String HTMLLegendElement::accessKey() const
-{
- return getAttribute(accesskeyAttr);
-}
-
-void HTMLLegendElement::setAccessKey(const String &value)
-{
- setAttribute(accesskeyAttr, value);
-}
-
-String HTMLLegendElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLLegendElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
HTMLFormControlElement* HTMLLegendElement::associatedControl()
{
// Check if there's a fieldset belonging to this legend.
diff --git a/WebCore/html/HTMLLegendElement.h b/WebCore/html/HTMLLegendElement.h
index fa2aa2b..732ef33 100644
--- a/WebCore/html/HTMLLegendElement.h
+++ b/WebCore/html/HTMLLegendElement.h
@@ -32,12 +32,6 @@ class HTMLLegendElement : public HTMLFormControlElement {
public:
static PassRefPtr<HTMLLegendElement> create(const QualifiedName&, Document*, HTMLFormElement*);
- String accessKey() const;
- void setAccessKey(const String&);
-
- String align() const;
- void setAlign(const String&);
-
private:
HTMLLegendElement(const QualifiedName&, Document*, HTMLFormElement*);
diff --git a/WebCore/html/HTMLLinkElement.cpp b/WebCore/html/HTMLLinkElement.cpp
index 13e43fd..64a52cc 100644
--- a/WebCore/html/HTMLLinkElement.cpp
+++ b/WebCore/html/HTMLLinkElement.cpp
@@ -420,96 +420,26 @@ bool HTMLLinkElement::isURLAttribute(Attribute *attr) const
return attr->name() == hrefAttr;
}
-bool HTMLLinkElement::disabled() const
-{
- return !getAttribute(disabledAttr).isNull();
-}
-
-void HTMLLinkElement::setDisabled(bool disabled)
-{
- setAttribute(disabledAttr, disabled ? "" : 0);
-}
-
-String HTMLLinkElement::charset() const
-{
- return getAttribute(charsetAttr);
-}
-
-void HTMLLinkElement::setCharset(const String& value)
-{
- setAttribute(charsetAttr, value);
-}
-
KURL HTMLLinkElement::href() const
{
return document()->completeURL(getAttribute(hrefAttr));
}
-void HTMLLinkElement::setHref(const String& value)
-{
- setAttribute(hrefAttr, value);
-}
-
-String HTMLLinkElement::hreflang() const
-{
- return getAttribute(hreflangAttr);
-}
-
-void HTMLLinkElement::setHreflang(const String& value)
-{
- setAttribute(hreflangAttr, value);
-}
-
-String HTMLLinkElement::media() const
-{
- return getAttribute(mediaAttr);
-}
-
-void HTMLLinkElement::setMedia(const String& value)
-{
- setAttribute(mediaAttr, value);
-}
-
String HTMLLinkElement::rel() const
{
return getAttribute(relAttr);
}
-void HTMLLinkElement::setRel(const String& value)
-{
- setAttribute(relAttr, value);
-}
-
-String HTMLLinkElement::rev() const
-{
- return getAttribute(revAttr);
-}
-
-void HTMLLinkElement::setRev(const String& value)
-{
- setAttribute(revAttr, value);
-}
-
String HTMLLinkElement::target() const
{
return getAttribute(targetAttr);
}
-void HTMLLinkElement::setTarget(const String& value)
-{
- setAttribute(targetAttr, value);
-}
-
String HTMLLinkElement::type() const
{
return getAttribute(typeAttr);
}
-void HTMLLinkElement::setType(const String& value)
-{
- setAttribute(typeAttr, value);
-}
-
void HTMLLinkElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
{
HTMLElement::addSubresourceAttributeURLs(urls);
diff --git a/WebCore/html/HTMLLinkElement.h b/WebCore/html/HTMLLinkElement.h
index bd1642b..a2d88c2 100644
--- a/WebCore/html/HTMLLinkElement.h
+++ b/WebCore/html/HTMLLinkElement.h
@@ -67,32 +67,12 @@ public:
static PassRefPtr<HTMLLinkElement> create(const QualifiedName&, Document*, bool createdByParser);
virtual ~HTMLLinkElement();
- bool disabled() const;
- void setDisabled(bool);
-
- String charset() const;
- void setCharset(const String&);
-
KURL href() const;
- void setHref(const String&);
-
- String hreflang() const;
- void setHreflang(const String&);
-
- String media() const;
- void setMedia(const String&);
-
String rel() const;
- void setRel(const String&);
-
- String rev() const;
- void setRev(const String&);
virtual String target() const;
- void setTarget(const String&);
String type() const;
- void setType(const String&);
StyleSheet* sheet() const;
diff --git a/WebCore/html/HTMLMapElement.cpp b/WebCore/html/HTMLMapElement.cpp
index 14c0feb..eba23ca 100644
--- a/WebCore/html/HTMLMapElement.cpp
+++ b/WebCore/html/HTMLMapElement.cpp
@@ -137,16 +137,6 @@ PassRefPtr<HTMLCollection> HTMLMapElement::areas()
return HTMLCollection::create(this, MapAreas);
}
-String HTMLMapElement::name() const
-{
- return getAttribute(nameAttr);
-}
-
-void HTMLMapElement::setName(const String& value)
-{
- setAttribute(nameAttr, value);
-}
-
void HTMLMapElement::insertedIntoDocument()
{
document()->addImageMap(this);
diff --git a/WebCore/html/HTMLMapElement.h b/WebCore/html/HTMLMapElement.h
index 483f17b..1394c95 100644
--- a/WebCore/html/HTMLMapElement.h
+++ b/WebCore/html/HTMLMapElement.h
@@ -44,9 +44,6 @@ public:
HTMLImageElement* imageElement() const;
PassRefPtr<HTMLCollection> areas();
- String name() const;
- void setName(const String&);
-
private:
HTMLMapElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLMenuElement.cpp b/WebCore/html/HTMLMenuElement.cpp
index 7acef0f..9f706ef 100644
--- a/WebCore/html/HTMLMenuElement.cpp
+++ b/WebCore/html/HTMLMenuElement.cpp
@@ -40,14 +40,4 @@ PassRefPtr<HTMLMenuElement> HTMLMenuElement::create(const QualifiedName& tagName
return adoptRef(new HTMLMenuElement(tagName, document));
}
-bool HTMLMenuElement::compact() const
-{
- return !getAttribute(compactAttr).isNull();
-}
-
-void HTMLMenuElement::setCompact(bool b)
-{
- setAttribute(compactAttr, b ? "" : 0);
-}
-
}
diff --git a/WebCore/html/HTMLMenuElement.h b/WebCore/html/HTMLMenuElement.h
index 7534e81..002df00 100644
--- a/WebCore/html/HTMLMenuElement.h
+++ b/WebCore/html/HTMLMenuElement.h
@@ -31,9 +31,6 @@ class HTMLMenuElement : public HTMLElement {
public:
static PassRefPtr<HTMLMenuElement> create(const QualifiedName&, Document*);
- bool compact() const;
- void setCompact(bool);
-
private:
HTMLMenuElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLMetaElement.cpp b/WebCore/html/HTMLMetaElement.cpp
index a7f2978..cdb9950 100644
--- a/WebCore/html/HTMLMetaElement.cpp
+++ b/WebCore/html/HTMLMetaElement.cpp
@@ -123,39 +123,14 @@ String HTMLMetaElement::content() const
return getAttribute(contentAttr);
}
-void HTMLMetaElement::setContent(const String& value)
-{
- setAttribute(contentAttr, value);
-}
-
String HTMLMetaElement::httpEquiv() const
{
return getAttribute(http_equivAttr);
}
-void HTMLMetaElement::setHttpEquiv(const String& value)
-{
- setAttribute(http_equivAttr, value);
-}
-
String HTMLMetaElement::name() const
{
return getAttribute(nameAttr);
}
-void HTMLMetaElement::setName(const String& value)
-{
- setAttribute(nameAttr, value);
-}
-
-String HTMLMetaElement::scheme() const
-{
- return getAttribute(schemeAttr);
-}
-
-void HTMLMetaElement::setScheme(const String &value)
-{
- setAttribute(schemeAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLMetaElement.h b/WebCore/html/HTMLMetaElement.h
index 7708a50..6af7483 100644
--- a/WebCore/html/HTMLMetaElement.h
+++ b/WebCore/html/HTMLMetaElement.h
@@ -32,16 +32,8 @@ public:
static PassRefPtr<HTMLMetaElement> create(const QualifiedName&, Document*);
String content() const;
- void setContent(const String&);
-
String httpEquiv() const;
- void setHttpEquiv(const String&);
-
String name() const;
- void setName(const String&);
-
- String scheme() const;
- void setScheme(const String&);
private:
HTMLMetaElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLModElement.cpp b/WebCore/html/HTMLModElement.cpp
index cb6da83..ab161d9 100644
--- a/WebCore/html/HTMLModElement.cpp
+++ b/WebCore/html/HTMLModElement.cpp
@@ -39,24 +39,4 @@ PassRefPtr<HTMLModElement> HTMLModElement::create(const QualifiedName& tagName,
return adoptRef(new HTMLModElement(tagName, document));
}
-String HTMLModElement::cite() const
-{
- return getAttribute(citeAttr);
-}
-
-void HTMLModElement::setCite(const String& value)
-{
- setAttribute(citeAttr, value);
-}
-
-String HTMLModElement::dateTime() const
-{
- return getAttribute(datetimeAttr);
-}
-
-void HTMLModElement::setDateTime(const String& value)
-{
- setAttribute(datetimeAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLModElement.h b/WebCore/html/HTMLModElement.h
index af003d7..7370320 100644
--- a/WebCore/html/HTMLModElement.h
+++ b/WebCore/html/HTMLModElement.h
@@ -32,12 +32,6 @@ class HTMLModElement : public HTMLElement {
public:
static PassRefPtr<HTMLModElement> create(const QualifiedName&, Document*);
- String cite() const;
- void setCite(const String&);
-
- String dateTime() const;
- void setDateTime(const String&);
-
private:
HTMLModElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLOListElement.cpp b/WebCore/html/HTMLOListElement.cpp
index c40f216..4c1d5a7 100644
--- a/WebCore/html/HTMLOListElement.cpp
+++ b/WebCore/html/HTMLOListElement.cpp
@@ -89,29 +89,9 @@ void HTMLOListElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-bool HTMLOListElement::compact() const
-{
- return !getAttribute(compactAttr).isNull();
-}
-
-void HTMLOListElement::setCompact(bool b)
-{
- setAttribute(compactAttr, b ? "" : 0);
-}
-
void HTMLOListElement::setStart(int start)
{
setAttribute(startAttr, String::number(start));
}
-String HTMLOListElement::type() const
-{
- return getAttribute(typeAttr);
-}
-
-void HTMLOListElement::setType(const String& value)
-{
- setAttribute(typeAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLOListElement.h b/WebCore/html/HTMLOListElement.h
index 871c34c..3067138 100644
--- a/WebCore/html/HTMLOListElement.h
+++ b/WebCore/html/HTMLOListElement.h
@@ -32,15 +32,9 @@ public:
static PassRefPtr<HTMLOListElement> create(Document*);
static PassRefPtr<HTMLOListElement> create(const QualifiedName&, Document*);
- bool compact() const;
- void setCompact(bool);
-
int start() const { return m_start; }
void setStart(int);
- String type() const;
- void setType(const String&);
-
private:
HTMLOListElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLObjectElement.cpp b/WebCore/html/HTMLObjectElement.cpp
index 45586d1..0724ce6 100644
--- a/WebCore/html/HTMLObjectElement.cpp
+++ b/WebCore/html/HTMLObjectElement.cpp
@@ -301,36 +301,6 @@ void HTMLObjectElement::updateDocNamedItem()
m_docNamedItem = isNamedItem;
}
-bool HTMLObjectElement::declare() const
-{
- return !getAttribute(declareAttr).isNull();
-}
-
-void HTMLObjectElement::setDeclare(bool declare)
-{
- setAttribute(declareAttr, declare ? "" : 0);
-}
-
-int HTMLObjectElement::hspace() const
-{
- return getAttribute(hspaceAttr).toInt();
-}
-
-void HTMLObjectElement::setHspace(int value)
-{
- setAttribute(hspaceAttr, String::number(value));
-}
-
-int HTMLObjectElement::vspace() const
-{
- return getAttribute(vspaceAttr).toInt();
-}
-
-void HTMLObjectElement::setVspace(int value)
-{
- setAttribute(vspaceAttr, String::number(value));
-}
-
bool HTMLObjectElement::containsJavaApplet() const
{
if (MIMETypeRegistry::isJavaAppletMIMEType(getAttribute(typeAttr)))
diff --git a/WebCore/html/HTMLObjectElement.h b/WebCore/html/HTMLObjectElement.h
index 4a22ea3..c904c74 100644
--- a/WebCore/html/HTMLObjectElement.h
+++ b/WebCore/html/HTMLObjectElement.h
@@ -35,15 +35,6 @@ public:
void renderFallbackContent();
- bool declare() const;
- void setDeclare(bool);
-
- int hspace() const;
- void setHspace(int);
-
- int vspace() const;
- void setVspace(int);
-
bool isDocNamedItem() const { return m_docNamedItem; }
const String& classId() const { return m_classId; }
diff --git a/WebCore/html/HTMLOptGroupElement.cpp b/WebCore/html/HTMLOptGroupElement.cpp
index 27bc40e..7db0924 100644
--- a/WebCore/html/HTMLOptGroupElement.cpp
+++ b/WebCore/html/HTMLOptGroupElement.cpp
@@ -86,16 +86,6 @@ void HTMLOptGroupElement::recalcSelectOptions()
static_cast<HTMLSelectElement*>(select)->setRecalcListItems();
}
-String HTMLOptGroupElement::label() const
-{
- return getAttribute(labelAttr);
-}
-
-void HTMLOptGroupElement::setLabel(const String &value)
-{
- setAttribute(labelAttr, value);
-}
-
bool HTMLOptGroupElement::checkDTD(const Node* newChild)
{
// Make sure to keep this in sync with <select> (other than not allowing an optgroup).
diff --git a/WebCore/html/HTMLOptGroupElement.h b/WebCore/html/HTMLOptGroupElement.h
index 394fdca..095b9d2 100644
--- a/WebCore/html/HTMLOptGroupElement.h
+++ b/WebCore/html/HTMLOptGroupElement.h
@@ -35,9 +35,6 @@ class HTMLOptGroupElement : public HTMLFormControlElement, public OptionGroupEle
public:
static PassRefPtr<HTMLOptGroupElement> create(const QualifiedName&, Document*, HTMLFormElement*);
- String label() const;
- void setLabel(const String&);
-
HTMLSelectElement* ownerSelectElement() const;
virtual String groupLabelText() const;
diff --git a/WebCore/html/HTMLOptionElement.cpp b/WebCore/html/HTMLOptionElement.cpp
index dfee748..19f40be 100644
--- a/WebCore/html/HTMLOptionElement.cpp
+++ b/WebCore/html/HTMLOptionElement.cpp
@@ -223,11 +223,6 @@ String HTMLOptionElement::label() const
return m_data.label();
}
-void HTMLOptionElement::setLabel(const String& value)
-{
- setAttribute(labelAttr, value);
-}
-
void HTMLOptionElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle)
{
m_style = newStyle;
diff --git a/WebCore/html/HTMLOptionElement.h b/WebCore/html/HTMLOptionElement.h
index b82bfae..d0ff23b 100644
--- a/WebCore/html/HTMLOptionElement.h
+++ b/WebCore/html/HTMLOptionElement.h
@@ -70,7 +70,6 @@ public:
void setDefaultSelected(bool);
String label() const;
- void setLabel(const String&);
bool ownElementDisabled() const { return HTMLFormControlElement::disabled(); }
diff --git a/WebCore/html/HTMLParagraphElement.cpp b/WebCore/html/HTMLParagraphElement.cpp
index 4afa9f8..4af5b77 100644
--- a/WebCore/html/HTMLParagraphElement.cpp
+++ b/WebCore/html/HTMLParagraphElement.cpp
@@ -74,14 +74,4 @@ void HTMLParagraphElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-String HTMLParagraphElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLParagraphElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLParagraphElement.h b/WebCore/html/HTMLParagraphElement.h
index 26e34a7..0a31a1c 100644
--- a/WebCore/html/HTMLParagraphElement.h
+++ b/WebCore/html/HTMLParagraphElement.h
@@ -31,9 +31,6 @@ class HTMLParagraphElement : public HTMLElement {
public:
static PassRefPtr<HTMLParagraphElement> create(const QualifiedName&, Document*);
- String align() const;
- void setAlign(const String&);
-
private:
HTMLParagraphElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLParamElement.cpp b/WebCore/html/HTMLParamElement.cpp
index 13a37d6..2dc9d1d 100644
--- a/WebCore/html/HTMLParamElement.cpp
+++ b/WebCore/html/HTMLParamElement.cpp
@@ -71,36 +71,6 @@ bool HTMLParamElement::isURLAttribute(Attribute* attr) const
return false;
}
-void HTMLParamElement::setName(const String& value)
-{
- setAttribute(nameAttr, value);
-}
-
-String HTMLParamElement::type() const
-{
- return getAttribute(typeAttr);
-}
-
-void HTMLParamElement::setType(const String& value)
-{
- setAttribute(typeAttr, value);
-}
-
-void HTMLParamElement::setValue(const String& value)
-{
- setAttribute(valueAttr, value);
-}
-
-String HTMLParamElement::valueType() const
-{
- return getAttribute(valuetypeAttr);
-}
-
-void HTMLParamElement::setValueType(const String& value)
-{
- setAttribute(valuetypeAttr, value);
-}
-
void HTMLParamElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
{
HTMLElement::addSubresourceAttributeURLs(urls);
diff --git a/WebCore/html/HTMLParamElement.h b/WebCore/html/HTMLParamElement.h
index a782353..a787927 100644
--- a/WebCore/html/HTMLParamElement.h
+++ b/WebCore/html/HTMLParamElement.h
@@ -32,16 +32,7 @@ public:
static PassRefPtr<HTMLParamElement> create(const QualifiedName&, Document*);
String name() const { return m_name; }
- void setName(const String&);
-
- String type() const;
- void setType(const String&);
-
String value() const { return m_value; }
- void setValue(const String&);
-
- String valueType() const;
- void setValueType(const String&);
private:
HTMLParamElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLPlugInElement.cpp b/WebCore/html/HTMLPlugInElement.cpp
index 18b1c6a..ffc6b64 100644
--- a/WebCore/html/HTMLPlugInElement.cpp
+++ b/WebCore/html/HTMLPlugInElement.cpp
@@ -24,6 +24,8 @@
#include "HTMLPlugInElement.h"
#include "Attribute.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
#include "CSSPropertyNames.h"
#include "Document.h"
#include "Frame.h"
@@ -31,6 +33,7 @@
#include "FrameTree.h"
#include "HTMLNames.h"
#include "Page.h"
+#include "RenderEmbeddedObject.h"
#include "RenderWidget.h"
#include "ScriptController.h"
#include "Settings.h"
@@ -88,26 +91,6 @@ PassScriptInstance HTMLPlugInElement::getInstance() const
return m_instance;
}
-String HTMLPlugInElement::height() const
-{
- return getAttribute(heightAttr);
-}
-
-void HTMLPlugInElement::setHeight(const String& value)
-{
- setAttribute(heightAttr, value);
-}
-
-String HTMLPlugInElement::width() const
-{
- return getAttribute(widthAttr);
-}
-
-void HTMLPlugInElement::setWidth(const String& value)
-{
- setAttribute(widthAttr, value);
-}
-
bool HTMLPlugInElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
{
if (attrName == widthAttr ||
@@ -158,6 +141,18 @@ void HTMLPlugInElement::defaultEventHandler(Event* event)
// FIXME: Mouse down and scroll events are passed down to plug-in via custom code in EventHandler; these code paths should be united.
RenderObject* r = renderer();
+ if (r && r->isEmbeddedObject() && toRenderEmbeddedObject(r)->showsMissingPluginIndicator()) {
+ if (event->type() != eventNames().clickEvent)
+ return;
+
+ Page* page = document()->page();
+ if (!page)
+ return;
+
+ page->chrome()->client()->missingPluginButtonClicked(this);
+ return;
+ }
+
if (!r || !r->isWidget())
return;
Widget* widget = toRenderWidget(r)->widget();
diff --git a/WebCore/html/HTMLPlugInElement.h b/WebCore/html/HTMLPlugInElement.h
index e9cd9d0..525dc40 100644
--- a/WebCore/html/HTMLPlugInElement.h
+++ b/WebCore/html/HTMLPlugInElement.h
@@ -38,12 +38,6 @@ class HTMLPlugInElement : public HTMLFrameOwnerElement {
public:
virtual ~HTMLPlugInElement();
- String height() const;
- void setHeight(const String&);
-
- String width() const;
- void setWidth(const String&);
-
PassScriptInstance getInstance() const;
#if ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/html/HTMLPreElement.cpp b/WebCore/html/HTMLPreElement.cpp
index b13c801..fc67aca 100644
--- a/WebCore/html/HTMLPreElement.cpp
+++ b/WebCore/html/HTMLPreElement.cpp
@@ -65,24 +65,4 @@ void HTMLPreElement::parseMappedAttribute(Attribute* attr)
return HTMLElement::parseMappedAttribute(attr);
}
-int HTMLPreElement::width() const
-{
- return getAttribute(widthAttr).toInt();
-}
-
-void HTMLPreElement::setWidth(int width)
-{
- setAttribute(widthAttr, String::number(width));
-}
-
-bool HTMLPreElement::wrap() const
-{
- return !getAttribute(wrapAttr).isNull();
-}
-
-void HTMLPreElement::setWrap(bool wrap)
-{
- setAttribute(wrapAttr, wrap ? "" : 0);
-}
-
}
diff --git a/WebCore/html/HTMLPreElement.h b/WebCore/html/HTMLPreElement.h
index 0975c0f..1a67c65 100644
--- a/WebCore/html/HTMLPreElement.h
+++ b/WebCore/html/HTMLPreElement.h
@@ -31,12 +31,6 @@ class HTMLPreElement : public HTMLElement {
public:
static PassRefPtr<HTMLPreElement> create(const QualifiedName&, Document*);
- int width() const;
- void setWidth(int);
-
- bool wrap() const;
- void setWrap(bool);
-
private:
HTMLPreElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLQuoteElement.cpp b/WebCore/html/HTMLQuoteElement.cpp
index 2d0013a..2a2440a 100644
--- a/WebCore/html/HTMLQuoteElement.cpp
+++ b/WebCore/html/HTMLQuoteElement.cpp
@@ -48,14 +48,4 @@ void HTMLQuoteElement::insertedIntoDocument()
HTMLElement::insertedIntoDocument();
}
-String HTMLQuoteElement::cite() const
-{
- return getAttribute(citeAttr);
-}
-
-void HTMLQuoteElement::setCite(const String &value)
-{
- setAttribute(citeAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLQuoteElement.h b/WebCore/html/HTMLQuoteElement.h
index fa21d2d..df47e73 100644
--- a/WebCore/html/HTMLQuoteElement.h
+++ b/WebCore/html/HTMLQuoteElement.h
@@ -34,9 +34,6 @@ class HTMLQuoteElement : public HTMLElement {
public:
static PassRefPtr<HTMLQuoteElement> create(const QualifiedName&, Document*);
- String cite() const;
- void setCite(const String&);
-
private:
HTMLQuoteElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLScriptElement.cpp b/WebCore/html/HTMLScriptElement.cpp
index 48da4b9..9e776e6 100644
--- a/WebCore/html/HTMLScriptElement.cpp
+++ b/WebCore/html/HTMLScriptElement.cpp
@@ -74,6 +74,8 @@ void HTMLScriptElement::parseMappedAttribute(Attribute* attr)
setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr));
else if (attrName == onbeforeloadAttr)
setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr));
+ else if (attrName == onbeforeprocessAttr)
+ setAttributeEventListener(eventNames().beforeprocessEvent, createAttributeEventListener(this, attr));
else
HTMLElement::parseMappedAttribute(attr);
}
@@ -117,78 +119,11 @@ void HTMLScriptElement::setText(const String &value)
appendChild(document()->createTextNode(value.impl()), ec);
}
-String HTMLScriptElement::htmlFor() const
-{
- // DOM Level 1 says: reserved for future use.
- return String();
-}
-
-void HTMLScriptElement::setHtmlFor(const String&)
-{
- // DOM Level 1 says: reserved for future use.
-}
-
-String HTMLScriptElement::event() const
-{
- // DOM Level 1 says: reserved for future use.
- return String();
-}
-
-void HTMLScriptElement::setEvent(const String&)
-{
- // DOM Level 1 says: reserved for future use.
-}
-
-String HTMLScriptElement::charset() const
-{
- return charsetAttributeValue();
-}
-
-void HTMLScriptElement::setCharset(const String &value)
-{
- setAttribute(charsetAttr, value);
-}
-
-bool HTMLScriptElement::async() const
-{
- return asyncAttributeValue();
-}
-
-void HTMLScriptElement::setAsync(bool async)
-{
- setAttribute(asyncAttr, async ? "" : 0);
-}
-
-bool HTMLScriptElement::defer() const
-{
- return deferAttributeValue();
-}
-
-void HTMLScriptElement::setDefer(bool defer)
-{
- setAttribute(deferAttr, defer ? "" : 0);
-}
-
KURL HTMLScriptElement::src() const
{
return document()->completeURL(sourceAttributeValue());
}
-void HTMLScriptElement::setSrc(const String &value)
-{
- setAttribute(srcAttr, value);
-}
-
-String HTMLScriptElement::type() const
-{
- return typeAttributeValue();
-}
-
-void HTMLScriptElement::setType(const String &value)
-{
- setAttribute(typeAttr, value);
-}
-
String HTMLScriptElement::scriptCharset() const
{
return m_data.scriptCharset();
diff --git a/WebCore/html/HTMLScriptElement.h b/WebCore/html/HTMLScriptElement.h
index 3c8e8ce..b18278d 100644
--- a/WebCore/html/HTMLScriptElement.h
+++ b/WebCore/html/HTMLScriptElement.h
@@ -38,26 +38,7 @@ public:
String text() const;
void setText(const String&);
- String htmlFor() const;
- void setHtmlFor(const String&);
-
- String event() const;
- void setEvent(const String&);
-
- String charset() const;
- void setCharset(const String&);
-
- bool async() const;
- void setAsync(bool);
-
- bool defer() const;
- void setDefer(bool);
-
KURL src() const;
- void setSrc(const String&);
-
- String type() const;
- void setType(const String&);
virtual String scriptCharset() const;
diff --git a/WebCore/html/HTMLScriptRunner.cpp b/WebCore/html/HTMLScriptRunner.cpp
index ab35449..29790c0 100644
--- a/WebCore/html/HTMLScriptRunner.cpp
+++ b/WebCore/html/HTMLScriptRunner.cpp
@@ -74,7 +74,7 @@ HTMLScriptRunner::HTMLScriptRunner(Document* document, HTMLScriptRunnerHost* hos
HTMLScriptRunner::~HTMLScriptRunner()
{
// FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction?
- if (m_parsingBlockingScript.cachedScript && m_parsingBlockingScript.watchingForLoad())
+ if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
stopWatchingForLoad(m_parsingBlockingScript);
}
@@ -99,10 +99,10 @@ inline PassRefPtr<Event> createScriptErrorEvent()
ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript& script, bool& errorOccurred)
{
- if (script.cachedScript) {
- errorOccurred = script.cachedScript->errorOccurred();
- ASSERT(script.cachedScript->isLoaded());
- return ScriptSourceCode(script.cachedScript.get());
+ if (script.cachedScript()) {
+ errorOccurred = script.cachedScript()->errorOccurred();
+ ASSERT(script.cachedScript()->isLoaded());
+ return ScriptSourceCode(script.cachedScript());
}
errorOccurred = false;
return ScriptSourceCode(script.element->textContent(), documentURLForScriptExecution(m_document), script.startingLineNumber);
@@ -113,7 +113,7 @@ bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
m_hasScriptsWaitingForStylesheets = !m_document->haveStylesheetsLoaded();
if (m_hasScriptsWaitingForStylesheets)
return false;
- if (script.cachedScript && !script.cachedScript->isLoaded())
+ if (script.cachedScript() && !script.cachedScript()->isLoaded())
return false;
return true;
}
@@ -127,12 +127,11 @@ void HTMLScriptRunner::executePendingScript()
ScriptSourceCode sourceCode = sourceFromPendingScript(m_parsingBlockingScript, errorOccurred);
// Stop watching loads before executeScript to prevent recursion if the script reloads itself.
- if (m_parsingBlockingScript.cachedScript && m_parsingBlockingScript.watchingForLoad())
+ if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
stopWatchingForLoad(m_parsingBlockingScript);
// Clear the pending script before possible rentrancy from executeScript()
- RefPtr<Element> scriptElement = m_parsingBlockingScript.element.release();
- m_parsingBlockingScript = PendingScript();
+ RefPtr<Element> scriptElement = m_parsingBlockingScript.releaseElementAndClear();
{
NestScript nestingLevel(m_scriptNestingLevel, m_host->inputStream());
if (errorOccurred)
@@ -161,30 +160,18 @@ void HTMLScriptRunner::executeScript(Element* element, const ScriptSourceCode& s
m_document->frame()->script()->executeScript(sourceCode);
}
-bool HTMLScriptRunner::hasScriptsWaitingForLoad() const
-{
- // We're only actually waiting for a load. This allows us to ignore load
- // callbacks when CachedResource::addClient calls notifyFinished because
- // of a cache hit (not because of a load we were set up to wait for).
- return m_parsingBlockingScript.watchingForLoadState == PendingScript::WatchingForLoad;
-}
-
void HTMLScriptRunner::watchForLoad(PendingScript& pendingScript)
{
ASSERT(!pendingScript.watchingForLoad());
- // CachedResource::addClient will call notifyFinished if the load is already
- // complete. We set watchingForLoadState to RegisteringForWatch so that we
- // know to ignore any notifyFinished call during addClient.
- pendingScript.watchingForLoadState = PendingScript::RegisteringForWatch;
- m_host->watchForLoad(pendingScript.cachedScript.get());
- pendingScript.watchingForLoadState = PendingScript::WatchingForLoad;
+ m_host->watchForLoad(pendingScript.cachedScript());
+ pendingScript.setWatchingForLoad(true);
}
void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
{
ASSERT(pendingScript.watchingForLoad());
- m_host->stopWatchingForLoad(pendingScript.cachedScript.get());
- pendingScript.watchingForLoadState = PendingScript::NotWatchingForLoad;
+ m_host->stopWatchingForLoad(pendingScript.cachedScript());
+ pendingScript.setWatchingForLoad(false);
}
// This function should match 10.2.5.11 "An end tag whose tag name is 'script'"
@@ -224,14 +211,10 @@ bool HTMLScriptRunner::executeParsingBlockingScripts()
bool HTMLScriptRunner::executeScriptsWaitingForLoad(CachedResource* cachedScript)
{
- // Callers should check hasScriptsWaitingForLoad() before calling
- // to prevent parser or script re-entry during due to
- // CachedResource::addClient calling notifyFinished on cache-hits.
- ASSERT(hasScriptsWaitingForLoad());
ASSERT(!m_scriptNestingLevel);
ASSERT(haveParsingBlockingScript());
- ASSERT_UNUSED(cachedScript, m_parsingBlockingScript.cachedScript == cachedScript);
- ASSERT(m_parsingBlockingScript.cachedScript->isLoaded());
+ ASSERT_UNUSED(cachedScript, m_parsingBlockingScript.cachedScript() == cachedScript);
+ ASSERT(m_parsingBlockingScript.cachedScript()->isLoaded());
return executeParsingBlockingScripts();
}
@@ -262,16 +245,14 @@ void HTMLScriptRunner::requestScript(Element* script)
notImplemented(); // Dispatch error event.
return;
}
- m_parsingBlockingScript.cachedScript = cachedScript;
-
- // Always call watchForLoad, even if the script is already loaded.
- // CachedResource may purge its data if it has no clients, which would cause
- // later script execution to fail. watchForLoad sets m_parsingBlockingScript
- // to the RegisteringForWatch state so we know to ignore any
- // executeScriptsWaitingForLoad callbacks during the watchForLoad call.
- watchForLoad(m_parsingBlockingScript);
- // Callers will attempt to run the m_parsingBlockingScript if possible
- // before returning control to the parser.
+
+ m_parsingBlockingScript.setCachedScript(cachedScript);
+
+ // We only care about a load callback if cachedScript is not already
+ // in the cache. Callers will attempt to run the m_parsingBlockingScript
+ // if possible before returning control to the parser.
+ if (!m_parsingBlockingScript.cachedScript()->isLoaded())
+ watchForLoad(m_parsingBlockingScript);
}
// This method is meant to match the HTML5 definition of "running a script"
@@ -297,4 +278,34 @@ void HTMLScriptRunner::runScript(Element* script, int startingLineNumber)
}
}
+HTMLScriptRunner::PendingScript::~PendingScript()
+{
+ if (m_cachedScript)
+ m_cachedScript->removeClient(this);
+}
+
+PassRefPtr<Element> HTMLScriptRunner::PendingScript::releaseElementAndClear()
+{
+ setCachedScript(0);
+ startingLineNumber = 0;
+ m_watchingForLoad = false;
+ return element.release();
+}
+
+void HTMLScriptRunner::PendingScript::setCachedScript(CachedScript* cachedScript)
+{
+ if (m_cachedScript == cachedScript)
+ return;
+ if (m_cachedScript)
+ m_cachedScript->removeClient(this);
+ m_cachedScript = cachedScript;
+ if (m_cachedScript)
+ m_cachedScript->addClient(this);
+}
+
+CachedScript* HTMLScriptRunner::PendingScript::cachedScript() const
+{
+ return m_cachedScript.get();
+}
+
}
diff --git a/WebCore/html/HTMLScriptRunner.h b/WebCore/html/HTMLScriptRunner.h
index 7260007..f93ae10 100644
--- a/WebCore/html/HTMLScriptRunner.h
+++ b/WebCore/html/HTMLScriptRunner.h
@@ -49,42 +49,50 @@ public:
// Processes the passed in script and any pending scripts if possible.
bool execute(PassRefPtr<Element> scriptToProcess, int scriptStartLine);
- bool hasScriptsWaitingForLoad() const;
bool executeScriptsWaitingForLoad(CachedResource*);
-
bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; }
bool executeScriptsWaitingForStylesheets();
bool inScriptExecution() { return !!m_scriptNestingLevel; }
private:
- struct PendingScript {
- // This state controls whether we need to do anything with this script
- // when we get a executeScriptsWaitingForLoad callback.
- // We ignore callbacks during RegisteringForWatch.
- enum WatchingForLoadState {
- NotWatchingForLoad,
- RegisteringForWatch,
- WatchingForLoad,
- };
-
+ // A container for an external script which may be loaded and executed.
+ //
+ // A CachedResourceHandle alone does not prevent the underlying CachedResource
+ // from purging its data buffer. This class holds a dummy client open for its
+ // lifetime in order to guarantee that the data buffer will not be purged.
+ //
+ // FIXME: Finish turning this into a proper class.
+ class PendingScript : public CachedResourceClient, Noncopyable {
+ public:
PendingScript()
- : watchingForLoadState(NotWatchingForLoad)
- , startingLineNumber(0)
+ : startingLineNumber(0)
+ , m_watchingForLoad(false)
{
}
- bool watchingForLoad()
+ ~PendingScript();
+
+ PassRefPtr<Element> releaseElementAndClear();
+
+ bool watchingForLoad() const { return m_watchingForLoad; }
+ void setWatchingForLoad(bool b) { m_watchingForLoad = b; }
+
+ CachedScript* cachedScript() const;
+ void setCachedScript(CachedScript*);
+
+ virtual void notifyFinished(CachedResource*)
{
- return watchingForLoadState != NotWatchingForLoad;
}
RefPtr<Element> element;
- CachedResourceHandle<CachedScript> cachedScript;
- WatchingForLoadState watchingForLoadState;
int startingLineNumber; // Only used for inline script tags.
// HTML5 has an isReady parameter, however isReady ends up equivalent to
// m_document->haveStylesheetsLoaded() && cachedScript->isLoaded()
+
+ private:
+ bool m_watchingForLoad;
+ CachedResourceHandle<CachedScript> m_cachedScript;
};
Frame* frame() const;
diff --git a/WebCore/html/HTMLScriptRunnerHost.h b/WebCore/html/HTMLScriptRunnerHost.h
index 82ad70d..a129520 100644
--- a/WebCore/html/HTMLScriptRunnerHost.h
+++ b/WebCore/html/HTMLScriptRunnerHost.h
@@ -38,7 +38,7 @@ class HTMLScriptRunnerHost {
public:
virtual ~HTMLScriptRunnerHost() { }
- // Implementors must call cachedResource->addClient() immediately.
+ // Implementors should call cachedResource->addClient() here or soon after.
virtual void watchForLoad(CachedResource*) = 0;
// Implementors must call cachedResource->removeClient() immediately.
virtual void stopWatchingForLoad(CachedResource*) = 0;
diff --git a/WebCore/html/HTMLSelectElement.cpp b/WebCore/html/HTMLSelectElement.cpp
index 2dcac59..6ddcc2d 100644
--- a/WebCore/html/HTMLSelectElement.cpp
+++ b/WebCore/html/HTMLSelectElement.cpp
@@ -329,7 +329,7 @@ void HTMLSelectElement::dispatchBlurEvent()
void HTMLSelectElement::defaultEventHandler(Event* event)
{
- SelectElement::defaultEventHandler(m_data, this, event);
+ SelectElement::defaultEventHandler(m_data, this, event, form());
if (event->defaultHandled())
return;
HTMLFormControlElementWithState::defaultEventHandler(event);
diff --git a/WebCore/html/HTMLSelectElement.idl b/WebCore/html/HTMLSelectElement.idl
index 3303272..2e53bca 100644
--- a/WebCore/html/HTMLSelectElement.idl
+++ b/WebCore/html/HTMLSelectElement.idl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -24,51 +24,48 @@ module html {
HasIndexGetter,
HasCustomIndexSetter
] HTMLSelectElement : HTMLElement {
-
- readonly attribute DOMString type;
- attribute long selectedIndex;
- attribute [ConvertNullToNullString] DOMString value;
+ readonly attribute DOMString type;
+ attribute long selectedIndex;
+ attribute [ConvertNullToNullString] DOMString value;
// Modified in DOM Level 2:
#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
- readonly attribute long length;
+ readonly attribute long length;
#else
- attribute unsigned long length
- setter raises (DOMException);
+ attribute unsigned long length setter raises (DOMException);
#endif
readonly attribute HTMLFormElement form;
- readonly attribute ValidityState validity;
- readonly attribute boolean willValidate;
- readonly attribute DOMString validationMessage;
- boolean checkValidity();
- void setCustomValidity(in [ConvertUndefinedOrNullToNullString] DOMString error);
+ readonly attribute ValidityState validity;
+ readonly attribute boolean willValidate;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ void setCustomValidity(in [ConvertUndefinedOrNullToNullString] DOMString error);
// Modified in DOM Level 2:
readonly attribute HTMLOptionsCollection options;
- attribute boolean disabled;
- attribute boolean autofocus;
- attribute boolean multiple;
- attribute [ConvertNullToNullString] DOMString name;
- attribute long size;
+ attribute [Reflect] boolean disabled;
+ attribute [Reflect] boolean autofocus;
+ attribute boolean multiple;
+ attribute [ConvertNullToNullString] DOMString name;
+ attribute long size;
- [OldStyleObjC] void add(in HTMLElement element,
- in HTMLElement before)
- raises(DOMException);
+ [OldStyleObjC] void add(in HTMLElement element, in HTMLElement before) raises(DOMException);
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
- // In JS, we support both options index and options object parameters - this cannot be autogenerated now.
- [Custom] void remove(/* 1 */);
+ // In JavaScript, we support both option index and option object parameters.
+ // As of this writing this cannot be auto-generated.
+ [Custom] void remove(/* indexOrOption */);
#else
- void remove(in long index);
+ void remove(in long index);
#endif
// These methods are not in DOM Level 2 IDL, but are mentioned in the standard:
// "The contained options can be directly accessed through the select element as a collection."
Node item(in [IsIndex] unsigned long index);
Node namedItem(in DOMString name);
- readonly attribute NodeList labels;
+ readonly attribute NodeList labels;
};
}
diff --git a/WebCore/html/HTMLStyleElement.cpp b/WebCore/html/HTMLStyleElement.cpp
index a8ea42e..79bafe6 100644
--- a/WebCore/html/HTMLStyleElement.cpp
+++ b/WebCore/html/HTMLStyleElement.cpp
@@ -27,6 +27,7 @@
#include "Attribute.h"
#include "Document.h"
#include "HTMLNames.h"
+#include "ScriptEventListener.h"
namespace WebCore {
@@ -45,14 +46,13 @@ PassRefPtr<HTMLStyleElement> HTMLStyleElement::create(const QualifiedName& tagNa
return adoptRef(new HTMLStyleElement(tagName, document, createdByParser));
}
-// other stuff...
void HTMLStyleElement::parseMappedAttribute(Attribute* attr)
{
- if (attr->name() == mediaAttr)
- m_media = attr->value().string().lower();
- else if (attr->name() == titleAttr && m_sheet)
+ if (attr->name() == titleAttr && m_sheet)
m_sheet->setTitle(attr->value());
- else
+ else if (attr->name() == onbeforeprocessAttr)
+ setAttributeEventListener(eventNames().beforeprocessEvent, createAttributeEventListener(this, attr));
+ else
HTMLElement::parseMappedAttribute(attr);
}
@@ -110,36 +110,16 @@ bool HTMLStyleElement::sheetLoaded()
return false;
}
-bool HTMLStyleElement::disabled() const
-{
- return !getAttribute(disabledAttr).isNull();
-}
-
-void HTMLStyleElement::setDisabled(bool disabled)
-{
- setAttribute(disabledAttr, disabled ? "" : 0);
-}
-
const AtomicString& HTMLStyleElement::media() const
{
return getAttribute(mediaAttr);
}
-void HTMLStyleElement::setMedia(const AtomicString &value)
-{
- setAttribute(mediaAttr, value);
-}
-
const AtomicString& HTMLStyleElement::type() const
{
return getAttribute(typeAttr);
}
-void HTMLStyleElement::setType(const AtomicString &value)
-{
- setAttribute(typeAttr, value);
-}
-
void HTMLStyleElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
{
HTMLElement::addSubresourceAttributeURLs(urls);
diff --git a/WebCore/html/HTMLStyleElement.h b/WebCore/html/HTMLStyleElement.h
index 58dce14..0f8a83b 100644
--- a/WebCore/html/HTMLStyleElement.h
+++ b/WebCore/html/HTMLStyleElement.h
@@ -19,6 +19,7 @@
* Boston, MA 02110-1301, USA.
*
*/
+
#ifndef HTMLStyleElement_h
#define HTMLStyleElement_h
@@ -29,17 +30,10 @@ namespace WebCore {
class StyleSheet;
-class HTMLStyleElement : public HTMLElement, public StyleElement {
+class HTMLStyleElement : public HTMLElement, private StyleElement {
public:
static PassRefPtr<HTMLStyleElement> create(const QualifiedName&, Document*, bool createdByParser);
- bool disabled() const;
- void setDisabled(bool);
-
- virtual const AtomicString& media() const;
- void setMedia(const AtomicString&);
-
- virtual const AtomicString& type() const;
void setType(const AtomicString&);
StyleSheet* sheet();
@@ -66,7 +60,9 @@ private:
virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
- String m_media;
+ virtual const AtomicString& media() const;
+ virtual const AtomicString& type() const;
+
bool m_loading;
bool m_createdByParser;
};
diff --git a/WebCore/html/HTMLStyleElement.idl b/WebCore/html/HTMLStyleElement.idl
index c98629c..29a8924 100644
--- a/WebCore/html/HTMLStyleElement.idl
+++ b/WebCore/html/HTMLStyleElement.idl
@@ -21,7 +21,7 @@
module html {
interface HTMLStyleElement : HTMLElement {
- attribute boolean disabled;
+ attribute [Reflect] boolean disabled;
attribute [Reflect] DOMString media;
attribute [Reflect] DOMString type;
diff --git a/WebCore/html/HTMLTableCaptionElement.cpp b/WebCore/html/HTMLTableCaptionElement.cpp
index 40f2ab6..b726df6 100644
--- a/WebCore/html/HTMLTableCaptionElement.cpp
+++ b/WebCore/html/HTMLTableCaptionElement.cpp
@@ -63,14 +63,4 @@ void HTMLTableCaptionElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-String HTMLTableCaptionElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLTableCaptionElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLTableCaptionElement.h b/WebCore/html/HTMLTableCaptionElement.h
index e97b03f..d19c7ce 100644
--- a/WebCore/html/HTMLTableCaptionElement.h
+++ b/WebCore/html/HTMLTableCaptionElement.h
@@ -34,9 +34,6 @@ class HTMLTableCaptionElement : public HTMLTablePartElement {
public:
static PassRefPtr<HTMLTableCaptionElement> create(const QualifiedName&, Document*);
- String align() const;
- void setAlign(const String&);
-
private:
HTMLTableCaptionElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLTableCellElement.cpp b/WebCore/html/HTMLTableCellElement.cpp
index e102d0b..d90b125 100644
--- a/WebCore/html/HTMLTableCellElement.cpp
+++ b/WebCore/html/HTMLTableCellElement.cpp
@@ -141,61 +141,11 @@ String HTMLTableCellElement::abbr() const
return getAttribute(abbrAttr);
}
-void HTMLTableCellElement::setAbbr(const String &value)
-{
- setAttribute(abbrAttr, value);
-}
-
-String HTMLTableCellElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLTableCellElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
String HTMLTableCellElement::axis() const
{
return getAttribute(axisAttr);
}
-void HTMLTableCellElement::setAxis(const String &value)
-{
- setAttribute(axisAttr, value);
-}
-
-String HTMLTableCellElement::bgColor() const
-{
- return getAttribute(bgcolorAttr);
-}
-
-void HTMLTableCellElement::setBgColor(const String &value)
-{
- setAttribute(bgcolorAttr, value);
-}
-
-String HTMLTableCellElement::ch() const
-{
- return getAttribute(charAttr);
-}
-
-void HTMLTableCellElement::setCh(const String &value)
-{
- setAttribute(charAttr, value);
-}
-
-String HTMLTableCellElement::chOff() const
-{
- return getAttribute(charoffAttr);
-}
-
-void HTMLTableCellElement::setChOff(const String &value)
-{
- setAttribute(charoffAttr, value);
-}
-
void HTMLTableCellElement::setColSpan(int n)
{
setAttribute(colspanAttr, String::number(n));
@@ -206,31 +156,6 @@ String HTMLTableCellElement::headers() const
return getAttribute(headersAttr);
}
-void HTMLTableCellElement::setHeaders(const String &value)
-{
- setAttribute(headersAttr, value);
-}
-
-String HTMLTableCellElement::height() const
-{
- return getAttribute(heightAttr);
-}
-
-void HTMLTableCellElement::setHeight(const String &value)
-{
- setAttribute(heightAttr, value);
-}
-
-bool HTMLTableCellElement::noWrap() const
-{
- return !getAttribute(nowrapAttr).isNull();
-}
-
-void HTMLTableCellElement::setNoWrap(bool b)
-{
- setAttribute(nowrapAttr, b ? "" : 0);
-}
-
void HTMLTableCellElement::setRowSpan(int n)
{
setAttribute(rowspanAttr, String::number(n));
@@ -241,31 +166,6 @@ String HTMLTableCellElement::scope() const
return getAttribute(scopeAttr);
}
-void HTMLTableCellElement::setScope(const String &value)
-{
- setAttribute(scopeAttr, value);
-}
-
-String HTMLTableCellElement::vAlign() const
-{
- return getAttribute(valignAttr);
-}
-
-void HTMLTableCellElement::setVAlign(const String &value)
-{
- setAttribute(valignAttr, value);
-}
-
-String HTMLTableCellElement::width() const
-{
- return getAttribute(widthAttr);
-}
-
-void HTMLTableCellElement::setWidth(const String &value)
-{
- setAttribute(widthAttr, value);
-}
-
void HTMLTableCellElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
{
HTMLTablePartElement::addSubresourceAttributeURLs(urls);
diff --git a/WebCore/html/HTMLTableCellElement.h b/WebCore/html/HTMLTableCellElement.h
index 6a514ec..a70bdcd 100644
--- a/WebCore/html/HTMLTableCellElement.h
+++ b/WebCore/html/HTMLTableCellElement.h
@@ -47,44 +47,11 @@ public:
void setCellIndex(int);
String abbr() const;
- void setAbbr(const String&);
-
- String align() const;
- void setAlign(const String&);
-
String axis() const;
- void setAxis(const String&);
-
- String bgColor() const;
- void setBgColor(const String&);
-
- String ch() const;
- void setCh(const String&);
-
- String chOff() const;
- void setChOff(const String&);
-
void setColSpan(int);
-
String headers() const;
- void setHeaders(const String&);
-
- String height() const;
- void setHeight(const String&);
-
- bool noWrap() const;
- void setNoWrap(bool);
-
void setRowSpan(int);
-
String scope() const;
- void setScope(const String&);
-
- String vAlign() const;
- void setVAlign(const String&);
-
- String width() const;
- void setWidth(const String&);
private:
HTMLTableCellElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLTableCellElement.idl b/WebCore/html/HTMLTableCellElement.idl
index 037581f..ae286f4 100644
--- a/WebCore/html/HTMLTableCellElement.idl
+++ b/WebCore/html/HTMLTableCellElement.idl
@@ -31,7 +31,7 @@ module html {
attribute long colSpan;
attribute [Reflect] DOMString headers;
attribute [Reflect] DOMString height;
- attribute boolean noWrap;
+ attribute [Reflect] boolean noWrap;
attribute long rowSpan;
attribute [Reflect] DOMString scope;
attribute [Reflect] DOMString vAlign;
diff --git a/WebCore/html/HTMLTableColElement.cpp b/WebCore/html/HTMLTableColElement.cpp
index 5269aaa..6c2f1fe 100644
--- a/WebCore/html/HTMLTableColElement.cpp
+++ b/WebCore/html/HTMLTableColElement.cpp
@@ -110,59 +110,14 @@ void HTMLTableColElement::additionalAttributeStyleDecls(Vector<CSSMutableStyleDe
static_cast<HTMLTableElement*>(p)->addSharedGroupDecls(false, results);
}
-String HTMLTableColElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLTableColElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
-String HTMLTableColElement::ch() const
-{
- return getAttribute(charAttr);
-}
-
-void HTMLTableColElement::setCh(const String &value)
-{
- setAttribute(charAttr, value);
-}
-
-String HTMLTableColElement::chOff() const
-{
- return getAttribute(charoffAttr);
-}
-
-void HTMLTableColElement::setChOff(const String &value)
-{
- setAttribute(charoffAttr, value);
-}
-
void HTMLTableColElement::setSpan(int n)
{
setAttribute(spanAttr, String::number(n));
}
-String HTMLTableColElement::vAlign() const
-{
- return getAttribute(valignAttr);
-}
-
-void HTMLTableColElement::setVAlign(const String &value)
-{
- setAttribute(valignAttr, value);
-}
-
String HTMLTableColElement::width() const
{
return getAttribute(widthAttr);
}
-void HTMLTableColElement::setWidth(const String &value)
-{
- setAttribute(widthAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLTableColElement.h b/WebCore/html/HTMLTableColElement.h
index 07b0ae8..4a219c1 100644
--- a/WebCore/html/HTMLTableColElement.h
+++ b/WebCore/html/HTMLTableColElement.h
@@ -35,23 +35,9 @@ public:
static PassRefPtr<HTMLTableColElement> create(const QualifiedName& tagName, Document*);
int span() const { return m_span; }
-
- String align() const;
- void setAlign(const String&);
-
- String ch() const;
- void setCh(const String&);
-
- String chOff() const;
- void setChOff(const String&);
-
void setSpan(int);
- String vAlign() const;
- void setVAlign(const String&);
-
String width() const;
- void setWidth(const String&);
private:
HTMLTableColElement(const QualifiedName& tagName, Document*);
diff --git a/WebCore/html/HTMLTableElement.cpp b/WebCore/html/HTMLTableElement.cpp
index 0cb33e1..56cb32a 100644
--- a/WebCore/html/HTMLTableElement.cpp
+++ b/WebCore/html/HTMLTableElement.cpp
@@ -251,18 +251,18 @@ void HTMLTableElement::deleteRow(int index, ExceptionCode& ec)
row->remove(ec);
}
-ContainerNode* HTMLTableElement::addChild(PassRefPtr<Node> child)
+ContainerNode* HTMLTableElement::legacyParserAddChild(PassRefPtr<Node> child)
{
if (child->hasTagName(formTag)) {
// First add the child.
- HTMLElement::addChild(child);
+ HTMLElement::legacyParserAddChild(child);
// Now simply return ourselves as the container to insert into.
// This has the effect of demoting the form to a leaf and moving it safely out of the way.
return this;
}
- return HTMLElement::addChild(child.get());
+ return HTMLElement::legacyParserAddChild(child.get());
}
bool HTMLTableElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
@@ -669,96 +669,16 @@ PassRefPtr<HTMLCollection> HTMLTableElement::tBodies()
return HTMLCollection::create(this, TableTBodies);
}
-String HTMLTableElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLTableElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
-String HTMLTableElement::bgColor() const
-{
- return getAttribute(bgcolorAttr);
-}
-
-void HTMLTableElement::setBgColor(const String &value)
-{
- setAttribute(bgcolorAttr, value);
-}
-
-String HTMLTableElement::border() const
-{
- return getAttribute(borderAttr);
-}
-
-void HTMLTableElement::setBorder(const String &value)
-{
- setAttribute(borderAttr, value);
-}
-
-String HTMLTableElement::cellPadding() const
-{
- return getAttribute(cellpaddingAttr);
-}
-
-void HTMLTableElement::setCellPadding(const String &value)
-{
- setAttribute(cellpaddingAttr, value);
-}
-
-String HTMLTableElement::cellSpacing() const
-{
- return getAttribute(cellspacingAttr);
-}
-
-void HTMLTableElement::setCellSpacing(const String &value)
-{
- setAttribute(cellspacingAttr, value);
-}
-
-String HTMLTableElement::frame() const
-{
- return getAttribute(frameAttr);
-}
-
-void HTMLTableElement::setFrame(const String &value)
-{
- setAttribute(frameAttr, value);
-}
-
String HTMLTableElement::rules() const
{
return getAttribute(rulesAttr);
}
-void HTMLTableElement::setRules(const String &value)
-{
- setAttribute(rulesAttr, value);
-}
-
String HTMLTableElement::summary() const
{
return getAttribute(summaryAttr);
}
-void HTMLTableElement::setSummary(const String &value)
-{
- setAttribute(summaryAttr, value);
-}
-
-String HTMLTableElement::width() const
-{
- return getAttribute(widthAttr);
-}
-
-void HTMLTableElement::setWidth(const String &value)
-{
- setAttribute(widthAttr, value);
-}
-
void HTMLTableElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
{
HTMLElement::addSubresourceAttributeURLs(urls);
diff --git a/WebCore/html/HTMLTableElement.h b/WebCore/html/HTMLTableElement.h
index 0189ce4..c48fee5 100644
--- a/WebCore/html/HTMLTableElement.h
+++ b/WebCore/html/HTMLTableElement.h
@@ -60,34 +60,10 @@ public:
PassRefPtr<HTMLCollection> rows();
PassRefPtr<HTMLCollection> tBodies();
- String align() const;
- void setAlign(const String&);
-
- String bgColor() const;
- void setBgColor(const String&);
-
- String border() const;
- void setBorder(const String&);
-
- String cellPadding() const;
- void setCellPadding(const String&);
-
- String cellSpacing() const;
- void setCellSpacing(const String&);
-
- String frame() const;
- void setFrame(const String&);
-
String rules() const;
- void setRules(const String&);
-
String summary() const;
- void setSummary(const String&);
-
- String width() const;
- void setWidth(const String&);
- virtual ContainerNode* addChild(PassRefPtr<Node>);
+ virtual ContainerNode* legacyParserAddChild(PassRefPtr<Node>);
virtual void attach();
diff --git a/WebCore/html/HTMLTableRowElement.cpp b/WebCore/html/HTMLTableRowElement.cpp
index cba2d48..0bafb12 100644
--- a/WebCore/html/HTMLTableRowElement.cpp
+++ b/WebCore/html/HTMLTableRowElement.cpp
@@ -62,18 +62,18 @@ bool HTMLTableRowElement::checkDTD(const Node* newChild)
newChild->hasTagName(formTag) || newChild->hasTagName(scriptTag);
}
-ContainerNode* HTMLTableRowElement::addChild(PassRefPtr<Node> child)
+ContainerNode* HTMLTableRowElement::legacyParserAddChild(PassRefPtr<Node> child)
{
if (child->hasTagName(formTag)) {
// First add the child.
- HTMLTablePartElement::addChild(child);
+ HTMLTablePartElement::legacyParserAddChild(child);
// Now simply return ourselves as the container to insert into.
// This has the effect of demoting the form to a leaf and moving it safely out of the way.
return this;
}
- return HTMLTablePartElement::addChild(child);
+ return HTMLTablePartElement::legacyParserAddChild(child);
}
int HTMLTableRowElement::rowIndex() const
@@ -181,59 +181,9 @@ PassRefPtr<HTMLCollection> HTMLTableRowElement::cells()
return HTMLCollection::create(this, TRCells);
}
-void HTMLTableRowElement::setCells(HTMLCollection *, ExceptionCode& ec)
+void HTMLTableRowElement::setCells(HTMLCollection*, ExceptionCode& ec)
{
ec = NO_MODIFICATION_ALLOWED_ERR;
}
-String HTMLTableRowElement::align() const
-{
- return getAttribute(alignAttr);
-}
-
-void HTMLTableRowElement::setAlign(const String &value)
-{
- setAttribute(alignAttr, value);
-}
-
-String HTMLTableRowElement::bgColor() const
-{
- return getAttribute(bgcolorAttr);
-}
-
-void HTMLTableRowElement::setBgColor(const String &value)
-{
- setAttribute(bgcolorAttr, value);
-}
-
-String HTMLTableRowElement::ch() const
-{
- return getAttribute(charAttr);
-}
-
-void HTMLTableRowElement::setCh(const String &value)
-{
- setAttribute(charAttr, value);
-}
-
-String HTMLTableRowElement::chOff() const
-{
- return getAttribute(charoffAttr);
-}
-
-void HTMLTableRowElement::setChOff(const String &value)
-{
- setAttribute(charoffAttr, value);
-}
-
-String HTMLTableRowElement::vAlign() const
-{
- return getAttribute(valignAttr);
-}
-
-void HTMLTableRowElement::setVAlign(const String &value)
-{
- setAttribute(valignAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLTableRowElement.h b/WebCore/html/HTMLTableRowElement.h
index b47edc2..825d763 100644
--- a/WebCore/html/HTMLTableRowElement.h
+++ b/WebCore/html/HTMLTableRowElement.h
@@ -35,7 +35,7 @@ public:
static PassRefPtr<HTMLTableRowElement> create(Document*);
static PassRefPtr<HTMLTableRowElement> create(const QualifiedName&, Document*);
- virtual ContainerNode* addChild(PassRefPtr<Node>);
+ virtual ContainerNode* legacyParserAddChild(PassRefPtr<Node>);
int rowIndex() const;
void setRowIndex(int);
@@ -49,21 +49,6 @@ public:
PassRefPtr<HTMLCollection> cells();
void setCells(HTMLCollection *, ExceptionCode&);
- String align() const;
- void setAlign(const String&);
-
- String bgColor() const;
- void setBgColor(const String&);
-
- String ch() const;
- void setCh(const String&);
-
- String chOff() const;
- void setChOff(const String&);
-
- String vAlign() const;
- void setVAlign(const String&);
-
private:
HTMLTableRowElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLTableSectionElement.cpp b/WebCore/html/HTMLTableSectionElement.cpp
index 122af8a..93bfef2 100644
--- a/WebCore/html/HTMLTableSectionElement.cpp
+++ b/WebCore/html/HTMLTableSectionElement.cpp
@@ -55,18 +55,18 @@ bool HTMLTableSectionElement::checkDTD(const Node* newChild)
newChild->hasTagName(scriptTag);
}
-ContainerNode* HTMLTableSectionElement::addChild(PassRefPtr<Node> child)
+ContainerNode* HTMLTableSectionElement::legacyParserAddChild(PassRefPtr<Node> child)
{
if (child->hasTagName(formTag)) {
// First add the child.
- HTMLTablePartElement::addChild(child);
+ HTMLTablePartElement::legacyParserAddChild(child);
// Now simply return ourselves as the container to insert into.
// This has the effect of demoting the form to a leaf and moving it safely out of the way.
return this;
}
- return HTMLTablePartElement::addChild(child);
+ return HTMLTablePartElement::legacyParserAddChild(child);
}
// used by table row groups to share style decls created by the enclosing table.
diff --git a/WebCore/html/HTMLTableSectionElement.h b/WebCore/html/HTMLTableSectionElement.h
index f7c1d8a..3e356da 100644
--- a/WebCore/html/HTMLTableSectionElement.h
+++ b/WebCore/html/HTMLTableSectionElement.h
@@ -34,7 +34,7 @@ class HTMLTableSectionElement : public HTMLTablePartElement {
public:
static PassRefPtr<HTMLTableSectionElement> create(const QualifiedName&, Document*);
- virtual ContainerNode* addChild(PassRefPtr<Node>);
+ virtual ContainerNode* legacyParserAddChild(PassRefPtr<Node>);
PassRefPtr<HTMLElement> insertRow(int index, ExceptionCode&);
void deleteRow(int index, ExceptionCode&);
diff --git a/WebCore/html/HTMLTagNames.in b/WebCore/html/HTMLTagNames.in
index 8e67cba..9c66a95 100644
--- a/WebCore/html/HTMLTagNames.in
+++ b/WebCore/html/HTMLTagNames.in
@@ -74,6 +74,7 @@ li interfaceName=HTMLLIElement
link constructorNeedsCreatedByParser
listing interfaceName=HTMLPreElement
map
+mark interfaceName=HTMLElement
marquee
menu
meta
@@ -131,3 +132,4 @@ noscript interfaceName=HTMLNoScriptElement
#else
noscript interfaceName=HTMLElement
#endif
+
diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp
index 47acc54..b528c19 100644
--- a/WebCore/html/HTMLTextAreaElement.cpp
+++ b/WebCore/html/HTMLTextAreaElement.cpp
@@ -407,16 +407,6 @@ void HTMLTextAreaElement::accessKeyAction(bool)
focus();
}
-const AtomicString& HTMLTextAreaElement::accessKey() const
-{
- return getAttribute(accesskeyAttr);
-}
-
-void HTMLTextAreaElement::setAccessKey(const String& value)
-{
- setAttribute(accesskeyAttr, value);
-}
-
void HTMLTextAreaElement::setCols(int cols)
{
setAttribute(colsAttr, String::number(cols));
diff --git a/WebCore/html/HTMLTextAreaElement.h b/WebCore/html/HTMLTextAreaElement.h
index af233ae..43fe493 100644
--- a/WebCore/html/HTMLTextAreaElement.h
+++ b/WebCore/html/HTMLTextAreaElement.h
@@ -51,9 +51,6 @@ public:
void rendererWillBeDestroyed();
- const AtomicString& accessKey() const;
- void setAccessKey(const String&);
-
void setCols(int);
void setRows(int);
diff --git a/WebCore/html/HTMLTextAreaElement.idl b/WebCore/html/HTMLTextAreaElement.idl
index 4229450..0f0c9fc 100644
--- a/WebCore/html/HTMLTextAreaElement.idl
+++ b/WebCore/html/HTMLTextAreaElement.idl
@@ -26,13 +26,13 @@ module html {
readonly attribute ValidityState validity;
attribute [Reflect] DOMString accessKey;
attribute long cols;
- attribute boolean disabled;
- attribute boolean autofocus;
+ attribute [Reflect] boolean disabled;
+ attribute [Reflect] boolean autofocus;
attribute long maxLength setter raises(DOMException);
attribute [ConvertNullToNullString] DOMString name;
attribute [Reflect] DOMString placeholder;
- attribute boolean readOnly;
- attribute boolean required;
+ attribute [Reflect] boolean readOnly;
+ attribute [Reflect] boolean required;
attribute long rows;
readonly attribute DOMString type;
attribute [ConvertNullToNullString] DOMString value;
diff --git a/WebCore/html/HTMLToken.h b/WebCore/html/HTMLToken.h
index 321b103..741f5cd 100644
--- a/WebCore/html/HTMLToken.h
+++ b/WebCore/html/HTMLToken.h
@@ -60,8 +60,15 @@ public:
m_type = Uninitialized;
}
+ void makeEndOfFile()
+ {
+ ASSERT(m_type == Uninitialized);
+ m_type = EndOfFile;
+ }
+
void beginStartTag(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == Uninitialized);
m_type = StartTag;
m_data.clear();
@@ -87,6 +94,7 @@ public:
void beginCharacter(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == Uninitialized);
m_type = Character;
m_data.clear();
@@ -110,12 +118,14 @@ public:
void beginDOCTYPE(UChar character)
{
+ ASSERT(character);
beginDOCTYPE();
m_data.append(character);
}
void appendToName(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == StartTag || m_type == EndTag || m_type == DOCTYPE);
m_data.append(character);
}
@@ -129,6 +139,7 @@ public:
void appendToComment(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == Comment);
m_data.append(character);
}
@@ -142,12 +153,14 @@ public:
void appendToAttributeName(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == StartTag || m_type == EndTag);
m_currentAttribute->m_name.append(character);
}
void appendToAttributeValue(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == StartTag || m_type == EndTag);
m_currentAttribute->m_value.append(character);
}
@@ -226,6 +239,7 @@ public:
void appendToPublicIdentifier(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == DOCTYPE);
ASSERT(m_doctypeData->m_hasPublicIdentifier);
m_doctypeData->m_publicIdentifier.append(character);
@@ -233,6 +247,7 @@ public:
void appendToSystemIdentifier(UChar character)
{
+ ASSERT(character);
ASSERT(m_type == DOCTYPE);
ASSERT(m_doctypeData->m_hasSystemIdentifier);
m_doctypeData->m_systemIdentifier.append(character);
@@ -336,6 +351,12 @@ public:
return m_name;
}
+ void setName(const AtomicString& name)
+ {
+ ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag || m_type == HTMLToken::DOCTYPE);
+ m_name = name;
+ }
+
bool selfClosing() const
{
ASSERT(m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag);
@@ -361,14 +382,14 @@ public:
}
// FIXME: Distinguish between a missing public identifer and an empty one.
- const WTF::Vector<UChar>& publicIdentifier() const
+ WTF::Vector<UChar>& publicIdentifier() const
{
ASSERT(m_type == HTMLToken::DOCTYPE);
return m_doctypeData->m_publicIdentifier;
}
// FIXME: Distinguish between a missing system identifer and an empty one.
- const WTF::Vector<UChar>& systemIdentifier() const
+ WTF::Vector<UChar>& systemIdentifier() const
{
ASSERT(m_type == HTMLToken::DOCTYPE);
return m_doctypeData->m_systemIdentifier;
diff --git a/WebCore/html/HTMLTokenizer.cpp b/WebCore/html/HTMLTokenizer.cpp
index 84894ff..54e604a 100644
--- a/WebCore/html/HTMLTokenizer.cpp
+++ b/WebCore/html/HTMLTokenizer.cpp
@@ -33,6 +33,7 @@
#include "HTMLToken.h"
#include "HTMLNames.h"
#include "NotImplemented.h"
+#include <wtf/ASCIICType.h>
#include <wtf/CurrentTime.h>
#include <wtf/UnusedParam.h>
#include <wtf/text/CString.h>
@@ -44,15 +45,22 @@ namespace WebCore {
using namespace HTMLNames;
+const UChar HTMLTokenizer::InputStreamPreprocessor::endOfFileMarker = 0;
+
namespace {
inline UChar toLowerCase(UChar cc)
{
- ASSERT(cc >= 'A' && cc <= 'Z');
+ ASSERT(isASCIIUpper(cc));
const int lowerCaseOffset = 0x20;
return cc + lowerCaseOffset;
}
+inline bool isTokenizerWhitespace(UChar cc)
+{
+ return cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ';
+}
+
inline void advanceStringAndASSERTIgnoringCase(SegmentedString& source, const char* expectedCharacters)
{
while (*expectedCharacters)
@@ -113,9 +121,9 @@ inline bool HTMLTokenizer::processEntity(SegmentedString& source)
if (notEnoughCharacters)
return false;
if (!value)
- emitCharacter('&');
+ bufferCharacter('&');
else
- emitCodePoint(value);
+ bufferCodePoint(value);
return true;
}
@@ -160,33 +168,63 @@ inline bool HTMLTokenizer::processEntity(SegmentedString& source)
goto stateName; \
} while (false)
-// We use this macro when the HTML5 spec says "Emit the current <mumble>
+
+inline void HTMLTokenizer::saveEndTagNameIfNeeded()
+{
+ ASSERT(m_token->type() != HTMLToken::Uninitialized);
+ if (m_token->type() == HTMLToken::StartTag)
+ m_appropriateEndTagName = m_token->name();
+}
+
+// We use this function when the HTML5 spec says "Emit the current <mumble>
// token. Switch to the <mumble> state." We use the word "resume" instead of
// switch to indicate that this macro actually returns and that we'll end up
// in the state when we "resume" (i.e., are called again).
-#define EMIT_AND_RESUME_IN(stateName) \
- do { \
- m_state = stateName; \
- source.advance(m_lineNumber); \
- emitCurrentToken(); \
- return true; \
- } while (false)
+bool HTMLTokenizer::emitAndResumeIn(SegmentedString& source, State state)
+{
+ m_state = state;
+ source.advance(m_lineNumber);
+ saveEndTagNameIfNeeded();
+ return true;
+}
-#define _FLUSH_BUFFERED_END_TAG() \
- do { \
- ASSERT(m_token->type() == HTMLToken::Character || \
- m_token->type() == HTMLToken::Uninitialized); \
- source.advance(m_lineNumber); \
- if (m_token->type() == HTMLToken::Character) \
- return true; \
- m_token->beginEndTag(m_bufferedEndTagName); \
- m_bufferedEndTagName.clear(); \
- } while (false)
+// Identical to emitAndResumeIn, except does not advance.
+bool HTMLTokenizer::emitAndReconsumeIn(SegmentedString&, State state)
+{
+ m_state = state;
+ saveEndTagNameIfNeeded();
+ return true;
+}
+
+// Used to emit the EndOfFile token.
+// Check if we have buffered characters to emit first before emitting the EOF.
+bool HTMLTokenizer::emitEndOfFile(SegmentedString& source)
+{
+ if (shouldEmitBufferedCharacterToken(source))
+ return true;
+ m_state = DataState;
+ source.advance(m_lineNumber);
+ m_token->clear();
+ m_token->makeEndOfFile();
+ return true;
+}
+
+bool HTMLTokenizer::flushBufferedEndTag(SegmentedString& source)
+{
+ ASSERT(m_token->type() == HTMLToken::Character || m_token->type() == HTMLToken::Uninitialized);
+ source.advance(m_lineNumber);
+ if (m_token->type() == HTMLToken::Character)
+ return true;
+ m_token->beginEndTag(m_bufferedEndTagName);
+ m_bufferedEndTagName.clear();
+ return false;
+}
#define FLUSH_AND_ADVANCE_TO(stateName) \
do { \
m_state = stateName; \
- _FLUSH_BUFFERED_END_TAG(); \
+ if (flushBufferedEndTag(source)) \
+ return true; \
if (source.isEmpty() \
|| !m_inputStreamPreprocessor.peek(source, m_lineNumber)) \
return shouldEmitBufferedCharacterToken(source); \
@@ -194,12 +232,12 @@ inline bool HTMLTokenizer::processEntity(SegmentedString& source)
goto stateName; \
} while (false)
-#define FLUSH_EMIT_AND_RESUME_IN(stateName) \
- do { \
- m_state = stateName; \
- _FLUSH_BUFFERED_END_TAG(); \
- return true; \
- } while (false)
+bool HTMLTokenizer::flushEmitAndResumeIn(SegmentedString& source, State state)
+{
+ m_state = state;
+ flushBufferedEndTag(source);
+ return true;
+}
bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
{
@@ -252,8 +290,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
return true;
}
ADVANCE_TO(TagOpenState);
- } else {
- emitCharacter(cc);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitEndOfFile(source);
+ else {
+ bufferCharacter(cc);
ADVANCE_TO(DataState);
}
}
@@ -271,8 +311,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
ADVANCE_TO(CharacterReferenceInRCDATAState);
else if (cc == '<')
ADVANCE_TO(RCDATALessThanSignState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitEndOfFile(source);
else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(RCDATAState);
}
}
@@ -288,8 +330,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
BEGIN_STATE(RAWTEXTState) {
if (cc == '<')
ADVANCE_TO(RAWTEXTLessThanSignState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitEndOfFile(source);
else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(RAWTEXTState);
}
}
@@ -298,15 +342,20 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
BEGIN_STATE(ScriptDataState) {
if (cc == '<')
ADVANCE_TO(ScriptDataLessThanSignState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitEndOfFile(source);
else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataState);
}
}
END_STATE()
BEGIN_STATE(PLAINTEXTState) {
- emitCharacter(cc);
+ if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitEndOfFile(source);
+ else
+ bufferCharacter(cc);
ADVANCE_TO(PLAINTEXTState);
}
END_STATE()
@@ -316,59 +365,65 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
ADVANCE_TO(MarkupDeclarationOpenState);
else if (cc == '/')
ADVANCE_TO(EndTagOpenState);
- else if (cc >= 'A' && cc <= 'Z') {
+ else if (isASCIIUpper(cc)) {
m_token->beginStartTag(toLowerCase(cc));
ADVANCE_TO(TagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_token->beginStartTag(cc);
ADVANCE_TO(TagNameState);
} else if (cc == '?') {
- emitParseError();
+ parseError();
// The spec consumes the current character before switching
// to the bogus comment state, but it's easier to implement
// if we reconsume the current character.
RECONSUME_IN(BogusCommentState);
} else {
- emitParseError();
- emitCharacter('<');
+ parseError();
+ bufferCharacter('<');
RECONSUME_IN(DataState);
}
}
END_STATE()
BEGIN_STATE(EndTagOpenState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_token->beginEndTag(toLowerCase(cc));
ADVANCE_TO(TagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_token->beginEndTag(cc);
ADVANCE_TO(TagNameState);
} else if (cc == '>') {
- emitParseError();
+ parseError();
ADVANCE_TO(DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ bufferCharacter('<');
+ bufferCharacter('/');
+ RECONSUME_IN(DataState);
} else {
- emitParseError();
+ parseError();
RECONSUME_IN(BogusCommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(TagNameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeAttributeNameState);
else if (cc == '/')
ADVANCE_TO(SelfClosingStartTagState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else if (cc >= 'A' && cc <= 'Z') {
+ return emitAndResumeIn(source, DataState);
+ else if (isASCIIUpper(cc)) {
m_token->appendToName(toLowerCase(cc));
ADVANCE_TO(TagNameState);
+ } if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
m_token->appendToName(cc);
ADVANCE_TO(TagNameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -378,40 +433,40 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
ASSERT(m_bufferedEndTagName.isEmpty());
ADVANCE_TO(RCDATAEndTagOpenState);
} else {
- emitCharacter('<');
+ bufferCharacter('<');
RECONSUME_IN(RCDATAState);
}
}
END_STATE()
BEGIN_STATE(RCDATAEndTagOpenState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(RCDATAEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(RCDATAEndTagNameState);
} else {
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
RECONSUME_IN(RCDATAState);
}
}
END_STATE()
BEGIN_STATE(RCDATAEndTagNameState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(RCDATAEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(RCDATAEndTagNameState);
} else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isTokenizerWhitespace(cc)) {
if (isAppropriateEndTag())
FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
} else if (cc == '/') {
@@ -419,10 +474,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
} else if (cc == '>') {
if (isAppropriateEndTag())
- FLUSH_EMIT_AND_RESUME_IN(DataState);
+ return flushEmitAndResumeIn(source, DataState);
}
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
m_token->appendToCharacter(m_temporaryBuffer);
m_bufferedEndTagName.clear();
RECONSUME_IN(RCDATAState);
@@ -436,40 +491,40 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
ASSERT(m_bufferedEndTagName.isEmpty());
ADVANCE_TO(RAWTEXTEndTagOpenState);
} else {
- emitCharacter('<');
+ bufferCharacter('<');
RECONSUME_IN(RAWTEXTState);
}
}
END_STATE()
BEGIN_STATE(RAWTEXTEndTagOpenState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(RAWTEXTEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(RAWTEXTEndTagNameState);
} else {
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
RECONSUME_IN(RAWTEXTState);
}
}
END_STATE()
BEGIN_STATE(RAWTEXTEndTagNameState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(RAWTEXTEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(RAWTEXTEndTagNameState);
} else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isTokenizerWhitespace(cc)) {
if (isAppropriateEndTag())
FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
} else if (cc == '/') {
@@ -477,10 +532,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
} else if (cc == '>') {
if (isAppropriateEndTag())
- FLUSH_EMIT_AND_RESUME_IN(DataState);
+ return flushEmitAndResumeIn(source, DataState);
}
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
m_token->appendToCharacter(m_temporaryBuffer);
m_bufferedEndTagName.clear();
RECONSUME_IN(RAWTEXTState);
@@ -494,44 +549,44 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
ASSERT(m_bufferedEndTagName.isEmpty());
ADVANCE_TO(ScriptDataEndTagOpenState);
} else if (cc == '!') {
- emitCharacter('<');
- emitCharacter('!');
+ bufferCharacter('<');
+ bufferCharacter('!');
ADVANCE_TO(ScriptDataEscapeStartState);
} else {
- emitCharacter('<');
+ bufferCharacter('<');
RECONSUME_IN(ScriptDataState);
}
}
END_STATE()
BEGIN_STATE(ScriptDataEndTagOpenState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(ScriptDataEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(ScriptDataEndTagNameState);
} else {
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
RECONSUME_IN(ScriptDataState);
}
}
END_STATE()
BEGIN_STATE(ScriptDataEndTagNameState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(ScriptDataEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(ScriptDataEndTagNameState);
} else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isTokenizerWhitespace(cc)) {
if (isAppropriateEndTag())
FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
} else if (cc == '/') {
@@ -539,10 +594,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
} else if (cc == '>') {
if (isAppropriateEndTag())
- FLUSH_EMIT_AND_RESUME_IN(DataState);
+ return flushEmitAndResumeIn(source, DataState);
}
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
m_token->appendToCharacter(m_temporaryBuffer);
m_bufferedEndTagName.clear();
RECONSUME_IN(ScriptDataState);
@@ -552,7 +607,7 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
BEGIN_STATE(ScriptDataEscapeStartState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapeStartDashState);
} else
RECONSUME_IN(ScriptDataState);
@@ -561,7 +616,7 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
BEGIN_STATE(ScriptDataEscapeStartDashState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedDashDashState);
} else
RECONSUME_IN(ScriptDataState);
@@ -570,46 +625,52 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
BEGIN_STATE(ScriptDataEscapedState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedDashState);
} else if (cc == '<')
ADVANCE_TO(ScriptDataEscapedLessThanSignState);
- else {
- emitCharacter(cc);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
+ } else {
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(ScriptDataEscapedDashState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedDashDashState);
} else if (cc == '<')
ADVANCE_TO(ScriptDataEscapedLessThanSignState);
- else {
- emitCharacter(cc);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
+ } else {
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(ScriptDataEscapedDashDashState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedDashDashState);
} else if (cc == '<')
ADVANCE_TO(ScriptDataEscapedLessThanSignState);
else if (cc == '>') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataState);
+ } if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataEscapedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -618,53 +679,53 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
m_temporaryBuffer.clear();
ASSERT(m_bufferedEndTagName.isEmpty());
ADVANCE_TO(ScriptDataEscapedEndTagOpenState);
- } else if (cc >= 'A' && cc <= 'Z') {
- emitCharacter('<');
- emitCharacter(cc);
+ } else if (isASCIIUpper(cc)) {
+ bufferCharacter('<');
+ bufferCharacter(cc);
m_temporaryBuffer.clear();
m_temporaryBuffer.append(toLowerCase(cc));
ADVANCE_TO(ScriptDataDoubleEscapeStartState);
- } else if (cc >= 'a' && cc <= 'z') {
- emitCharacter('<');
- emitCharacter(cc);
+ } else if (isASCIILower(cc)) {
+ bufferCharacter('<');
+ bufferCharacter(cc);
m_temporaryBuffer.clear();
m_temporaryBuffer.append(cc);
ADVANCE_TO(ScriptDataDoubleEscapeStartState);
} else {
- emitCharacter('<');
+ bufferCharacter('<');
RECONSUME_IN(ScriptDataEscapedState);
}
}
END_STATE()
BEGIN_STATE(ScriptDataEscapedEndTagOpenState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(ScriptDataEscapedEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(ScriptDataEscapedEndTagNameState);
} else {
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
RECONSUME_IN(ScriptDataEscapedState);
}
}
END_STATE()
BEGIN_STATE(ScriptDataEscapedEndTagNameState) {
- if (cc >= 'A' && cc <= 'Z') {
+ if (isASCIIUpper(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(toLowerCase(cc));
ADVANCE_TO(ScriptDataEscapedEndTagNameState);
- } else if (cc >= 'a' && cc <= 'z') {
+ } else if (isASCIILower(cc)) {
m_temporaryBuffer.append(cc);
addToPossibleEndTag(cc);
ADVANCE_TO(ScriptDataEscapedEndTagNameState);
} else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isTokenizerWhitespace(cc)) {
if (isAppropriateEndTag())
FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
} else if (cc == '/') {
@@ -672,10 +733,10 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
} else if (cc == '>') {
if (isAppropriateEndTag())
- FLUSH_EMIT_AND_RESUME_IN(DataState);
+ return flushEmitAndResumeIn(source, DataState);
}
- emitCharacter('<');
- emitCharacter('/');
+ bufferCharacter('<');
+ bufferCharacter('/');
m_token->appendToCharacter(m_temporaryBuffer);
m_bufferedEndTagName.clear();
RECONSUME_IN(ScriptDataEscapedState);
@@ -684,18 +745,18 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
END_STATE()
BEGIN_STATE(ScriptDataDoubleEscapeStartState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '/' || cc == '>') {
- emitCharacter(cc);
+ if (isTokenizerWhitespace(cc) || cc == '/' || cc == '>') {
+ bufferCharacter(cc);
if (temporaryBufferIs(scriptTag.localName()))
ADVANCE_TO(ScriptDataDoubleEscapedState);
else
ADVANCE_TO(ScriptDataEscapedState);
- } else if (cc >= 'A' && cc <= 'Z') {
- emitCharacter(cc);
+ } else if (isASCIIUpper(cc)) {
+ bufferCharacter(cc);
m_temporaryBuffer.append(toLowerCase(cc));
ADVANCE_TO(ScriptDataDoubleEscapeStartState);
- } else if (cc >= 'a' && cc <= 'z') {
- emitCharacter(cc);
+ } else if (isASCIILower(cc)) {
+ bufferCharacter(cc);
m_temporaryBuffer.append(cc);
ADVANCE_TO(ScriptDataDoubleEscapeStartState);
} else
@@ -705,55 +766,61 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
BEGIN_STATE(ScriptDataDoubleEscapedState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedDashState);
} else if (cc == '<') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(ScriptDataDoubleEscapedDashState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedDashDashState);
} else if (cc == '<') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(ScriptDataDoubleEscapedDashDashState) {
if (cc == '-') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedDashDashState);
} else if (cc == '<') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
} else if (cc == '>') {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
- emitCharacter(cc);
+ bufferCharacter(cc);
ADVANCE_TO(ScriptDataDoubleEscapedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(ScriptDataDoubleEscapedLessThanSignState) {
if (cc == '/') {
- emitCharacter(cc);
+ bufferCharacter(cc);
m_temporaryBuffer.clear();
ADVANCE_TO(ScriptDataDoubleEscapeEndState);
} else
@@ -762,18 +829,18 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
END_STATE()
BEGIN_STATE(ScriptDataDoubleEscapeEndState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '/' || cc == '>') {
- emitCharacter(cc);
+ if (isTokenizerWhitespace(cc) || cc == '/' || cc == '>') {
+ bufferCharacter(cc);
if (temporaryBufferIs(scriptTag.localName()))
ADVANCE_TO(ScriptDataEscapedState);
else
ADVANCE_TO(ScriptDataDoubleEscapedState);
- } else if (cc >= 'A' && cc <= 'Z') {
- emitCharacter(cc);
+ } else if (isASCIIUpper(cc)) {
+ bufferCharacter(cc);
m_temporaryBuffer.append(toLowerCase(cc));
ADVANCE_TO(ScriptDataDoubleEscapeEndState);
- } else if (cc >= 'a' && cc <= 'z') {
- emitCharacter(cc);
+ } else if (isASCIILower(cc)) {
+ bufferCharacter(cc);
m_temporaryBuffer.append(cc);
ADVANCE_TO(ScriptDataDoubleEscapeEndState);
} else
@@ -782,75 +849,81 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
END_STATE()
BEGIN_STATE(BeforeAttributeNameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeAttributeNameState);
else if (cc == '/')
ADVANCE_TO(SelfClosingStartTagState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else if (cc >= 'A' && cc <= 'Z') {
+ return emitAndResumeIn(source, DataState);
+ else if (isASCIIUpper(cc)) {
m_token->addNewAttribute();
m_token->appendToAttributeName(toLowerCase(cc));
ADVANCE_TO(AttributeNameState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
- emitParseError();
+ parseError();
m_token->addNewAttribute();
m_token->appendToAttributeName(cc);
ADVANCE_TO(AttributeNameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AttributeNameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(AfterAttributeNameState);
else if (cc == '/')
ADVANCE_TO(SelfClosingStartTagState);
else if (cc == '=')
ADVANCE_TO(BeforeAttributeValueState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else if (cc >= 'A' && cc <= 'Z') {
+ return emitAndResumeIn(source, DataState);
+ else if (isASCIIUpper(cc)) {
m_token->appendToAttributeName(toLowerCase(cc));
ADVANCE_TO(AttributeNameState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
- emitParseError();
+ parseError();
m_token->appendToAttributeName(cc);
ADVANCE_TO(AttributeNameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AfterAttributeNameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(AfterAttributeNameState);
else if (cc == '/')
ADVANCE_TO(SelfClosingStartTagState);
else if (cc == '=')
ADVANCE_TO(BeforeAttributeValueState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else if (cc >= 'A' && cc <= 'Z') {
+ return emitAndResumeIn(source, DataState);
+ else if (isASCIIUpper(cc)) {
m_token->addNewAttribute();
m_token->appendToAttributeName(toLowerCase(cc));
ADVANCE_TO(AttributeNameState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
if (cc == '"' || cc == '\'' || cc == '<')
- emitParseError();
+ parseError();
m_token->addNewAttribute();
m_token->appendToAttributeName(cc);
ADVANCE_TO(AttributeNameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BeforeAttributeValueState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeAttributeValueState);
else if (cc == '"')
ADVANCE_TO(AttributeValueDoubleQuotedState);
@@ -859,11 +932,14 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
else if (cc == '\'')
ADVANCE_TO(AttributeValueSingleQuotedState);
else if (cc == '>') {
- emitParseError();
- EMIT_AND_RESUME_IN(DataState);
+ parseError();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
if (cc == '<' || cc == '=' || cc == '`')
- emitParseError();
+ parseError();
m_token->appendToAttributeValue(cc);
ADVANCE_TO(AttributeValueUnquotedState);
}
@@ -876,11 +952,13 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
else if (cc == '&') {
m_additionalAllowedCharacter = '"';
ADVANCE_TO(CharacterReferenceInAttributeValueState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
m_token->appendToAttributeValue(cc);
ADVANCE_TO(AttributeValueDoubleQuotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -890,29 +968,33 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
else if (cc == '&') {
m_additionalAllowedCharacter = '\'';
ADVANCE_TO(CharacterReferenceInAttributeValueState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
m_token->appendToAttributeValue(cc);
ADVANCE_TO(AttributeValueSingleQuotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AttributeValueUnquotedState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeAttributeNameState);
else if (cc == '&') {
m_additionalAllowedCharacter = '>';
ADVANCE_TO(CharacterReferenceInAttributeValueState);
} else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else {
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
+ } else {
if (cc == '"' || cc == '\'' || cc == '<' || cc == '=' || cc == '`')
- emitParseError();
+ parseError();
m_token->appendToAttributeValue(cc);
ADVANCE_TO(AttributeValueUnquotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -945,48 +1027,51 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
END_STATE()
BEGIN_STATE(AfterAttributeValueQuotedState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeAttributeNameState);
else if (cc == '/')
ADVANCE_TO(SelfClosingStartTagState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else {
- emitParseError();
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
+ } else {
+ parseError();
RECONSUME_IN(BeforeAttributeNameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(SelfClosingStartTagState) {
if (cc == '>') {
notImplemented();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ RECONSUME_IN(DataState);
} else {
- emitParseError();
+ parseError();
RECONSUME_IN(BeforeAttributeNameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BogusCommentState) {
- // FIXME: This state isn't correct because we'll terminate the
- // comment early if we don't have the whole input stream available.
m_token->beginComment();
- while (!source.isEmpty()) {
- cc = m_inputStreamPreprocessor.nextInputCharacter();
- if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
+ RECONSUME_IN(ContinueBogusCommentState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(ContinueBogusCommentState) {
+ if (cc == '>')
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitAndReconsumeIn(source, DataState);
+ else {
m_token->appendToComment(cc);
- m_inputStreamPreprocessor.advance(source, m_lineNumber);
- // We ignore the return value (which indicates that |source| is
- // empty) because it's checked by the loop condition above.
+ ADVANCE_TO(ContinueBogusCommentState);
}
- m_state = DataState;
- return true;
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1013,7 +1098,7 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
notImplemented();
// FIXME: We're still missing the bits about the insertion mode being in foreign content:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#markup-declaration-open-state
- emitParseError();
+ parseError();
RECONSUME_IN(BogusCommentState);
}
END_STATE()
@@ -1022,13 +1107,15 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
if (cc == '-')
ADVANCE_TO(CommentStartDashState);
else if (cc == '>') {
- emitParseError();
- EMIT_AND_RESUME_IN(DataState);
+ parseError();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1036,65 +1123,72 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
if (cc == '-')
ADVANCE_TO(CommentEndState);
else if (cc == '>') {
- emitParseError();
- EMIT_AND_RESUME_IN(DataState);
+ parseError();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToComment('-');
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(CommentState) {
if (cc == '-')
ADVANCE_TO(CommentEndDashState);
- else {
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(CommentEndDashState) {
if (cc == '-')
ADVANCE_TO(CommentEndState);
- else {
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
m_token->appendToComment('-');
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(CommentEndState) {
if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
- emitParseError();
+ return emitAndResumeIn(source, DataState);
+ else if (isTokenizerWhitespace(cc)) {
+ parseError();
m_token->appendToComment('-');
m_token->appendToComment('-');
m_token->appendToComment(cc);
ADVANCE_TO(CommentEndSpaceState);
} else if (cc == '!') {
- emitParseError();
+ parseError();
ADVANCE_TO(CommentEndBangState);
} else if (cc == '-') {
- emitParseError();
+ parseError();
m_token->appendToComment('-');
- m_token->appendToComment(cc);
ADVANCE_TO(CommentEndState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->appendToComment('-');
m_token->appendToComment('-');
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1105,86 +1199,105 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
m_token->appendToComment('!');
ADVANCE_TO(CommentEndDashState);
} else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else {
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
m_token->appendToComment('-');
m_token->appendToComment('-');
m_token->appendToComment('!');
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(CommentEndSpaceState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isTokenizerWhitespace(cc)) {
m_token->appendToComment(cc);
ADVANCE_TO(CommentEndSpaceState);
} else if (cc == '-')
ADVANCE_TO(CommentEndDashState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else {
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
m_token->appendToComment(cc);
ADVANCE_TO(CommentState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(DOCTYPEState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeDOCTYPENameState);
- else {
- emitParseError();
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->beginDOCTYPE();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
+ parseError();
RECONSUME_IN(BeforeDOCTYPENameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BeforeDOCTYPENameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeDOCTYPENameState);
- else if (cc >= 'A' && cc <= 'Z') {
+ else if (isASCIIUpper(cc)) {
m_token->beginDOCTYPE(toLowerCase(cc));
ADVANCE_TO(DOCTYPENameState);
} else if (cc == '>') {
- emitParseError();
+ parseError();
+ m_token->beginDOCTYPE();
+ m_token->setForceQuirks();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
m_token->beginDOCTYPE();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->beginDOCTYPE(cc);
ADVANCE_TO(DOCTYPENameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(DOCTYPENameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(AfterDOCTYPENameState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else if (cc >= 'A' && cc <= 'Z') {
+ return emitAndResumeIn(source, DataState);
+ else if (isASCIIUpper(cc)) {
m_token->appendToName(toLowerCase(cc));
ADVANCE_TO(DOCTYPENameState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToName(cc);
ADVANCE_TO(DOCTYPENameState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AfterDOCTYPENameState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(AfterDOCTYPENameState);
if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else {
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
DEFINE_STATIC_LOCAL(String, publicString, ("public"));
DEFINE_STATIC_LOCAL(String, systemString, ("system"));
if (cc == 'P' || cc == 'p') {
@@ -1202,40 +1315,42 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
} else if (result == SegmentedString::NotEnoughCharacters)
return shouldEmitBufferedCharacterToken(source);
}
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AfterDOCTYPEPublicKeywordState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeDOCTYPEPublicIdentifierState);
else if (cc == '"') {
- emitParseError();
+ parseError();
m_token->setPublicIdentifierToEmptyString();
ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
} else if (cc == '\'') {
- emitParseError();
+ parseError();
m_token->setPublicIdentifierToEmptyString();
ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
} else if (cc == '>') {
- emitParseError();
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BeforeDOCTYPEPublicIdentifierState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeDOCTYPEPublicIdentifierState);
else if (cc == '"') {
m_token->setPublicIdentifierToEmptyString();
@@ -1244,15 +1359,18 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
m_token->setPublicIdentifierToEmptyString();
ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
} else if (cc == '>') {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1260,14 +1378,17 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
if (cc == '"')
ADVANCE_TO(AfterDOCTYPEPublicIdentifierState);
else if (cc == '>') {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToPublicIdentifier(cc);
ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1275,85 +1396,97 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
if (cc == '\'')
ADVANCE_TO(AfterDOCTYPEPublicIdentifierState);
else if (cc == '>') {
- emitParseError();
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToPublicIdentifier(cc);
ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AfterDOCTYPEPublicIdentifierState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BetweenDOCTYPEPublicAndSystemIdentifiersState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
else if (cc == '"') {
- emitParseError();
+ parseError();
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
} else if (cc == '\'') {
- emitParseError();
+ parseError();
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BetweenDOCTYPEPublicAndSystemIdentifiersState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BetweenDOCTYPEPublicAndSystemIdentifiersState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
else if (cc == '"') {
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
} else if (cc == '\'') {
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AfterDOCTYPESystemKeywordState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeDOCTYPESystemIdentifierState);
else if (cc == '"') {
- emitParseError();
+ parseError();
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
} else if (cc == '\'') {
- emitParseError();
+ parseError();
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
} else if (cc == '>') {
- emitParseError();
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BeforeDOCTYPESystemIdentifierState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(BeforeDOCTYPESystemIdentifierState);
if (cc == '"') {
m_token->setSystemIdentifierToEmptyString();
@@ -1362,15 +1495,18 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
m_token->setSystemIdentifierToEmptyString();
ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
} else if (cc == '>') {
- emitParseError();
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndReconsumeIn(source, DataState);
} else {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1378,14 +1514,17 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
if (cc == '"')
ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
else if (cc == '>') {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToSystemIdentifier(cc);
ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1393,41 +1532,49 @@ bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
if (cc == '\'')
ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
else if (cc == '>') {
- emitParseError();
+ parseError();
m_token->setForceQuirks();
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
+ } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
} else {
m_token->appendToSystemIdentifier(cc);
ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(AfterDOCTYPESystemIdentifierState) {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ if (isTokenizerWhitespace(cc))
ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
else if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
- else {
- emitParseError();
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+ parseError();
+ m_token->setForceQuirks();
+ return emitAndReconsumeIn(source, DataState);
+ } else {
+ parseError();
ADVANCE_TO(BogusDOCTYPEState);
}
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(BogusDOCTYPEState) {
if (cc == '>')
- EMIT_AND_RESUME_IN(DataState);
+ return emitAndResumeIn(source, DataState);
+ else if (cc == InputStreamPreprocessor::endOfFileMarker)
+ return emitAndReconsumeIn(source, DataState);
ADVANCE_TO(BogusDOCTYPEState);
- // FIXME: Handle EOF properly.
}
END_STATE()
BEGIN_STATE(CDATASectionState) {
notImplemented();
ADVANCE_TO(CDATASectionState);
+ // FIXME: Handle EOF properly.
}
END_STATE()
@@ -1453,8 +1600,9 @@ inline bool HTMLTokenizer::isAppropriateEndTag()
return m_bufferedEndTagName == m_appropriateEndTagName;
}
-inline void HTMLTokenizer::emitCharacter(UChar character)
+inline void HTMLTokenizer::bufferCharacter(UChar character)
{
+ ASSERT(character != InputStreamPreprocessor::endOfFileMarker);
if (m_token->type() != HTMLToken::Character) {
m_token->beginCharacter(character);
return;
@@ -1462,28 +1610,21 @@ inline void HTMLTokenizer::emitCharacter(UChar character)
m_token->appendToCharacter(character);
}
-inline void HTMLTokenizer::emitCodePoint(unsigned value)
+inline void HTMLTokenizer::bufferCodePoint(unsigned value)
{
if (value < 0xFFFF) {
- emitCharacter(value);
+ bufferCharacter(value);
return;
}
- emitCharacter(U16_LEAD(value));
- emitCharacter(U16_TRAIL(value));
+ bufferCharacter(U16_LEAD(value));
+ bufferCharacter(U16_TRAIL(value));
}
-inline void HTMLTokenizer::emitParseError()
+inline void HTMLTokenizer::parseError()
{
notImplemented();
}
-inline void HTMLTokenizer::emitCurrentToken()
-{
- ASSERT(m_token->type() != HTMLToken::Uninitialized);
- if (m_token->type() == HTMLToken::StartTag)
- m_appropriateEndTagName = m_token->name();
-}
-
inline bool HTMLTokenizer::shouldEmitBufferedCharacterToken(const SegmentedString& source)
{
return source.isClosed() && m_token->type() == HTMLToken::Character;
diff --git a/WebCore/html/HTMLTokenizer.h b/WebCore/html/HTMLTokenizer.h
index c2e52ab..96c2d7c 100644
--- a/WebCore/html/HTMLTokenizer.h
+++ b/WebCore/html/HTMLTokenizer.h
@@ -83,6 +83,10 @@ public:
AfterAttributeValueQuotedState,
SelfClosingStartTagState,
BogusCommentState,
+ // The ContinueBogusCommentState is not in the HTML5 spec, but we use
+ // it internally to keep track of whether we've started the bogus
+ // comment token yet.
+ ContinueBogusCommentState,
MarkupDeclarationOpenState,
CommentStartState,
CommentStartDashState,
@@ -164,7 +168,7 @@ private:
// a number of specific character values are parse errors and should be replaced
// by the replacement character. We suspect this is a problem with the spec as doing
// that filtering breaks surrogate pair handling and causes us not to match Minefield.
- if (m_nextInputCharacter == '\0')
+ if (m_nextInputCharacter == '\0' && !shouldTreatNullAsEndOfFileMarker(source))
m_nextInputCharacter = 0xFFFD;
}
return true;
@@ -179,25 +183,40 @@ private:
return peek(source, lineNumber);
}
+ static const UChar endOfFileMarker;
+
private:
+ bool shouldTreatNullAsEndOfFileMarker(SegmentedString& source) const
+ {
+ return source.isClosed() && source.length() == 1;
+ }
+
// http://www.whatwg.org/specs/web-apps/current-work/#next-input-character
UChar m_nextInputCharacter;
bool m_skipNextNewLine;
};
- inline void emitCharacter(UChar);
- inline void emitParseError();
- inline void emitCurrentToken();
- inline void emitCodePoint(unsigned);
+ inline bool processEntity(SegmentedString&);
+
+ inline void parseError();
+ inline void bufferCharacter(UChar);
+ inline void bufferCodePoint(unsigned);
- inline bool processEntity(SegmentedString& source);
+ inline bool emitAndResumeIn(SegmentedString&, State);
+ inline bool emitAndReconsumeIn(SegmentedString&, State);
+ inline bool emitEndOfFile(SegmentedString&);
+ inline bool flushEmitAndResumeIn(SegmentedString&, State);
+ // Return whether we need to emit a character token before dealing with
+ // the buffered end tag.
+ inline bool flushBufferedEndTag(SegmentedString&);
inline bool temporaryBufferIs(const String&);
// Sometimes we speculatively consume input characters and we don't
// know whether they represent end tags or RCDATA, etc. These
// functions help manage these state.
inline void addToPossibleEndTag(UChar cc);
+ inline void saveEndTagNameIfNeeded();
inline bool isAppropriateEndTag();
inline bool shouldEmitBufferedCharacterToken(const SegmentedString&);
diff --git a/WebCore/html/HTMLTreeBuilder.cpp b/WebCore/html/HTMLTreeBuilder.cpp
index 6e40fd7..b4e7ce1 100644
--- a/WebCore/html/HTMLTreeBuilder.cpp
+++ b/WebCore/html/HTMLTreeBuilder.cpp
@@ -26,17 +26,27 @@
#include "config.h"
#include "HTMLTreeBuilder.h"
+#include "Comment.h"
#include "DocumentFragment.h"
+#include "DocumentType.h"
#include "Element.h"
#include "Frame.h"
-#include "HTMLTokenizer.h"
-#include "HTMLToken.h"
#include "HTMLDocument.h"
-#include "LegacyHTMLDocumentParser.h"
+#include "HTMLElementFactory.h"
+#include "HTMLHtmlElement.h"
#include "HTMLNames.h"
+#include "HTMLScriptElement.h"
+#include "HTMLToken.h"
+#include "HTMLTokenizer.h"
+#include "LegacyHTMLDocumentParser.h"
#include "LegacyHTMLTreeBuilder.h"
#include "NotImplemented.h"
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
#include "ScriptController.h"
+#include "Settings.h"
+#include "Text.h"
#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -52,6 +62,142 @@ inline bool isTreeBuilderWhiteSpace(UChar cc)
return cc == '\t' || cc == '\x0A' || cc == '\x0C' || cc == '\x0D' || cc == ' ';
}
+bool shouldUseLegacyTreeBuilder(Document* document)
+{
+ return !document->settings() || !document->settings()->html5TreeBuilderEnabled();
+}
+
+bool isNumberedHeaderTag(const AtomicString& tagName)
+{
+ return tagName == h1Tag
+ || tagName == h2Tag
+ || tagName == h3Tag
+ || tagName == h4Tag
+ || tagName == h5Tag
+ || tagName == h6Tag;
+}
+
+bool isTableBodyContextTag(const AtomicString& tagName)
+{
+ return tagName == tbodyTag
+ || tagName == tfootTag
+ || tagName == theadTag;
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special
+bool isSpecialTag(const AtomicString& tagName)
+{
+ return tagName == addressTag
+ || tagName == articleTag
+ || tagName == asideTag
+ || tagName == baseTag
+ || tagName == basefontTag
+ || tagName == "bgsound"
+ || tagName == blockquoteTag
+ || tagName == bodyTag
+ || tagName == brTag
+ || tagName == buttonTag
+ || tagName == centerTag
+ || tagName == colTag
+ || tagName == colgroupTag
+ || tagName == "command"
+ || tagName == ddTag
+ || tagName == "details"
+ || tagName == dirTag
+ || tagName == divTag
+ || tagName == dlTag
+ || tagName == dtTag
+ || tagName == embedTag
+ || tagName == fieldsetTag
+ || tagName == "figure"
+ || tagName == footerTag
+ || tagName == formTag
+ || tagName == frameTag
+ || tagName == framesetTag
+ || isNumberedHeaderTag(tagName)
+ || tagName == headTag
+ || tagName == headerTag
+ || tagName == hgroupTag
+ || tagName == hrTag
+ || tagName == iframeTag
+ || tagName == imgTag
+ || tagName == inputTag
+ || tagName == isindexTag
+ || tagName == liTag
+ || tagName == linkTag
+ || tagName == listingTag
+ || tagName == menuTag
+ || tagName == metaTag
+ || tagName == navTag
+ || tagName == noembedTag
+ || tagName == noframesTag
+ || tagName == noscriptTag
+ || tagName == olTag
+ || tagName == pTag
+ || tagName == paramTag
+ || tagName == plaintextTag
+ || tagName == preTag
+ || tagName == scriptTag
+ || tagName == sectionTag
+ || tagName == selectTag
+ || tagName == styleTag
+ || isTableBodyContextTag(tagName)
+ || tagName == textareaTag
+ || tagName == titleTag
+ || tagName == trTag
+ || tagName == ulTag
+ || tagName == wbrTag
+ || tagName == xmpTag;
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#scoping
+// Same as isScopingTag in LegacyHTMLTreeBuilder.cpp
+// and isScopeMarker in HTMLElementStack.cpp
+bool isScopingTag(const AtomicString& tagName)
+{
+ return tagName == appletTag
+ || tagName == buttonTag
+ || tagName == captionTag
+#if ENABLE(SVG_FOREIGN_OBJECT)
+ || tagName == SVGNames::foreignObjectTag
+#endif
+ || tagName == htmlTag
+ || tagName == marqueeTag
+ || tagName == objectTag
+ || tagName == tableTag
+ || tagName == tdTag
+ || tagName == thTag;
+}
+
+bool isNonAnchorFormattingTag(const AtomicString& tagName)
+{
+ return tagName == bTag
+ || tagName == bigTag
+ || tagName == codeTag
+ || tagName == emTag
+ || tagName == fontTag
+ || tagName == iTag
+ || tagName == nobrTag
+ || tagName == sTag
+ || tagName == smallTag
+ || tagName == strikeTag
+ || tagName == strongTag
+ || tagName == ttTag
+ || tagName == uTag;
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#formatting
+bool isFormattingTag(const AtomicString& tagName)
+{
+ return tagName == aTag || isNonAnchorFormattingTag(tagName);
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#phrasing
+bool isPhrasingTag(const AtomicString& tagName)
+{
+ return !isSpecialTag(tagName) && !isScopingTag(tagName) && !isFormattingTag(tagName);
+}
+
} // namespace
HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* document, bool reportErrors)
@@ -60,11 +206,13 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* documen
, m_reportErrors(reportErrors)
, m_isPaused(false)
, m_insertionMode(InitialMode)
+ , m_originalInsertionMode(InitialMode)
, m_tokenizer(tokenizer)
- , m_legacyTreeBuilder(new LegacyHTMLTreeBuilder(document, reportErrors))
+ , m_legacyTreeBuilder(shouldUseLegacyTreeBuilder(document) ? new LegacyHTMLTreeBuilder(document, reportErrors) : 0)
, m_lastScriptElementStartLine(uninitializedLineNumberValue)
, m_scriptToProcessStartLine(uninitializedLineNumberValue)
, m_fragmentScriptingPermission(FragmentScriptingAllowed)
+ , m_isParsingFragment(false)
{
}
@@ -76,11 +224,13 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, DocumentFragment* fra
, m_reportErrors(false) // FIXME: Why not report errors in fragments?
, m_isPaused(false)
, m_insertionMode(InitialMode)
+ , m_originalInsertionMode(InitialMode)
, m_tokenizer(tokenizer)
, m_legacyTreeBuilder(new LegacyHTMLTreeBuilder(fragment, scriptingPermission))
, m_lastScriptElementStartLine(uninitializedLineNumberValue)
, m_scriptToProcessStartLine(uninitializedLineNumberValue)
, m_fragmentScriptingPermission(scriptingPermission)
+ , m_isParsingFragment(true)
{
}
@@ -166,7 +316,7 @@ HTMLTokenizer::State HTMLTreeBuilder::adjustedLexerState(HTMLTokenizer::State st
return state;
}
-PassRefPtr<Node> HTMLTreeBuilder::passTokenToLegacyParser(HTMLToken& token)
+void HTMLTreeBuilder::passTokenToLegacyParser(HTMLToken& token)
{
if (token.type() == HTMLToken::DOCTYPE) {
DoctypeToken doctypeToken;
@@ -176,9 +326,12 @@ PassRefPtr<Node> HTMLTreeBuilder::passTokenToLegacyParser(HTMLToken& token)
doctypeToken.m_forceQuirks = token.forceQuirks();
m_legacyTreeBuilder->parseDoctypeToken(&doctypeToken);
- return 0;
+ return;
}
+ if (token.type() == HTMLToken::EndOfFile)
+ return;
+
// For now, we translate into an old-style token for testing.
Token oldStyleToken;
AtomicHTMLToken atomicToken(token);
@@ -214,371 +367,1302 @@ PassRefPtr<Node> HTMLTreeBuilder::passTokenToLegacyParser(HTMLToken& token)
} else if (oldStyleToken.tagName == framesetTag)
setInsertionMode(AfterFramesetMode);
}
- return result.release();
}
-PassRefPtr<Node> HTMLTreeBuilder::constructTreeFromToken(HTMLToken& rawToken)
+void HTMLTreeBuilder::constructTreeFromToken(HTMLToken& rawToken)
{
- // Make MSVC ignore our unreachable code for now.
- if (true)
- return passTokenToLegacyParser(rawToken);
+ if (m_legacyTreeBuilder) {
+ passTokenToLegacyParser(rawToken);
+ return;
+ }
AtomicHTMLToken token(rawToken);
+ processToken(token);
+}
+
+void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
+{
+ switch (token.type()) {
+ case HTMLToken::Uninitialized:
+ ASSERT_NOT_REACHED();
+ break;
+ case HTMLToken::DOCTYPE:
+ processDoctypeToken(token);
+ break;
+ case HTMLToken::StartTag:
+ processStartTag(token);
+ break;
+ case HTMLToken::EndTag:
+ processEndTag(token);
+ break;
+ case HTMLToken::Comment:
+ processComment(token);
+ return;
+ case HTMLToken::Character:
+ processCharacter(token);
+ break;
+ case HTMLToken::EndOfFile:
+ processEndOfFile(token);
+ break;
+ }
+}
+
+void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token)
+{
+ if (insertionMode() == InitialMode) {
+ insertDoctype(token);
+ return;
+ }
+ parseError(token);
+}
- // HTML5 expects the tokenizer to call the parser every time a character is
- // emitted. We instead collect characters and call the parser with a batch.
- // In order to make our first-pass parser code simple, processToken matches
- // the spec in only handling one character at a time.
- if (token.type() == HTMLToken::Character) {
- StringImpl* characters = token.characters().impl();
- // FIXME: Calling processToken for each character is probably slow.
- for (unsigned i = 0; i < characters->length(); ++i)
- processToken(token, (*characters)[i]);
- return 0; // FIXME: Should we be returning the Text node?
+void HTMLTreeBuilder::insertHTMLStartTagBeforeHTML(AtomicHTMLToken& token)
+{
+ RefPtr<Element> element = HTMLHtmlElement::create(m_document);
+ element->setAttributeMap(token.attributes(), m_fragmentScriptingPermission);
+ m_openElements.pushHTMLHtmlElement(attach(m_document, element.release()));
+}
+
+void HTMLTreeBuilder::mergeAttributesFromTokenIntoElement(AtomicHTMLToken& token, Element* element)
+{
+ if (!token.attributes())
+ return;
+
+ NamedNodeMap* attributes = element->attributes(false);
+ for (unsigned i = 0; i < token.attributes()->length(); ++i) {
+ Attribute* attribute = token.attributes()->attributeItem(i);
+ if (!attributes->getAttributeItem(attribute->name()))
+ element->setAttribute(attribute->name(), attribute->value());
}
- return processToken(token);
}
-PassRefPtr<Node> HTMLTreeBuilder::processToken(AtomicHTMLToken& token, UChar cc)
+void HTMLTreeBuilder::insertHTMLStartTagInBody(AtomicHTMLToken& token)
+{
+ parseError(token);
+ mergeAttributesFromTokenIntoElement(token, m_openElements.htmlElement());
+}
+
+void HTMLTreeBuilder::processFakePEndTagIfPInScope()
+{
+ if (!m_openElements.inScope(pTag.localName()))
+ return;
+ AtomicHTMLToken endP(HTMLToken::EndTag, pTag.localName());
+ processEndTag(endP);
+}
+
+void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
{
-reprocessToken:
switch (insertionMode()) {
- case InitialMode: {
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::DOCTYPE:
- return insertDoctype(token);
- case HTMLToken::Comment:
- return insertComment(token);
- case HTMLToken::Character:
- if (isTreeBuilderWhiteSpace(cc))
- return 0;
- break;
- case HTMLToken::StartTag:
- case HTMLToken::EndTag:
- case HTMLToken::EndOfFile:
- break;
+ case InitialMode:
+ ASSERT(insertionMode() == InitialMode);
+ processDefaultForInitialMode(token);
+ // Fall through.
+ case BeforeHTMLMode:
+ ASSERT(insertionMode() == BeforeHTMLMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagBeforeHTML(token);
+ setInsertionMode(BeforeHeadMode);
+ return;
}
- notImplemented();
- parseError(token);
- setInsertionMode(BeforeHTMLMode);
- goto reprocessToken;
- }
- case BeforeHTMLMode: {
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::DOCTYPE:
+ processDefaultForBeforeHTMLMode(token);
+ // Fall through.
+ case BeforeHeadMode:
+ ASSERT(insertionMode() == BeforeHeadMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ if (token.name() == headTag) {
+ insertHTMLHeadElement(token);
+ setInsertionMode(InHeadMode);
+ return;
+ }
+ processDefaultForBeforeHeadMode(token);
+ // Fall through.
+ case InHeadMode:
+ ASSERT(insertionMode() == InHeadMode);
+ if (processStartTagForInHead(token))
+ return;
+ processDefaultForInHeadMode(token);
+ // Fall through.
+ case AfterHeadMode:
+ ASSERT(insertionMode() == AfterHeadMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ if (token.name() == bodyTag) {
+ m_framesetOk = false;
+ insertHTMLBodyElement(token);
+ m_insertionMode = InBodyMode;
+ return;
+ }
+ if (token.name() == framesetTag) {
+ insertElement(token);
+ setInsertionMode(InFramesetMode);
+ return;
+ }
+ if (token.name() == baseTag || token.name() == linkTag || token.name() == metaTag || token.name() == noframesTag || token.name() == scriptTag || token.name() == styleTag || token.name() == titleTag) {
parseError(token);
- return 0;
- case HTMLToken::Comment:
- return insertComment(token);
- case HTMLToken::Character:
- if (isTreeBuilderWhiteSpace(cc))
- return 0;
- break;
- case HTMLToken::StartTag:
- if (token.name() == htmlTag) {
- notImplemented();
- setInsertionMode(BeforeHeadMode);
- return 0;
- }
- break;
- case HTMLToken::EndTag:
- if (token.name() == headTag || token.name() == bodyTag || token.name() == htmlTag || token.name() == brTag)
- break;
+ ASSERT(m_headElement);
+ m_openElements.pushHTMLHeadElement(m_headElement);
+ processStartTagForInHead(token);
+ m_openElements.removeHTMLHeadElement(m_headElement.get());
+ return;
+ }
+ if (token.name() == headTag) {
parseError(token);
- return 0;
- case HTMLToken::EndOfFile:
- break;
+ return;
}
- notImplemented();
- setInsertionMode(BeforeHeadMode);
- goto reprocessToken;
- }
- case BeforeHeadMode: {
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::Character:
- if (isTreeBuilderWhiteSpace(cc))
- return 0;
- break;
- case HTMLToken::Comment:
- return insertComment(token);
- case HTMLToken::DOCTYPE:
+ processDefaultForAfterHeadMode(token);
+ // Fall through
+ case InBodyMode:
+ ASSERT(insertionMode() == InBodyMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ if (token.name() == baseTag || token.name() == "command" || token.name() == linkTag || token.name() == metaTag || token.name() == noframesTag || token.name() == scriptTag || token.name() == styleTag || token.name() == titleTag) {
+ bool didProcess = processStartTagForInHead(token);
+ ASSERT_UNUSED(didProcess, didProcess);
+ return;
+ }
+ if (token.name() == bodyTag) {
parseError(token);
- return 0;
- case HTMLToken::StartTag:
- if (token.name() == htmlTag) {
- notImplemented();
- return 0;
- }
- if (token.name() == headTag) {
- m_headElement = insertElement(token);
- setInsertionMode(InHeadMode);
- return m_headElement;
+ notImplemented(); // fragment case
+ mergeAttributesFromTokenIntoElement(token, m_openElements.bodyElement());
+ return;
+ }
+ if (token.name() == framesetTag) {
+ parseError(token);
+ notImplemented(); // fragment case
+ if (!m_framesetOk)
+ return;
+ ExceptionCode ec = 0;
+ m_openElements.bodyElement()->remove(ec);
+ ASSERT(!ec);
+ m_openElements.popUntil(m_openElements.bodyElement());
+ m_openElements.popHTMLBodyElement();
+ ASSERT(m_openElements.top() == m_openElements.htmlElement());
+ insertElement(token);
+ m_insertionMode = InFramesetMode;
+ return;
+ }
+ if (token.name() == addressTag || token.name() == articleTag || token.name() == asideTag || token.name() == blockquoteTag || token.name() == centerTag || token.name() == "details" || token.name() == dirTag || token.name() == divTag || token.name() == dlTag || token.name() == fieldsetTag || token.name() == "figure" || token.name() == footerTag || token.name() == headerTag || token.name() == hgroupTag || token.name() == menuTag || token.name() == navTag || token.name() == olTag || token.name() == pTag || token.name() == sectionTag || token.name() == ulTag) {
+ processFakePEndTagIfPInScope();
+ insertElement(token);
+ return;
+ }
+ if (isNumberedHeaderTag(token.name())) {
+ processFakePEndTagIfPInScope();
+ notImplemented();
+ insertElement(token);
+ return;
+ }
+ if (token.name() == preTag || token.name() == listingTag) {
+ processFakePEndTagIfPInScope();
+ insertElement(token);
+ m_tokenizer->skipLeadingNewLineForListing();
+ m_framesetOk = false;
+ return;
+ }
+ if (token.name() == formTag) {
+ notImplemented();
+ processFakePEndTagIfPInScope();
+ insertElement(token);
+ m_formElement = currentElement();
+ return;
+ }
+ if (token.name() == liTag) {
+ notImplemented();
+ processFakePEndTagIfPInScope();
+ insertElement(token);
+ return;
+ }
+ if (token.name() == ddTag || token.name() == dtTag) {
+ notImplemented();
+ processFakePEndTagIfPInScope();
+ insertElement(token);
+ return;
+ }
+ if (token.name() == plaintextTag) {
+ processFakePEndTagIfPInScope();
+ insertElement(token);
+ m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
+ return;
+ }
+ if (token.name() == buttonTag) {
+ notImplemented();
+ reconstructTheActiveFormattingElements();
+ insertElement(token);
+ m_framesetOk = false;
+ return;
+ }
+ if (token.name() == aTag) {
+ notImplemented();
+ reconstructTheActiveFormattingElements();
+ insertFormattingElement(token);
+ return;
+ }
+ if (isNonAnchorFormattingTag(token.name())) {
+ reconstructTheActiveFormattingElements();
+ insertFormattingElement(token);
+ return;
+ }
+ if (token.name() == nobrTag) {
+ reconstructTheActiveFormattingElements();
+ notImplemented();
+ insertFormattingElement(token);
+ return;
+ }
+ if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
+ reconstructTheActiveFormattingElements();
+ insertElement(token);
+ notImplemented();
+ m_framesetOk = false;
+ return;
+ }
+ if (token.name() == tableTag) {
+ notImplemented();
+ insertElement(token);
+ m_framesetOk = false;
+ m_insertionMode = InTableMode;
+ return;
+ }
+ if (token.name() == imageTag) {
+ parseError(token);
+ // Apparently we're not supposed to ask.
+ token.setName(imgTag.localName());
+ // Note the fall through to the imgTag handling below!
+ }
+ if (token.name() == areaTag || token.name() == basefontTag || token.name() == "bgsound" || token.name() == brTag || token.name() == embedTag || token.name() == imgTag || token.name() == inputTag || token.name() == keygenTag || token.name() == wbrTag) {
+ reconstructTheActiveFormattingElements();
+ insertSelfClosingElement(token);
+ m_framesetOk = false;
+ return;
+ }
+ if (token.name() == paramTag || token.name() == sourceTag || token.name() == "track") {
+ insertSelfClosingElement(token);
+ return;
+ }
+ if (token.name() == hrTag) {
+ processFakePEndTagIfPInScope();
+ insertSelfClosingElement(token);
+ m_framesetOk = false;
+ return;
+ }
+ if (token.name() == isindexTag) {
+ parseError(token);
+ notImplemented();
+ return;
+ }
+ if (token.name() == textareaTag) {
+ insertElement(token);
+ m_tokenizer->skipLeadingNewLineForListing();
+ m_tokenizer->setState(HTMLTokenizer::RCDATAState);
+ m_originalInsertionMode = m_insertionMode;
+ m_framesetOk = false;
+ m_insertionMode = TextMode;
+ return;
+ }
+ if (token.name() == xmpTag) {
+ processFakePEndTagIfPInScope();
+ reconstructTheActiveFormattingElements();
+ m_framesetOk = false;
+ insertGenericRawTextElement(token);
+ return;
+ }
+ if (token.name() == iframeTag) {
+ m_framesetOk = false;
+ insertGenericRawTextElement(token);
+ return;
+ }
+ if (token.name() == noembedTag) {
+ insertGenericRawTextElement(token);
+ return;
+ }
+ if (token.name() == noscriptTag && isScriptingFlagEnabled(m_document->frame())) {
+ insertGenericRawTextElement(token);
+ return;
+ }
+ if (token.name() == selectTag) {
+ reconstructTheActiveFormattingElements();
+ insertElement(token);
+ m_framesetOk = false;
+ if (m_insertionMode == InTableMode || m_insertionMode == InCaptionMode || m_insertionMode == InColumnGroupMode || m_insertionMode == InTableBodyMode || m_insertionMode == InRowMode || m_insertionMode == InCellMode)
+ m_insertionMode = InSelectInTableMode;
+ else
+ m_insertionMode = InSelectMode;
+ return;
+ }
+ if (token.name() == optgroupTag || token.name() == optionTag) {
+ if (m_openElements.inScope(optionTag.localName())) {
+ AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
+ processEndTag(endOption);
}
- break;
- case HTMLToken::EndTag:
- if (token.name() == headTag || token.name() == bodyTag || token.name() == brTag) {
- AtomicHTMLToken fakeHead(HTMLToken::StartTag, headTag.localName());
- processToken(fakeHead);
- goto reprocessToken;
+ reconstructTheActiveFormattingElements();
+ insertElement(token);
+ return;
+ }
+ if (token.name() == rpTag || token.name() == rtTag) {
+ if (m_openElements.inScope(rubyTag.localName())) {
+ generateImpliedEndTags();
+ if (!currentElement()->hasTagName(rubyTag)) {
+ parseError(token);
+ m_openElements.popUntil(rubyTag.localName());
+ }
}
+ insertElement(token);
+ return;
+ }
+ if (token.name() == "math") {
+ // This is the MathML foreign content branch point.
+ notImplemented();
+ }
+ if (token.name() == "svg") {
+ // This is the SVG foreign content branch point.
+ notImplemented();
+ }
+ if (token.name() == captionTag || token.name() == colTag || token.name() == colgroupTag || token.name() == frameTag || token.name() == headTag || token.name() == tbodyTag || token.name() == tdTag || token.name() == tfootTag || token.name() == thTag || token.name() == theadTag || token.name() == trTag) {
+ parseError(token);
+ return;
+ }
+ reconstructTheActiveFormattingElements();
+ insertElement(token);
+ break;
+ case InTableMode:
+ ASSERT(insertionMode() == InTableMode);
+ if (token.name() == captionTag) {
+ m_openElements.popUntilTableScopeMarker();
+ m_activeFormattingElements.appendMarker();
+ insertElement(token);
+ m_insertionMode = InCaptionMode;
+ return;
+ }
+ if (token.name() == colgroupTag) {
+ m_openElements.popUntilTableScopeMarker();
+ insertElement(token);
+ m_insertionMode = InColumnGroupMode;
+ return;
+ }
+ if (token.name() == colTag) {
+ notImplemented();
+ return;
+ }
+ if (isTableBodyContextTag(token.name())) {
+ m_openElements.popUntilTableScopeMarker();
+ insertElement(token);
+ m_insertionMode = InTableBodyMode;
+ return;
+ }
+ if (token.name() == tdTag || token.name() == thTag || token.name() == trTag) {
+ notImplemented();
+ return;
+ }
+ if (token.name() == tableTag) {
+ notImplemented();
+ return;
+ }
+ if (token.name() == styleTag || token.name() == scriptTag) {
+ processStartTagForInHead(token);
+ return;
+ }
+ if (token.name() == inputTag) {
+ notImplemented();
+ return;
+ }
+ if (token.name() == formTag) {
+ parseError(token);
+ if (m_formElement)
+ return;
+ insertSelfClosingElement(token);
+ return;
+ }
+ parseError(token);
+ notImplemented();
+ break;
+ case InTableBodyMode:
+ ASSERT(insertionMode() == InTableBodyMode);
+ if (token.name() == trTag) {
+ m_openElements.popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
+ insertElement(token);
+ m_insertionMode = InRowMode;
+ return;
+ }
+ if (token.name() == thTag || token.name() == tdTag) {
+ parseError(token);
+ AtomicHTMLToken fakeToken(HTMLToken::StartTag, trTag.localName());
+ processStartTag(fakeToken);
+ ASSERT(insertionMode() == InRowMode);
+ processStartTag(token);
+ return;
+ }
+ if (token.name() == captionTag || token.name() == colTag || token.name() == colgroupTag || isTableBodyContextTag(token.name())) {
+ // FIXME: The spec is unclear as to what is supposed to happen here.
+ notImplemented();
+ return;
+ }
+ notImplemented(); // process using "in table" rules
+ break;
+ case AfterBodyMode:
+ case AfterAfterBodyMode:
+ ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ m_insertionMode = InBodyMode;
+ processStartTag(token);
+ break;
+ case InHeadNoscriptMode:
+ ASSERT(insertionMode() == InHeadNoscriptMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ if (token.name() == linkTag || token.name() == metaTag || token.name() == noframesTag || token.name() == styleTag) {
+ bool didProcess = processStartTagForInHead(token);
+ ASSERT_UNUSED(didProcess, didProcess);
+ return;
+ }
+ if (token.name() == htmlTag || token.name() == noscriptTag) {
parseError(token);
- return 0;
- case HTMLToken::EndOfFile:
- break;
+ return;
+ }
+ processDefaultForInHeadNoscriptMode(token);
+ processToken(token);
+ break;
+ case InFramesetMode:
+ ASSERT(insertionMode() == InFramesetMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ if (token.name() == framesetTag) {
+ insertElement(token);
+ return;
+ }
+ if (token.name() == frameTag) {
+ insertSelfClosingElement(token);
+ return;
+ }
+ if (token.name() == noframesTag) {
+ processStartTagForInHead(token);
+ return;
}
- AtomicHTMLToken fakeHead(HTMLToken::StartTag, headTag.localName());
- processToken(fakeHead);
- goto reprocessToken;
+ parseError(token);
+ break;
+ case AfterFramesetMode:
+ case AfterAfterFramesetMode:
+ ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return;
+ }
+ if (token.name() == noframesTag) {
+ processStartTagForInHead(token);
+ return;
+ }
+ parseError(token);
+ break;
+ default:
+ notImplemented();
+ }
+}
+
+bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken& token)
+{
+ if (!m_openElements.inScope(bodyTag.localName())) {
+ parseError(token);
+ return false;
}
- case InHeadMode: {
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::Character:
- insertCharacter(cc);
- break;
- case HTMLToken::Comment:
- return insertComment(token);
- case HTMLToken::DOCTYPE:
+ notImplemented();
+ m_insertionMode = AfterBodyMode;
+ return true;
+}
+
+// FIXME: This probably belongs on HTMLElementStack.
+HTMLElementStack::ElementRecord* HTMLTreeBuilder::furthestBlockForFormattingElement(Element* formattingElement)
+{
+ HTMLElementStack::ElementRecord* furthestBlock = 0;
+ HTMLElementStack::ElementRecord* record = m_openElements.topRecord();
+ for (; record; record = record->next()) {
+ if (record->element() == formattingElement)
+ return furthestBlock;
+ const AtomicString& tagName = record->element()->localName();
+ // !phrasing && !formatting == scoping || special
+ if (isScopingTag(tagName) || isSpecialTag(tagName))
+ furthestBlock = record;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+void HTMLTreeBuilder::findFosterParentFor(Element* element)
+{
+ Element* fosterParentElement = 0;
+ HTMLElementStack::ElementRecord* lastTableElementRecord = m_openElements.topmost(tableTag.localName());
+ if (lastTableElementRecord) {
+ Element* lastTableElement = lastTableElementRecord->element();
+ if (lastTableElement->parent()) {
+ // FIXME: We need an insertElement which does not send mutation events.
+ ExceptionCode ec = 0;
+ lastTableElement->parent()->insertBefore(element, lastTableElement, ec);
+ ASSERT(!ec);
+ return;
+ }
+ fosterParentElement = lastTableElementRecord->next()->element();
+ } else {
+ ASSERT(m_isParsingFragment);
+ fosterParentElement = m_openElements.bottom(); // <html> element
+ }
+
+ fosterParentElement->parserAddChild(element);
+}
+
+// FIXME: This should have a whitty name.
+// FIXME: This must be implemented in many other places in WebCore.
+void HTMLTreeBuilder::reparentChildren(Element* oldParent, Element* newParent)
+{
+ Node* child = oldParent->firstChild();
+ while (child) {
+ Node* nextChild = child->nextSibling();
+ ExceptionCode ec;
+ newParent->appendChild(child, ec);
+ ASSERT(!ec);
+ child = nextChild;
+ }
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
+void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
+{
+ while (1) {
+ // 1.
+ Element* formattingElement = m_activeFormattingElements.closestElementInScopeWithName(token.name());
+ if (!formattingElement || !m_openElements.inScope(formattingElement)) {
parseError(token);
- return 0;
- case HTMLToken::StartTag:
- if (token.name() == htmlTag) {
- notImplemented();
- return 0;
- }
- // FIXME: Atomize "command".
- if (token.name() == baseTag || token.name() == "command" || token.name() == linkTag) {
- PassRefPtr<Node> node = insertElement(token);
- m_openElements.pop();
- notImplemented();
- return node;
- }
- if (token.name() == metaTag) {
- PassRefPtr<Node> node = insertElement(token);
- m_openElements.pop();
- notImplemented();
- return node;
- }
- if (token.name() == titleTag)
- return insertGenericRCDATAElement(token);
- if (token.name() == noscriptTag) {
- if (isScriptingFlagEnabled(m_document->frame()))
- return insertGenericRawTextElement(token);
- PassRefPtr<Node> node = insertElement(token);
- setInsertionMode(InHeadNoscriptMode);
- return node;
- }
- if (token.name() == noframesTag || token.name() == styleTag)
- return insertGenericRawTextElement(token);
- if (token.name() == scriptTag)
- return insertScriptElement(token);
- if (token.name() == headTag) {
- notImplemented();
- return 0;
- }
- break;
- case HTMLToken::EndTag:
- if (token.name() == headTag) {
- ASSERT(m_openElements.top()->tagQName() == headTag);
- m_openElements.pop();
- setInsertionMode(AfterHeadMode);
- return 0;
+ notImplemented(); // Check the stack of open elements for a more specific parse error.
+ return;
+ }
+ HTMLElementStack::ElementRecord* formattingElementRecord = m_openElements.find(formattingElement);
+ if (!formattingElementRecord) {
+ parseError(token);
+ m_activeFormattingElements.remove(formattingElement);
+ return;
+ }
+ if (formattingElement != currentElement())
+ parseError(token);
+ // 2.
+ HTMLElementStack::ElementRecord* furthestBlock = furthestBlockForFormattingElement(formattingElement);
+ // 3.
+ if (!furthestBlock) {
+ m_openElements.popUntil(formattingElement);
+ m_openElements.pop();
+ m_activeFormattingElements.remove(formattingElement);
+ return;
+ }
+ // 4.
+ ASSERT(furthestBlock->isAbove(formattingElementRecord));
+ Element* commonAncestor = formattingElementRecord->next()->element();
+ // 5.
+ notImplemented(); // bookmark?
+ // 6.
+ HTMLElementStack::ElementRecord* node = furthestBlock;
+ HTMLElementStack::ElementRecord* nextNode = node->next();
+ HTMLElementStack::ElementRecord* lastNode = furthestBlock;
+ while (1) {
+ // 6.1
+ node = nextNode;
+ ASSERT(node);
+ nextNode = node->next(); // Save node->next() for the next iteration in case node is deleted in 6.2.
+ // 6.2
+ if (!m_activeFormattingElements.contains(node->element())) {
+ m_openElements.remove(node->element());
+ node = 0;
+ continue;
}
- if (token.name() == bodyTag || token.name() == htmlTag || token.name() == brTag)
+ // 6.3
+ if (node == formattingElementRecord)
break;
- parseError(token);
- return 0;
- break;
- case HTMLToken::EndOfFile:
- break;
- }
- AtomicHTMLToken fakeHead(HTMLToken::EndTag, headTag.localName());
- processToken(fakeHead);
- goto reprocessToken;
+ // 6.4
+ if (lastNode == furthestBlock)
+ notImplemented(); // move bookmark.
+ // 6.5
+ // FIXME: We're supposed to save the original token in the entry.
+ AtomicHTMLToken fakeToken(HTMLToken::StartTag, node->element()->localName());
+ // Is createElement correct? (instead of insertElement)
+ // Does this code ever leave newElement unattached?
+ RefPtr<Element> newElement = createElement(fakeToken);
+ HTMLFormattingElementList::Entry* nodeEntry = m_activeFormattingElements.find(node->element());
+ nodeEntry->replaceElement(newElement.get());
+ node->replaceElement(newElement.release());
+ // 6.6
+ // Use appendChild instead of parserAddChild to handle possible reparenting.
+ ExceptionCode ec;
+ node->element()->appendChild(lastNode->element(), ec);
+ ASSERT(!ec);
+ // 6.7
+ lastNode = node;
+ }
+ // 7
+ const AtomicString& commonAncestorTag = commonAncestor->localName();
+ if (commonAncestorTag == tableTag
+ || commonAncestorTag == trTag
+ || isTableBodyContextTag(commonAncestorTag))
+ findFosterParentFor(lastNode->element());
+ else {
+ ExceptionCode ec;
+ commonAncestor->appendChild(lastNode->element(), ec);
+ ASSERT(!ec);
+ }
+ // 8
+ // FIXME: We're supposed to save the original token in the entry.
+ AtomicHTMLToken fakeToken(HTMLToken::StartTag, formattingElement->localName());
+ RefPtr<Element> newElement = createElement(fakeToken);
+ // 9
+ reparentChildren(furthestBlock->element(), newElement.get());
+ // 10
+ furthestBlock->element()->parserAddChild(newElement);
+ // 11
+ m_activeFormattingElements.remove(formattingElement);
+ notImplemented(); // insert new element at bookmark
+ // 12
+ m_openElements.remove(formattingElement);
+ m_openElements.insertAbove(newElement, furthestBlock);
}
- case InHeadNoscriptMode: {
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::DOCTYPE:
+}
+
+void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
+{
+ switch (insertionMode()) {
+ case InitialMode:
+ ASSERT(insertionMode() == InitialMode);
+ processDefaultForInitialMode(token);
+ // Fall through.
+ case BeforeHTMLMode:
+ ASSERT(insertionMode() == BeforeHTMLMode);
+ if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
parseError(token);
- return 0;
- case HTMLToken::StartTag:
- if (token.name() == htmlTag) {
- notImplemented();
- return 0;
- }
- if (token.name() == linkTag || token.name() == metaTag || token.name() == noframesTag || token.name() == styleTag) {
- notImplemented();
- return 0;
- }
- if (token.name() == htmlTag || token.name() == noscriptTag) {
+ return;
+ }
+ processDefaultForBeforeHTMLMode(token);
+ // Fall through.
+ case BeforeHeadMode:
+ ASSERT(insertionMode() == BeforeHeadMode);
+ if (token.name() != headTag && token.name() != bodyTag && token.name() != brTag) {
+ parseError(token);
+ return;
+ }
+ processDefaultForBeforeHeadMode(token);
+ // Fall through.
+ case InHeadMode:
+ ASSERT(insertionMode() == InHeadMode);
+ if (token.name() == headTag) {
+ m_openElements.popHTMLHeadElement();
+ setInsertionMode(AfterHeadMode);
+ return;
+ }
+ if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
+ parseError(token);
+ return;
+ }
+ processDefaultForInHeadMode(token);
+ // Fall through.
+ case AfterHeadMode:
+ ASSERT(insertionMode() == AfterHeadMode);
+ if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
+ parseError(token);
+ return;
+ }
+ processDefaultForAfterHeadMode(token);
+ // Fall through
+ case InBodyMode:
+ ASSERT(insertionMode() == InBodyMode);
+ if (token.name() == bodyTag) {
+ processBodyEndTagForInBody(token);
+ return;
+ }
+ if (token.name() == htmlTag) {
+ if (processBodyEndTagForInBody(token))
+ processEndTag(token);
+ return;
+ }
+ if (token.name() == addressTag || token.name() == articleTag || token.name() == asideTag || token.name() == blockquoteTag || token.name() == buttonTag || token.name() == centerTag || token.name() == "details" || token.name() == dirTag || token.name() == divTag || token.name() == dlTag || token.name() == fieldsetTag || token.name() == "figure" || token.name() == footerTag || token.name() == headerTag || token.name() == hgroupTag || token.name() == listingTag || token.name() == menuTag || token.name() == navTag || token.name() == olTag || token.name() == preTag || token.name() == sectionTag || token.name() == ulTag) {
+ if (!m_openElements.inScope(token.name())) {
parseError(token);
- return 0;
+ return;
}
- break;
- case HTMLToken::EndTag:
- if (token.name() == noscriptTag) {
- ASSERT(m_openElements.top()->tagQName() == noscriptTag);
- m_openElements.pop();
- ASSERT(m_openElements.top()->tagQName() == headTag);
- setInsertionMode(InHeadMode);
- return 0;
- }
- if (token.name() == brTag)
- break;
- parseError(token);
- return 0;
- case HTMLToken::Character:
- notImplemented();
- break;
- case HTMLToken::Comment:
- notImplemented();
- return 0;
- case HTMLToken::EndOfFile:
- break;
+ generateImpliedEndTags();
+ if (currentElement()->tagQName() != token.name())
+ parseError(token);
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
}
- AtomicHTMLToken fakeNoscript(HTMLToken::EndTag, noscriptTag.localName());
- processToken(fakeNoscript);
- goto reprocessToken;
- }
- case AfterHeadMode: {
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::Character:
- if (isTreeBuilderWhiteSpace(cc)) {
- insertCharacter(cc);
- return 0;
+ if (token.name() == formTag) {
+ RefPtr<Element> node = m_formElement.release();
+ if (!node || !m_openElements.inScope(node.get())) {
+ parseError(token);
+ return;
}
- break;
- case HTMLToken::Comment:
- return insertComment(token);
- case HTMLToken::DOCTYPE:
- parseError(token);
- return 0;
- case HTMLToken::StartTag:
- if (token.name() == htmlTag) {
+ generateImpliedEndTags();
+ if (currentElement() != node.get())
+ parseError(token);
+ m_openElements.remove(node.get());
+ }
+ if (token.name() == pTag) {
+ if (!m_openElements.inScope(token.name())) {
+ parseError(token);
notImplemented();
- return 0;
+ return;
}
- if (token.name() == bodyTag) {
- m_framesetOk = false;
- return insertElement(token);
+ generateImpliedEndTagsWithExclusion(token.name());
+ if (!currentElement()->hasLocalName(token.name()))
+ parseError(token);
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
+ return;
+ }
+ if (token.name() == liTag) {
+ if (!m_openElements.inListItemScope(token.name())) {
+ parseError(token);
+ return;
}
- if (token.name() == framesetTag) {
- PassRefPtr<Node> node = insertElement(token);
- setInsertionMode(InFramesetMode);
- return node;
+ generateImpliedEndTagsWithExclusion(token.name());
+ if (!currentElement()->hasLocalName(token.name()))
+ parseError(token);
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
+ return;
+ }
+ if (token.name() == ddTag || token.name() == dtTag) {
+ if (!m_openElements.inScope(token.name())) {
+ parseError(token);
+ return;
}
- if (token.name() == baseTag || token.name() == linkTag || token.name() == metaTag || token.name() == noframesTag || token.name() == scriptTag || token.name() == styleTag || token.name() == titleTag) {
+ generateImpliedEndTagsWithExclusion(token.name());
+ if (!currentElement()->hasLocalName(token.name()))
parseError(token);
- ASSERT(m_headElement);
- m_openElements.push(m_headElement.get());
- notImplemented();
- m_openElements.remove(m_headElement.get());
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
+ return;
+ }
+ if (isNumberedHeaderTag(token.name())) {
+ if (!m_openElements.inScope(token.name())) {
+ parseError(token);
+ return;
}
- if (token.name() == headTag) {
+ generateImpliedEndTags();
+ if (!currentElement()->hasLocalName(token.name()))
parseError(token);
- return 0;
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
+ return;
+ }
+ if (token.name() == "sarcasm") {
+ notImplemented(); // Take a deep breath.
+ return;
+ }
+ if (isFormattingTag(token.name())) {
+ callTheAdoptionAgency(token);
+ return;
+ }
+ if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
+ if (!m_openElements.inScope(token.name())) {
+ parseError(token);
+ return;
}
- break;
- case HTMLToken::EndTag:
- if (token.name() == bodyTag || token.name() == htmlTag || token.name() == brTag)
- break;
+ generateImpliedEndTags();
+ if (currentElement()->tagQName() != token.name())
+ parseError(token);
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
+ m_activeFormattingElements.clearToLastMarker();
+ return;
+ }
+ if (token.name() == brTag) {
+ parseError(token);
+ reconstructTheActiveFormattingElements();
+ // Notice that we lose the attributes.
+ AtomicHTMLToken startBr(HTMLToken::StartTag, token.name());
+ insertSelfClosingElement(startBr);
+ m_framesetOk = false;
+ return;
+ }
+ // FIXME: We need an iterator over m_openElements to implement this
+ // correctly.
+ notImplemented();
+ if (!m_openElements.inScope(token.name()))
+ return;
+ m_openElements.popUntil(token.name());
+ m_openElements.pop();
+ break;
+ case AfterBodyMode:
+ ASSERT(insertionMode() == AfterBodyMode);
+ if (token.name() == htmlTag) {
+ if (m_isParsingFragment) {
+ parseError(token);
+ return;
+ }
+ m_insertionMode = AfterAfterBodyMode;
+ return;
+ }
+ // Fall through.
+ case AfterAfterBodyMode:
+ ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
+ parseError(token);
+ m_insertionMode = InBodyMode;
+ processEndTag(token);
+ break;
+ case InHeadNoscriptMode:
+ ASSERT(insertionMode() == InHeadNoscriptMode);
+ if (token.name() == noscriptTag) {
+ ASSERT(currentElement()->tagQName() == noscriptTag);
+ m_openElements.pop();
+ ASSERT(currentElement()->tagQName() == headTag);
+ setInsertionMode(InHeadMode);
+ return;
+ }
+ if (token.name() != brTag) {
parseError(token);
- return 0;
- case HTMLToken::EndOfFile:
- break;
- }
- AtomicHTMLToken fakeBody(HTMLToken::StartTag, bodyTag.localName());
- processToken(fakeBody);
- m_framesetOk = true;
- goto reprocessToken;
+ return;
+ }
+ processDefaultForInHeadNoscriptMode(token);
+ processToken(token);
+ break;
+ case TextMode:
+ if (token.name() == scriptTag) {
+ // Pause ourselves so that parsing stops until the script can be processed by the caller.
+ m_isPaused = true;
+ ASSERT(currentElement()->tagQName() == scriptTag);
+ m_scriptToProcess = currentElement();
+ m_openElements.pop();
+ m_insertionMode = m_originalInsertionMode;
+ return;
+ }
+ m_openElements.pop();
+ m_insertionMode = m_originalInsertionMode;
+ break;
+ case InFramesetMode:
+ ASSERT(insertionMode() == InFramesetMode);
+ if (token.name() == framesetTag) {
+ if (currentElement() == m_openElements.htmlElement()) {
+ parseError(token);
+ return;
+ }
+ m_openElements.pop();
+ if (!m_isParsingFragment && !currentElement()->hasTagName(framesetTag))
+ m_insertionMode = AfterFramesetMode;
+ return;
+ }
+ break;
+ case AfterFramesetMode:
+ ASSERT(insertionMode() == AfterFramesetMode);
+ if (token.name() == htmlTag) {
+ m_insertionMode = AfterAfterFramesetMode;
+ return;
+ }
+ // Fall through.
+ case AfterAfterFramesetMode:
+ ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
+ parseError(token);
+ break;
+ default:
+ notImplemented();
}
+}
+
+void HTMLTreeBuilder::processComment(AtomicHTMLToken& token)
+{
+ if (m_insertionMode == InitialMode || m_insertionMode == BeforeHTMLMode || m_insertionMode == AfterAfterBodyMode || m_insertionMode == AfterAfterFramesetMode) {
+ insertCommentOnDocument(token);
+ return;
+ }
+ if (m_insertionMode == AfterBodyMode) {
+ insertCommentOnHTMLHtmlElement(token);
+ return;
+ }
+ insertComment(token);
+}
+
+void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
+{
+ // FIXME: We need to figure out how to handle each character individually.
+ switch (insertionMode()) {
+ case InitialMode:
+ ASSERT(insertionMode() == InitialMode);
+ notImplemented();
+ processDefaultForInitialMode(token);
+ // Fall through.
+ case BeforeHTMLMode:
+ ASSERT(insertionMode() == BeforeHTMLMode);
+ notImplemented();
+ processDefaultForBeforeHTMLMode(token);
+ // Fall through.
+ case BeforeHeadMode:
+ ASSERT(insertionMode() == BeforeHeadMode);
+ notImplemented();
+ processDefaultForBeforeHeadMode(token);
+ // Fall through.
+ case InHeadMode:
+ ASSERT(insertionMode() == InHeadMode);
+ notImplemented();
+ processDefaultForInHeadMode(token);
+ // Fall through.
+ case AfterHeadMode:
+ ASSERT(insertionMode() == AfterHeadMode);
+ notImplemented();
+ processDefaultForAfterHeadMode(token);
+ // Fall through
case InBodyMode:
- case TextMode:
- case InTableMode:
- case InTableTextMode:
- case InCaptionMode:
- case InColumnGroupMode:
- case InTableBodyMode:
- case InRowMode:
- case InCellMode:
- case InSelectMode:
- case InSelectInTableMode:
- case InForeignContentMode:
+ ASSERT(insertionMode() == InBodyMode);
+ notImplemented();
+ insertTextNode(token);
+ break;
case AfterBodyMode:
+ case AfterAfterBodyMode:
+ ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
+ parseError(token);
+ m_insertionMode = InBodyMode;
+ processCharacter(token);
+ break;
+ case TextMode:
+ notImplemented();
+ insertTextNode(token);
+ break;
+ case InHeadNoscriptMode:
+ ASSERT(insertionMode() == InHeadNoscriptMode);
+ processDefaultForInHeadNoscriptMode(token);
+ processToken(token);
+ break;
case InFramesetMode:
case AfterFramesetMode:
+ case AfterAfterFramesetMode:
+ ASSERT(insertionMode() == InFramesetMode || insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
+ parseError(token);
+ break;
+ default:
+ notImplemented();
+ }
+}
+
+void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
+{
+ switch (insertionMode()) {
+ case InitialMode:
+ ASSERT(insertionMode() == InitialMode);
+ processDefaultForInitialMode(token);
+ // Fall through.
+ case BeforeHTMLMode:
+ ASSERT(insertionMode() == BeforeHTMLMode);
+ processDefaultForBeforeHTMLMode(token);
+ // Fall through.
+ case BeforeHeadMode:
+ ASSERT(insertionMode() == BeforeHeadMode);
+ processDefaultForBeforeHeadMode(token);
+ // Fall through.
+ case InHeadMode:
+ ASSERT(insertionMode() == InHeadMode);
+ processDefaultForInHeadMode(token);
+ // Fall through.
+ case AfterHeadMode:
+ ASSERT(insertionMode() == AfterHeadMode);
+ processDefaultForAfterHeadMode(token);
+ // Fall through
+ case InBodyMode:
+ ASSERT(insertionMode() == InBodyMode);
+ notImplemented();
+ break;
+ case AfterBodyMode:
case AfterAfterBodyMode:
+ ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
+ notImplemented();
+ break;
+ case InHeadNoscriptMode:
+ ASSERT(insertionMode() == InHeadNoscriptMode);
+ processDefaultForInHeadNoscriptMode(token);
+ processToken(token);
+ break;
+ case InFramesetMode:
+ ASSERT(insertionMode() == InFramesetMode);
+ if (currentElement() != m_openElements.htmlElement())
+ parseError(token);
+ break;
+ case AfterFramesetMode:
case AfterAfterFramesetMode:
- ASSERT_NOT_REACHED();
+ ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
+ break;
+ default:
+ notImplemented();
}
+}
- // Implementation coming in the next patch.
- return 0;
+void HTMLTreeBuilder::processDefaultForInitialMode(AtomicHTMLToken& token)
+{
+ notImplemented();
+ parseError(token);
+ setInsertionMode(BeforeHTMLMode);
}
-PassRefPtr<Node> HTMLTreeBuilder::insertDoctype(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processDefaultForBeforeHTMLMode(AtomicHTMLToken&)
{
- ASSERT_UNUSED(token, token.type() == HTMLToken::DOCTYPE);
- return 0;
+ AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag.localName());
+ insertHTMLStartTagBeforeHTML(startHTML);
+ setInsertionMode(BeforeHeadMode);
}
-PassRefPtr<Node> HTMLTreeBuilder::insertComment(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processDefaultForBeforeHeadMode(AtomicHTMLToken&)
{
- ASSERT_UNUSED(token, token.type() == HTMLToken::Comment);
- return 0;
+ AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
+ processStartTag(startHead);
}
-PassRefPtr<Element> HTMLTreeBuilder::insertElement(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processDefaultForInHeadMode(AtomicHTMLToken&)
{
- ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
- return 0;
+ AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
+ processEndTag(endHead);
}
-void HTMLTreeBuilder::insertCharacter(UChar cc)
+void HTMLTreeBuilder::processDefaultForInHeadNoscriptMode(AtomicHTMLToken&)
{
- ASSERT_UNUSED(cc, cc);
+ AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
+ processEndTag(endNoscript);
}
-PassRefPtr<Node> HTMLTreeBuilder::insertGenericRCDATAElement(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processDefaultForAfterHeadMode(AtomicHTMLToken&)
{
- ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
- return 0;
+ AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
+ processStartTag(startBody);
+ m_framesetOk = true;
}
-PassRefPtr<Node> HTMLTreeBuilder::insertGenericRawTextElement(AtomicHTMLToken& token)
+bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken& token)
{
- ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
- return 0;
+ if (token.name() == htmlTag) {
+ insertHTMLStartTagInBody(token);
+ return true;
+ }
+ // FIXME: Atomize "command".
+ if (token.name() == baseTag || token.name() == "command" || token.name() == linkTag || token.name() == metaTag) {
+ insertSelfClosingElement(token);
+ // Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
+ return true;
+ }
+ if (token.name() == titleTag) {
+ insertGenericRCDATAElement(token);
+ return true;
+ }
+ if (token.name() == noscriptTag) {
+ if (isScriptingFlagEnabled(m_document->frame())) {
+ insertGenericRawTextElement(token);
+ return true;
+ }
+ insertElement(token);
+ setInsertionMode(InHeadNoscriptMode);
+ return true;
+ }
+ if (token.name() == noframesTag || token.name() == styleTag) {
+ insertGenericRawTextElement(token);
+ return true;
+ }
+ if (token.name() == scriptTag) {
+ insertScriptElement(token);
+ return true;
+ }
+ if (token.name() == headTag) {
+ parseError(token);
+ return true;
+ }
+ return false;
+}
+
+void HTMLTreeBuilder::insertDoctype(AtomicHTMLToken& token)
+{
+ ASSERT(token.type() == HTMLToken::DOCTYPE);
+ attach(m_document, DocumentType::create(m_document, token.name(), String::adopt(token.publicIdentifier()), String::adopt(token.systemIdentifier())));
+ // FIXME: Move quirks mode detection from DocumentType element to here.
+ notImplemented();
+ if (token.forceQuirks())
+ m_document->setParseMode(Document::Compat);
+}
+
+void HTMLTreeBuilder::insertComment(AtomicHTMLToken& token)
+{
+ ASSERT(token.type() == HTMLToken::Comment);
+ attach(currentElement(), Comment::create(m_document, token.comment()));
+}
+
+void HTMLTreeBuilder::insertCommentOnDocument(AtomicHTMLToken& token)
+{
+ ASSERT(token.type() == HTMLToken::Comment);
+ attach(m_document, Comment::create(m_document, token.comment()));
+}
+
+void HTMLTreeBuilder::insertCommentOnHTMLHtmlElement(AtomicHTMLToken& token)
+{
+ ASSERT(token.type() == HTMLToken::Comment);
+ attach(m_openElements.htmlElement(), Comment::create(m_document, token.comment()));
+}
+
+PassRefPtr<Element> HTMLTreeBuilder::createElementAndAttachToCurrent(AtomicHTMLToken& token)
+{
+ ASSERT(token.type() == HTMLToken::StartTag);
+ return attach(currentElement(), createElement(token));
+}
+
+void HTMLTreeBuilder::insertHTMLHtmlElement(AtomicHTMLToken& token)
+{
+ m_openElements.pushHTMLHtmlElement(createElementAndAttachToCurrent(token));
}
-PassRefPtr<Node> HTMLTreeBuilder::insertScriptElement(AtomicHTMLToken& token)
+void HTMLTreeBuilder::insertHTMLHeadElement(AtomicHTMLToken& token)
+{
+ m_headElement = createElementAndAttachToCurrent(token);
+ m_openElements.pushHTMLHeadElement(m_headElement);
+}
+
+void HTMLTreeBuilder::insertHTMLBodyElement(AtomicHTMLToken& token)
+{
+ m_openElements.pushHTMLBodyElement(createElementAndAttachToCurrent(token));
+}
+
+void HTMLTreeBuilder::insertElement(AtomicHTMLToken& token)
+{
+ m_openElements.push(createElementAndAttachToCurrent(token));
+}
+
+void HTMLTreeBuilder::insertSelfClosingElement(AtomicHTMLToken& token)
+{
+ ASSERT(token.type() == HTMLToken::StartTag);
+ attach(currentElement(), createElement(token));
+ // FIXME: Do we want to acknowledge the token's self-closing flag?
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#acknowledge-self-closing-flag
+}
+
+void HTMLTreeBuilder::insertFormattingElement(AtomicHTMLToken& token)
+{
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements
+ // Possible active formatting elements include:
+ // a, b, big, code, em, font, i, nobr, s, small, strike, strong, tt, and u.
+ insertElement(token);
+ m_activeFormattingElements.append(currentElement());
+}
+
+void HTMLTreeBuilder::insertGenericRCDATAElement(AtomicHTMLToken& token)
+{
+ insertElement(token);
+ m_tokenizer->setState(HTMLTokenizer::RCDATAState);
+ m_originalInsertionMode = m_insertionMode;
+ m_insertionMode = TextMode;
+}
+
+void HTMLTreeBuilder::insertGenericRawTextElement(AtomicHTMLToken& token)
+{
+ insertElement(token);
+ m_tokenizer->setState(HTMLTokenizer::RAWTEXTState);
+ m_originalInsertionMode = m_insertionMode;
+ m_insertionMode = TextMode;
+}
+
+void HTMLTreeBuilder::insertScriptElement(AtomicHTMLToken& token)
{
ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
- return 0;
+ RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, m_document, true);
+ element->setAttributeMap(token.attributes(), m_fragmentScriptingPermission);
+ m_openElements.push(attach(currentElement(), element.release()));
+ m_tokenizer->setState(HTMLTokenizer::ScriptDataState);
+ m_originalInsertionMode = m_insertionMode;
+ m_insertionMode = TextMode;
+}
+
+void HTMLTreeBuilder::insertTextNode(AtomicHTMLToken& token)
+{
+ attach(currentElement(), Text::create(m_document, token.characters()));
+}
+
+PassRefPtr<Element> HTMLTreeBuilder::createElement(AtomicHTMLToken& token)
+{
+ RefPtr<Element> element = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, token.name(), xhtmlNamespaceURI), m_document, 0);
+ element->setAttributeMap(token.attributes(), m_fragmentScriptingPermission);
+ return element.release();
+}
+
+bool HTMLTreeBuilder::indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const
+{
+ if (m_activeFormattingElements.isEmpty())
+ return false;
+ unsigned index = m_activeFormattingElements.size();
+ do {
+ --index;
+ const HTMLFormattingElementList::Entry& entry = m_activeFormattingElements[index];
+ if (entry.isMarker() || m_openElements.contains(entry.element())) {
+ firstUnopenElementIndex = index;
+ return true;
+ }
+ } while (index);
+ return false;
+}
+
+void HTMLTreeBuilder::reconstructTheActiveFormattingElements()
+{
+ unsigned firstUnopenElementIndex;
+ if (!indexOfFirstUnopenFormattingElement(firstUnopenElementIndex))
+ return;
+
+ unsigned unopenEntryIndex = firstUnopenElementIndex;
+ ASSERT(unopenEntryIndex < m_activeFormattingElements.size());
+ for (; unopenEntryIndex < m_activeFormattingElements.size(); ++unopenEntryIndex) {
+ HTMLFormattingElementList::Entry& unopenedEntry = m_activeFormattingElements[unopenEntryIndex];
+ // FIXME: We're supposed to save the original token in the entry.
+ AtomicHTMLToken fakeToken(HTMLToken::StartTag, unopenedEntry.element()->localName());
+ insertElement(fakeToken);
+ unopenedEntry.replaceElement(currentElement());
+ }
+}
+
+namespace {
+
+bool hasImpliedEndTag(Element* element)
+{
+ return element->hasTagName(ddTag)
+ || element->hasTagName(dtTag)
+ || element->hasTagName(liTag)
+ || element->hasTagName(optionTag)
+ || element->hasTagName(optgroupTag)
+ || element->hasTagName(pTag)
+ || element->hasTagName(rpTag)
+ || element->hasTagName(rtTag);
+}
+
+}
+
+void HTMLTreeBuilder::generateImpliedEndTagsWithExclusion(const AtomicString& tagName)
+{
+ while (hasImpliedEndTag(currentElement()) && !currentElement()->hasLocalName(tagName))
+ m_openElements.pop();
+}
+
+void HTMLTreeBuilder::generateImpliedEndTags()
+{
+ while (hasImpliedEndTag(currentElement()))
+ m_openElements.pop();
}
void HTMLTreeBuilder::finished()
{
// We should call m_document->finishedParsing() here, except
// m_legacyTreeBuilder->finished() does it for us.
- m_legacyTreeBuilder->finished();
+ if (m_legacyTreeBuilder) {
+ m_legacyTreeBuilder->finished();
+ return;
+ }
+
+ AtomicHTMLToken eofToken(HTMLToken::EndOfFile, nullAtom);
+ processToken(eofToken);
+
+ // Warning, this may delete the parser, so don't try to do anything else after this.
+ if (!m_isParsingFragment)
+ m_document->finishedParsing();
}
bool HTMLTreeBuilder::isScriptingFlagEnabled(Frame* frame)
diff --git a/WebCore/html/HTMLTreeBuilder.h b/WebCore/html/HTMLTreeBuilder.h
index 76360ae..37e4279 100644
--- a/WebCore/html/HTMLTreeBuilder.h
+++ b/WebCore/html/HTMLTreeBuilder.h
@@ -26,10 +26,14 @@
#ifndef HTMLTreeBuilder_h
#define HTMLTreeBuilder_h
+#include "Element.h"
#include "FragmentScriptingPermission.h"
+#include "HTMLElementStack.h"
+#include "HTMLFormattingElementList.h"
#include "HTMLTokenizer.h"
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
#include <wtf/unicode/Unicode.h>
@@ -39,7 +43,6 @@ namespace WebCore {
class AtomicHTMLToken;
class Document;
class DocumentFragment;
-class Element;
class Frame;
class HTMLToken;
class HTMLDocument;
@@ -57,7 +60,7 @@ public:
bool isPaused() const { return m_isPaused; }
// The token really should be passed as a const& since it's never modified.
- PassRefPtr<Node> constructTreeFromToken(HTMLToken&);
+ void constructTreeFromToken(HTMLToken&);
// Must be called when parser is paused before calling the parser again.
PassRefPtr<Element> takeScriptToProcess(int& scriptStartLine);
@@ -99,27 +102,83 @@ private:
AfterAfterFramesetMode,
};
- class ElementStack : public Noncopyable {
- public:
- void pop() { }
- void push(Element*) { }
- void remove(Element*) { }
- Element* top() const { return 0; }
- };
-
- PassRefPtr<Node> passTokenToLegacyParser(HTMLToken&);
- PassRefPtr<Node> processToken(AtomicHTMLToken&, UChar cc = 0);
-
- PassRefPtr<Node> insertDoctype(AtomicHTMLToken&);
- PassRefPtr<Node> insertComment(AtomicHTMLToken&);
- PassRefPtr<Element> insertElement(AtomicHTMLToken&);
- void insertCharacter(UChar cc);
- PassRefPtr<Node> insertGenericRCDATAElement(AtomicHTMLToken&);
- PassRefPtr<Node> insertGenericRawTextElement(AtomicHTMLToken&);
- PassRefPtr<Node> insertScriptElement(AtomicHTMLToken&);
+ void passTokenToLegacyParser(HTMLToken&);
+
+ // Specialized functions for processing the different types of tokens.
+ void processToken(AtomicHTMLToken&);
+ void processDoctypeToken(AtomicHTMLToken&);
+ void processStartTag(AtomicHTMLToken&);
+ void processEndTag(AtomicHTMLToken&);
+ void processComment(AtomicHTMLToken&);
+ void processCharacter(AtomicHTMLToken&);
+ void processEndOfFile(AtomicHTMLToken&);
+
+ // Default processing for the different insertion modes.
+ void processDefaultForInitialMode(AtomicHTMLToken&);
+ void processDefaultForBeforeHTMLMode(AtomicHTMLToken&);
+ void processDefaultForBeforeHeadMode(AtomicHTMLToken&);
+ void processDefaultForInHeadMode(AtomicHTMLToken&);
+ void processDefaultForInHeadNoscriptMode(AtomicHTMLToken&);
+ void processDefaultForAfterHeadMode(AtomicHTMLToken&);
+
+ bool processStartTagForInHead(AtomicHTMLToken&);
+ bool processBodyEndTagForInBody(AtomicHTMLToken&);
+ void processFakePEndTagIfPInScope();
+
+ HTMLElementStack::ElementRecord* furthestBlockForFormattingElement(Element*);
+ void findFosterParentFor(Element*);
+ void reparentChildren(Element* oldParent, Element* newParent);
+ void callTheAdoptionAgency(AtomicHTMLToken&);
+
+ template<typename ChildType>
+ PassRefPtr<ChildType> attach(Node* parent, PassRefPtr<ChildType> prpChild)
+ {
+ RefPtr<ChildType> child = prpChild;
+ parent->parserAddChild(child);
+ // It's slightly unfortunate that we need to hold a reference to child
+ // here to call attach(). We should investigate whether we can rely on
+ // |parent| to hold a ref at this point. In the common case (at least
+ // for elements), however, we'll get to use this ref in the stack of
+ // open elements.
+ child->attach();
+ return child.release();
+ }
+
+ void insertDoctype(AtomicHTMLToken&);
+ void insertComment(AtomicHTMLToken&);
+ void insertCommentOnDocument(AtomicHTMLToken&);
+ void insertCommentOnHTMLHtmlElement(AtomicHTMLToken&);
+ void insertHTMLHtmlElement(AtomicHTMLToken&);
+ void insertHTMLHeadElement(AtomicHTMLToken&);
+ void insertHTMLBodyElement(AtomicHTMLToken&);
+ void insertElement(AtomicHTMLToken&);
+ void insertSelfClosingElement(AtomicHTMLToken&);
+ void insertFormattingElement(AtomicHTMLToken&);
+ void insertGenericRCDATAElement(AtomicHTMLToken&);
+ void insertGenericRawTextElement(AtomicHTMLToken&);
+ void insertScriptElement(AtomicHTMLToken&);
+ void insertTextNode(AtomicHTMLToken&);
+
+ void insertHTMLStartTagBeforeHTML(AtomicHTMLToken&);
+ void insertHTMLStartTagInBody(AtomicHTMLToken&);
+
+ PassRefPtr<Element> createElement(AtomicHTMLToken&);
+ PassRefPtr<Element> createElementAndAttachToCurrent(AtomicHTMLToken&);
+
+ void mergeAttributesFromTokenIntoElement(AtomicHTMLToken&, Element*);
+
+ bool indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const;
+ void reconstructTheActiveFormattingElements();
+
+ void generateImpliedEndTags();
+ void generateImpliedEndTagsWithExclusion(const AtomicString& tagName);
+
+ Element* currentElement() { return m_openElements.top(); }
RefPtr<Element> m_headElement;
- ElementStack m_openElements;
+ RefPtr<Element> m_formElement;
+ HTMLElementStack m_openElements;
+ HTMLFormattingElementList m_activeFormattingElements;
bool m_framesetOk;
// FIXME: Implement error reporting.
@@ -138,6 +197,7 @@ private:
bool m_isPaused;
InsertionMode m_insertionMode;
+ InsertionMode m_originalInsertionMode;
// HTML5 spec requires that we be able to change the state of the tokenizer
// from within parser actions.
@@ -158,6 +218,7 @@ private:
// FragmentScriptingNotAllowed causes the Parser to remove children
// from <script> tags (so javascript doesn't show up in pastes).
FragmentScriptingPermission m_fragmentScriptingPermission;
+ bool m_isParsingFragment;
};
}
diff --git a/WebCore/html/HTMLUListElement.cpp b/WebCore/html/HTMLUListElement.cpp
index e022ba9..4b121aa 100644
--- a/WebCore/html/HTMLUListElement.cpp
+++ b/WebCore/html/HTMLUListElement.cpp
@@ -65,24 +65,4 @@ void HTMLUListElement::parseMappedAttribute(Attribute* attr)
HTMLElement::parseMappedAttribute(attr);
}
-bool HTMLUListElement::compact() const
-{
- return !getAttribute(compactAttr).isNull();
-}
-
-void HTMLUListElement::setCompact(bool b)
-{
- setAttribute(compactAttr, b ? "" : 0);
-}
-
-String HTMLUListElement::type() const
-{
- return getAttribute(typeAttr);
-}
-
-void HTMLUListElement::setType(const String &value)
-{
- setAttribute(typeAttr, value);
-}
-
}
diff --git a/WebCore/html/HTMLUListElement.h b/WebCore/html/HTMLUListElement.h
index 0b74c43..996626c 100644
--- a/WebCore/html/HTMLUListElement.h
+++ b/WebCore/html/HTMLUListElement.h
@@ -32,12 +32,6 @@ public:
static PassRefPtr<HTMLUListElement> create(Document*);
static PassRefPtr<HTMLUListElement> create(const QualifiedName&, Document*);
- bool compact() const;
- void setCompact(bool);
-
- String type() const;
- void setType(const String&);
-
private:
HTMLUListElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLUListElement.idl b/WebCore/html/HTMLUListElement.idl
index f6d3b78..221dcca 100644
--- a/WebCore/html/HTMLUListElement.idl
+++ b/WebCore/html/HTMLUListElement.idl
@@ -20,7 +20,7 @@
module html {
interface HTMLUListElement : HTMLElement {
- attribute boolean compact;
+ attribute [Reflect] boolean compact;
attribute [Reflect] DOMString type;
};
diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp
index 9fd1a09..cf7d64c 100644
--- a/WebCore/html/HTMLVideoElement.cpp
+++ b/WebCore/html/HTMLVideoElement.cpp
@@ -154,11 +154,6 @@ unsigned HTMLVideoElement::width() const
unsigned w = getAttribute(widthAttr).string().toUInt(&ok);
return ok ? w : 0;
}
-
-void HTMLVideoElement::setWidth(unsigned value)
-{
- setAttribute(widthAttr, String::number(value));
-}
unsigned HTMLVideoElement::height() const
{
@@ -167,16 +162,6 @@ unsigned HTMLVideoElement::height() const
return ok ? h : 0;
}
-void HTMLVideoElement::setHeight(unsigned value)
-{
- setAttribute(heightAttr, String::number(value));
-}
-
-void HTMLVideoElement::setPoster(const String& value)
-{
- setAttribute(posterAttr, value);
-}
-
bool HTMLVideoElement::isURLAttribute(Attribute* attribute) const
{
return HTMLMediaElement::isURLAttribute(attribute)
diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h
index 4b8acbb..c27962f 100644
--- a/WebCore/html/HTMLVideoElement.h
+++ b/WebCore/html/HTMLVideoElement.h
@@ -39,15 +39,12 @@ public:
static PassRefPtr<HTMLVideoElement> create(const QualifiedName&, Document*);
unsigned width() const;
- void setWidth(unsigned);
unsigned height() const;
- void setHeight(unsigned);
unsigned videoWidth() const;
unsigned videoHeight() const;
virtual const KURL poster() const { return m_posterURL; }
- void setPoster(const String&);
// Fullscreen
void webkitEnterFullscreen(bool isUserGesture, ExceptionCode&);
diff --git a/WebCore/html/HTMLViewSourceDocument.cpp b/WebCore/html/HTMLViewSourceDocument.cpp
index f66703a..6cee27c 100644
--- a/WebCore/html/HTMLViewSourceDocument.cpp
+++ b/WebCore/html/HTMLViewSourceDocument.cpp
@@ -69,10 +69,10 @@ DocumentParser* HTMLViewSourceDocument::createParser()
void HTMLViewSourceDocument::createContainingTable()
{
RefPtr<HTMLHtmlElement> html = HTMLHtmlElement::create(this);
- addChild(html);
+ legacyParserAddChild(html);
html->attach();
RefPtr<HTMLBodyElement> body = HTMLBodyElement::create(this);
- html->addChild(body);
+ html->legacyParserAddChild(body);
body->attach();
// Create a line gutter div that can be used to make sure the gutter extends down the height of the whole
@@ -81,14 +81,14 @@ void HTMLViewSourceDocument::createContainingTable()
RefPtr<NamedNodeMap> attrs = NamedNodeMap::create();
attrs->addAttribute(Attribute::createMapped(classAttr, "webkit-line-gutter-backdrop"));
div->setAttributeMap(attrs.release());
- body->addChild(div);
+ body->legacyParserAddChild(div);
div->attach();
RefPtr<HTMLTableElement> table = HTMLTableElement::create(this);
- body->addChild(table);
+ body->legacyParserAddChild(table);
table->attach();
m_tbody = HTMLTableSectionElement::create(tbodyTag, this);
- table->addChild(m_tbody);
+ table->legacyParserAddChild(m_tbody);
m_tbody->attach();
m_current = m_tbody;
}
@@ -214,7 +214,7 @@ PassRefPtr<Element> HTMLViewSourceDocument::addSpanWithClassName(const String& c
RefPtr<NamedNodeMap> attrs = NamedNodeMap::create();
attrs->addAttribute(Attribute::createMapped(classAttr, className));
span->setAttributeMap(attrs.release());
- m_current->addChild(span);
+ m_current->legacyParserAddChild(span);
span->attach();
return span.release();
}
@@ -223,7 +223,7 @@ void HTMLViewSourceDocument::addLine(const String& className)
{
// Create a table row.
RefPtr<HTMLTableRowElement> trow = HTMLTableRowElement::create(this);
- m_tbody->addChild(trow);
+ m_tbody->legacyParserAddChild(trow);
trow->attach();
// Create a cell that will hold the line number (it is generated in the stylesheet using counters).
@@ -231,7 +231,7 @@ void HTMLViewSourceDocument::addLine(const String& className)
RefPtr<NamedNodeMap> attrs = NamedNodeMap::create();
attrs->addAttribute(Attribute::createMapped(classAttr, "webkit-line-number"));
td->setAttributeMap(attrs.release());
- trow->addChild(td);
+ trow->legacyParserAddChild(td);
td->attach();
// Create a second cell for the line contents
@@ -239,7 +239,7 @@ void HTMLViewSourceDocument::addLine(const String& className)
attrs = NamedNodeMap::create();
attrs->addAttribute(Attribute::createMapped(classAttr, "webkit-line-content"));
td->setAttributeMap(attrs.release());
- trow->addChild(td);
+ trow->legacyParserAddChild(td);
td->attach();
m_current = m_td = td;
@@ -276,7 +276,7 @@ void HTMLViewSourceDocument::addText(const String& text, const String& className
if (m_current == m_tbody)
addLine(className);
RefPtr<Text> t = Text::create(this, substring);
- m_current->addChild(t);
+ m_current->legacyParserAddChild(t);
t->attach();
if (i < size - 1)
m_current = m_tbody;
@@ -304,7 +304,7 @@ PassRefPtr<Element> HTMLViewSourceDocument::addLink(const String& url, bool isAn
attrs->addAttribute(Attribute::createMapped(targetAttr, "_blank"));
attrs->addAttribute(Attribute::createMapped(hrefAttr, url));
anchor->setAttributeMap(attrs.release());
- m_current->addChild(anchor);
+ m_current->legacyParserAddChild(anchor);
anchor->attach();
return anchor.release();
}
diff --git a/WebCore/html/LegacyHTMLDocumentParser.cpp b/WebCore/html/LegacyHTMLDocumentParser.cpp
index 38c8a75..cb5fac8 100644
--- a/WebCore/html/LegacyHTMLDocumentParser.cpp
+++ b/WebCore/html/LegacyHTMLDocumentParser.cpp
@@ -147,7 +147,7 @@ inline void Token::addAttribute(AtomicString& attrName, const AtomicString& attr
// ----------------------------------------------------------------------------
LegacyHTMLDocumentParser::LegacyHTMLDocumentParser(HTMLDocument* document, bool reportErrors)
- : DocumentParser(document)
+ : ScriptableDocumentParser(document)
, m_buffer(0)
, m_scriptCode(0)
, m_scriptCodeSize(0)
@@ -167,7 +167,7 @@ LegacyHTMLDocumentParser::LegacyHTMLDocumentParser(HTMLDocument* document, bool
}
LegacyHTMLDocumentParser::LegacyHTMLDocumentParser(HTMLViewSourceDocument* document)
- : DocumentParser(document, true)
+ : ScriptableDocumentParser(document, true)
, m_buffer(0)
, m_scriptCode(0)
, m_scriptCodeSize(0)
@@ -186,7 +186,7 @@ LegacyHTMLDocumentParser::LegacyHTMLDocumentParser(HTMLViewSourceDocument* docum
}
LegacyHTMLDocumentParser::LegacyHTMLDocumentParser(DocumentFragment* frag, FragmentScriptingPermission scriptingPermission)
- : DocumentParser(frag->document())
+ : ScriptableDocumentParser(frag->document())
, m_buffer(0)
, m_scriptCode(0)
, m_scriptCodeSize(0)
@@ -1391,7 +1391,7 @@ LegacyHTMLDocumentParser::State LegacyHTMLDocumentParser::parseTag(SegmentedStri
if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_treeBuilder->skipMode() && m_attrName == srcAttr) {
String context(m_rawAttributeBeforeValue.data(), m_rawAttributeBeforeValue.size());
- if (m_XSSAuditor && !m_XSSAuditor->canLoadExternalScriptFromSrc(attributeValue))
+ if (xssAuditor() && !xssAuditor()->canLoadExternalScriptFromSrc(attributeValue))
attributeValue = blankURL().string();
}
@@ -1428,7 +1428,7 @@ LegacyHTMLDocumentParser::State LegacyHTMLDocumentParser::parseTag(SegmentedStri
if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_treeBuilder->skipMode() && m_attrName == srcAttr) {
String context(m_rawAttributeBeforeValue.data(), m_rawAttributeBeforeValue.size());
- if (m_XSSAuditor && !m_XSSAuditor->canLoadExternalScriptFromSrc(attributeValue))
+ if (xssAuditor() && !xssAuditor()->canLoadExternalScriptFromSrc(attributeValue))
attributeValue = blankURL().string();
}
@@ -1787,8 +1787,28 @@ void LegacyHTMLDocumentParser::write(const SegmentedString& str, bool appendData
if (m_noMoreData && !m_inWrite && !state.loadingExtScript() && !m_executingScript && !m_timer.isActive())
end(); // this actually causes us to be deleted
- // After parsing, go ahead and dispatch image beforeload events.
- ImageLoader::dispatchPendingBeforeLoadEvents();
+ // After parsing, go ahead and dispatch image beforeload events, but only if we're doing
+ // document parsing. For document fragments we wait, since they'll likely end up in the document by the time
+ // the beforeload events fire.
+ if (!m_fragment)
+ ImageLoader::dispatchPendingBeforeLoadEvents();
+}
+
+void LegacyHTMLDocumentParser::insert(const SegmentedString& source)
+{
+ // FIXME: forceSynchronous should always be the same as the bool passed to
+ // write(). However LegacyHTMLDocumentParser uses write("", false) to pump
+ // the parser (after running external scripts, etc.) thus necessitating a
+ // separate state for forceSynchronous.
+ bool wasForcedSynchronous = forceSynchronous();
+ setForceSynchronous(true);
+ write(source, false);
+ setForceSynchronous(wasForcedSynchronous);
+}
+
+void LegacyHTMLDocumentParser::append(const SegmentedString& source)
+{
+ write(source, true);
}
void LegacyHTMLDocumentParser::stopParsing()
diff --git a/WebCore/html/LegacyHTMLDocumentParser.h b/WebCore/html/LegacyHTMLDocumentParser.h
index 5b96bc3..49e6976 100644
--- a/WebCore/html/LegacyHTMLDocumentParser.h
+++ b/WebCore/html/LegacyHTMLDocumentParser.h
@@ -28,9 +28,9 @@
#include "CachedResourceHandle.h"
#include "FragmentScriptingPermission.h"
#include "NamedNodeMap.h"
+#include "ScriptableDocumentParser.h"
#include "SegmentedString.h"
#include "Timer.h"
-#include "DocumentParser.h"
#include <wtf/Deque.h>
#include <wtf/OwnPtr.h>
#include <wtf/Vector.h>
@@ -140,7 +140,7 @@ public:
// (like dealing with <script> tags). The HTML tokenizer bits should be pushed
// down into a separate HTML tokenizer class.
-class LegacyHTMLDocumentParser : public DocumentParser, public CachedResourceClient {
+class LegacyHTMLDocumentParser : public ScriptableDocumentParser, public CachedResourceClient {
public:
LegacyHTMLDocumentParser(HTMLDocument*, bool reportErrors);
LegacyHTMLDocumentParser(HTMLViewSourceDocument*);
@@ -150,18 +150,16 @@ public:
bool forceSynchronous() const { return m_state.forceSynchronous(); }
void setForceSynchronous(bool force);
- // Exposed for LegacyHTMLTreeBuilder::reportErrorToConsole
- bool processingContentWrittenByScript() const { return m_src.excludeLineNumbers(); }
-
static void parseDocumentFragment(const String&, DocumentFragment*, FragmentScriptingPermission = FragmentScriptingAllowed);
protected:
// Exposed for FTPDirectoryDocumentParser
- virtual void write(const SegmentedString&, bool appendData);
+ virtual void insert(const SegmentedString&);
virtual void finish();
private:
- // DocumentParser
+ // ScriptableDocumentParser
+ virtual void append(const SegmentedString&);
virtual bool finishWasCalled();
virtual bool isWaitingForScripts() const;
virtual void stopParsing();
@@ -171,10 +169,11 @@ private:
virtual int lineNumber() const { return m_lineNumber; }
virtual int columnNumber() const { return 1; }
+ virtual bool processingContentWrittenByScript() const { return m_src.excludeLineNumbers(); }
+
virtual void executeScriptsWaitingForStylesheets();
virtual LegacyHTMLTreeBuilder* htmlTreeBuilder() const { return m_treeBuilder.get(); }
- virtual LegacyHTMLDocumentParser* asHTMLDocumentParser() { return this; }
class State;
@@ -183,6 +182,7 @@ private:
void reset();
void willWriteHTML(const SegmentedString&);
+ void write(const SegmentedString&, bool appendData);
ALWAYS_INLINE void advance(State&);
void didWriteHTML();
diff --git a/WebCore/html/LegacyHTMLTreeBuilder.cpp b/WebCore/html/LegacyHTMLTreeBuilder.cpp
index 7b44943..afd79b6 100644
--- a/WebCore/html/LegacyHTMLTreeBuilder.cpp
+++ b/WebCore/html/LegacyHTMLTreeBuilder.cpp
@@ -67,7 +67,7 @@ using namespace HTMLNames;
static const unsigned cMaxRedundantTagDepth = 20;
static const unsigned cResidualStyleMaxDepth = 200;
-static const unsigned cResidualStyleIterationLimit = 5;
+static const unsigned cResidualStyleIterationLimit = 10;
static const int minBlockLevelTagPriority = 3;
@@ -344,7 +344,7 @@ void LegacyHTMLTreeBuilder::parseDoctypeToken(DoctypeToken* t)
return;
// Make a new doctype node and set it as our doctype.
- m_document->addChild(DocumentType::create(m_document, String::adopt(t->m_name), String::adopt(t->m_publicID), String::adopt(t->m_systemID)));
+ m_document->legacyParserAddChild(DocumentType::create(m_document, String::adopt(t->m_name), String::adopt(t->m_publicID), String::adopt(t->m_systemID)));
if (t->m_forceQuirks)
m_document->setParseMode(Document::Compat);
}
@@ -390,7 +390,7 @@ bool LegacyHTMLTreeBuilder::insertNode(Node* n, bool flat)
// let's be stupid and just try to insert it.
// this should work if the document is well-formed
- Node* newNode = m_current->addChild(n);
+ Node* newNode = m_current->legacyParserAddChild(n);
if (!newNode)
return handleError(n, flat, localName, tagPriority); // Try to handle the error.
@@ -459,12 +459,12 @@ bool LegacyHTMLTreeBuilder::handleError(Node* n, bool flat, const AtomicString&
if (m_head) {
if (!createdHead)
reportError(MisplacedHeadContentError, &localName, &m_current->localName());
- if (m_head->addChild(n)) {
+ if (m_head->legacyParserAddChild(n)) {
if (!n->attached() && !m_isParsingFragment)
n->attach();
return true;
- } else
- return false;
+ }
+ return false;
}
} else if (h->hasLocalName(htmlTag)) {
if (!m_current->isDocumentNode() ) {
@@ -490,7 +490,7 @@ bool LegacyHTMLTreeBuilder::handleError(Node* n, bool flat, const AtomicString&
createdHead = true;
}
if (m_head) {
- Node* newNode = m_head->addChild(n);
+ Node* newNode = m_head->legacyParserAddChild(n);
if (!newNode) {
setSkipMode(h->tagQName());
return false;
@@ -530,7 +530,7 @@ bool LegacyHTMLTreeBuilder::handleError(Node* n, bool flat, const AtomicString&
} else if (h->hasLocalName(areaTag)) {
if (m_currentMapElement) {
reportError(MisplacedAreaError, &m_current->localName());
- m_currentMapElement->addChild(n);
+ m_currentMapElement->legacyParserAddChild(n);
if (!n->attached() && !m_isParsingFragment)
n->attach();
handled = true;
@@ -944,7 +944,7 @@ PassRefPtr<Node> LegacyHTMLTreeBuilder::getNode(Token* t)
QualifiedName nestedCreateErrorTags[] = { aTag, buttonTag, nobrTag, trTag };
mapTagsToFunc(gFunctionMap, nestedCreateErrorTags, &LegacyHTMLTreeBuilder::nestedCreateErrorCheck);
- QualifiedName nestedStyleCreateErrorTags[] = { bTag, bigTag, iTag, sTag, smallTag, strikeTag, ttTag, uTag };
+ QualifiedName nestedStyleCreateErrorTags[] = { bTag, bigTag, iTag, markTag, sTag, smallTag, strikeTag, ttTag, uTag };
mapTagsToFunc(gFunctionMap, nestedStyleCreateErrorTags, &LegacyHTMLTreeBuilder::nestedStyleCreateErrorCheck);
QualifiedName pCloserCreateErrorTags[] = { addressTag, articleTag,
@@ -1057,7 +1057,7 @@ bool LegacyHTMLTreeBuilder::isInline(Node* node) const
e->hasLocalName(abbrTag) || e->hasLocalName(acronymTag) || e->hasLocalName(subTag) ||
e->hasLocalName(supTag) || e->hasLocalName(spanTag) || e->hasLocalName(nobrTag) ||
e->hasLocalName(noframesTag) || e->hasLocalName(nolayerTag) ||
- e->hasLocalName(noembedTag))
+ e->hasLocalName(noembedTag) || e->hasLocalName(markTag))
return true;
#if !ENABLE(XHTMLMP)
if (e->hasLocalName(noscriptTag) && !m_isParsingFragment) {
@@ -1077,7 +1077,7 @@ bool LegacyHTMLTreeBuilder::isResidualStyleTag(const AtomicString& tagName)
if (residualStyleTags.isEmpty()) {
QualifiedName tagNames[] = { aTag, fontTag, ttTag, uTag, bTag, iTag,
sTag, strikeTag, bigTag, smallTag, emTag, strongTag, dfnTag,
- codeTag, sampTag, kbdTag, varTag, nobrTag };
+ codeTag, sampTag, kbdTag, varTag, nobrTag, markTag };
addTags(residualStyleTags, tagNames);
}
return residualStyleTags.contains(tagName.impl());
@@ -1606,10 +1606,10 @@ PassRefPtr<Node> LegacyHTMLTreeBuilder::handleIsindex(Token* t)
t->attrs = 0;
}
- n->addChild(HTMLHRElement::create(m_document));
- n->addChild(Text::create(m_document, text));
- n->addChild(isIndex.release());
- n->addChild(HTMLHRElement::create(m_document));
+ n->legacyParserAddChild(HTMLHRElement::create(m_document));
+ n->legacyParserAddChild(Text::create(m_document, text));
+ n->legacyParserAddChild(isIndex.release());
+ n->legacyParserAddChild(HTMLHRElement::create(m_document));
return n.release();
}
@@ -1647,8 +1647,9 @@ void LegacyHTMLTreeBuilder::reportErrorToConsole(HTMLParserErrorCode errorCode,
Frame* frame = m_document->frame();
if (!frame)
return;
-
- int lineNumber = m_document->parser()->lineNumber() + 1;
+
+ ScriptableDocumentParser* parser = m_document->scriptableDocumentParser();
+ int lineNumber = parser->lineNumber() + 1;
AtomicString tag1;
AtomicString tag2;
@@ -1674,9 +1675,7 @@ void LegacyHTMLTreeBuilder::reportErrorToConsole(HTMLParserErrorCode errorCode,
return;
String message;
- // FIXME: This doesn't work for the new HTMLDocumentParser and should.
- LegacyHTMLDocumentParser* htmlParser = m_document->parser()->asHTMLDocumentParser();
- if (htmlParser && htmlParser->processingContentWrittenByScript())
+ if (parser->processingContentWrittenByScript())
message += htmlParserDocumentWriteMessage();
message += errorMsg;
message.replace("%tag1", tag1);
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 522e51d..2ac2ca3 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -4,6 +4,7 @@
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
* Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,6 +45,7 @@
#include "GraphicsContext.h"
#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
+#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "ImageBuffer.h"
#include "ImageData.h"
@@ -572,9 +574,8 @@ void CanvasRenderingContext2D::quadraticCurveTo(float cpx, float cpy, float x, f
if (!state().m_invertibleCTM)
return;
if (!m_path.hasCurrentPoint())
- m_path.moveTo(FloatPoint(x, y));
- else
- m_path.addQuadCurveTo(FloatPoint(cpx, cpy), FloatPoint(x, y));
+ m_path.moveTo(FloatPoint(cpx, cpy));
+ m_path.addQuadCurveTo(FloatPoint(cpx, cpy), FloatPoint(x, y));
}
void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
@@ -584,9 +585,8 @@ void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x,
if (!state().m_invertibleCTM)
return;
if (!m_path.hasCurrentPoint())
- m_path.moveTo(FloatPoint(x, y));
- else
- m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), FloatPoint(x, y));
+ m_path.moveTo(FloatPoint(cp1x, cp1y));
+ m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), FloatPoint(x, y));
}
void CanvasRenderingContext2D::arcTo(float x0, float y0, float x1, float y1, float r, ExceptionCode& ec)
@@ -755,8 +755,9 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei
// from the HTML5 Canvas spec:
// If x0 = x1 and y0 = y1, then the linear gradient must paint nothing
+ // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint nothing
Gradient* gradient = c->fillGradient();
- if (gradient && gradient->isZeroSize() && !gradient->isRadial())
+ if (gradient && gradient->isZeroSize())
return;
FloatRect rect(x, y, width, height);
@@ -958,12 +959,20 @@ static inline FloatRect normalizeRect(const FloatRect& rect)
void CanvasRenderingContext2D::checkOrigin(const KURL& url)
{
+ if (m_cleanOrigins.contains(url.string()))
+ return;
+
if (canvas()->securityOrigin().taintsCanvas(url))
canvas()->setOriginTainted();
+ else
+ m_cleanOrigins.add(url.string());
}
void CanvasRenderingContext2D::checkOrigin(const String& url)
{
+ if (m_cleanOrigins.contains(url))
+ return;
+
checkOrigin(KURL(KURL(), url));
}
@@ -1009,6 +1018,13 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec
ec = 0;
+ if (!isfinite(dstRect.x()) || !isfinite(dstRect.y()) || !isfinite(dstRect.width()) || !isfinite(dstRect.height())
+ || !isfinite(srcRect.x()) || !isfinite(srcRect.y()) || !isfinite(srcRect.width()) || !isfinite(srcRect.height()))
+ return;
+
+ if (!image->complete())
+ return;
+
FloatRect imageRect = FloatRect(FloatPoint(), size(image));
if (!imageRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) {
ec = INDEX_SIZE_ERR;
@@ -1074,14 +1090,20 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
return;
}
- ec = 0;
-
FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size());
+
+ if (!srcCanvasRect.width() || !srcCanvasRect.height()) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
if (!srcCanvasRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) {
ec = INDEX_SIZE_ERR;
return;
}
+ ec = 0;
+
if (!dstRect.width() || !dstRect.height())
return;
@@ -1145,6 +1167,10 @@ void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec
}
ec = 0;
+
+ if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readyState() == HTMLMediaElement::HAVE_METADATA)
+ return;
+
FloatRect videoRect = FloatRect(FloatPoint(), size(video));
if (!videoRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) {
ec = INDEX_SIZE_ERR;
@@ -1489,7 +1515,16 @@ void CanvasRenderingContext2D::setFont(const String& newFont)
state().m_font.update(styleSelector->fontSelector());
state().m_realizedFont = true;
}
-
+
+void CanvasRenderingContext2D::updateFont()
+{
+ if (!state().m_realizedFont)
+ return;
+
+ const Font& font = state().m_font;
+ font.update(font.fontSelector());
+}
+
String CanvasRenderingContext2D::textAlign() const
{
return textAlignName(state().m_textAlign);
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.h b/WebCore/html/canvas/CanvasRenderingContext2D.h
index d6b0c8a..43f3b35 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.h
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.h
@@ -34,6 +34,7 @@
#include "GraphicsTypes.h"
#include "Path.h"
#include "PlatformString.h"
+#include <wtf/text/StringHash.h>
#include <wtf/Vector.h>
#if PLATFORM(CG)
@@ -192,6 +193,7 @@ namespace WebCore {
String font() const;
void setFont(const String&);
+ void updateFont();
String textAlign() const;
void setTextAlign(const String&);
@@ -264,6 +266,9 @@ namespace WebCore {
#endif
void prepareGradientForDashboard(CanvasGradient* gradient) const;
+
+ HashSet<String> m_cleanOrigins;
+
void checkOrigin(const KURL&);
void checkOrigin(const String&);
diff --git a/WebCore/html/canvas/CheckedInt.h b/WebCore/html/canvas/CheckedInt.h
new file mode 100644
index 0000000..861e8e6
--- /dev/null
+++ b/WebCore/html/canvas/CheckedInt.h
@@ -0,0 +1,527 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Benoit Jacob <bjacob@mozilla.com>
+ * Jeff Muizelaar <jmuizelaar@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Necessary modifications are made to the original CheckedInt.h file to remove
+// dependencies on prtypes.
+// Also, change define Mozilla_CheckedInt_h to CheckedInt_h, change namespace
+// from mozilla to WebCore for easier usage.
+
+#ifndef CheckedInt_h
+#define CheckedInt_h
+
+#include <climits>
+
+namespace WebCore {
+
+namespace CheckedInt_internal {
+
+/* we don't want to use std::numeric_limits here because int... types may not support it,
+ * depending on the platform, e.g. on certain platform they use nonstandard built-in types
+ */
+
+/*** Step 1: manually record information for all the types that we want to support
+ ***/
+
+struct unsupported_type {};
+
+template<typename T> struct integer_type_manually_recorded_info
+{
+ enum { is_supported = 0 };
+ typedef unsupported_type twice_bigger_type;
+};
+
+
+#define CHECKEDINT_REGISTER_SUPPORTED_TYPE(T,_twice_bigger_type) \
+template<> struct integer_type_manually_recorded_info<T> \
+{ \
+ enum { is_supported = 1 }; \
+ typedef _twice_bigger_type twice_bigger_type; \
+ static void TYPE_NOT_SUPPORTED_BY_CheckedInt() {} \
+};
+
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(int8_t, int16_t)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint8_t, uint16_t)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(int16_t, int32_t)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint16_t, uint32_t)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(int32_t, int64_t)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint32_t, uint64_t)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(int64_t, unsupported_type)
+CHECKEDINT_REGISTER_SUPPORTED_TYPE(uint64_t, unsupported_type)
+
+
+/*** Step 2: record some info about a given integer type,
+ *** including whether it is supported, whether a twice bigger integer type
+ *** is supported, what that twice bigger type is, and some stuff as found
+ *** in std::numeric_limits (which we don't use because int.. types may
+ *** not support it, if they are defined directly from compiler built-in types).
+ ***/
+
+template<typename T> struct is_unsupported_type { enum { answer = 0 }; };
+template<> struct is_unsupported_type<unsupported_type> { enum { answer = 1 }; };
+
+template<typename T> struct integer_traits
+{
+ typedef typename integer_type_manually_recorded_info<T>::twice_bigger_type twice_bigger_type;
+
+ enum {
+ is_supported = integer_type_manually_recorded_info<T>::is_supported,
+ twice_bigger_type_is_supported
+ = is_unsupported_type<
+ typename integer_type_manually_recorded_info<T>::twice_bigger_type
+ >::answer ? 0 : 1,
+ size = sizeof(T),
+ position_of_sign_bit = CHAR_BIT * size - 1,
+ is_signed = (T(-1) > T(0)) ? 0 : 1
+ };
+
+ static T min()
+ {
+ // bitwise ops may return a larger type, that's why we cast explicitly to T
+ return is_signed ? T(T(1) << position_of_sign_bit) : T(0);
+ }
+
+ static T max()
+ {
+ return ~min();
+ }
+};
+
+/*** Step 3: Implement the actual validity checks --- ideas taken from IntegerLib, code different.
+ ***/
+
+// bitwise ops may return a larger type, so it's good to use these inline helpers guaranteeing that
+// the result is really of type T
+
+template<typename T> inline T has_sign_bit(T x)
+{
+ return x >> integer_traits<T>::position_of_sign_bit;
+}
+
+template<typename T> inline T binary_complement(T x)
+{
+ return ~x;
+}
+
+template<typename T, typename U,
+ bool is_T_signed = integer_traits<T>::is_signed,
+ bool is_U_signed = integer_traits<U>::is_signed>
+struct is_in_range_impl {};
+
+template<typename T, typename U>
+struct is_in_range_impl<T, U, true, true>
+{
+ static T run(U x)
+ {
+ return (x <= integer_traits<T>::max()) &
+ (x >= integer_traits<T>::min());
+ }
+};
+
+template<typename T, typename U>
+struct is_in_range_impl<T, U, false, false>
+{
+ static T run(U x)
+ {
+ return x <= integer_traits<T>::max();
+ }
+};
+
+template<typename T, typename U>
+struct is_in_range_impl<T, U, true, false>
+{
+ static T run(U x)
+ {
+ if (sizeof(T) > sizeof(U))
+ return 1;
+ else
+ return x <= U(integer_traits<T>::max());
+ }
+};
+
+template<typename T, typename U>
+struct is_in_range_impl<T, U, false, true>
+{
+ static T run(U x)
+ {
+ if (sizeof(T) >= sizeof(U))
+ return x >= 0;
+ else
+ return x >= 0 && x <= U(integer_traits<T>::max());
+ }
+};
+
+template<typename T, typename U> inline T is_in_range(U x)
+{
+ return is_in_range_impl<T, U>::run(x);
+}
+
+template<typename T> inline T is_add_valid(T x, T y, T result)
+{
+ return integer_traits<T>::is_signed ?
+ // addition is valid if the sign of x+y is equal to either that of x or that of y.
+ // Beware! These bitwise operations can return a larger integer type, if T was a
+ // small type like int8, so we explicitly cast to T.
+ has_sign_bit(binary_complement(T((result^x) & (result^y))))
+ :
+ binary_complement(x) >= y;
+}
+
+template<typename T> inline T is_sub_valid(T x, T y, T result)
+{
+ return integer_traits<T>::is_signed ?
+ // substraction is valid if either x and y have same sign, or x-y and x have same sign
+ has_sign_bit(binary_complement(T((result^x) & (x^y))))
+ :
+ x >= y;
+}
+
+template<typename T,
+ bool is_signed = integer_traits<T>::is_signed,
+ bool twice_bigger_type_is_supported = integer_traits<T>::twice_bigger_type_is_supported>
+struct is_mul_valid_impl {};
+
+template<typename T>
+struct is_mul_valid_impl<T, true, true>
+{
+ static T run(T x, T y)
+ {
+ typedef typename integer_traits<T>::twice_bigger_type twice_bigger_type;
+ twice_bigger_type product = twice_bigger_type(x) * twice_bigger_type(y);
+ return is_in_range<T>(product);
+ }
+};
+
+template<typename T>
+struct is_mul_valid_impl<T, false, true>
+{
+ static T run(T x, T y)
+ {
+ typedef typename integer_traits<T>::twice_bigger_type twice_bigger_type;
+ twice_bigger_type product = twice_bigger_type(x) * twice_bigger_type(y);
+ return is_in_range<T>(product);
+ }
+};
+
+template<typename T>
+struct is_mul_valid_impl<T, true, false>
+{
+ static T run(T x, T y)
+ {
+ const T max_value = integer_traits<T>::max();
+ const T min_value = integer_traits<T>::min();
+
+ if (x == 0 || y == 0) return true;
+
+ if (x > 0) {
+ if (y > 0)
+ return x <= max_value / y;
+ else
+ return y >= min_value / x;
+ } else {
+ if (y > 0)
+ return x >= min_value / y;
+ else
+ return y >= max_value / x;
+ }
+ }
+};
+
+template<typename T>
+struct is_mul_valid_impl<T, false, false>
+{
+ static T run(T x, T y)
+ {
+ const T max_value = integer_traits<T>::max();
+ if (x == 0 || y == 0) return true;
+ return x <= max_value / y;
+ }
+};
+
+template<typename T> inline T is_mul_valid(T x, T y, T /*result not used*/)
+{
+ return is_mul_valid_impl<T>::run(x, y);
+}
+
+template<typename T> inline T is_div_valid(T x, T y)
+{
+ return integer_traits<T>::is_signed ?
+ // keep in mind that min/-1 is invalid because abs(min)>max
+ y != 0 && (x != integer_traits<T>::min() || y != T(-1))
+ :
+ y != 0;
+}
+
+} // end namespace CheckedInt_internal
+
+
+/*** Step 4: Now define the CheckedInt class.
+ ***/
+
+/** \class CheckedInt
+ * \brief Integer wrapper class checking for integer overflow and other errors
+ * \param T the integer type to wrap. Can be any of int8_t, uint8_t, int16_t, uint16_t,
+ * int32_t, uint32_t, int64_t, uint64_t.
+ *
+ * This class implements guarded integer arithmetic. Do a computation, then check that
+ * valid() returns true, you then have a guarantee that no problem, such as integer overflow,
+ * happened during this computation.
+ *
+ * The arithmetic operators in this class are guaranteed not to crash your app
+ * in case of a division by zero.
+ *
+ * For example, suppose that you want to implement a function that computes (x+y)/z,
+ * that doesn't crash if z==0, and that reports on error (divide by zero or integer overflow).
+ * You could code it as follows:
+ \code
+ bool compute_x_plus_y_over_z(int32_t x, int32_t y, int32_t z, int32_t *result)
+ {
+ CheckedInt<int32_t> checked_result = (CheckedInt<int32_t>(x) + y) / z;
+ *result = checked_result.value();
+ return checked_result.valid();
+ }
+ \endcode
+ *
+ * Implicit conversion from plain integers to checked integers is allowed. The plain integer
+ * is checked to be in range before being casted to the destination type. This means that the following
+ * lines all compile, and the resulting CheckedInts are correctly detected as valid or invalid:
+ * \code
+ CheckedInt<uint8_t> x(1); // 1 is of type int, is found to be in range for uint8_t, x is valid
+ CheckedInt<uint8_t> x(-1); // -1 is of type int, is found not to be in range for uint8_t, x is invalid
+ CheckedInt<int8_t> x(-1); // -1 is of type int, is found to be in range for int8_t, x is valid
+ CheckedInt<int8_t> x(int16_t(1000)); // 1000 is of type int16_t, is found not to be in range for int8_t, x is invalid
+ CheckedInt<int32_t> x(uint32_t(123456789)); // 3123456789 is of type uint32_t, is found not to be in range
+ // for int32_t, x is invalid
+ * \endcode
+ * Implicit conversion from
+ * checked integers to plain integers is not allowed. As shown in the
+ * above example, to get the value of a checked integer as a normal integer, call value().
+ *
+ * Arithmetic operations between checked and plain integers is allowed; the result type
+ * is the type of the checked integer.
+ *
+ * Safe integers of different types cannot be used in the same arithmetic expression.
+ */
+template<typename T>
+class CheckedInt
+{
+protected:
+ T mValue;
+ T mIsValid; // stored as a T to limit the number of integer conversions when
+ // evaluating nested arithmetic expressions.
+
+ template<typename U>
+ CheckedInt(const U& value, bool isValid) : mValue(value), mIsValid(isValid)
+ {
+ CheckedInt_internal::integer_type_manually_recorded_info<T>
+ ::TYPE_NOT_SUPPORTED_BY_CheckedInt();
+ }
+
+public:
+ /** Constructs a checked integer with given \a value. The checked integer is initialized as valid or invalid
+ * depending on whether the \a value is in range.
+ *
+ * This constructor is not explicit. Instead, the type of its argument is a separate template parameter,
+ * ensuring that no conversion is performed before this constructor is actually called.
+ * As explained in the above documentation for class CheckedInt, this constructor checks that its argument is
+ * valid.
+ */
+ template<typename U>
+ CheckedInt(const U& value)
+ : mValue(value),
+ mIsValid(CheckedInt_internal::is_in_range<T>(value))
+ {
+ CheckedInt_internal::integer_type_manually_recorded_info<T>
+ ::TYPE_NOT_SUPPORTED_BY_CheckedInt();
+ }
+
+ /** Constructs a valid checked integer with uninitialized value */
+ CheckedInt() : mIsValid(1)
+ {
+ CheckedInt_internal::integer_type_manually_recorded_info<T>
+ ::TYPE_NOT_SUPPORTED_BY_CheckedInt();
+ }
+
+ /** \returns the actual value */
+ T value() const { return mValue; }
+
+ /** \returns true if the checked integer is valid, i.e. is not the result
+ * of an invalid operation or of an operation involving an invalid checked integer
+ */
+ bool valid() const { return mIsValid; }
+
+ /** \returns the sum. Checks for overflow. */
+ template<typename U> friend CheckedInt<U> operator +(const CheckedInt<U>& lhs, const CheckedInt<U>& rhs);
+ /** Adds. Checks for overflow. \returns self reference */
+ template<typename U> CheckedInt& operator +=(const U &rhs);
+ /** \returns the difference. Checks for overflow. */
+ template<typename U> friend CheckedInt<U> operator -(const CheckedInt<U>& lhs, const CheckedInt<U> &rhs);
+ /** Substracts. Checks for overflow. \returns self reference */
+ template<typename U> CheckedInt& operator -=(const U &rhs);
+ /** \returns the product. Checks for overflow. */
+ template<typename U> friend CheckedInt<U> operator *(const CheckedInt<U>& lhs, const CheckedInt<U> &rhs);
+ /** Multiplies. Checks for overflow. \returns self reference */
+ template<typename U> CheckedInt& operator *=(const U &rhs);
+ /** \returns the quotient. Checks for overflow and for divide-by-zero. */
+ template<typename U> friend CheckedInt<U> operator /(const CheckedInt<U>& lhs, const CheckedInt<U> &rhs);
+ /** Divides. Checks for overflow and for divide-by-zero. \returns self reference */
+ template<typename U> CheckedInt& operator /=(const U &rhs);
+
+ /** \returns the opposite value. Checks for overflow. */
+ CheckedInt operator -() const
+ {
+ T result = -value();
+ /* give the compiler a good chance to perform RVO */
+ return CheckedInt(result,
+ mIsValid & CheckedInt_internal::is_sub_valid(T(0), value(), result));
+ }
+
+ /** \returns true if the left and right hand sides are valid and have the same value. */
+ bool operator ==(const CheckedInt& other) const
+ {
+ return bool(mIsValid & other.mIsValid & T(value() == other.value()));
+ }
+
+private:
+ /** operator!= is disabled. Indeed: (a!=b) should be the same as !(a==b) but that
+ * would mean that if a or b is invalid, (a!=b) is always true, which is very tricky.
+ */
+ template<typename U>
+ bool operator !=(const U& other) const { return !(*this == other); }
+};
+
+#define CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
+template<typename T> \
+inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, const CheckedInt<T> &rhs) \
+{ \
+ T x = lhs.value(); \
+ T y = rhs.value(); \
+ T result = x OP y; \
+ T is_op_valid \
+ = CheckedInt_internal::is_##NAME##_valid(x, y, result); \
+ /* give the compiler a good chance to perform RVO */ \
+ return CheckedInt<T>(result, \
+ lhs.mIsValid & \
+ rhs.mIsValid & \
+ is_op_valid); \
+}
+
+CHECKEDINT_BASIC_BINARY_OPERATOR(add, +)
+CHECKEDINT_BASIC_BINARY_OPERATOR(sub, -)
+CHECKEDINT_BASIC_BINARY_OPERATOR(mul, *)
+
+// division can't be implemented by CHECKEDINT_BASIC_BINARY_OPERATOR
+// because if rhs == 0, we are not allowed to even try to compute the quotient.
+template<typename T>
+inline CheckedInt<T> operator /(const CheckedInt<T> &lhs, const CheckedInt<T> &rhs)
+{
+ T x = lhs.value();
+ T y = rhs.value();
+ T is_op_valid = CheckedInt_internal::is_div_valid(x, y);
+ T result = is_op_valid ? (x / y) : 0;
+ /* give the compiler a good chance to perform RVO */
+ return CheckedInt<T>(result,
+ lhs.mIsValid &
+ rhs.mIsValid &
+ is_op_valid);
+}
+
+// implement cast_to_CheckedInt<T>(x), making sure that
+// - it allows x to be either a CheckedInt<T> or any integer type that can be casted to T
+// - if x is already a CheckedInt<T>, we just return a reference to it, instead of copying it (optimization)
+
+template<typename T, typename U>
+struct cast_to_CheckedInt_impl
+{
+ typedef CheckedInt<T> return_type;
+ static CheckedInt<T> run(const U& u) { return u; }
+};
+
+template<typename T>
+struct cast_to_CheckedInt_impl<T, CheckedInt<T> >
+{
+ typedef const CheckedInt<T>& return_type;
+ static const CheckedInt<T>& run(const CheckedInt<T>& u) { return u; }
+};
+
+template<typename T, typename U>
+inline typename cast_to_CheckedInt_impl<T, U>::return_type
+cast_to_CheckedInt(const U& u)
+{
+ return cast_to_CheckedInt_impl<T, U>::run(u);
+}
+
+#define CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
+template<typename T> \
+template<typename U> \
+CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(const U &rhs) \
+{ \
+ *this = *this OP cast_to_CheckedInt<T>(rhs); \
+ return *this; \
+} \
+template<typename T, typename U> \
+inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, const U &rhs) \
+{ \
+ return lhs OP cast_to_CheckedInt<T>(rhs); \
+} \
+template<typename T, typename U> \
+inline CheckedInt<T> operator OP(const U & lhs, const CheckedInt<T> &rhs) \
+{ \
+ return cast_to_CheckedInt<T>(lhs) OP rhs; \
+}
+
+CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
+CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
+CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
+CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
+
+template<typename T, typename U>
+inline bool operator ==(const CheckedInt<T> &lhs, const U &rhs)
+{
+ return lhs == cast_to_CheckedInt<T>(rhs);
+}
+
+template<typename T, typename U>
+inline bool operator ==(const U & lhs, const CheckedInt<T> &rhs)
+{
+ return cast_to_CheckedInt<T>(lhs) == rhs;
+}
+
+} // end namespace WebCore
+
+#endif /* CheckedInt_h */
diff --git a/WebCore/html/canvas/WebGLBuffer.cpp b/WebCore/html/canvas/WebGLBuffer.cpp
index 8790b1a..4c87958 100644
--- a/WebCore/html/canvas/WebGLBuffer.cpp
+++ b/WebCore/html/canvas/WebGLBuffer.cpp
@@ -39,8 +39,8 @@ PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx)
WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx)
: CanvasObject(ctx)
- , m_elementArrayBufferByteLength(0)
- , m_arrayBufferByteLength(0)
+ , m_target(0)
+ , m_byteLength(0)
, m_nextAvailableCacheEntry(0)
{
setObject(context()->graphicsContext3D()->createBuffer());
@@ -52,50 +52,51 @@ void WebGLBuffer::_deleteObject(Platform3DObject object)
context()->graphicsContext3D()->deleteBuffer(object);
}
-bool WebGLBuffer::associateBufferData(unsigned long target, int size)
+bool WebGLBuffer::associateBufferData(int size)
{
- if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
- m_elementArrayBufferByteLength = size;
- return true;
- }
-
- if (target == GraphicsContext3D::ARRAY_BUFFER) {
- m_arrayBufferByteLength = size;
+ switch (m_target) {
+ case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
+ case GraphicsContext3D::ARRAY_BUFFER:
+ m_byteLength = size;
return true;
+ default:
+ return false;
}
-
- return false;
}
-bool WebGLBuffer::associateBufferData(unsigned long target, ArrayBufferView* array)
+bool WebGLBuffer::associateBufferData(ArrayBufferView* array)
{
+ if (!m_target)
+ return false;
if (!array)
return false;
-
- if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
+
+ if (m_target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
clearCachedMaxIndices();
- m_elementArrayBufferByteLength = array->byteLength();
+ m_byteLength = array->byteLength();
// We must always clone the incoming data because client-side
// modifications without calling bufferData or bufferSubData
// must never be able to change the validation results.
m_elementArrayBuffer = ArrayBuffer::create(array->buffer().get());
return true;
}
-
- if (target == GraphicsContext3D::ARRAY_BUFFER) {
- m_arrayBufferByteLength = array->byteLength();
+
+ if (m_target == GraphicsContext3D::ARRAY_BUFFER) {
+ m_byteLength = array->byteLength();
return true;
}
return false;
}
-bool WebGLBuffer::associateBufferSubData(unsigned long target, long offset, ArrayBufferView* array)
+bool WebGLBuffer::associateBufferSubData(long offset, ArrayBufferView* array)
{
+ if (!m_target)
+ return false;
if (!array)
return false;
-
- if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
+
+ if (m_target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
clearCachedMaxIndices();
// We need to protect against integer overflow with these tests
@@ -103,22 +104,22 @@ bool WebGLBuffer::associateBufferSubData(unsigned long target, long offset, Arra
return false;
unsigned long uoffset = static_cast<unsigned long>(offset);
- if (uoffset > m_elementArrayBufferByteLength || array->byteLength() > m_elementArrayBufferByteLength - uoffset)
+ if (uoffset > m_byteLength || array->byteLength() > m_byteLength - uoffset)
return false;
memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()) + offset, array->baseAddress(), array->byteLength());
return true;
}
-
- if (target == GraphicsContext3D::ARRAY_BUFFER)
- return array->byteLength() + offset <= m_arrayBufferByteLength;
+
+ if (m_target == GraphicsContext3D::ARRAY_BUFFER)
+ return array->byteLength() + offset <= m_byteLength;
return false;
}
-unsigned WebGLBuffer::byteLength(unsigned long target) const
+unsigned WebGLBuffer::byteLength() const
{
- return (target == GraphicsContext3D::ARRAY_BUFFER) ? m_arrayBufferByteLength : m_elementArrayBufferByteLength;
+ return m_byteLength;
}
long WebGLBuffer::getCachedMaxIndex(unsigned long type)
@@ -143,6 +144,15 @@ void WebGLBuffer::setCachedMaxIndex(unsigned long type, long value)
m_nextAvailableCacheEntry = (m_nextAvailableCacheEntry + 1) % numEntries;
}
+void WebGLBuffer::setTarget(unsigned long target)
+{
+ // In WebGL, a buffer is bound to one target in its lifetime
+ if (m_target)
+ return;
+ if (target == GraphicsContext3D::ARRAY_BUFFER || target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
+ m_target = target;
+}
+
void WebGLBuffer::clearCachedMaxIndices()
{
memset(m_maxIndexCache, 0, sizeof(m_maxIndexCache));
diff --git a/WebCore/html/canvas/WebGLBuffer.h b/WebCore/html/canvas/WebGLBuffer.h
index bd9f190..e1fec47 100644
--- a/WebCore/html/canvas/WebGLBuffer.h
+++ b/WebCore/html/canvas/WebGLBuffer.h
@@ -40,11 +40,11 @@ namespace WebCore {
static PassRefPtr<WebGLBuffer> create(WebGLRenderingContext*);
- bool associateBufferData(unsigned long target, int size);
- bool associateBufferData(unsigned long target, ArrayBufferView* array);
- bool associateBufferSubData(unsigned long target, long offset, ArrayBufferView* array);
+ bool associateBufferData(int size);
+ bool associateBufferData(ArrayBufferView* array);
+ bool associateBufferSubData(long offset, ArrayBufferView* array);
- unsigned byteLength(unsigned long target) const;
+ unsigned byteLength() const;
const ArrayBuffer* elementArrayBuffer() const { return m_elementArrayBuffer.get(); }
// Gets the cached max index for the given type. Returns -1 if
@@ -53,6 +53,9 @@ namespace WebCore {
// Sets the cached max index for the given type.
void setCachedMaxIndex(unsigned long type, long value);
+ unsigned long getTarget() const { return m_target; }
+ void setTarget(unsigned long);
+
protected:
WebGLBuffer(WebGLRenderingContext*);
@@ -61,9 +64,10 @@ namespace WebCore {
private:
virtual bool isBuffer() const { return true; }
+ unsigned long m_target;
+
RefPtr<ArrayBuffer> m_elementArrayBuffer;
- unsigned m_elementArrayBufferByteLength;
- unsigned m_arrayBufferByteLength;
+ unsigned m_byteLength;
// Optimization for index validation. For each type of index
// (i.e., UNSIGNED_SHORT), cache the maximum index in the
diff --git a/WebCore/html/canvas/WebGLGetInfo.cpp b/WebCore/html/canvas/WebGLGetInfo.cpp
index 79fc971..0c8b548 100644
--- a/WebCore/html/canvas/WebGLGetInfo.cpp
+++ b/WebCore/html/canvas/WebGLGetInfo.cpp
@@ -46,6 +46,16 @@ WebGLGetInfo::WebGLGetInfo(bool value)
{
}
+WebGLGetInfo::WebGLGetInfo(const bool* value, int size)
+ : m_type(kTypeBoolArray)
+{
+ if (!value || size <=0)
+ return;
+ m_boolArray.resize(size);
+ for (int ii = 0; ii < size; ++ii)
+ m_boolArray[ii] = value[ii];
+}
+
WebGLGetInfo::WebGLGetInfo(float value)
: m_type(kTypeFloat)
, m_float(value)
@@ -138,6 +148,12 @@ bool WebGLGetInfo::getBool() const
return m_bool;
}
+const Vector<bool>& WebGLGetInfo::getBoolArray() const
+{
+ ASSERT(getType() == kTypeBoolArray);
+ return m_boolArray;
+}
+
float WebGLGetInfo::getFloat() const
{
ASSERT(getType() == kTypeFloat);
diff --git a/WebCore/html/canvas/WebGLGetInfo.h b/WebCore/html/canvas/WebGLGetInfo.h
index b35add8..94f6f9b 100644
--- a/WebCore/html/canvas/WebGLGetInfo.h
+++ b/WebCore/html/canvas/WebGLGetInfo.h
@@ -53,6 +53,7 @@ class WebGLGetInfo {
public:
enum Type {
kTypeBool,
+ kTypeBoolArray,
kTypeFloat,
kTypeLong,
kTypeNull,
@@ -70,6 +71,7 @@ public:
};
WebGLGetInfo(bool value);
+ WebGLGetInfo(const bool* value, int size);
WebGLGetInfo(float value);
WebGLGetInfo(long value);
// Represents the NULL value and type
@@ -92,6 +94,7 @@ public:
Type getType() const;
bool getBool() const;
+ const Vector<bool>& getBoolArray() const;
float getFloat() const;
long getLong() const;
const String& getString() const;
@@ -110,6 +113,7 @@ public:
private:
Type m_type;
bool m_bool;
+ Vector<bool> m_boolArray;
float m_float;
long m_long;
String m_string;
diff --git a/WebCore/html/canvas/WebGLProgram.cpp b/WebCore/html/canvas/WebGLProgram.cpp
index 750df45..0004465 100644
--- a/WebCore/html/canvas/WebGLProgram.cpp
+++ b/WebCore/html/canvas/WebGLProgram.cpp
@@ -39,6 +39,7 @@ PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx)
WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
: CanvasObject(ctx)
+ , m_linkFailure(false)
{
setObject(context()->graphicsContext3D()->createProgram());
}
@@ -71,18 +72,27 @@ bool WebGLProgram::cacheActiveAttribLocations()
return true;
}
-int WebGLProgram::numActiveAttribLocations()
+int WebGLProgram::numActiveAttribLocations() const
{
return static_cast<int>(m_activeAttribLocations.size());
}
-int WebGLProgram::getActiveAttribLocation(int index)
+int WebGLProgram::getActiveAttribLocation(int index) const
{
if (index < 0 || index >= numActiveAttribLocations())
return -1;
return m_activeAttribLocations[static_cast<size_t>(index)];
}
+bool WebGLProgram::isUsingVertexAttrib0() const
+{
+ for (int ii = 0; ii < numActiveAttribLocations(); ++ii) {
+ if (!getActiveAttribLocation(ii))
+ return true;
+ }
+ return false;
+}
+
}
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/html/canvas/WebGLProgram.h b/WebCore/html/canvas/WebGLProgram.h
index b13fc22..1049334 100644
--- a/WebCore/html/canvas/WebGLProgram.h
+++ b/WebCore/html/canvas/WebGLProgram.h
@@ -43,8 +43,16 @@ namespace WebCore {
// cacheActiveAttribLocation() is only called once after linkProgram()
// succeeds.
bool cacheActiveAttribLocations();
- int numActiveAttribLocations();
- int getActiveAttribLocation(int index);
+ int numActiveAttribLocations() const;
+ int getActiveAttribLocation(int index) const;
+
+ bool isUsingVertexAttrib0() const;
+
+ // Return true means getProgramParameter(LINK_STATUS) should return
+ // false; return false means we should actually call
+ // getProgramParameter(LINK_STATUS) to find out.
+ bool isLinkFailureFlagSet() const { return m_linkFailure; }
+ void setLinkFailureFlag(bool failed) { m_linkFailure = failed; }
protected:
WebGLProgram(WebGLRenderingContext*);
@@ -55,6 +63,8 @@ namespace WebCore {
virtual bool isProgram() const { return true; }
Vector<int> m_activeAttribLocations;
+
+ bool m_linkFailure;
};
} // namespace WebCore
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index 2124506..c3dea58 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -29,6 +29,7 @@
#include "WebGLRenderingContext.h"
+#include "CheckedInt.h"
#include "CanvasPixelArray.h"
#include "Console.h"
#include "DOMWindow.h"
@@ -52,6 +53,7 @@
#include "WebGLUniformLocation.h"
#include <wtf/ByteArray.h>
+#include <wtf/OwnArrayPtr.h>
namespace WebCore {
@@ -120,8 +122,10 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize);
m_maxCubeMapTextureSize = maxCubeMapTextureSize;
- if (!isGLES2Compliant())
+ if (!isGLES2Compliant()) {
createFallbackBlackTextures1x1();
+ initVertexAttrib0();
+ }
m_context->reshape(canvas()->width(), canvas()->height());
m_context->viewport(0, 0, canvas()->width(), canvas()->height());
}
@@ -192,7 +196,7 @@ int WebGLRenderingContext::sizeInBytes(int type, ExceptionCode& ec)
void WebGLRenderingContext::activeTexture(unsigned long texture, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if ((texture - GraphicsContext3D::TEXTURE0) > sizeof(m_textureUnits) / sizeof(TextureUnitState)) {
+ if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
return;
}
@@ -204,10 +208,8 @@ void WebGLRenderingContext::activeTexture(unsigned long texture, ExceptionCode&
void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this || !shader || shader->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!validateWebGLObject(program) || !validateWebGLObject(shader))
return;
- }
m_context->attachShader(program, shader);
cleanupAfterGraphicsCall(false);
}
@@ -228,6 +230,10 @@ void WebGLRenderingContext::bindBuffer(unsigned long target, WebGLBuffer* buffer
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
+ if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
if (target == GraphicsContext3D::ARRAY_BUFFER)
m_boundArrayBuffer = buffer;
@@ -239,6 +245,8 @@ void WebGLRenderingContext::bindBuffer(unsigned long target, WebGLBuffer* buffer
}
m_context->bindBuffer(target, buffer);
+ if (buffer)
+ buffer->setTarget(target);
cleanupAfterGraphicsCall(false);
}
@@ -307,12 +315,20 @@ void WebGLRenderingContext::blendColor(double red, double green, double blue, do
void WebGLRenderingContext::blendEquation( unsigned long mode )
{
+ if (!isGLES2Compliant()) {
+ if (!validateBlendEquation(mode))
+ return;
+ }
m_context->blendEquation(mode);
cleanupAfterGraphicsCall(false);
}
void WebGLRenderingContext::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
{
+ if (!isGLES2Compliant()) {
+ if (!validateBlendEquation(modeRGB) || !validateBlendEquation(modeAlpha))
+ return;
+ }
m_context->blendEquationSeparate(modeRGB, modeAlpha);
cleanupAfterGraphicsCall(false);
}
@@ -334,12 +350,12 @@ void WebGLRenderingContext::bufferData(unsigned long target, int size, unsigned
{
UNUSED_PARAM(ec);
if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
- if (!m_boundElementArrayBuffer->associateBufferData(target, size)) {
+ if (!m_boundElementArrayBuffer->associateBufferData(size)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
} else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
- if (!m_boundArrayBuffer->associateBufferData(target, size)) {
+ if (!m_boundArrayBuffer->associateBufferData(size)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
@@ -356,12 +372,12 @@ void WebGLRenderingContext::bufferData(unsigned long target, ArrayBufferView* da
{
UNUSED_PARAM(ec);
if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
- if (!m_boundElementArrayBuffer->associateBufferData(target, data)) {
+ if (!m_boundElementArrayBuffer->associateBufferData(data)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
} else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
- if (!m_boundArrayBuffer->associateBufferData(target, data)) {
+ if (!m_boundArrayBuffer->associateBufferData(data)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
@@ -378,12 +394,12 @@ void WebGLRenderingContext::bufferSubData(unsigned long target, long offset, Arr
{
UNUSED_PARAM(ec);
if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
- if (!m_boundElementArrayBuffer->associateBufferSubData(target, offset, data)) {
+ if (!m_boundElementArrayBuffer->associateBufferSubData(offset, data)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
} else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
- if (!m_boundArrayBuffer->associateBufferSubData(target, offset, data)) {
+ if (!m_boundArrayBuffer->associateBufferSubData(offset, data)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
@@ -562,6 +578,20 @@ void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
return;
buffer->deleteObject();
+
+ if (!isGLES2Compliant()) {
+ VertexAttribState& state = m_vertexAttribState[0];
+ if (buffer == state.bufferBinding) {
+ state.bufferBinding = m_vertexAttrib0Buffer;
+ state.bytesPerElement = 0;
+ state.size = 4;
+ state.type = GraphicsContext3D::FLOAT;
+ state.normalized = false;
+ state.stride = 16;
+ state.originalStride = 0;
+ state.offset = 0;
+ }
+ }
}
void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
@@ -638,6 +668,10 @@ void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* sha
void WebGLRenderingContext::disable(unsigned long cap)
{
+ if (!isGLES2Compliant()) {
+ if (!validateCapability(cap))
+ return;
+ }
m_context->disable(cap);
cleanupAfterGraphicsCall(false);
}
@@ -652,9 +686,11 @@ void WebGLRenderingContext::disableVertexAttribArray(unsigned long index, Except
if (index < m_vertexAttribState.size())
m_vertexAttribState[index].enabled = false;
-
- m_context->disableVertexAttribArray(index);
- cleanupAfterGraphicsCall(false);
+
+ if (index > 0 || isGLES2Compliant()) {
+ m_context->disableVertexAttribArray(index);
+ cleanupAfterGraphicsCall(false);
+ }
}
bool WebGLRenderingContext::validateElementArraySize(unsigned long count, unsigned long type, long offset)
@@ -675,11 +711,11 @@ bool WebGLRenderingContext::validateElementArraySize(unsigned long count, unsign
// Make uoffset an element offset.
uoffset /= 2;
- unsigned long n = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER) / 2;
+ unsigned long n = m_boundElementArrayBuffer->byteLength() / 2;
if (uoffset > n || count > n - uoffset)
return false;
} else if (type == GraphicsContext3D::UNSIGNED_BYTE) {
- unsigned long n = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER);
+ unsigned long n = m_boundElementArrayBuffer->byteLength();
if (uoffset > n || count > n - uoffset)
return false;
}
@@ -699,17 +735,25 @@ bool WebGLRenderingContext::validateIndexArrayConservative(unsigned long type, l
// Compute the maximum index in the entire buffer for the given type of index.
switch (type) {
case GraphicsContext3D::UNSIGNED_BYTE: {
- unsigned numElements = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER);
- const unsigned char* p = static_cast<const unsigned char*>(m_boundElementArrayBuffer->elementArrayBuffer()->data());
- for (unsigned i = 0; i < numElements; i++)
- maxIndex = max(maxIndex, static_cast<long>(p[i]));
+ unsigned numElements = m_boundElementArrayBuffer->byteLength();
+ if (!numElements)
+ maxIndex = 0;
+ else {
+ const unsigned char* p = static_cast<const unsigned char*>(m_boundElementArrayBuffer->elementArrayBuffer()->data());
+ for (unsigned i = 0; i < numElements; i++)
+ maxIndex = max(maxIndex, static_cast<long>(p[i]));
+ }
break;
}
case GraphicsContext3D::UNSIGNED_SHORT: {
- unsigned numElements = m_boundElementArrayBuffer->byteLength(GraphicsContext3D::ELEMENT_ARRAY_BUFFER) / sizeof(unsigned short);
- const unsigned short* p = static_cast<const unsigned short*>(m_boundElementArrayBuffer->elementArrayBuffer()->data());
- for (unsigned i = 0; i < numElements; i++)
- maxIndex = max(maxIndex, static_cast<long>(p[i]));
+ unsigned numElements = m_boundElementArrayBuffer->byteLength() / sizeof(unsigned short);
+ if (!numElements)
+ maxIndex = 0;
+ else {
+ const unsigned short* p = static_cast<const unsigned short*>(m_boundElementArrayBuffer->elementArrayBuffer()->data());
+ for (unsigned i = 0; i < numElements; i++)
+ maxIndex = max(maxIndex, static_cast<long>(p[i]));
+ }
break;
}
default:
@@ -766,8 +810,10 @@ bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
if (!m_currentProgram)
return false;
+ int numAttribStates = static_cast<int>(m_vertexAttribState.size());
+
// Look in each enabled vertex attrib and check if they've been bound to a buffer.
- for (size_t i = 0; i < m_vertexAttribState.size(); ++i) {
+ for (int i = 0; i < numAttribStates; ++i) {
if (m_vertexAttribState[i].enabled
&& (!m_vertexAttribState[i].bufferBinding || !m_vertexAttribState[i].bufferBinding->object()))
return false;
@@ -776,13 +822,21 @@ bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
// Look in each consumed vertex attrib (by the current program) and find the smallest buffer size
long smallestNumElements = LONG_MAX;
int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations();
- int numAttribStates = static_cast<int>(m_vertexAttribState.size());
for (int i = 0; i < numActiveAttribLocations; ++i) {
int loc = m_currentProgram->getActiveAttribLocation(i);
if (loc >=0 && loc < numAttribStates) {
const VertexAttribState& state = m_vertexAttribState[loc];
- if (state.enabled && state.numElements < smallestNumElements)
- smallestNumElements = state.numElements;
+ if (state.enabled) {
+ // Avoid off-by-one errors in numElements computation.
+ // For the last element, we will only touch the data for the
+ // element and nothing beyond it.
+ long bytesRemaining = state.bufferBinding->byteLength() - state.offset;
+ long numElements = 0;
+ if (bytesRemaining >= state.bytesPerElement)
+ numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride;
+ if (numElements < smallestNumElements)
+ smallestNumElements = numElements;
+ }
}
}
@@ -817,18 +871,26 @@ void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long coun
return;
}
- if (!count)
- return;
-
// Ensure we have a valid rendering state
- if (!validateRenderingState(first + count)) {
+ CheckedInt<int32_t> checkedFirst(first);
+ CheckedInt<int32_t> checkedCount(count);
+ CheckedInt<int32_t> checkedSum = checkedFirst + checkedCount;
+ if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
- handleNPOTTextures(true);
+ bool vertexAttrib0Simulated = false;
+ if (!isGLES2Compliant()) {
+ vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1);
+ handleNPOTTextures(true);
+ }
m_context->drawArrays(mode, first, count);
- handleNPOTTextures(false);
+ if (!isGLES2Compliant()) {
+ handleNPOTTextures(false);
+ if (vertexAttrib0Simulated)
+ restoreStatesAfterVertexAttrib0Simulation();
+ }
cleanupAfterGraphicsCall(true);
}
@@ -853,9 +915,6 @@ void WebGLRenderingContext::drawElements(unsigned long mode, long count, unsigne
return;
}
- if (!count)
- return;
-
// Ensure we have a valid rendering state
long numElements;
@@ -870,14 +929,26 @@ void WebGLRenderingContext::drawElements(unsigned long mode, long count, unsigne
return;
}
- handleNPOTTextures(true);
+ bool vertexAttrib0Simulated = false;
+ if (!isGLES2Compliant()) {
+ vertexAttrib0Simulated = simulateVertexAttrib0(numElements);
+ handleNPOTTextures(true);
+ }
m_context->drawElements(mode, count, type, offset);
- handleNPOTTextures(false);
+ if (!isGLES2Compliant()) {
+ handleNPOTTextures(false);
+ if (vertexAttrib0Simulated)
+ restoreStatesAfterVertexAttrib0Simulation();
+ }
cleanupAfterGraphicsCall(true);
}
void WebGLRenderingContext::enable(unsigned long cap)
{
+ if (!isGLES2Compliant()) {
+ if (!validateCapability(cap))
+ return;
+ }
m_context->enable(cap);
cleanupAfterGraphicsCall(false);
}
@@ -1040,6 +1111,33 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram
return WebGLActiveInfo::create(info.name, info.type, info.size);
}
+bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<WebGLShader*>& shaderObjects, ExceptionCode& ec)
+{
+ UNUSED_PARAM(ec);
+ shaderObjects.clear();
+ if (!validateWebGLObject(program))
+ return false;
+ int numShaders = 0;
+ m_context->getProgramiv(program, GraphicsContext3D::ATTACHED_SHADERS, &numShaders);
+ if (numShaders) {
+ OwnArrayPtr<unsigned int> shaders(new unsigned int[numShaders]);
+ int count;
+ m_context->getAttachedShaders(program, numShaders, &count, shaders.get());
+ if (count != numShaders)
+ return false;
+ shaderObjects.resize(numShaders);
+ for (int ii = 0; ii < numShaders; ++ii) {
+ WebGLShader* shader = findShader(shaders[ii]);
+ if (!shader) {
+ shaderObjects.clear();
+ return false;
+ }
+ shaderObjects[ii] = shader;
+ }
+ }
+ return true;
+}
+
int WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name)
{
return m_context->getAttribLocation(program, name);
@@ -1162,7 +1260,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionC
case GraphicsContext3D::COLOR_CLEAR_VALUE:
return getWebGLFloatArrayParameter(pname);
case GraphicsContext3D::COLOR_WRITEMASK:
- return getWebGLUnsignedByteArrayParameter(pname);
+ return getBooleanArrayParameter(pname);
case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
// Defined as null in the spec
return WebGLGetInfo();
@@ -1318,10 +1416,14 @@ WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, u
int value = 0;
switch (pname) {
case GraphicsContext3D::DELETE_STATUS:
- case GraphicsContext3D::LINK_STATUS:
case GraphicsContext3D::VALIDATE_STATUS:
m_context->getProgramiv(program, pname, &value);
return WebGLGetInfo(static_cast<bool>(value));
+ case GraphicsContext3D::LINK_STATUS:
+ if (program->isLinkFailureFlagSet())
+ return WebGLGetInfo(false);
+ m_context->getProgramiv(program, pname, &value);
+ return WebGLGetInfo(static_cast<bool>(value));
case GraphicsContext3D::INFO_LOG_LENGTH:
case GraphicsContext3D::ATTACHED_SHADERS:
case GraphicsContext3D::ACTIVE_ATTRIBUTES:
@@ -1469,13 +1571,24 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
ActiveInfo info;
if (!m_context->getActiveUniform(program, i, info))
return WebGLGetInfo();
- // Now need to look this up by name again to find its location
- long loc = m_context->getUniformLocation(program, info.name);
- if (loc == location) {
- // Found it. Use the type in the ActiveInfo to determine the return type.
- GraphicsContext3D::WebGLEnumType baseType;
- unsigned length;
- switch (info.type) {
+ // Strip "[0]" from the name if it's an array.
+ if (info.size > 1)
+ info.name = info.name.left(info.name.length() - 3);
+ // If it's an array, we need to iterate through each element, appending "[index]" to the name.
+ for (int index = 0; index < info.size; ++index) {
+ String name = info.name;
+ if (info.size > 1 && index >= 1) {
+ name.append('[');
+ name.append(String::number(index));
+ name.append(']');
+ }
+ // Now need to look this up by name again to find its location
+ long loc = m_context->getUniformLocation(program, name);
+ if (loc == location) {
+ // Found it. Use the type in the ActiveInfo to determine the return type.
+ GraphicsContext3D::WebGLEnumType baseType;
+ unsigned length;
+ switch (info.type) {
case GraphicsContext3D::BOOL:
baseType = GraphicsContext3D::BOOL;
length = 1;
@@ -1541,38 +1654,36 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
// FIXME: what to do about samplers?
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return WebGLGetInfo();
- }
- switch (baseType) {
- case GraphicsContext3D::FLOAT: {
- float value[16] = {0};
- m_context->getUniformfv(program, location, value);
- if (length == 1)
- return WebGLGetInfo(value[0]);
- else
+ }
+ switch (baseType) {
+ case GraphicsContext3D::FLOAT: {
+ float value[16] = {0};
+ m_context->getUniformfv(program, location, value);
+ if (length == 1)
+ return WebGLGetInfo(value[0]);
return WebGLGetInfo(Float32Array::create(value, length));
- }
- case GraphicsContext3D::INT: {
- int value[16] = {0};
- m_context->getUniformiv(program, location, value);
- if (length == 1)
- return WebGLGetInfo(static_cast<long>(value[0]));
- else
+ }
+ case GraphicsContext3D::INT: {
+ int value[16] = {0};
+ m_context->getUniformiv(program, location, value);
+ if (length == 1)
+ return WebGLGetInfo(static_cast<long>(value[0]));
return WebGLGetInfo(Int32Array::create(value, length));
- }
- case GraphicsContext3D::BOOL: {
- int value[16] = {0};
- m_context->getUniformiv(program, location, value);
- if (length == 1)
+ }
+ case GraphicsContext3D::BOOL: {
+ int value[16] = {0};
+ m_context->getUniformiv(program, location, value);
+ if (length > 1) {
+ unsigned char boolValue[16] = {0};
+ for (unsigned j = 0; j < length; j++)
+ boolValue[j] = static_cast<bool>(value[j]);
+ return WebGLGetInfo(Uint8Array::create(boolValue, length));
+ }
return WebGLGetInfo(static_cast<bool>(value[0]));
- else {
- unsigned char boolValue[16] = {0};
- for (unsigned j = 0; j < length; j++)
- boolValue[j] = static_cast<bool>(value[j]);
- return WebGLGetInfo(Uint8Array::create(boolValue, length));
}
- }
- default:
- notImplemented();
+ default:
+ notImplemented();
+ }
}
}
}
@@ -1597,39 +1708,48 @@ WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigne
{
UNUSED_PARAM(ec);
WebGLStateRestorer(this, false);
- switch (pname) {
- case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
- int name = 0;
- m_context->getVertexAttribiv(index, pname, &name);
- return WebGLGetInfo(PassRefPtr<WebGLBuffer>(findBuffer(static_cast<Platform3DObject>(name))));
+ if (index >= m_maxVertexAttribs) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return WebGLGetInfo();
}
+ switch (pname) {
+ case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ if (!isGLES2Compliant() && !index && m_vertexAttribState[0].bufferBinding == m_vertexAttrib0Buffer
+ || index >= m_vertexAttribState.size()
+ || !m_vertexAttribState[index].bufferBinding
+ || !m_vertexAttribState[index].bufferBinding->object())
+ return WebGLGetInfo();
+ return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_vertexAttribState[index].bufferBinding));
case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
- case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED: {
- int value = 0;
- m_context->getVertexAttribiv(index, pname, &value);
- return WebGLGetInfo(static_cast<bool>(value));
- }
+ if (index >= m_vertexAttribState.size())
+ return WebGLGetInfo(false);
+ return WebGLGetInfo(m_vertexAttribState[index].enabled);
+ case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ if (index >= m_vertexAttribState.size())
+ return WebGLGetInfo(false);
+ return WebGLGetInfo(m_vertexAttribState[index].normalized);
case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
- case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE: {
- int value = 0;
- m_context->getVertexAttribiv(index, pname, &value);
- return WebGLGetInfo(static_cast<long>(value));
- }
- case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE: {
- int value = 0;
- m_context->getVertexAttribiv(index, pname, &value);
- return WebGLGetInfo(static_cast<unsigned long>(value));
- }
- case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: {
- float value[4] = {0};
- m_context->getVertexAttribfv(index, pname, value);
- return WebGLGetInfo(Float32Array::create(value, 4));
- }
- default: {
+ if (index >= m_vertexAttribState.size())
+ return WebGLGetInfo(static_cast<long>(4));
+ return WebGLGetInfo(m_vertexAttribState[index].size);
+ case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
+ if (index >= m_vertexAttribState.size())
+ return WebGLGetInfo(static_cast<long>(0));
+ return WebGLGetInfo(m_vertexAttribState[index].originalStride);
+ case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
+ if (index >= m_vertexAttribState.size())
+ return WebGLGetInfo(static_cast<unsigned long>(GraphicsContext3D::FLOAT));
+ return WebGLGetInfo(m_vertexAttribState[index].type);
+ case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
+ if (index >= m_vertexAttribState.size()) {
+ float value[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ return WebGLGetInfo(Float32Array::create(value, 4));
+ }
+ return WebGLGetInfo(Float32Array::create(m_vertexAttribState[index].value, 4));
+ default:
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
return WebGLGetInfo();
}
- }
}
long WebGLRenderingContext::getVertexAttribOffset(unsigned long index, unsigned long pname)
@@ -1641,6 +1761,12 @@ long WebGLRenderingContext::getVertexAttribOffset(unsigned long index, unsigned
void WebGLRenderingContext::hint(unsigned long target, unsigned long mode)
{
+ if (!isGLES2Compliant()) {
+ if (target != GraphicsContext3D::GENERATE_MIPMAP_HINT) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return;
+ }
+ }
m_context->hint(target, mode);
cleanupAfterGraphicsCall(false);
}
@@ -1655,6 +1781,10 @@ bool WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
bool WebGLRenderingContext::isEnabled(unsigned long cap)
{
+ if (!isGLES2Compliant()) {
+ if (!validateCapability(cap))
+ return false;
+ }
return m_context->isEnabled(cap);
}
@@ -1709,6 +1839,28 @@ void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec
UNUSED_PARAM(ec);
if (!validateWebGLObject(program))
return;
+ if (!isGLES2Compliant()) {
+ Vector<WebGLShader*> shaders;
+ bool succeed = getAttachedShaders(program, shaders, ec);
+ if (succeed) {
+ bool vShader = false;
+ bool fShader = false;
+ for (size_t ii = 0; ii < shaders.size() && (!vShader || !fShader); ++ii) {
+ if (shaders[ii]->getType() == GraphicsContext3D::VERTEX_SHADER)
+ vShader = true;
+ else if (shaders[ii]->getType() == GraphicsContext3D::FRAGMENT_SHADER)
+ fShader = true;
+ }
+ if (!vShader || !fShader)
+ succeed = false;
+ }
+ if (!succeed) {
+ program->setLinkFailureFlag(true);
+ return;
+ }
+ program->setLinkFailureFlag(false);
+ }
+
m_context->linkProgram(program);
program->cacheActiveAttribLocations();
cleanupAfterGraphicsCall(false);
@@ -1716,22 +1868,26 @@ void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec
void WebGLRenderingContext::pixelStorei(unsigned long pname, long param)
{
- if (pname == GraphicsContext3D::UNPACK_FLIP_Y_WEBGL) {
+ switch (pname) {
+ case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
m_unpackFlipY = param;
- } else if (pname == GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL) {
+ break;
+ case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
m_unpackPremultiplyAlpha = param;
- } else {
+ break;
+ case GraphicsContext3D::PACK_ALIGNMENT:
+ case GraphicsContext3D::UNPACK_ALIGNMENT:
m_context->pixelStorei(pname, param);
if (param == 1 || param == 2 || param == 4 || param == 8) {
- switch (pname) {
- case GraphicsContext3D::PACK_ALIGNMENT:
+ if (pname == GraphicsContext3D::PACK_ALIGNMENT)
m_packAlignment = static_cast<int>(param);
- break;
- case GraphicsContext3D::UNPACK_ALIGNMENT:
+ else // GraphicsContext3D::UNPACK_ALIGNMENT:
m_unpackAlignment = static_cast<int>(param);
- break;
- }
}
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return;
}
cleanupAfterGraphicsCall(false);
}
@@ -1940,9 +2096,27 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned
unsigned width, unsigned height, unsigned border,
unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode& ec)
{
- // FIXME: Need to make sure passed buffer has enough bytes to define the texture
+ if (!validateTexFuncData(width, height, format, type, pixels))
+ return;
+ void* data = pixels ? pixels->baseAddress() : 0;
+ Vector<uint8_t> tempData;
+ bool changeUnpackAlignment = false;
+ if (pixels && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
+ if (!m_context->extractTextureData(width, height, format, type,
+ m_unpackAlignment,
+ m_unpackFlipY, m_unpackPremultiplyAlpha,
+ pixels,
+ tempData))
+ return;
+ data = tempData.data();
+ changeUnpackAlignment = true;
+ }
+ if (changeUnpackAlignment)
+ m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
texImage2DBase(target, level, internalformat, width, height, border,
- format, type, pixels ? pixels->baseAddress() : 0, ec);
+ format, type, data, ec);
+ if (changeUnpackAlignment)
+ m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
@@ -2196,8 +2370,26 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
unsigned width, unsigned height,
unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode& ec)
{
- // FIXME: Need to make sure passed buffer has enough bytes to define the texture
- texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, pixels ? pixels->baseAddress() : 0, ec);
+ if (!validateTexFuncData(width, height, format, type, pixels))
+ return;
+ void* data = pixels ? pixels->baseAddress() : 0;
+ Vector<uint8_t> tempData;
+ bool changeUnpackAlignment = false;
+ if (pixels && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
+ if (!m_context->extractTextureData(width, height, format, type,
+ m_unpackAlignment,
+ m_unpackFlipY, m_unpackPremultiplyAlpha,
+ pixels,
+ tempData))
+ return;
+ data = tempData.data();
+ changeUnpackAlignment = true;
+ }
+ if (changeUnpackAlignment)
+ m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
+ texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
+ if (changeUnpackAlignment)
+ m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
@@ -2381,18 +2573,9 @@ void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateUniformParameters(location, v, 1))
return;
- }
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
m_context->uniform1fv(location->location(), v->data(), v->length());
cleanupAfterGraphicsCall(false);
}
@@ -2400,18 +2583,9 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 1))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
m_context->uniform1fv(location->location(), v, size);
cleanupAfterGraphicsCall(false);
}
@@ -2434,18 +2608,9 @@ void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateUniformParameters(location, v, 1))
return;
- }
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
m_context->uniform1iv(location->location(), v->data(), v->length());
cleanupAfterGraphicsCall(false);
}
@@ -2453,18 +2618,9 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 1))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
m_context->uniform1iv(location->location(), v, size);
cleanupAfterGraphicsCall(false);
}
@@ -2487,19 +2643,9 @@ void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, 2))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 2
m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
cleanupAfterGraphicsCall(false);
}
@@ -2507,19 +2653,9 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 2))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 2
m_context->uniform2fv(location->location(), v, size / 2);
cleanupAfterGraphicsCall(false);
}
@@ -2542,19 +2678,9 @@ void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateUniformParameters(location, v, 2))
return;
- }
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 2
m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
cleanupAfterGraphicsCall(false);
}
@@ -2562,19 +2688,9 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 2))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 2
m_context->uniform2iv(location->location(), v, size / 2);
cleanupAfterGraphicsCall(false);
}
@@ -2597,19 +2713,9 @@ void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateUniformParameters(location, v, 3))
return;
- }
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 3
m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
cleanupAfterGraphicsCall(false);
}
@@ -2617,19 +2723,9 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 3))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 3
m_context->uniform3fv(location->location(), v, size / 3);
cleanupAfterGraphicsCall(false);
}
@@ -2652,19 +2748,9 @@ void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, 3))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 3
m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
cleanupAfterGraphicsCall(false);
}
@@ -2672,19 +2758,9 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 3))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 3
m_context->uniform3iv(location->location(), v, size / 3);
cleanupAfterGraphicsCall(false);
}
@@ -2707,19 +2783,9 @@ void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, floa
void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateUniformParameters(location, v, 4))
return;
- }
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 4
m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
cleanupAfterGraphicsCall(false);
}
@@ -2727,19 +2793,9 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 4))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 4
m_context->uniform4fv(location->location(), v, size / 4);
cleanupAfterGraphicsCall(false);
}
@@ -2762,19 +2818,9 @@ void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, 4))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 4
m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
cleanupAfterGraphicsCall(false);
}
@@ -2782,19 +2828,9 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformParameters(location, v, size, 4))
return;
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 4
m_context->uniform4iv(location->location(), v, size / 4);
cleanupAfterGraphicsCall(false);
}
@@ -2802,19 +2838,8 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!validateUniformMatrixParameters(location, transpose, v, 4))
return;
- }
- // FIXME: length needs to be a multiple of 4
m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
cleanupAfterGraphicsCall(false);
}
@@ -2822,19 +2847,8 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformMatrixParameters(location, transpose, v, size, 4))
return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 4
m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
cleanupAfterGraphicsCall(false);
}
@@ -2842,19 +2856,8 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformMatrixParameters(location, transpose, v, 9))
return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 9
m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
cleanupAfterGraphicsCall(false);
}
@@ -2862,19 +2865,8 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateUniformMatrixParameters(location, transpose, v, size, 9))
return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 9
m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
cleanupAfterGraphicsCall(false);
}
@@ -2882,19 +2874,8 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
- return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!validateUniformMatrixParameters(location, transpose, v, 16))
return;
- }
- // FIXME: length needs to be a multiple of 16
m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
cleanupAfterGraphicsCall(false);
}
@@ -2902,19 +2883,8 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location)
+ if (!validateUniformMatrixParameters(location, transpose, v, size, 16))
return;
-
- if (location->program() != m_currentProgram) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return;
- }
-
- if (!v) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- // FIXME: length needs to be a multiple of 16
m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
cleanupAfterGraphicsCall(false);
}
@@ -2922,11 +2892,10 @@ void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio
void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (program && program->context() != this) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
-
m_currentProgram = program;
m_context->useProgram(program);
cleanupAfterGraphicsCall(false);
@@ -2935,139 +2904,111 @@ void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!program || program->context() != this) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ if (!validateWebGLObject(program))
return;
- }
-
m_context->validateProgram(program);
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::vertexAttrib1f(unsigned long indx, float v0)
+void WebGLRenderingContext::vertexAttrib1f(unsigned long index, float v0)
{
- m_context->vertexAttrib1f(indx, v0);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfImpl(index, 1, v0, 0.0f, 0.0f, 1.0f);
}
-void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, Float32Array* v)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- m_context->vertexAttrib1fv(indx, v->data());
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, 1);
}
-void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib1fv(unsigned long index, float* v, int size)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- UNUSED_PARAM(size);
-
- m_context->vertexAttrib1fv(indx, v);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, size, 1);
}
-void WebGLRenderingContext::vertexAttrib2f(unsigned long indx, float v0, float v1)
+void WebGLRenderingContext::vertexAttrib2f(unsigned long index, float v0, float v1)
{
- m_context->vertexAttrib2f(indx, v0, v1);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfImpl(index, 2, v0, v1, 0.0f, 1.0f);
}
-void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, Float32Array* v)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- m_context->vertexAttrib2fv(indx, v->data());
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, 2);
}
-void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib2fv(unsigned long index, float* v, int size)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- UNUSED_PARAM(size);
-
- m_context->vertexAttrib2fv(indx, v);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, size, 2);
}
-void WebGLRenderingContext::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
+void WebGLRenderingContext::vertexAttrib3f(unsigned long index, float v0, float v1, float v2)
{
- m_context->vertexAttrib3f(indx, v0, v1, v2);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfImpl(index, 3, v0, v1, v2, 1.0f);
}
-void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, Float32Array* v)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- m_context->vertexAttrib3fv(indx, v->data());
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, 3);
}
-void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib3fv(unsigned long index, float* v, int size)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- UNUSED_PARAM(size);
-
- m_context->vertexAttrib3fv(indx, v);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, size, 3);
}
-void WebGLRenderingContext::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
+void WebGLRenderingContext::vertexAttrib4f(unsigned long index, float v0, float v1, float v2, float v3)
{
- m_context->vertexAttrib4f(indx, v0, v1, v2, v3);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfImpl(index, 4, v0, v1, v2, v3);
}
-void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, Float32Array* v)
+void WebGLRenderingContext::vertexAttrib4fv(unsigned long index, Float32Array* v)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- m_context->vertexAttrib4fv(indx, v->data());
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, 4);
}
-void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, float* v, int size)
+void WebGLRenderingContext::vertexAttrib4fv(unsigned long index, float* v, int size)
{
- // FIXME: Need to make sure array is big enough for attribute being set
- UNUSED_PARAM(size);
-
- m_context->vertexAttrib4fv(indx, v);
- cleanupAfterGraphicsCall(false);
+ vertexAttribfvImpl(index, v, size, 4);
}
-void WebGLRenderingContext::vertexAttribPointer(unsigned long indx, long size, unsigned long type, bool normalized, unsigned long stride, unsigned long offset, ExceptionCode& ec)
+void WebGLRenderingContext::vertexAttribPointer(unsigned long index, long size, unsigned long type, bool normalized, long stride, long offset, ExceptionCode& ec)
{
- UNUSED_PARAM(ec);
- if (!m_boundArrayBuffer || indx >= m_maxVertexAttribs) {
+ if (index >= m_maxVertexAttribs) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
-
- if (indx >= m_vertexAttribState.size())
- m_vertexAttribState.resize(indx + 1);
-
+ if (size < 1 || size > 4 || stride < 0 || offset < 0) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ if (!m_boundArrayBuffer) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
// Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
long bytesPerElement = size * sizeInBytes(type, ec);
if (bytesPerElement <= 0)
return;
+
+ if (index >= m_vertexAttribState.size())
+ m_vertexAttribState.resize(index + 1);
+
long validatedStride = bytesPerElement;
if (stride != 0) {
if ((long) stride < bytesPerElement) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
-
validatedStride = stride;
}
-
- m_vertexAttribState[indx].bufferBinding = m_boundArrayBuffer;
- // Avoid off-by-one errors in numElements computation.
- // For the last element, we will only touch the data for the
- // element and nothing beyond it.
- long bytesRemaining = m_boundArrayBuffer->byteLength(GraphicsContext3D::ARRAY_BUFFER) - offset;
- if (bytesRemaining < bytesPerElement)
- m_vertexAttribState[indx].numElements = 0;
- else
- m_vertexAttribState[indx].numElements = 1 + (bytesRemaining - bytesPerElement) / validatedStride;
-
- m_context->vertexAttribPointer(indx, size, type, normalized, stride, offset);
+ m_vertexAttribState[index].bufferBinding = m_boundArrayBuffer;
+ m_vertexAttribState[index].bytesPerElement = bytesPerElement;
+ m_vertexAttribState[index].size = size;
+ m_vertexAttribState[index].type = type;
+ m_vertexAttribState[index].normalized = normalized;
+ m_vertexAttribState[index].stride = validatedStride;
+ m_vertexAttribState[index].originalStride = stride;
+ m_vertexAttribState[index].offset = offset;
+ m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
cleanupAfterGraphicsCall(false);
}
@@ -3141,6 +3082,18 @@ WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj)
return 0;
}
+WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj)
+{
+ if (!obj)
+ return 0;
+ HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end();
+ for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
+ if ((*it)->isShader() && (*it)->object() == obj)
+ return reinterpret_cast<WebGLShader*>((*it).get());
+ }
+ return 0;
+}
+
WebGLGetInfo WebGLRenderingContext::getBooleanParameter(unsigned long pname)
{
unsigned char value;
@@ -3148,6 +3101,20 @@ WebGLGetInfo WebGLRenderingContext::getBooleanParameter(unsigned long pname)
return WebGLGetInfo(static_cast<bool>(value));
}
+WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(unsigned long pname)
+{
+ if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
+ notImplemented();
+ return WebGLGetInfo(0, 0);
+ }
+ unsigned char value[4] = {0};
+ m_context->getBooleanv(pname, value);
+ bool boolValue[4];
+ for (int ii = 0; ii < 4; ++ii)
+ boolValue[ii] = static_cast<bool>(value[ii]);
+ return WebGLGetInfo(boolValue, 4);
+}
+
WebGLGetInfo WebGLRenderingContext::getFloatParameter(unsigned long pname)
{
float value;
@@ -3214,21 +3181,6 @@ WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(unsigned long pnam
return WebGLGetInfo(Int32Array::create(value, length));
}
-WebGLGetInfo WebGLRenderingContext::getWebGLUnsignedByteArrayParameter(unsigned long pname)
-{
- unsigned char value[4] = {0};
- m_context->getBooleanv(pname, value);
- unsigned length = 0;
- switch (pname) {
- case GraphicsContext3D::COLOR_WRITEMASK:
- length = 4;
- break;
- default:
- notImplemented();
- }
- return WebGLGetInfo(Uint8Array::create(value, length));
-}
-
bool WebGLRenderingContext::isGLES2Compliant()
{
return m_context->isGLES2Compliant();
@@ -3236,8 +3188,6 @@ bool WebGLRenderingContext::isGLES2Compliant()
void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
{
- if (isGLES2Compliant())
- return;
bool resetActiveUnit = false;
for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()
@@ -3445,6 +3395,56 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
return true;
}
+bool WebGLRenderingContext::validateTexFuncData(long width, long height,
+ unsigned long format, unsigned long type,
+ ArrayBufferView* pixels)
+{
+ if (!pixels)
+ return true;
+
+ if (!validateTexFuncFormatAndType(format, type))
+ return false;
+
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_BYTE:
+ if (!pixels->isUnsignedByteArray()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return false;
+ }
+ break;
+ case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+ case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+ case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+ if (!pixels->isUnsignedShortArray()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return false;
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ unsigned long componentsPerPixel, bytesPerComponent;
+ if (!m_context->computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+
+ if (!width || !height)
+ return true;
+ unsigned int validRowBytes = width * componentsPerPixel * bytesPerComponent;
+ unsigned int totalRowBytes = validRowBytes;
+ unsigned int remainder = validRowBytes % m_unpackAlignment;
+ if (remainder)
+ totalRowBytes += (m_unpackAlignment - remainder);
+ unsigned int totalBytesRequired = (height - 1) * totalRowBytes + validRowBytes;
+ if (pixels->byteLength() < totalBytesRequired) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return false;
+ }
+ return true;
+}
+
bool WebGLRenderingContext::validateDrawMode(unsigned long mode)
{
switch (mode) {
@@ -3487,6 +3487,231 @@ bool WebGLRenderingContext::validateFramebufferFuncParameters(unsigned long targ
return true;
}
+bool WebGLRenderingContext::validateBlendEquation(unsigned long mode)
+{
+ switch (mode) {
+ case GraphicsContext3D::FUNC_ADD:
+ case GraphicsContext3D::FUNC_SUBTRACT:
+ case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
+ return true;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+}
+
+bool WebGLRenderingContext::validateCapability(unsigned long cap)
+{
+ switch (cap) {
+ case GraphicsContext3D::BLEND:
+ case GraphicsContext3D::CULL_FACE:
+ case GraphicsContext3D::DEPTH_TEST:
+ case GraphicsContext3D::DITHER:
+ case GraphicsContext3D::POLYGON_OFFSET_FILL:
+ case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
+ case GraphicsContext3D::SAMPLE_COVERAGE:
+ case GraphicsContext3D::SCISSOR_TEST:
+ case GraphicsContext3D::STENCIL_TEST:
+ return true;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+}
+
+bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, int requiredMinSize)
+{
+ if (!v) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
+}
+
+bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, int requiredMinSize)
+{
+ if (!v) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
+}
+
+bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, void* v, int size, int requiredMinSize)
+{
+ return validateUniformMatrixParameters(location, false, v, size, requiredMinSize);
+}
+
+bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, Float32Array* v, int requiredMinSize)
+{
+ if (!v) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ return validateUniformMatrixParameters(location, transpose, v->data(), v->length(), requiredMinSize);
+}
+
+bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, void* v, int size, int requiredMinSize)
+{
+ if (!location)
+ return false;
+ if (location->program() != m_currentProgram) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return false;
+ }
+ if (!v) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ if (transpose) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ if (size < requiredMinSize) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ return true;
+}
+
+void WebGLRenderingContext::vertexAttribfImpl(unsigned long index, int expectedSize, float v0, float v1, float v2, float v3)
+{
+ if (index >= m_maxVertexAttribs) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ // In GL, we skip setting vertexAttrib0 values.
+ if (index || isGLES2Compliant()) {
+ switch (expectedSize) {
+ case 1:
+ m_context->vertexAttrib1f(index, v0);
+ break;
+ case 2:
+ m_context->vertexAttrib2f(index, v0, v1);
+ break;
+ case 3:
+ m_context->vertexAttrib3f(index, v0, v1, v2);
+ break;
+ case 4:
+ m_context->vertexAttrib4f(index, v0, v1, v2, v3);
+ break;
+ }
+ cleanupAfterGraphicsCall(false);
+ }
+ if (index >= m_vertexAttribState.size())
+ m_vertexAttribState.resize(index + 1);
+ m_vertexAttribState[index].value[0] = v0;
+ m_vertexAttribState[index].value[1] = v1;
+ m_vertexAttribState[index].value[2] = v2;
+ m_vertexAttribState[index].value[3] = v3;
+}
+
+void WebGLRenderingContext::vertexAttribfvImpl(unsigned long index, Float32Array* v, int expectedSize)
+{
+ if (!v) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ vertexAttribfvImpl(index, v->data(), v->length(), expectedSize);
+}
+
+void WebGLRenderingContext::vertexAttribfvImpl(unsigned long index, float* v, int size, int expectedSize)
+{
+ if (!v) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ if (size < expectedSize) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ if (index >= m_maxVertexAttribs) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ // In GL, we skip setting vertexAttrib0 values.
+ if (index || isGLES2Compliant()) {
+ switch (expectedSize) {
+ case 1:
+ m_context->vertexAttrib1fv(index, v);
+ break;
+ case 2:
+ m_context->vertexAttrib2fv(index, v);
+ break;
+ case 3:
+ m_context->vertexAttrib3fv(index, v);
+ break;
+ case 4:
+ m_context->vertexAttrib4fv(index, v);
+ break;
+ }
+ cleanupAfterGraphicsCall(false);
+ }
+ if (index >= m_vertexAttribState.size())
+ m_vertexAttribState.resize(index + 1);
+ m_vertexAttribState[index].initValue();
+ for (int ii = 0; ii < expectedSize; ++ii)
+ m_vertexAttribState[index].value[ii] = v[ii];
+}
+
+void WebGLRenderingContext::initVertexAttrib0()
+{
+ m_vertexAttribState.resize(1);
+ m_vertexAttrib0Buffer = createBuffer();
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer.get());
+ m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
+ m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_vertexAttribState[0].bufferBinding = m_vertexAttrib0Buffer;
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
+ m_context->enableVertexAttribArray(0);
+ m_vertexAttrib0BufferSize = 0;
+ m_vertexAttrib0BufferValue[0] = 0.0f;
+ m_vertexAttrib0BufferValue[1] = 0.0f;
+ m_vertexAttrib0BufferValue[2] = 0.0f;
+ m_vertexAttrib0BufferValue[3] = 1.0f;
+}
+
+bool WebGLRenderingContext::simulateVertexAttrib0(long numVertex)
+{
+ const VertexAttribState& state = m_vertexAttribState[0];
+ if (state.enabled || !m_currentProgram || !m_currentProgram->object()
+ || !m_currentProgram->isUsingVertexAttrib0())
+ return false;
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer.get());
+ long bufferDataSize = (numVertex + 1) * 4 * sizeof(float);
+ if (bufferDataSize > m_vertexAttrib0BufferSize
+ || state.value[0] != m_vertexAttrib0BufferValue[0]
+ || state.value[1] != m_vertexAttrib0BufferValue[1]
+ || state.value[2] != m_vertexAttrib0BufferValue[2]
+ || state.value[3] != m_vertexAttrib0BufferValue[3]) {
+ RefPtr<Float32Array> bufferData = Float32Array::create((numVertex + 1) * 4);
+ for (long ii = 0; ii < numVertex + 1; ++ii) {
+ bufferData->set(ii * 4, state.value[0]);
+ bufferData->set(ii * 4 + 1, state.value[1]);
+ bufferData->set(ii * 4 + 2, state.value[2]);
+ bufferData->set(ii * 4 + 3, state.value[3]);
+ }
+ m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferData.get(), GraphicsContext3D::DYNAMIC_DRAW);
+ m_vertexAttrib0BufferSize = bufferDataSize;
+ m_vertexAttrib0BufferValue[0] = state.value[0];
+ m_vertexAttrib0BufferValue[1] = state.value[1];
+ m_vertexAttrib0BufferValue[2] = state.value[2];
+ m_vertexAttrib0BufferValue[3] = state.value[3];
+ }
+ m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
+ return true;
+}
+
+void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
+{
+ const VertexAttribState& state = m_vertexAttribState[0];
+ if (state.bufferBinding != m_vertexAttrib0Buffer) {
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, state.bufferBinding.get());
+ m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
+ }
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_boundArrayBuffer.get());
+}
+
} // namespace WebCore
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index d05d60b..be74001 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -131,6 +131,8 @@ class WebKitCSSMatrix;
PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, unsigned long index, ExceptionCode&);
PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, unsigned long index, ExceptionCode&);
+ bool getAttachedShaders(WebGLProgram*, Vector<WebGLShader*>&, ExceptionCode&);
+
int getAttribLocation(WebGLProgram*, const String& name);
WebGLGetInfo getBufferParameter(unsigned long target, unsigned long pname, ExceptionCode&);
@@ -281,20 +283,20 @@ class WebKitCSSMatrix;
void useProgram(WebGLProgram*, ExceptionCode&);
void validateProgram(WebGLProgram*, ExceptionCode&);
- void vertexAttrib1f(unsigned long indx, float x);
- void vertexAttrib1fv(unsigned long indx, Float32Array* values);
- void vertexAttrib1fv(unsigned long indx, float* values, int size);
- void vertexAttrib2f(unsigned long indx, float x, float y);
- void vertexAttrib2fv(unsigned long indx, Float32Array* values);
- void vertexAttrib2fv(unsigned long indx, float* values, int size);
- void vertexAttrib3f(unsigned long indx, float x, float y, float z);
- void vertexAttrib3fv(unsigned long indx, Float32Array* values);
- void vertexAttrib3fv(unsigned long indx, float* values, int size);
- void vertexAttrib4f(unsigned long indx, float x, float y, float z, float w);
- void vertexAttrib4fv(unsigned long indx, Float32Array* values);
- void vertexAttrib4fv(unsigned long indx, float* values, int size);
- void vertexAttribPointer(unsigned long indx, long size, unsigned long type, bool normalized,
- unsigned long stride, unsigned long offset, ExceptionCode&);
+ void vertexAttrib1f(unsigned long index, float x);
+ void vertexAttrib1fv(unsigned long index, Float32Array* values);
+ void vertexAttrib1fv(unsigned long index, float* values, int size);
+ void vertexAttrib2f(unsigned long index, float x, float y);
+ void vertexAttrib2fv(unsigned long index, Float32Array* values);
+ void vertexAttrib2fv(unsigned long index, float* values, int size);
+ void vertexAttrib3f(unsigned long index, float x, float y, float z);
+ void vertexAttrib3fv(unsigned long index, Float32Array* values);
+ void vertexAttrib3fv(unsigned long index, float* values, int size);
+ void vertexAttrib4f(unsigned long index, float x, float y, float z, float w);
+ void vertexAttrib4fv(unsigned long index, Float32Array* values);
+ void vertexAttrib4fv(unsigned long index, float* values, int size);
+ void vertexAttribPointer(unsigned long index, long size, unsigned long type, bool normalized,
+ long stride, long offset, ExceptionCode&);
void viewport(long x, long y, unsigned long width, unsigned long height);
@@ -318,6 +320,7 @@ class WebKitCSSMatrix;
WebGLTexture* findTexture(Platform3DObject);
WebGLRenderbuffer* findRenderbuffer(Platform3DObject);
WebGLBuffer* findBuffer(Platform3DObject);
+ WebGLShader* findShader(Platform3DObject);
void markContextChanged();
void cleanupAfterGraphicsCall(bool changed)
@@ -354,14 +357,44 @@ class WebKitCSSMatrix;
// Cached values for vertex attrib range checks
class VertexAttribState {
public:
- VertexAttribState() : enabled(false), numElements(0) { }
+ VertexAttribState()
+ : enabled(false)
+ , bytesPerElement(0)
+ , size(4)
+ , type(GraphicsContext3D::FLOAT)
+ , normalized(false)
+ , stride(16)
+ , originalStride(0)
+ , offset(0)
+ {
+ initValue();
+ }
+
+ void initValue()
+ {
+ value[0] = 0.0f;
+ value[1] = 0.0f;
+ value[2] = 0.0f;
+ value[3] = 1.0f;
+ }
+
bool enabled;
- long numElements;
RefPtr<WebGLBuffer> bufferBinding;
+ long bytesPerElement;
+ long size;
+ unsigned long type;
+ bool normalized;
+ long stride;
+ long originalStride;
+ long offset;
+ float value[4];
};
Vector<VertexAttribState> m_vertexAttribState;
unsigned m_maxVertexAttribs;
+ RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
+ long m_vertexAttrib0BufferSize;
+ float m_vertexAttrib0BufferValue[4];
RefPtr<WebGLProgram> m_currentProgram;
RefPtr<WebGLFramebuffer> m_framebufferBinding;
@@ -389,13 +422,13 @@ class WebKitCSSMatrix;
// Helpers for getParameter and others
WebGLGetInfo getBooleanParameter(unsigned long pname);
+ WebGLGetInfo getBooleanArrayParameter(unsigned long pname);
WebGLGetInfo getFloatParameter(unsigned long pname);
WebGLGetInfo getIntParameter(unsigned long pname);
WebGLGetInfo getLongParameter(unsigned long pname);
WebGLGetInfo getUnsignedLongParameter(unsigned long pname);
WebGLGetInfo getWebGLFloatArrayParameter(unsigned long pname);
WebGLGetInfo getWebGLIntArrayParameter(unsigned long pname);
- WebGLGetInfo getWebGLUnsignedByteArrayParameter(unsigned long pname);
void texImage2DBase(unsigned target, unsigned level, unsigned internalformat,
unsigned width, unsigned height, unsigned border,
@@ -424,16 +457,23 @@ class WebKitCSSMatrix;
WebGLTexture* getTextureBinding(unsigned long target);
// Helper function to check input format/type for functions {copy}Tex{Sub}Image.
- // Generate GL error and return false if parameters are invalid.
+ // Generates GL error and returns false if parameters are invalid.
bool validateTexFuncFormatAndType(unsigned long format, unsigned long type);
// Helper function to check input parameters for functions {copy}Tex{Sub}Image.
- // Generate GL error and return false if parameters are invalid.
+ // Generates GL error and returns false if parameters are invalid.
bool validateTexFuncParameters(unsigned long target, long level,
unsigned long internalformat,
long width, long height, long border,
unsigned long format, unsigned long type);
+ // Helper function to validate that the given ArrayBufferView
+ // is of the correct type and contains enough data for the texImage call.
+ // Generates GL error and returns false if parameters are invalid.
+ bool validateTexFuncData(long width, long height,
+ unsigned long format, unsigned long type,
+ ArrayBufferView* pixels);
+
// Helper function to validate mode for draw{Arrays/Elements}.
bool validateDrawMode(unsigned long);
@@ -448,6 +488,29 @@ class WebKitCSSMatrix;
// Generate GL error if parameters are illegal.
bool validateFramebufferFuncParameters(unsigned long target, unsigned long attachment);
+ // Helper function to validate blend equation mode.
+ bool validateBlendEquation(unsigned long);
+
+ // Helper function to validate a GL capability.
+ bool validateCapability(unsigned long);
+
+ // Helper function to validate input parameters for uniform functions.
+ bool validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, int mod);
+ bool validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, int mod);
+ bool validateUniformParameters(const WebGLUniformLocation* location, void* v, int size, int mod);
+ bool validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, Float32Array* v, int mod);
+ bool validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, void* v, int size, int mod);
+
+ // Helper functions for vertexAttribNf{v}.
+ void vertexAttribfImpl(unsigned long index, int expectedSize, float v0, float v1, float v2, float v3);
+ void vertexAttribfvImpl(unsigned long index, Float32Array* v, int expectedSize);
+ void vertexAttribfvImpl(unsigned long index, float* v, int size, int expectedSize);
+
+ // Helpers for simulating vertexAttrib0
+ void initVertexAttrib0();
+ bool simulateVertexAttrib0(long numVertex);
+ void restoreStatesAfterVertexAttrib0Simulation();
+
friend class WebGLStateRestorer;
};
diff --git a/WebCore/html/canvas/WebGLRenderingContext.idl b/WebCore/html/canvas/WebGLRenderingContext.idl
index b3793f5..1ea4c6d 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.idl
+++ b/WebCore/html/canvas/WebGLRenderingContext.idl
@@ -536,7 +536,9 @@ module html {
WebGLActiveInfo getActiveUniform(in WebGLProgram program, in unsigned long index)
raises (DOMException);
- // WebGLShaderArray glGetAttachedShaders(GLuint program);
+ // Array getAttachedShaders(GLuint program) raises (DOMException);
+ [Custom] void getAttachedShaders(GLuint program)
+ raises (DOMException);
int getAttribLocation(in WebGLProgram program, in DOMString name);
diff --git a/WebCore/html/canvas/WebGLShader.cpp b/WebCore/html/canvas/WebGLShader.cpp
index a353b15..664d3cb 100644
--- a/WebCore/html/canvas/WebGLShader.cpp
+++ b/WebCore/html/canvas/WebGLShader.cpp
@@ -39,6 +39,7 @@ PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContext* ctx, Graphics
WebGLShader::WebGLShader(WebGLRenderingContext* ctx, GraphicsContext3D::WebGLEnumType type)
: CanvasObject(ctx)
+ , m_type(type)
{
setObject(context()->graphicsContext3D()->createShader(type));
}
diff --git a/WebCore/html/canvas/WebGLShader.h b/WebCore/html/canvas/WebGLShader.h
index d4006aa..a0daa59 100644
--- a/WebCore/html/canvas/WebGLShader.h
+++ b/WebCore/html/canvas/WebGLShader.h
@@ -39,12 +39,16 @@ namespace WebCore {
static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GraphicsContext3D::WebGLEnumType);
+ GraphicsContext3D::WebGLEnumType getType() const { return m_type; }
+
private:
WebGLShader(WebGLRenderingContext*, GraphicsContext3D::WebGLEnumType);
virtual void _deleteObject(Platform3DObject);
virtual bool isShader() const { return true; }
+
+ GraphicsContext3D::WebGLEnumType m_type;
};
} // namespace WebCore