summaryrefslogtreecommitdiffstats
path: root/WebCore/html
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html')
-rw-r--r--WebCore/html/AsyncImageResizer.cpp77
-rw-r--r--WebCore/html/AsyncImageResizer.h107
-rw-r--r--WebCore/html/Blob.cpp91
-rw-r--r--WebCore/html/Blob.h60
-rw-r--r--WebCore/html/DocTypeStrings.gperf10
-rw-r--r--WebCore/html/File.cpp11
-rw-r--r--WebCore/html/File.h8
-rw-r--r--WebCore/html/FileReader.cpp2
-rw-r--r--WebCore/html/FileStream.cpp41
-rw-r--r--WebCore/html/FormDataList.cpp60
-rw-r--r--WebCore/html/FormDataList.h24
-rw-r--r--WebCore/html/HTML5DocumentParser.cpp310
-rw-r--r--WebCore/html/HTML5DocumentParser.h192
-rw-r--r--WebCore/html/HTML5EntityParser.cpp242
-rw-r--r--WebCore/html/HTML5EntityParser.h38
-rw-r--r--WebCore/html/HTML5Lexer.cpp2580
-rw-r--r--WebCore/html/HTML5Lexer.h67
-rw-r--r--WebCore/html/HTML5ScriptRunner.cpp50
-rw-r--r--WebCore/html/HTML5ScriptRunner.h7
-rw-r--r--WebCore/html/HTML5ScriptRunnerHost.h3
-rw-r--r--WebCore/html/HTML5Token.h59
-rw-r--r--WebCore/html/HTML5Tokenizer.cpp182
-rw-r--r--WebCore/html/HTML5Tokenizer.h87
-rw-r--r--WebCore/html/HTML5TreeBuilder.cpp60
-rw-r--r--WebCore/html/HTML5TreeBuilder.h38
-rw-r--r--WebCore/html/HTMLAppletElement.cpp4
-rw-r--r--WebCore/html/HTMLAttributeNames.in1
-rw-r--r--WebCore/html/HTMLCanvasElement.cpp6
-rw-r--r--WebCore/html/HTMLCanvasElement.idl5
-rw-r--r--WebCore/html/HTMLCollection.cpp6
-rw-r--r--WebCore/html/HTMLDataGridColElement.cpp6
-rw-r--r--WebCore/html/HTMLDocument.cpp10
-rw-r--r--WebCore/html/HTMLDocument.h2
-rw-r--r--WebCore/html/HTMLDocument.idl2
-rw-r--r--WebCore/html/HTMLDocumentParser.cpp (renamed from WebCore/html/HTMLTokenizer.cpp)234
-rw-r--r--WebCore/html/HTMLDocumentParser.h (renamed from WebCore/html/HTMLTokenizer.h)50
-rw-r--r--WebCore/html/HTMLElement.cpp6
-rw-r--r--WebCore/html/HTMLEntityNames.gperf13
-rw-r--r--WebCore/html/HTMLFormCollection.cpp15
-rw-r--r--WebCore/html/HTMLFormControlElement.cpp15
-rw-r--r--WebCore/html/HTMLFormElement.cpp4
-rw-r--r--WebCore/html/HTMLFrameElementBase.cpp4
-rw-r--r--WebCore/html/HTMLImageElement.cpp2
-rw-r--r--WebCore/html/HTMLImageElement.idl4
-rw-r--r--WebCore/html/HTMLInputElement.cpp30
-rw-r--r--WebCore/html/HTMLInputElement.h4
-rw-r--r--WebCore/html/HTMLInputElement.idl2
-rw-r--r--WebCore/html/HTMLMapElement.cpp48
-rw-r--r--WebCore/html/HTMLMapElement.h3
-rw-r--r--WebCore/html/HTMLMediaElement.cpp7
-rw-r--r--WebCore/html/HTMLMeterElement.cpp36
-rw-r--r--WebCore/html/HTMLMeterElement.h7
-rw-r--r--WebCore/html/HTMLMeterElement.idl1
-rw-r--r--WebCore/html/HTMLNameCollection.cpp8
-rw-r--r--WebCore/html/HTMLObjectElement.cpp2
-rw-r--r--WebCore/html/HTMLParamElement.cpp2
-rw-r--r--WebCore/html/HTMLProgressElement.cpp3
-rw-r--r--WebCore/html/HTMLVideoElement.idl5
-rw-r--r--WebCore/html/HTMLViewSourceDocument.cpp14
-rw-r--r--WebCore/html/HTMLViewSourceDocument.h8
-rw-r--r--WebCore/html/ImageResizerThread.cpp97
-rw-r--r--WebCore/html/ImageResizerThread.h70
-rw-r--r--WebCore/html/LegacyHTMLTreeConstructor.cpp (renamed from WebCore/html/HTMLParser.cpp)183
-rw-r--r--WebCore/html/LegacyHTMLTreeConstructor.h (renamed from WebCore/html/HTMLParser.h)14
-rw-r--r--WebCore/html/PreloadScanner.cpp2
-rw-r--r--WebCore/html/StepRange.cpp2
-rw-r--r--WebCore/html/TextMetrics.h1
-rw-r--r--WebCore/html/ValidityState.cpp2
-rw-r--r--WebCore/html/canvas/CanvasGradient.idl3
-rw-r--r--WebCore/html/canvas/CanvasPattern.idl3
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.cpp10
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.idl2
-rw-r--r--WebCore/html/canvas/Float32Array.cpp (renamed from WebCore/html/canvas/FloatArray.cpp)20
-rw-r--r--WebCore/html/canvas/Float32Array.h (renamed from WebCore/html/canvas/FloatArray.h)16
-rw-r--r--WebCore/html/canvas/Float32Array.idl (renamed from WebCore/html/canvas/FloatArray.idl)6
-rw-r--r--WebCore/html/canvas/Int16Array.idl2
-rw-r--r--WebCore/html/canvas/Int32Array.idl2
-rw-r--r--WebCore/html/canvas/Int8Array.idl2
-rw-r--r--WebCore/html/canvas/Uint16Array.idl2
-rw-r--r--WebCore/html/canvas/Uint32Array.idl2
-rw-r--r--WebCore/html/canvas/Uint8Array.idl2
-rw-r--r--WebCore/html/canvas/WebGLFramebuffer.cpp18
-rw-r--r--WebCore/html/canvas/WebGLFramebuffer.h2
-rw-r--r--WebCore/html/canvas/WebGLGetInfo.cpp6
-rw-r--r--WebCore/html/canvas/WebGLGetInfo.h8
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.cpp731
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.h96
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.idl63
-rw-r--r--WebCore/html/canvas/WebGLTexture.cpp1
-rw-r--r--WebCore/html/canvas/WebGLTexture.h5
90 files changed, 3845 insertions, 2503 deletions
diff --git a/WebCore/html/AsyncImageResizer.cpp b/WebCore/html/AsyncImageResizer.cpp
new file mode 100644
index 0000000..4bb74c9
--- /dev/null
+++ b/WebCore/html/AsyncImageResizer.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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"
+#if ENABLE(IMAGE_RESIZER)
+
+#include "AsyncImageResizer.h"
+
+#include "CachedImage.h"
+#include "ImageResizerThread.h"
+#include "SharedBuffer.h"
+#include <utility>
+
+namespace WebCore {
+
+PassRefPtr<AsyncImageResizer> AsyncImageResizer::create(CachedImage* cachedImage, OutputType outputType, IntSize desiredBounds, ScriptValue successCallback, ScriptValue errorCallback, float quality, AspectRatioOption aspectRatioOption, OrientationOption orientationOption)
+{
+ return adoptRef(new AsyncImageResizer(cachedImage, outputType, desiredBounds, successCallback, errorCallback, quality, aspectRatioOption, orientationOption));
+}
+
+AsyncImageResizer::AsyncImageResizer(CachedImage* cachedImage, OutputType outputType, IntSize desiredBounds, ScriptValue successCallback, ScriptValue errorCallback, float quality, AspectRatioOption aspectRatioOption, OrientationOption orientationOption)
+ : m_cachedImage(cachedImage)
+ , m_successCallback(successCallback)
+ , m_errorCallback(errorCallback)
+ , m_outputType(outputType)
+ , m_desiredBounds(desiredBounds)
+ , m_quality(quality)
+ , m_aspectRatioOption(aspectRatioOption)
+ , m_orientationOption(orientationOption)
+{
+ ASSERT(m_successCallback.isObject());
+ m_cachedImage->addClient(this);
+}
+
+AsyncImageResizer::~AsyncImageResizer()
+{
+}
+
+void AsyncImageResizer::notifyFinished(CachedResource* cachedResource)
+{
+ RefPtr<SharedBuffer> imageData = cachedResource->data()->copy();
+ cachedResource->removeClient(this);
+ CallbackInfo* callbackInfo = new CallbackInfo(this);
+ if (!ImageResizerThread::start(imageData, callbackInfo, m_outputType, m_desiredBounds, m_quality, m_aspectRatioOption, m_orientationOption))
+ resizeError();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(IMAGE_RESIZER)
diff --git a/WebCore/html/AsyncImageResizer.h b/WebCore/html/AsyncImageResizer.h
new file mode 100644
index 0000000..3eeeead
--- /dev/null
+++ b/WebCore/html/AsyncImageResizer.h
@@ -0,0 +1,107 @@
+/*
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 AsyncImageResizer_h
+#define AsyncImageResizer_h
+
+#if ENABLE(IMAGE_RESIZER)
+
+#include "Blob.h"
+#include "CachedResourceClient.h"
+#include "ScriptValue.h"
+
+namespace WebCore {
+
+class CachedImage;
+class ImageResizerThread;
+
+// AsyncImageResizer waits for the CachedImage that is passed in to load completely,
+// then starts an ImageResizerThread to resize the image. Once created, ImageResizerThread
+// becomes in charge of its own lifetime and that of AsyncImageResizer. After the callbacks
+// occur, both objects are destroyed. If the document is destroyed during resizing,
+// AsyncImageResizer will receive a notification and subsequently block the callbacks from
+// occurring.
+class AsyncImageResizer : public CachedResourceClient, public RefCounted<AsyncImageResizer> {
+public:
+ struct CallbackInfo {
+ CallbackInfo(PassRefPtr<AsyncImageResizer> asyncImageResizer)
+ : asyncImageResizer(asyncImageResizer)
+ , blob(0)
+ {
+ }
+
+ RefPtr<AsyncImageResizer> asyncImageResizer;
+ RefPtr<Blob> blob;
+ };
+
+ enum OutputType {
+ JPEG,
+ PNG
+ };
+
+ enum AspectRatioOption {
+ PreserveAspectRatio,
+ IgnoreAspectRatio
+ };
+
+ enum OrientationOption {
+ CorrectOrientation,
+ IgnoreOrientation
+ };
+
+ static PassRefPtr<AsyncImageResizer> create(CachedImage*, OutputType, IntSize desiredBounds, ScriptValue successCallback, ScriptValue errorCallback, float quality, AspectRatioOption, OrientationOption);
+ ~AsyncImageResizer();
+
+ // FIXME: Insert override function for notification of document destruction (change m_callbacksOk).
+
+ void resizeComplete(RefPtr<Blob>) { /* FIXME: Not yet implemented. */ }
+ void resizeError() { /* FIXME: Not yet implemented. */ }
+
+private:
+ AsyncImageResizer(CachedImage*, OutputType, IntSize desiredBounds, ScriptValue successCallback, ScriptValue errorCallback, float quality, AspectRatioOption, OrientationOption);
+ virtual void notifyFinished(CachedResource*);
+
+ CachedImage* m_cachedImage;
+ ScriptValue m_successCallback;
+ ScriptValue m_errorCallback;
+
+ // Parameters to pass into ImageResizerThread.
+ OutputType m_outputType;
+ IntSize m_desiredBounds;
+ float m_quality;
+ AspectRatioOption m_aspectRatioOption;
+ OrientationOption m_orientationOption;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(IMAGE_RESIZER)
+
+#endif // AsyncImageResizer_h
diff --git a/WebCore/html/Blob.cpp b/WebCore/html/Blob.cpp
index 83bbdc0..0546f1c 100644
--- a/WebCore/html/Blob.cpp
+++ b/WebCore/html/Blob.cpp
@@ -31,88 +31,65 @@
#include "config.h"
#include "Blob.h"
+#include "BlobItem.h"
#include "FileSystem.h"
namespace WebCore {
-#if ENABLE(BLOB_SLICE)
-const int Blob::toEndOfFile = -1;
-const double Blob::doNotCheckFileChange = 0;
-#endif
-
Blob::Blob(const String& path)
- : m_path(path)
-#if ENABLE(BLOB_SLICE)
- , m_start(0)
- , m_length(toEndOfFile)
- , m_snapshotCaptured(false)
- , m_snapshotSize(0)
- , m_snapshotModificationTime(doNotCheckFileChange)
-#endif
-{
-}
-
-#if ENABLE(BLOB_SLICE)
-Blob::Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime)
- : m_path(path)
- , m_start(start)
- , m_length(length)
- , m_snapshotCaptured(true)
- , m_snapshotSize(snapshotSize)
- , m_snapshotModificationTime(snapshotModificationTime)
{
- ASSERT(start >= 0 && length >= 0 && start + length <= snapshotSize && snapshotModificationTime);
+ // Note: this doesn't initialize the type unlike File(path).
+ append(FileBlobItem::create(path));
}
-#endif
unsigned long long Blob::size() const
{
// FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
// come up with an exception to throw if file size is not represetable.
-#if ENABLE(BLOB_SLICE)
- if (m_snapshotCaptured)
- return m_length;
-#endif
- long long size;
- if (!getFileSize(m_path, size))
- return 0;
- return static_cast<unsigned long long>(size);
+ unsigned long long size = 0;
+ for (size_t i = 0; i < m_items.size(); ++i)
+ size += m_items[i]->size();
+ return size;
+}
+
+const String& Blob::path() const
+{
+ ASSERT(m_items.size() == 1 && m_items[0]->toFileBlobItem());
+ return m_items[0]->toFileBlobItem()->path();
+}
+
+void Blob::append(PassRefPtr<BlobItem> item)
+{
+ m_items.append(item);
}
#if ENABLE(BLOB_SLICE)
PassRefPtr<Blob> Blob::slice(long long start, long long length) const
{
- // When we slice a file for the first time, we obtain a snapshot of the file by capturing its current size and modification time.
- // The modification time will be used to verify if the file has been changed or not, when the underlying data are accessed.
- long long snapshotSize;
- double snapshotModificationTime;
- if (m_snapshotCaptured) {
- snapshotSize = m_snapshotSize;
- snapshotModificationTime = m_snapshotModificationTime;
- } else {
- // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, an empty blob will be returned.
- time_t modificationTime;
- if (!getFileSize(m_path, snapshotSize) || !getFileModificationTime(m_path, modificationTime)) {
- snapshotSize = 0;
- snapshotModificationTime = 0;
- } else
- snapshotModificationTime = modificationTime;
- }
-
- // Clamp the range if it exceeds the size limit.
if (start < 0)
start = 0;
if (length < 0)
length = 0;
- if (start > snapshotSize) {
+ // Clamp the range if it exceeds the size limit.
+ unsigned long long totalSize = size();
+ if (static_cast<unsigned long long>(start) > totalSize) {
start = 0;
length = 0;
- } else if (start + length > snapshotSize)
- length = snapshotSize - start;
+ } else if (static_cast<unsigned long long>(start + length) > totalSize)
+ length = totalSize - start;
- return adoptRef(new Blob(m_path, m_start + start, length, snapshotSize, snapshotModificationTime));
+ size_t i = 0;
+ RefPtr<Blob> blob = Blob::create();
+ for (; i < m_items.size() && static_cast<unsigned long long>(start) >= m_items[i]->size(); ++i)
+ start -= m_items[i]->size();
+ for (; length > 0 && i < m_items.size(); ++i) {
+ blob->m_items.append(m_items[i]->slice(start, length));
+ length -= blob->m_items.last()->size();
+ start = 0;
+ }
+ return blob.release();
}
-#endif
+#endif // ENABLE(BLOB_SLICE)
} // namespace WebCore
diff --git a/WebCore/html/Blob.h b/WebCore/html/Blob.h
index e8b5f3f..39177b5 100644
--- a/WebCore/html/Blob.h
+++ b/WebCore/html/Blob.h
@@ -31,21 +31,24 @@
#ifndef Blob_h
#define Blob_h
-#include "ExceptionCode.h"
+#include "BlobItem.h"
#include "PlatformString.h"
-#include <time.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
namespace WebCore {
class Blob : public RefCounted<Blob> {
public:
-#if ENABLE(BLOB_SLICE)
- static const int toEndOfFile;
- static const double doNotCheckFileChange;
-#endif
+ static PassRefPtr<Blob> create()
+ {
+ return adoptRef(new Blob());
+ }
+ // FIXME: Deprecated method. This is called only from
+ // bindings/v8/SerializedScriptValue.cpp and the usage in it will become invalid once
+ // BlobBuilder is introduced.
static PassRefPtr<Blob> create(const String& path)
{
return adoptRef(new Blob(path));
@@ -53,47 +56,28 @@ public:
virtual ~Blob() { }
+ unsigned long long size() const;
+ const String& type() const { return m_type; }
virtual bool isFile() const { return false; }
-#if ENABLE(BLOB_SLICE)
- PassRefPtr<Blob> slice(long long start, long long length) const;
-#endif
-
- const String& path() const { return m_path; }
- unsigned long long size() const;
-#if ENABLE(BLOB_SLICE)
- long long start() const { return m_start; }
- long long length() const { return m_length; }
- double modificationTime() const { return m_snapshotModificationTime; }
-#endif
+ // FIXME: Deprecated method.
+ const String& path() const;
-protected:
- Blob(const String& path);
+ void append(PassRefPtr<BlobItem>);
+ const BlobItemList& items() const { return m_items; }
-private:
#if ENABLE(BLOB_SLICE)
- Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime);
+ PassRefPtr<Blob> slice(long long start, long long length) const;
#endif
- // The underlying path of the file-based blob.
- String m_path;
-
-#if ENABLE(BLOB_SLICE)
- // The starting position of the file-based blob.
- long long m_start;
-
- // The length of the file-based blob. The value of -1 means to the end of the file.
- long long m_length;
-
- // A flag to tell if a snapshot has been captured.
- bool m_snapshotCaptured;
+protected:
+ Blob() { }
- // The size of the file when a snapshot is captured. It can be 0 if the file is empty.
- long long m_snapshotSize;
+ // FIXME: Deprecated constructor. See also the comment for Blob::create(path).
+ Blob(const String& path);
- // The last modification time of the file when a snapshot is captured. The value of 0 also means that the snapshot is not captured.
- double m_snapshotModificationTime;
-#endif
+ BlobItemList m_items;
+ String m_type;
};
} // namespace WebCore
diff --git a/WebCore/html/DocTypeStrings.gperf b/WebCore/html/DocTypeStrings.gperf
index 398626e..5c213b0 100644
--- a/WebCore/html/DocTypeStrings.gperf
+++ b/WebCore/html/DocTypeStrings.gperf
@@ -1,3 +1,4 @@
+%struct-type
struct PubIDInfo {
enum eMode {
eQuirks,
@@ -9,6 +10,15 @@ struct PubIDInfo {
eMode mode_if_no_sysid;
eMode mode_if_sysid;
}
+%language=ANSI-C
+%readonly-tables
+%global-table
+%compare-strncmp
+%define initializer-suffix ,PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards
+%define lookup-function-name findDoctypeEntry
+%define hash-function-name doctype_hash_function
+%includes
+%enum
%%
"+//silmaril//dtd html pro v0r11 19970101//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
"-//advasoft ltd//dtd html 3.0 aswedit + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
diff --git a/WebCore/html/File.cpp b/WebCore/html/File.cpp
index 97fdc45..2c9ce53 100644
--- a/WebCore/html/File.cpp
+++ b/WebCore/html/File.cpp
@@ -33,12 +33,17 @@ namespace WebCore {
File::File(const String& path)
: Blob(path)
- , m_name(pathGetFileName(path))
{
// We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure.
- int index = m_name.reverseFind('.');
+ const String& fileName = name();
+ int index = fileName.reverseFind('.');
if (index != -1)
- m_type = MIMETypeRegistry::getMIMETypeForExtension(m_name.substring(index + 1));
+ m_type = MIMETypeRegistry::getMIMETypeForExtension(fileName.substring(index + 1));
+}
+
+const String& File::name() const
+{
+ return items().at(0)->toFileBlobItem()->name();
}
} // namespace WebCore
diff --git a/WebCore/html/File.h b/WebCore/html/File.h
index 065dd86..582db28 100644
--- a/WebCore/html/File.h
+++ b/WebCore/html/File.h
@@ -41,18 +41,14 @@ public:
virtual bool isFile() const { return true; }
- const String& name() const { return m_name; }
- const String& type() const { return m_type; }
+ const String& name() const;
// FIXME: obsolete attributes. To be removed.
- const String& fileName() const { return m_name; }
+ const String& fileName() const { return name(); }
unsigned long long fileSize() const { return size(); }
private:
File(const String& path);
-
- String m_name;
- String m_type;
};
} // namespace WebCore
diff --git a/WebCore/html/FileReader.cpp b/WebCore/html/FileReader.cpp
index 3442342..2e020c1 100644
--- a/WebCore/html/FileReader.cpp
+++ b/WebCore/html/FileReader.cpp
@@ -85,6 +85,7 @@ void FileReader::stop()
void FileReader::readAsBinaryString(Blob* fileBlob)
{
+ // FIXME: needs to handle non-file blobs.
LOG(FileAPI, "FileReader: reading as binary: %s\n", fileBlob->path().utf8().data());
readInternal(fileBlob, ReadFileAsBinaryString);
@@ -92,6 +93,7 @@ void FileReader::readAsBinaryString(Blob* fileBlob)
void FileReader::readAsText(Blob* fileBlob, const String& encoding)
{
+ // FIXME: needs to handle non-file blobs.
LOG(FileAPI, "FileReader: reading as text: %s\n", fileBlob->path().utf8().data());
if (!encoding.isEmpty())
diff --git a/WebCore/html/FileStream.cpp b/WebCore/html/FileStream.cpp
index 9a06eed..f859b63 100644
--- a/WebCore/html/FileStream.cpp
+++ b/WebCore/html/FileStream.cpp
@@ -72,48 +72,53 @@ void FileStream::openForRead(Blob* blob)
if (isHandleValid(m_handle))
return;
+ // FIXME: Need to handle multiple items that may include non-file ones when BlobBuilder is introduced.
+ ASSERT(blob->items().size() >= 1);
+ const FileBlobItem* fileItem = blob->items().at(0)->toFileBlobItem();
+ if (!fileItem) {
+ ASSERT(false);
+ m_client->didFail(NOT_READABLE_ERR);
+ return;
+ }
+
// Check if the file exists by querying its modification time. We choose not to call fileExists() in order to save an
// extra file system call when the modification time is needed to check the validity of the sliced file blob.
// Per the spec, we need to return different error codes to differentiate between non-existent file and permission error.
// openFile() could not tell use the failure reason.
time_t currentModificationTime;
- if (!getFileModificationTime(blob->path(), currentModificationTime)) {
+ if (!getFileModificationTime(fileItem->path(), currentModificationTime)) {
m_client->didFail(NOT_FOUND_ERR);
return;
}
// Open the file blob.
- m_handle = openFile(blob->path(), OpenForRead);
+ m_handle = openFile(fileItem->path(), OpenForRead);
if (!isHandleValid(m_handle)) {
m_client->didFail(NOT_READABLE_ERR);
return;
}
#if ENABLE(BLOB_SLICE)
- // Check the modificationt time for the possible file change.
- if (blob->modificationTime() != Blob::doNotCheckFileChange && static_cast<time_t>(blob->modificationTime()) != currentModificationTime) {
- m_client->didFail(NOT_READABLE_ERR);
- return;
- }
-
- // Jump to the beginning position if the file has been sliced.
- if (blob->start() > 0) {
- if (!seekFile(m_handle, blob->start(), SeekFromBeginning)) {
+ const FileRangeBlobItem* fileRangeItem = fileItem->toFileRangeBlobItem();
+ if (fileRangeItem) {
+ // Check the modificationt time for the possible file change.
+ if (static_cast<time_t>(fileRangeItem->snapshotModificationTime()) != currentModificationTime) {
m_client->didFail(NOT_READABLE_ERR);
return;
}
+
+ // Jump to the beginning position if the file has been sliced.
+ if (fileRangeItem->start() > 0) {
+ if (seekFile(m_handle, fileRangeItem->start(), SeekFromBeginning) < 0) {
+ m_client->didFail(NOT_READABLE_ERR);
+ return;
+ }
+ }
}
#endif
// Get the size.
-#if ENABLE(BLOB_SLICE)
- m_totalBytesToRead = blob->length();
- if (m_totalBytesToRead == Blob::toEndOfFile)
- m_totalBytesToRead = blob->size() - blob->start();
-#else
m_totalBytesToRead = blob->size();
-#endif
-
m_client->didGetSize(m_totalBytesToRead);
}
diff --git a/WebCore/html/FormDataList.cpp b/WebCore/html/FormDataList.cpp
index 281c9fe..0f62595 100644
--- a/WebCore/html/FormDataList.cpp
+++ b/WebCore/html/FormDataList.cpp
@@ -28,64 +28,22 @@ FormDataList::FormDataList(const TextEncoding& c)
{
}
-void FormDataList::appendString(const CString& s)
+void FormDataList::appendString(const String& s)
{
- m_list.append(s);
+ m_items.append(StringBlobItem::create(s, EndingCRLF, m_encoding));
}
-// Change plain CR and plain LF to CRLF pairs.
-static CString fixLineBreaks(const CString& s)
+void FormDataList::appendString(const CString& s)
{
- // Compute the length.
- unsigned newLen = 0;
- const char* p = s.data();
- while (char c = *p++) {
- if (c == '\r') {
- // Safe to look ahead because of trailing '\0'.
- if (*p != '\n') {
- // Turn CR into CRLF.
- newLen += 2;
- }
- } else if (c == '\n') {
- // Turn LF into CRLF.
- newLen += 2;
- } else {
- // Leave other characters alone.
- newLen += 1;
- }
- }
- if (newLen == s.length()) {
- return s;
- }
-
- // Make a copy of the string.
- p = s.data();
- char* q;
- CString result = CString::newUninitialized(newLen, q);
- while (char c = *p++) {
- if (c == '\r') {
- // Safe to look ahead because of trailing '\0'.
- if (*p != '\n') {
- // Turn CR into CRLF.
- *q++ = '\r';
- *q++ = '\n';
- }
- } else if (c == '\n') {
- // Turn LF into CRLF.
- *q++ = '\r';
- *q++ = '\n';
- } else {
- // Leave other characters alone.
- *q++ = c;
- }
- }
- return result;
+ m_items.append(StringBlobItem::create(s));
}
-void FormDataList::appendString(const String& s)
+void FormDataList::appendBlob(const String& key, PassRefPtr<Blob> blob)
{
- CString cstr = fixLineBreaks(m_encoding.encode(s.characters(), s.length(), EntitiesForUnencodables));
- m_list.append(cstr);
+ appendString(key);
+ const BlobItemList& items = blob->items();
+ for (size_t i = 0; i < items.size(); ++i)
+ m_items.append(items.at(i));
}
} // namespace
diff --git a/WebCore/html/FormDataList.h b/WebCore/html/FormDataList.h
index 8ecf64e..f4bb905 100644
--- a/WebCore/html/FormDataList.h
+++ b/WebCore/html/FormDataList.h
@@ -46,27 +46,9 @@ public:
appendString(key);
appendString(String::number(value));
}
- void appendBlob(const String& key, PassRefPtr<Blob> blob)
- {
- appendString(key);
- m_list.append(blob);
- }
-
- class Item {
- public:
- Item() { }
- Item(const WTF::CString& data) : m_data(data) { }
- Item(PassRefPtr<Blob> blob) : m_blob(blob) { }
-
- const WTF::CString& data() const { return m_data; }
- Blob* blob() const { return m_blob.get(); }
-
- private:
- WTF::CString m_data;
- RefPtr<Blob> m_blob;
- };
+ void appendBlob(const String& key, PassRefPtr<Blob>);
- const Vector<Item>& list() const { return m_list; }
+ const BlobItemList& items() const { return m_items; }
const TextEncoding& encoding() const { return m_encoding; }
private:
@@ -74,7 +56,7 @@ private:
void appendString(const String&);
TextEncoding m_encoding;
- Vector<Item> m_list;
+ BlobItemList m_items;
};
} // namespace WebCore
diff --git a/WebCore/html/HTML5DocumentParser.cpp b/WebCore/html/HTML5DocumentParser.cpp
new file mode 100644
index 0000000..28df14e
--- /dev/null
+++ b/WebCore/html/HTML5DocumentParser.cpp
@@ -0,0 +1,310 @@
+/*
+ * 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 APPLE 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 APPLE 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 "HTML5DocumentParser.h"
+
+#include "Element.h"
+#include "Frame.h"
+#include "HTML5Lexer.h"
+#include "HTML5ScriptRunner.h"
+#include "HTML5TreeBuilder.h"
+#include "HTMLDocument.h"
+#include "Node.h"
+#include "NotImplemented.h"
+#include "XSSAuditor.h"
+
+#if ENABLE(INSPECTOR)
+#include "InspectorTimelineAgent.h"
+#endif
+
+namespace WebCore {
+
+namespace {
+
+class NestingLevelIncrementer : public Noncopyable {
+public:
+ NestingLevelIncrementer(int& counter)
+ : m_counter(&counter)
+ {
+ ++(*m_counter);
+ }
+
+ ~NestingLevelIncrementer()
+ {
+ --(*m_counter);
+ }
+
+private:
+ int* m_counter;
+};
+
+} // namespace
+
+HTML5DocumentParser::HTML5DocumentParser(HTMLDocument* document, bool reportErrors)
+ : DocumentParser()
+ , m_document(document)
+ , m_lexer(new HTML5Lexer)
+ , m_scriptRunner(new HTML5ScriptRunner(document, this))
+ , m_treeConstructor(new HTML5TreeBuilder(m_lexer.get(), document, reportErrors))
+ , m_endWasDelayed(false)
+ , m_writeNestingLevel(0)
+{
+ begin();
+}
+
+HTML5DocumentParser::~HTML5DocumentParser()
+{
+ // FIXME: We'd like to ASSERT that normal operation of this class clears
+ // out any delayed actions, but we can't because we're unceremoniously
+ // deleted. If there were a required call to some sort of cancel function,
+ // then we could ASSERT some invariants here.
+}
+
+void HTML5DocumentParser::begin()
+{
+ // FIXME: Should we reset the lexer?
+}
+
+void HTML5DocumentParser::pumpLexerIfPossible()
+{
+ if (m_parserStopped || m_treeConstructor->isPaused())
+ return;
+ pumpLexer();
+}
+
+void HTML5DocumentParser::pumpLexer()
+{
+ // We tell the InspectorTimelineAgent about every pump, even if we
+ // end up pumping nothing. It can filter out empty pumps itself.
+ willPumpLexer();
+
+ ASSERT(!m_parserStopped);
+ ASSERT(!m_treeConstructor->isPaused());
+ while (!m_parserStopped && m_lexer->nextToken(m_input.current(), m_token)) {
+ if (ScriptController* scriptController = script())
+ scriptController->setEventHandlerLineNumber(lineNumber() + 1);
+
+ m_treeConstructor->constructTreeFromToken(m_token);
+ m_token.clear();
+
+ if (ScriptController* scriptController = script())
+ scriptController->setEventHandlerLineNumber(0);
+
+ if (!m_treeConstructor->isPaused())
+ continue;
+
+ // The parser will pause itself when waiting on a script to load or run.
+ // ScriptRunner executes scripts at the right times and handles reentrancy.
+ int scriptStartLine = 0;
+ RefPtr<Element> scriptElement = m_treeConstructor->takeScriptToProcess(scriptStartLine);
+ bool shouldContinueParsing = m_scriptRunner->execute(scriptElement.release(), scriptStartLine);
+ m_treeConstructor->setPaused(!shouldContinueParsing);
+ if (!shouldContinueParsing)
+ return;
+ }
+
+ didPumpLexer();
+}
+
+void HTML5DocumentParser::willPumpLexer()
+{
+#if ENABLE(INSPECTOR)
+ // FIXME: m_input.current().length() is only accurate if we
+ // end up parsing the whole buffer in this pump. We should pass how
+ // much we parsed as part of didWriteHTML instead of willWriteHTML.
+ if (InspectorTimelineAgent* timelineAgent = m_document->inspectorTimelineAgent())
+ timelineAgent->willWriteHTML(m_input.current().length(), m_lexer->lineNumber());
+#endif
+}
+
+void HTML5DocumentParser::didPumpLexer()
+{
+#if ENABLE(INSPECTOR)
+ if (InspectorTimelineAgent* timelineAgent = m_document->inspectorTimelineAgent())
+ timelineAgent->didWriteHTML(m_lexer->lineNumber());
+#endif
+}
+
+void HTML5DocumentParser::write(const SegmentedString& source, bool appendData)
+{
+ if (m_parserStopped)
+ return;
+
+ NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
+
+ if (appendData) {
+ m_input.appendToEnd(source);
+ if (m_writeNestingLevel > 1) {
+ // We've gotten data off the network in a nested call to 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().
+ return;
+ }
+ } else
+ m_input.insertAtCurrentInsertionPoint(source);
+
+ pumpLexerIfPossible();
+ endIfDelayed();
+}
+
+void HTML5DocumentParser::end()
+{
+ pumpLexerIfPossible();
+ // Informs the the rest of WebCore that parsing is really finished.
+ m_treeConstructor->finished();
+}
+
+void HTML5DocumentParser::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() || executingScript()) {
+ m_endWasDelayed = true;
+ return;
+ }
+ end();
+}
+
+void HTML5DocumentParser::endIfDelayed()
+{
+ if (!m_endWasDelayed || isWaitingForScripts() || executingScript())
+ return;
+
+ m_endWasDelayed = false;
+ end();
+}
+
+void HTML5DocumentParser::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();
+ attemptToEnd();
+}
+
+int HTML5DocumentParser::executingScript() const
+{
+ return m_scriptRunner->inScriptExecution();
+}
+
+int HTML5DocumentParser::lineNumber() const
+{
+ return m_lexer->lineNumber();
+}
+
+int HTML5DocumentParser::columnNumber() const
+{
+ return m_lexer->columnNumber();
+}
+
+LegacyHTMLTreeConstructor* HTML5DocumentParser::htmlTreeConstructor() const
+{
+ return m_treeConstructor->legacyTreeConstructor();
+}
+
+bool HTML5DocumentParser::isWaitingForScripts() const
+{
+ return m_treeConstructor->isPaused();
+}
+
+void HTML5DocumentParser::resumeParsingAfterScriptExecution()
+{
+ ASSERT(!m_scriptRunner->inScriptExecution());
+ ASSERT(!m_treeConstructor->isPaused());
+ pumpLexerIfPossible();
+
+ // The document already finished parsing we were just waiting on scripts when finished() was called.
+ endIfDelayed();
+}
+
+void HTML5DocumentParser::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);
+}
+
+void HTML5DocumentParser::stopWatchingForLoad(CachedResource* cachedScript)
+{
+ cachedScript->removeClient(this);
+}
+
+bool HTML5DocumentParser::shouldLoadExternalScriptFromSrc(const AtomicString& srcValue)
+{
+ if (!m_XSSAuditor)
+ return true;
+ return m_XSSAuditor->canLoadExternalScriptFromSrc(srcValue);
+}
+
+void HTML5DocumentParser::executeScript(const ScriptSourceCode& sourceCode)
+{
+ ASSERT(m_scriptRunner->inScriptExecution());
+ if (!m_document->frame())
+ return;
+ InsertionPointRecord savedInsertionPoint(m_input);
+ m_document->frame()->script()->executeScript(sourceCode);
+}
+
+void HTML5DocumentParser::notifyFinished(CachedResource* cachedResource)
+{
+ ASSERT(!m_scriptRunner->inScriptExecution());
+ ASSERT(m_treeConstructor->isPaused());
+ // Note: We only ever wait on one script at a time, so we always know this
+ // is the one we were waiting on and can un-pause the tree builder.
+ m_treeConstructor->setPaused(false);
+ bool shouldContinueParsing = m_scriptRunner->executeScriptsWaitingForLoad(cachedResource);
+ m_treeConstructor->setPaused(!shouldContinueParsing);
+ if (shouldContinueParsing)
+ resumeParsingAfterScriptExecution();
+}
+
+void HTML5DocumentParser::executeScriptsWaitingForStylesheets()
+{
+ // Ignore calls unless we have a script blocking the parser waiting on a
+ // stylesheet load. Otherwise we are currently parsing and this
+ // is a re-entrant call from encountering a </ style> tag.
+ if (!m_scriptRunner->hasScriptsWaitingForStylesheets())
+ return;
+ ASSERT(!m_scriptRunner->inScriptExecution());
+ ASSERT(m_treeConstructor->isPaused());
+ // Note: We only ever wait on one script at a time, so we always know this
+ // is the one we were waiting on and can un-pause the tree builder.
+ m_treeConstructor->setPaused(false);
+ bool shouldContinueParsing = m_scriptRunner->executeScriptsWaitingForStylesheets();
+ m_treeConstructor->setPaused(!shouldContinueParsing);
+ if (shouldContinueParsing)
+ resumeParsingAfterScriptExecution();
+}
+
+ScriptController* HTML5DocumentParser::script() const
+{
+ return m_document->frame() ? m_document->frame()->script() : 0;
+}
+
+}
diff --git a/WebCore/html/HTML5DocumentParser.h b/WebCore/html/HTML5DocumentParser.h
new file mode 100644
index 0000000..4a75cec
--- /dev/null
+++ b/WebCore/html/HTML5DocumentParser.h
@@ -0,0 +1,192 @@
+/*
+ * 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 APPLE 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 APPLE 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 HTML5Tokenizer_h
+#define HTML5Tokenizer_h
+
+#include "CachedResourceClient.h"
+#include "HTML5ScriptRunnerHost.h"
+#include "HTML5Token.h"
+#include "SegmentedString.h"
+#include "DocumentParser.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class HTMLDocument;
+class LegacyHTMLTreeConstructor;
+class HTML5Lexer;
+class HTML5ScriptRunner;
+class HTML5TreeBuilder;
+class ScriptController;
+class ScriptSourceCode;
+
+class HTML5DocumentParser : public DocumentParser, HTML5ScriptRunnerHost, CachedResourceClient {
+public:
+ HTML5DocumentParser(HTMLDocument*, bool reportErrors);
+ virtual ~HTML5DocumentParser();
+
+ // DocumentParser
+ virtual void begin();
+ virtual void write(const SegmentedString&, bool appendData);
+ virtual void end();
+ virtual void finish();
+ virtual int executingScript() const;
+ virtual bool isWaitingForScripts() const;
+ virtual void executeScriptsWaitingForStylesheets();
+ virtual int lineNumber() const;
+ virtual int columnNumber() const;
+ // FIXME: HTMLFormControlElement accesses the LegacyHTMLTreeConstructor via this method.
+ // Remove this when the LegacyHTMLTreeConstructor is no longer used.
+ virtual LegacyHTMLTreeConstructor* htmlTreeConstructor() const;
+
+ // HTML5ScriptRunnerHost
+ virtual void watchForLoad(CachedResource*);
+ virtual void stopWatchingForLoad(CachedResource*);
+ virtual bool shouldLoadExternalScriptFromSrc(const AtomicString&);
+ virtual void executeScript(const ScriptSourceCode&);
+
+ // CachedResourceClient
+ virtual void notifyFinished(CachedResource*);
+
+private:
+ // The InputStream is made up of a sequence of SegmentedStrings:
+ //
+ // [--current--][--next--][--next--] ... [--next--]
+ // /\ (also called m_last)
+ // L_ current insertion point
+ //
+ // The current segmented string is stored in InputStream. Each of the
+ // afterInsertionPoint buffers are stored in InsertionPointRecords on the
+ // stack.
+ //
+ // We remove characters from the "current" string in the InputStream.
+ // document.write() will add characters at the current insertion point,
+ // which appends them to the "current" string.
+ //
+ // m_last is a pointer to the last of the afterInsertionPoint strings.
+ // The network adds data at the end of the InputStream, which appends
+ // them to the "last" string.
+ class InputStream {
+ public:
+ InputStream()
+ : m_last(&m_first)
+ {
+ }
+
+ void appendToEnd(const SegmentedString& string)
+ {
+ m_last->append(string);
+ }
+
+ void insertAtCurrentInsertionPoint(const SegmentedString& string)
+ {
+ m_first.append(string);
+ }
+
+ void close() { m_last->close(); }
+
+ SegmentedString& current() { return m_first; }
+
+ void splitInto(SegmentedString& next)
+ {
+ next = m_first;
+ m_first = SegmentedString();
+ if (m_last == &m_first) {
+ // We used to only have one SegmentedString in the InputStream
+ // but now we have two. That means m_first is no longer also
+ // the m_last string, |next| is now the last one.
+ m_last = &next;
+ }
+ }
+
+ void mergeFrom(SegmentedString& next)
+ {
+ m_first.append(next);
+ if (m_last == &next) {
+ // The string |next| used to be the last SegmentedString in
+ // the InputStream. Now that it's been merged into m_first,
+ // that makes m_first the last one.
+ m_last = &m_first;
+ }
+ if (next.isClosed()) {
+ // We also need to merge the "closed" state from next to
+ // m_first. Arguably, this work could be done in append().
+ m_first.close();
+ }
+ }
+
+ private:
+ SegmentedString m_first;
+ SegmentedString* m_last;
+ };
+
+ class InsertionPointRecord {
+ public:
+ InsertionPointRecord(InputStream& inputStream)
+ : m_inputStream(&inputStream)
+ {
+ m_inputStream->splitInto(m_next);
+ }
+
+ ~InsertionPointRecord()
+ {
+ m_inputStream->mergeFrom(m_next);
+ }
+
+ private:
+ InputStream* m_inputStream;
+ SegmentedString m_next;
+ };
+
+ void willPumpLexer();
+ void didPumpLexer();
+
+ void pumpLexer();
+ void pumpLexerIfPossible();
+ void resumeParsingAfterScriptExecution();
+
+ void attemptToEnd();
+ void endIfDelayed();
+ bool inWrite() const { return m_writeNestingLevel > 0; }
+
+ ScriptController* script() const;
+
+ InputStream m_input;
+
+ // We hold m_token here because it might be partially complete.
+ HTML5Token m_token;
+
+ HTMLDocument* m_document;
+ OwnPtr<HTML5Lexer> m_lexer;
+ OwnPtr<HTML5ScriptRunner> m_scriptRunner;
+ OwnPtr<HTML5TreeBuilder> m_treeConstructor;
+ bool m_endWasDelayed;
+ int m_writeNestingLevel;
+};
+
+}
+
+#endif
diff --git a/WebCore/html/HTML5EntityParser.cpp b/WebCore/html/HTML5EntityParser.cpp
new file mode 100644
index 0000000..f168245
--- /dev/null
+++ b/WebCore/html/HTML5EntityParser.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
+ * 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 APPLE 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 APPLE 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 "HTML5EntityParser.h"
+
+#include <wtf/Vector.h>
+
+// Use __GNUC__ instead of PLATFORM(GCC) to stay consistent with the gperf generated c file
+#ifdef __GNUC__
+// The main parser includes this too so we are getting two copies of the data. However, this way the code gets inlined.
+#include "HTMLEntityNames.cpp"
+#else
+// Not inlined for non-GCC compilers
+struct Entity {
+ const char* name;
+ int code;
+};
+const struct Entity* findEntity(register const char* str, register unsigned int len);
+#endif
+
+using namespace WTF;
+
+namespace WebCore {
+
+namespace {
+
+static const UChar windowsLatin1ExtensionArray[32] = {
+ 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, // 80-87
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, // 88-8F
+ 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, // 90-97
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, // 98-9F
+};
+
+inline UChar adjustEntity(unsigned value)
+{
+ if ((value & ~0x1F) != 0x0080)
+ return value;
+ return windowsLatin1ExtensionArray[value - 0x80];
+}
+
+inline unsigned legalEntityFor(unsigned value)
+{
+ // FIXME: A number of specific entity values generate parse errors.
+ if (value == 0 || value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF))
+ return 0xFFFD;
+ if (value < 0xFFFF)
+ return adjustEntity(value);
+ return value;
+}
+
+inline bool isHexDigit(UChar cc)
+{
+ return (cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f') || (cc >= 'A' && cc <= 'F');
+}
+
+inline bool isAlphaNumeric(UChar cc)
+{
+ return (cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z');
+}
+
+void unconsumeCharacters(SegmentedString& source, const Vector<UChar, 10>& consumedCharacters)
+{
+ if (consumedCharacters.size() == 1)
+ source.push(consumedCharacters[0]);
+ else if (consumedCharacters.size() == 2) {
+ source.push(consumedCharacters[0]);
+ source.push(consumedCharacters[1]);
+ } else
+ source.prepend(SegmentedString(String(consumedCharacters.data(), consumedCharacters.size())));
+}
+
+}
+
+unsigned consumeHTML5Entity(SegmentedString& source, bool& notEnoughCharacters, UChar additionalAllowedCharacter)
+{
+ ASSERT(!additionalAllowedCharacter || additionalAllowedCharacter == '"' || additionalAllowedCharacter == '\'' || additionalAllowedCharacter == '>');
+ ASSERT(!notEnoughCharacters);
+
+ enum EntityState {
+ Initial,
+ NumberType,
+ MaybeHexLowerCaseX,
+ MaybeHexUpperCaseX,
+ Hex,
+ Decimal,
+ Named
+ };
+ EntityState entityState = Initial;
+ unsigned result = 0;
+ Vector<UChar, 10> consumedCharacters;
+ Vector<char, 10> entityName;
+
+ while (!source.isEmpty()) {
+ UChar cc = *source;
+ switch (entityState) {
+ case Initial: {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '<' || cc == '&')
+ return 0;
+ if (additionalAllowedCharacter && cc == additionalAllowedCharacter)
+ return 0;
+ if (cc == '#') {
+ entityState = NumberType;
+ break;
+ }
+ if ((cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')) {
+ entityState = Named;
+ continue;
+ }
+ return 0;
+ }
+ case NumberType: {
+ if (cc == 'x') {
+ entityState = MaybeHexLowerCaseX;
+ break;
+ }
+ if (cc == 'X') {
+ entityState = MaybeHexUpperCaseX;
+ break;
+ }
+ if (cc >= '0' && cc <= '9') {
+ entityState = Decimal;
+ continue;
+ }
+ source.push('#');
+ return 0;
+ }
+ case MaybeHexLowerCaseX: {
+ if (isHexDigit(cc)) {
+ entityState = Hex;
+ continue;
+ }
+ source.push('#');
+ source.push('x');
+ return 0;
+ }
+ case MaybeHexUpperCaseX: {
+ if (isHexDigit(cc)) {
+ entityState = Hex;
+ continue;
+ }
+ source.push('#');
+ source.push('X');
+ return 0;
+ }
+ case Hex: {
+ if (cc >= '0' && cc <= '9')
+ result = result * 16 + cc - '0';
+ else if (cc >= 'a' && cc <= 'f')
+ result = result * 16 + 10 + cc - 'a';
+ else if (cc >= 'A' && cc <= 'F')
+ result = result * 16 + 10 + cc - 'A';
+ else if (cc == ';') {
+ source.advancePastNonNewline();
+ return legalEntityFor(result);
+ } else
+ return legalEntityFor(result);
+ break;
+ }
+ case Decimal: {
+ if (cc >= '0' && cc <= '9')
+ result = result * 10 + cc - '0';
+ else if (cc == ';') {
+ source.advancePastNonNewline();
+ return legalEntityFor(result);
+ } else
+ return legalEntityFor(result);
+ break;
+ }
+ case Named: {
+ // FIXME: This code is wrong. We need to find the longest matching entity.
+ // The examples from the spec are:
+ // I'm &notit; I tell you
+ // I'm &notin; I tell you
+ // In the first case, "&not" is the entity. In the second
+ // case, "&notin;" is the entity.
+ // FIXME: Our list of HTML entities is incomplete.
+ // FIXME: The number 8 below is bogus.
+ while (!source.isEmpty() && entityName.size() <= 8) {
+ cc = *source;
+ if (cc == ';') {
+ const Entity* entity = findEntity(entityName.data(), entityName.size());
+ if (entity) {
+ source.advanceAndASSERT(';');
+ return entity->code;
+ }
+ break;
+ }
+ if (!isAlphaNumeric(cc)) {
+ const Entity* entity = findEntity(entityName.data(), entityName.size());
+ if (entity) {
+ // HTML5 tells us to ignore this entity, for historical reasons,
+ // if the lookhead character is '='.
+ if (additionalAllowedCharacter && cc == '=')
+ break;
+ return entity->code;
+ }
+ break;
+ }
+ entityName.append(cc);
+ consumedCharacters.append(cc);
+ source.advanceAndASSERT(cc);
+ }
+ notEnoughCharacters = source.isEmpty();
+ unconsumeCharacters(source, consumedCharacters);
+ return 0;
+ }
+ }
+ consumedCharacters.append(cc);
+ source.advanceAndASSERT(cc);
+ }
+ ASSERT(source.isEmpty());
+ notEnoughCharacters = true;
+ unconsumeCharacters(source, consumedCharacters);
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/html/HTML5EntityParser.h b/WebCore/html/HTML5EntityParser.h
new file mode 100644
index 0000000..f0a921f
--- /dev/null
+++ b/WebCore/html/HTML5EntityParser.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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 APPLE 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 APPLE 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 HTML5EntityParser_h
+#define HTML5EntityParser_h
+
+#include "SegmentedString.h"
+
+namespace WebCore {
+
+unsigned consumeHTML5Entity(SegmentedString&, bool& notEnoughCharacters, UChar additionalAllowedCharacter = '\0');
+
+}
+
+#endif
diff --git a/WebCore/html/HTML5Lexer.cpp b/WebCore/html/HTML5Lexer.cpp
index 6c23bb0..0cc4ed1 100644
--- a/WebCore/html/HTML5Lexer.cpp
+++ b/WebCore/html/HTML5Lexer.cpp
@@ -29,6 +29,7 @@
#include "HTML5Lexer.h"
#include "AtomicString.h"
+#include "HTML5EntityParser.h"
#include "HTML5Token.h"
#include "HTMLNames.h"
#include "NotImplemented.h"
@@ -37,20 +38,6 @@
#include <wtf/text/CString.h>
#include <wtf/unicode/Unicode.h>
-
-// Use __GNUC__ instead of PLATFORM(GCC) to stay consistent with the gperf generated c file
-#ifdef __GNUC__
-// The main tokenizer includes this too so we are getting two copies of the data. However, this way the code gets inlined.
-#include "HTMLEntityNames.c"
-#else
-// Not inlined for non-GCC compilers
-struct Entity {
- const char* name;
- int code;
-};
-const struct Entity* findEntity(register const char* str, register unsigned int len);
-#endif
-
using namespace WTF;
namespace WebCore {
@@ -59,13 +46,6 @@ using namespace HTMLNames;
namespace {
-static const UChar windowsLatin1ExtensionArray[32] = {
- 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, // 80-87
- 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, // 88-8F
- 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, // 90-97
- 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, // 98-9F
-};
-
inline UChar toLowerCase(UChar cc)
{
ASSERT(cc >= 'A' && cc <= 'Z');
@@ -89,44 +69,6 @@ inline bool vectorEqualsString(const Vector<UChar, 32>& vector, const String& st
return !memcmp(stringData, vectorData, vector.size() * sizeof(UChar));
}
-inline UChar adjustEntity(unsigned value)
-{
- if ((value & ~0x1F) != 0x0080)
- return value;
- return windowsLatin1ExtensionArray[value - 0x80];
-}
-
-inline unsigned legalEntityFor(unsigned value)
-{
- // FIXME: A number of specific entity values generate parse errors.
- if (value == 0 || value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF))
- return 0xFFFD;
- if (value < 0xFFFF)
- return adjustEntity(value);
- return value;
-}
-
-inline bool isHexDigit(UChar cc)
-{
- return (cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f') || (cc >= 'A' && cc <= 'F');
-}
-
-inline bool isAlphaNumeric(UChar cc)
-{
- return (cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z');
-}
-
-void unconsumeCharacters(SegmentedString& source, const Vector<UChar, 10>& consumedCharacters)
-{
- if (consumedCharacters.size() == 1)
- source.push(consumedCharacters[0]);
- else if (consumedCharacters.size() == 2) {
- source.push(consumedCharacters[0]);
- source.push(consumedCharacters[1]);
- } else
- source.prepend(SegmentedString(String(consumedCharacters.data(), consumedCharacters.size())));
-}
-
inline bool isEndTagBufferingState(HTML5Lexer::State state)
{
return state == HTML5Lexer::RCDATAEndTagOpenState
@@ -154,160 +96,15 @@ void HTML5Lexer::reset()
{
m_state = DataState;
m_token = 0;
+ m_lineNumber = 0;
m_skipLeadingNewLineForListing = false;
- m_emitPending = false;
m_additionalAllowedCharacter = '\0';
}
-unsigned HTML5Lexer::consumeEntity(SegmentedString& source, bool& notEnoughCharacters)
-{
- ASSERT(m_state != CharacterReferenceInAttributeValueState || m_additionalAllowedCharacter == '"' || m_additionalAllowedCharacter == '\'' || m_additionalAllowedCharacter == '>');
- ASSERT(!notEnoughCharacters);
-
- enum EntityState {
- Initial,
- NumberType,
- MaybeHexLowerCaseX,
- MaybeHexUpperCaseX,
- Hex,
- Decimal,
- Named
- };
- EntityState entityState = Initial;
- unsigned result = 0;
- Vector<UChar, 10> consumedCharacters;
- Vector<char, 10> entityName;
-
- while (!source.isEmpty()) {
- UChar cc = *source;
- switch (entityState) {
- case Initial: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '<' || cc == '&')
- return 0;
- if (m_state == CharacterReferenceInAttributeValueState && cc == m_additionalAllowedCharacter)
- return 0;
- if (cc == '#') {
- entityState = NumberType;
- break;
- }
- if ((cc >= 'a' && cc <= 'z') || (cc >= 'A' && cc <= 'Z')) {
- entityState = Named;
- continue;
- }
- return 0;
- }
- case NumberType: {
- if (cc == 'x') {
- entityState = MaybeHexLowerCaseX;
- break;
- }
- if (cc == 'X') {
- entityState = MaybeHexUpperCaseX;
- break;
- }
- if (cc >= '0' && cc <= '9') {
- entityState = Decimal;
- continue;
- }
- source.push('#');
- return 0;
- }
- case MaybeHexLowerCaseX: {
- if (isHexDigit(cc)) {
- entityState = Hex;
- continue;
- }
- source.push('#');
- source.push('x');
- return 0;
- }
- case MaybeHexUpperCaseX: {
- if (isHexDigit(cc)) {
- entityState = Hex;
- continue;
- }
- source.push('#');
- source.push('X');
- return 0;
- }
- case Hex: {
- if (cc >= '0' && cc <= '9')
- result = result * 16 + cc - '0';
- else if (cc >= 'a' && cc <= 'f')
- result = result * 16 + 10 + cc - 'a';
- else if (cc >= 'A' && cc <= 'F')
- result = result * 16 + 10 + cc - 'A';
- else if (cc == ';') {
- source.advance();
- return legalEntityFor(result);
- } else
- return legalEntityFor(result);
- break;
- }
- case Decimal: {
- if (cc >= '0' && cc <= '9')
- result = result * 10 + cc - '0';
- else if (cc == ';') {
- source.advance();
- return legalEntityFor(result);
- } else
- return legalEntityFor(result);
- break;
- }
- case Named: {
- // FIXME: This code is wrong. We need to find the longest matching entity.
- // The examples from the spec are:
- // I'm &notit; I tell you
- // I'm &notin; I tell you
- // In the first case, "&not" is the entity. In the second
- // case, "&notin;" is the entity.
- // FIXME: Our list of HTML entities is incomplete.
- // FIXME: The number 8 below is bogus.
- while (!source.isEmpty() && entityName.size() <= 8) {
- cc = *source;
- if (cc == ';') {
- const Entity* entity = findEntity(entityName.data(), entityName.size());
- if (entity) {
- source.advanceAndASSERT(';');
- return entity->code;
- }
- emitParseError();
- break;
- }
- if (!isAlphaNumeric(cc)) {
- const Entity* entity = findEntity(entityName.data(), entityName.size());
- if (entity) {
- // HTML5 tells us to ignore this entity, for historical reasons,
- // if the lookhead character is '='.
- if (m_state == CharacterReferenceInAttributeValueState && cc == '=')
- break;
- emitParseError();
- return entity->code;
- }
- break;
- }
- entityName.append(cc);
- consumedCharacters.append(cc);
- source.advanceAndASSERT(cc);
- }
- notEnoughCharacters = source.isEmpty();
- unconsumeCharacters(source, consumedCharacters);
- return 0;
- }
- }
- consumedCharacters.append(cc);
- source.advanceAndASSERT(cc);
- }
- ASSERT(source.isEmpty());
- notEnoughCharacters = true;
- unconsumeCharacters(source, consumedCharacters);
- return 0;
-}
-
inline bool HTML5Lexer::processEntity(SegmentedString& source)
{
bool notEnoughCharacters = false;
- unsigned value = consumeEntity(source, notEnoughCharacters);
+ unsigned value = consumeHTML5Entity(source, notEnoughCharacters);
if (notEnoughCharacters)
return false;
if (!value)
@@ -317,6 +114,88 @@ inline bool HTML5Lexer::processEntity(SegmentedString& source)
return true;
}
+#if COMPILER(MSVC)
+// We need to disable the "unreachable code" warning because we want to assert
+// that some code points aren't reached in the state machine.
+#pragma warning(disable: 4702)
+#endif
+
+#define BEGIN_STATE(stateName) case stateName: stateName:
+#define END_STATE() ASSERT_NOT_REACHED(); break;
+
+// We use this macro when the HTML5 spec says "reconsume the current input
+// character in the <mumble> state."
+#define RECONSUME_IN(stateName) \
+ do { \
+ m_state = stateName; \
+ goto stateName; \
+ } while (false)
+
+// We use this macro when the HTML5 spec says "consume the next input
+// character ... and switch to the <mumble> state."
+#define ADVANCE_TO(stateName) \
+ do { \
+ m_state = stateName; \
+ if (!m_inputStreamPreprocessor.advance(source, m_lineNumber)) \
+ return shouldEmitBufferedCharacterToken(source); \
+ cc = m_inputStreamPreprocessor.nextInputCharacter(); \
+ goto stateName; \
+ } while (false)
+
+// Sometimes there's more complicated logic in the spec that separates when
+// we consume the next input character and when we switch to a particular
+// state. We handle those cases by advancing the source directly and using
+// this macro to switch to the indicated state.
+#define SWITCH_TO(stateName) \
+ do { \
+ m_state = stateName; \
+ if (!m_inputStreamPreprocessor.peek(source, m_lineNumber)) \
+ return shouldEmitBufferedCharacterToken(source); \
+ cc = m_inputStreamPreprocessor.nextInputCharacter(); \
+ goto stateName; \
+ } while (false)
+
+// We use this macro 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)
+
+#define _FLUSH_BUFFERED_END_TAG() \
+ do { \
+ ASSERT(m_token->type() == HTML5Token::Character || \
+ m_token->type() == HTML5Token::Uninitialized); \
+ source.advance(m_lineNumber); \
+ if (m_token->type() == HTML5Token::Character) \
+ return true; \
+ m_token->beginEndTag(m_bufferedEndTagName); \
+ m_bufferedEndTagName.clear(); \
+ } while (false)
+
+#define FLUSH_AND_ADVANCE_TO(stateName) \
+ do { \
+ m_state = stateName; \
+ _FLUSH_BUFFERED_END_TAG(); \
+ if (source.isEmpty() \
+ || !m_inputStreamPreprocessor.peek(source, m_lineNumber)) \
+ return shouldEmitBufferedCharacterToken(source); \
+ cc = m_inputStreamPreprocessor.nextInputCharacter(); \
+ goto stateName; \
+ } while (false)
+
+#define FLUSH_EMIT_AND_RESUME_IN(stateName) \
+ do { \
+ m_state = stateName; \
+ _FLUSH_BUFFERED_END_TAG(); \
+ return true; \
+ } while (false)
+
bool HTML5Lexer::nextToken(SegmentedString& source, HTML5Token& token)
{
// If we have a token in progress, then we're supposed to be called back
@@ -335,1189 +214,1222 @@ bool HTML5Lexer::nextToken(SegmentedString& source, HTML5Token& token)
}
}
+ if (source.isEmpty() || !m_inputStreamPreprocessor.peek(source, m_lineNumber))
+ return shouldEmitBufferedCharacterToken(source);
+ UChar cc = m_inputStreamPreprocessor.nextInputCharacter();
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
- if (m_skipLeadingNewLineForListing && m_state == DataState && !source.isEmpty() && *source == '\x0A')
- source.advanceAndASSERT('\x0A');
- m_skipLeadingNewLineForListing = false;
+ // Note that this logic is different than the generic \r\n collapsing
+ // handled in the input stream preprocessor. This logic is here as an
+ // "authoring convenience" so folks can write:
+ //
+ // <pre>
+ // lorem ipsum
+ // lorem ipsum
+ // </pre>
+ //
+ // without getting an extra newline at the start of their <pre> element.
+ if (m_skipLeadingNewLineForListing) {
+ m_skipLeadingNewLineForListing = false;
+ if (m_state == DataState && cc == '\n')
+ ADVANCE_TO(DataState);
+ }
// Source: http://www.whatwg.org/specs/web-apps/current-work/#tokenisation0
- // FIXME: This while should stop as soon as we have a token to return.
- while (!source.isEmpty()) {
- UChar cc = *source;
- switch (m_state) {
- case DataState: {
- if (cc == '&')
- m_state = CharacterReferenceInDataState;
- else if (cc == '<') {
- if (m_token->type() == HTML5Token::Character) {
- // We have a bunch of character tokens queued up that we
- // are emitting lazily here.
- return true;
- }
- m_state = TagOpenState;
- } else
- emitCharacter(cc);
- break;
+ switch (m_state) {
+ BEGIN_STATE(DataState) {
+ if (cc == '&')
+ ADVANCE_TO(CharacterReferenceInDataState);
+ else if (cc == '<') {
+ if (m_token->type() == HTML5Token::Character) {
+ // We have a bunch of character tokens queued up that we
+ // are emitting lazily here.
+ return true;
+ }
+ ADVANCE_TO(TagOpenState);
+ } else {
+ emitCharacter(cc);
+ ADVANCE_TO(DataState);
}
- case CharacterReferenceInDataState: {
- if (!processEntity(source))
- return shouldEmitBufferedCharacterToken(source);
- m_state = DataState;
- continue;
+ }
+ END_STATE()
+
+ BEGIN_STATE(CharacterReferenceInDataState) {
+ if (!processEntity(source))
+ return shouldEmitBufferedCharacterToken(source);
+ SWITCH_TO(DataState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(RCDATAState) {
+ if (cc == '&')
+ ADVANCE_TO(CharacterReferenceInRCDATAState);
+ else if (cc == '<')
+ ADVANCE_TO(RCDATALessThanSignState);
+ else {
+ emitCharacter(cc);
+ ADVANCE_TO(RCDATAState);
}
- case RCDATAState: {
- if (cc == '&')
- m_state = CharacterReferenceInRCDATAState;
- else if (cc == '<')
- m_state = RCDATALessThanSignState;
- else
- emitCharacter(cc);
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(CharacterReferenceInRCDATAState) {
+ if (!processEntity(source))
+ return shouldEmitBufferedCharacterToken(source);
+ SWITCH_TO(RCDATAState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(RAWTEXTState) {
+ if (cc == '<')
+ ADVANCE_TO(RAWTEXTLessThanSignState);
+ else {
+ emitCharacter(cc);
+ ADVANCE_TO(RAWTEXTState);
}
- case CharacterReferenceInRCDATAState: {
- if (!processEntity(source))
- return shouldEmitBufferedCharacterToken(source);
- m_state = RCDATAState;
- continue;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataState) {
+ if (cc == '<')
+ ADVANCE_TO(ScriptDataLessThanSignState);
+ else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataState);
}
- case RAWTEXTState: {
- if (cc == '<')
- m_state = RAWTEXTLessThanSignState;
- else
- emitCharacter(cc);
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(PLAINTEXTState) {
+ emitCharacter(cc);
+ ADVANCE_TO(PLAINTEXTState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(TagOpenState) {
+ if (cc == '!')
+ ADVANCE_TO(MarkupDeclarationOpenState);
+ else if (cc == '/')
+ ADVANCE_TO(EndTagOpenState);
+ else if (cc >= 'A' && cc <= 'Z') {
+ m_token->beginStartTag(toLowerCase(cc));
+ ADVANCE_TO(TagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_token->beginStartTag(cc);
+ ADVANCE_TO(TagNameState);
+ } else if (cc == '?') {
+ emitParseError();
+ // 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('<');
+ RECONSUME_IN(DataState);
}
- case ScriptDataState: {
- if (cc == '<')
- m_state = ScriptDataLessThanSignState;
- else
- emitCharacter(cc);
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(EndTagOpenState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_token->beginEndTag(toLowerCase(cc));
+ ADVANCE_TO(TagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_token->beginEndTag(cc);
+ ADVANCE_TO(TagNameState);
+ } else if (cc == '>') {
+ emitParseError();
+ ADVANCE_TO(DataState);
+ } else {
+ emitParseError();
+ RECONSUME_IN(BogusCommentState);
}
- case PLAINTEXTState: {
- emitCharacter(cc);
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(TagNameState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeAttributeNameState);
+ else if (cc == '/')
+ ADVANCE_TO(SelfClosingStartTagState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else if (cc >= 'A' && cc <= 'Z') {
+ m_token->appendToName(toLowerCase(cc));
+ ADVANCE_TO(TagNameState);
+ } else {
+ m_token->appendToName(cc);
+ ADVANCE_TO(TagNameState);
+ }
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(RCDATALessThanSignState) {
+ if (cc == '/') {
+ m_temporaryBuffer.clear();
+ ASSERT(m_bufferedEndTagName.isEmpty());
+ ADVANCE_TO(RCDATAEndTagOpenState);
+ } else {
+ emitCharacter('<');
+ RECONSUME_IN(RCDATAState);
}
- case TagOpenState: {
- if (cc == '!')
- m_state = MarkupDeclarationOpenState;
- else if (cc == '/')
- m_state = EndTagOpenState;
- else if (cc >= 'A' && cc <= 'Z') {
- m_token->beginStartTag(toLowerCase(cc));
- m_state = TagNameState;
- } else if (cc >= 'a' && cc <= 'z') {
- m_token->beginStartTag(cc);
- m_state = TagNameState;
- } else if (cc == '?') {
- emitParseError();
- m_state = BogusCommentState;
- // 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.
- continue;
- } else {
- emitParseError();
- m_state = DataState;
- emitCharacter('<');
- continue;
- }
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(RCDATAEndTagOpenState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(RCDATAEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(RCDATAEndTagNameState);
+ } else {
+ emitCharacter('<');
+ emitCharacter('/');
+ RECONSUME_IN(RCDATAState);
}
- case EndTagOpenState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_token->beginEndTag(toLowerCase(cc));
- m_state = TagNameState;
- } else if (cc >= 'a' && cc <= 'z') {
- m_token->beginEndTag(cc);
- m_state = TagNameState;
+ }
+ END_STATE()
+
+ BEGIN_STATE(RCDATAEndTagNameState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(RCDATAEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(RCDATAEndTagNameState);
+ } else {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
+ } else if (cc == '/') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
} else if (cc == '>') {
- emitParseError();
- m_state = DataState;
- } else {
- emitParseError();
- m_state = BogusCommentState;
- continue;
+ if (isAppropriateEndTag())
+ FLUSH_EMIT_AND_RESUME_IN(DataState);
}
- // FIXME: Handle EOF properly.
- break;
+ emitCharacter('<');
+ emitCharacter('/');
+ m_token->appendToCharacter(m_temporaryBuffer);
+ m_bufferedEndTagName.clear();
+ RECONSUME_IN(RCDATAState);
}
- case TagNameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BeforeAttributeNameState;
- else if (cc == '/')
- m_state = SelfClosingStartTagState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc >= 'A' && cc <= 'Z')
- m_token->appendToName(toLowerCase(cc));
- else
- m_token->appendToName(cc);
- // FIXME: Handle EOF properly.
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(RAWTEXTLessThanSignState) {
+ if (cc == '/') {
+ m_temporaryBuffer.clear();
+ ASSERT(m_bufferedEndTagName.isEmpty());
+ ADVANCE_TO(RAWTEXTEndTagOpenState);
+ } else {
+ emitCharacter('<');
+ RECONSUME_IN(RAWTEXTState);
}
- case RCDATALessThanSignState: {
- if (cc == '/') {
- m_temporaryBuffer.clear();
- ASSERT(m_bufferedEndTagName.isEmpty());
- m_state = RCDATAEndTagOpenState;
- } else {
- emitCharacter('<');
- m_state = RCDATAState;
- continue;
- }
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(RAWTEXTEndTagOpenState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(RAWTEXTEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(RAWTEXTEndTagNameState);
+ } else {
+ emitCharacter('<');
+ emitCharacter('/');
+ RECONSUME_IN(RAWTEXTState);
}
- case RCDATAEndTagOpenState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- m_state = RCDATAEndTagNameState;
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- m_state = RCDATAEndTagNameState;
- } else {
- emitCharacter('<');
- emitCharacter('/');
- m_state = RCDATAState;
- continue;
+ }
+ END_STATE()
+
+ BEGIN_STATE(RAWTEXTEndTagNameState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(RAWTEXTEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(RAWTEXTEndTagNameState);
+ } else {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
+ } else if (cc == '/') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
+ } else if (cc == '>') {
+ if (isAppropriateEndTag())
+ FLUSH_EMIT_AND_RESUME_IN(DataState);
}
- break;
+ emitCharacter('<');
+ emitCharacter('/');
+ m_token->appendToCharacter(m_temporaryBuffer);
+ m_bufferedEndTagName.clear();
+ RECONSUME_IN(RAWTEXTState);
}
- case RCDATAEndTagNameState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- } else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
- if (isAppropriateEndTag()) {
- m_state = BeforeAttributeNameState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '/') {
- if (isAppropriateEndTag()) {
- m_state = SelfClosingStartTagState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '>') {
- if (isAppropriateEndTag()) {
- m_state = DataState;
- maybeFlushBufferedEndTag();
- break;
- }
- }
- emitCharacter('<');
- emitCharacter('/');
- m_token->appendToCharacter(m_temporaryBuffer);
- m_bufferedEndTagName.clear();
- m_state = RCDATAState;
- continue;
- }
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataLessThanSignState) {
+ if (cc == '/') {
+ m_temporaryBuffer.clear();
+ ASSERT(m_bufferedEndTagName.isEmpty());
+ ADVANCE_TO(ScriptDataEndTagOpenState);
+ } else if (cc == '!') {
+ emitCharacter('<');
+ emitCharacter('!');
+ ADVANCE_TO(ScriptDataEscapeStartState);
+ } else {
+ emitCharacter('<');
+ RECONSUME_IN(ScriptDataState);
}
- case RAWTEXTLessThanSignState: {
- if (cc == '/') {
- m_temporaryBuffer.clear();
- ASSERT(m_bufferedEndTagName.isEmpty());
- m_state = RAWTEXTEndTagOpenState;
- } else {
- emitCharacter('<');
- m_state = RAWTEXTState;
- continue;
- }
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEndTagOpenState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(ScriptDataEndTagNameState);
+ } else {
+ emitCharacter('<');
+ emitCharacter('/');
+ RECONSUME_IN(ScriptDataState);
}
- case RAWTEXTEndTagOpenState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- m_state = RAWTEXTEndTagNameState;
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- m_state = RAWTEXTEndTagNameState;
- } else {
- emitCharacter('<');
- emitCharacter('/');
- m_state = RAWTEXTState;
- continue;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEndTagNameState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(ScriptDataEndTagNameState);
+ } else {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
+ } else if (cc == '/') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
+ } else if (cc == '>') {
+ if (isAppropriateEndTag())
+ FLUSH_EMIT_AND_RESUME_IN(DataState);
}
- break;
+ emitCharacter('<');
+ emitCharacter('/');
+ m_token->appendToCharacter(m_temporaryBuffer);
+ m_bufferedEndTagName.clear();
+ RECONSUME_IN(ScriptDataState);
}
- case RAWTEXTEndTagNameState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- } else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
- if (isAppropriateEndTag()) {
- m_state = BeforeAttributeNameState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '/') {
- if (isAppropriateEndTag()) {
- m_state = SelfClosingStartTagState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '>') {
- if (isAppropriateEndTag()) {
- m_state = DataState;
- maybeFlushBufferedEndTag();
- break;
- }
- }
- emitCharacter('<');
- emitCharacter('/');
- m_token->appendToCharacter(m_temporaryBuffer);
- m_bufferedEndTagName.clear();
- m_state = RAWTEXTState;
- continue;
- }
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapeStartState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapeStartDashState);
+ } else
+ RECONSUME_IN(ScriptDataState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapeStartDashState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedDashDashState);
+ } else
+ RECONSUME_IN(ScriptDataState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapedState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedDashState);
+ } else if (cc == '<')
+ ADVANCE_TO(ScriptDataEscapedLessThanSignState);
+ else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedState);
}
- case ScriptDataLessThanSignState: {
- if (cc == '/') {
- m_temporaryBuffer.clear();
- ASSERT(m_bufferedEndTagName.isEmpty());
- m_state = ScriptDataEndTagOpenState;
- } else if (cc == '!') {
- emitCharacter('<');
- emitCharacter('!');
- m_state = ScriptDataEscapeStartState;
- } else {
- emitCharacter('<');
- m_state = ScriptDataState;
- continue;
- }
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapedDashState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedDashDashState);
+ } else if (cc == '<')
+ ADVANCE_TO(ScriptDataEscapedLessThanSignState);
+ else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedState);
}
- case ScriptDataEndTagOpenState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- m_state = ScriptDataEndTagNameState;
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- m_state = ScriptDataEndTagNameState;
- } else {
- emitCharacter('<');
- emitCharacter('/');
- m_state = ScriptDataState;
- continue;
- }
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapedDashDashState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedDashDashState);
+ } else if (cc == '<')
+ ADVANCE_TO(ScriptDataEscapedLessThanSignState);
+ else if (cc == '>') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataState);
+ } else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataEscapedState);
}
- case ScriptDataEndTagNameState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- } else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
- if (isAppropriateEndTag()) {
- m_state = BeforeAttributeNameState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '/') {
- if (isAppropriateEndTag()) {
- m_state = SelfClosingStartTagState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '>') {
- if (isAppropriateEndTag()) {
- m_state = DataState;
- maybeFlushBufferedEndTag();
- break;
- }
- }
- emitCharacter('<');
- emitCharacter('/');
- m_token->appendToCharacter(m_temporaryBuffer);
- m_bufferedEndTagName.clear();
- m_state = ScriptDataState;
- continue;
- }
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapedLessThanSignState) {
+ if (cc == '/') {
+ m_temporaryBuffer.clear();
+ ASSERT(m_bufferedEndTagName.isEmpty());
+ ADVANCE_TO(ScriptDataEscapedEndTagOpenState);
+ } else if (cc >= 'A' && cc <= 'Z') {
+ emitCharacter('<');
+ emitCharacter(cc);
+ m_temporaryBuffer.clear();
+ m_temporaryBuffer.append(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataDoubleEscapeStartState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ emitCharacter('<');
+ emitCharacter(cc);
+ m_temporaryBuffer.clear();
+ m_temporaryBuffer.append(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapeStartState);
+ } else {
+ emitCharacter('<');
+ RECONSUME_IN(ScriptDataEscapedState);
}
- case ScriptDataEscapeStartState: {
- if (cc == '-') {
- emitCharacter(cc);
- m_state = ScriptDataEscapeStartDashState;
- } else {
- m_state = ScriptDataState;
- continue;
- }
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapedEndTagOpenState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataEscapedEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(ScriptDataEscapedEndTagNameState);
+ } else {
+ emitCharacter('<');
+ emitCharacter('/');
+ RECONSUME_IN(ScriptDataEscapedState);
}
- case ScriptDataEscapeStartDashState: {
- if (cc == '-') {
- emitCharacter(cc);
- m_state = ScriptDataEscapedDashDashState;
- } else {
- m_state = ScriptDataState;
- continue;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataEscapedEndTagNameState) {
+ if (cc >= 'A' && cc <= 'Z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataEscapedEndTagNameState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ m_temporaryBuffer.append(cc);
+ addToPossibleEndTag(cc);
+ ADVANCE_TO(ScriptDataEscapedEndTagNameState);
+ } else {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(BeforeAttributeNameState);
+ } else if (cc == '/') {
+ if (isAppropriateEndTag())
+ FLUSH_AND_ADVANCE_TO(SelfClosingStartTagState);
+ } else if (cc == '>') {
+ if (isAppropriateEndTag())
+ FLUSH_EMIT_AND_RESUME_IN(DataState);
}
- break;
+ emitCharacter('<');
+ emitCharacter('/');
+ m_token->appendToCharacter(m_temporaryBuffer);
+ m_bufferedEndTagName.clear();
+ RECONSUME_IN(ScriptDataEscapedState);
}
- case ScriptDataEscapedState: {
- if (cc == '-') {
- emitCharacter(cc);
- m_state = ScriptDataEscapedDashState;
- } else if (cc == '<')
- m_state = ScriptDataEscapedLessThanSignState;
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataDoubleEscapeStartState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '/' || cc == '>') {
+ emitCharacter(cc);
+ if (temporaryBufferIs(scriptTag.localName()))
+ ADVANCE_TO(ScriptDataDoubleEscapedState);
else
- emitCharacter(cc);
- // FIXME: Handle EOF properly.
- break;
- }
- case ScriptDataEscapedDashState: {
- if (cc == '-') {
- emitCharacter(cc);
- m_state = ScriptDataEscapedDashDashState;
- } else if (cc == '<')
- m_state = ScriptDataEscapedLessThanSignState;
- else {
- emitCharacter(cc);
- m_state = ScriptDataEscapedState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case ScriptDataEscapedDashDashState: {
- if (cc == '-')
- emitCharacter(cc);
- else if (cc == '<')
- m_state = ScriptDataEscapedLessThanSignState;
- else if (cc == '>') {
- emitCharacter(cc);
- m_state = ScriptDataState;
- } else {
- emitCharacter(cc);
- m_state = ScriptDataEscapedState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case ScriptDataEscapedLessThanSignState: {
- if (cc == '/') {
- m_temporaryBuffer.clear();
- ASSERT(m_bufferedEndTagName.isEmpty());
- m_state = ScriptDataEscapedEndTagOpenState;
- } else if (cc >= 'A' && cc <= 'Z') {
- emitCharacter('<');
- emitCharacter(cc);
- m_temporaryBuffer.clear();
- m_temporaryBuffer.append(toLowerCase(cc));
- m_state = ScriptDataDoubleEscapeStartState;
- } else if (cc >= 'a' && cc <= 'z') {
- emitCharacter('<');
- emitCharacter(cc);
- m_temporaryBuffer.clear();
- m_temporaryBuffer.append(cc);
- m_state = ScriptDataDoubleEscapeStartState;
- } else {
- emitCharacter('<');
- m_state = ScriptDataEscapedState;
- continue;
- }
- break;
- }
- case ScriptDataEscapedEndTagOpenState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- m_state = ScriptDataEscapedEndTagNameState;
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- m_state = ScriptDataEscapedEndTagNameState;
- } else {
- emitCharacter('<');
- emitCharacter('/');
- m_state = ScriptDataEscapedState;
- continue;
- }
- break;
- }
- case ScriptDataEscapedEndTagNameState: {
- if (cc >= 'A' && cc <= 'Z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(toLowerCase(cc));
- } else if (cc >= 'a' && cc <= 'z') {
- m_temporaryBuffer.append(cc);
- addToPossibleEndTag(cc);
- } else {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
- if (isAppropriateEndTag()) {
- m_state = BeforeAttributeNameState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '/') {
- if (isAppropriateEndTag()) {
- m_state = SelfClosingStartTagState;
- maybeFlushBufferedEndTag();
- break;
- }
- } else if (cc == '>') {
- if (isAppropriateEndTag()) {
- m_state = DataState;
- maybeFlushBufferedEndTag();
- break;
- }
- }
- emitCharacter('<');
- emitCharacter('/');
- m_token->appendToCharacter(m_temporaryBuffer);
- m_bufferedEndTagName.clear();
- m_state = ScriptDataEscapedState;
- continue;
- }
- break;
- }
- case ScriptDataDoubleEscapeStartState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '/' || cc == '>') {
- emitCharacter(cc);
- if (temporaryBufferIs(scriptTag.localName()))
- m_state = ScriptDataDoubleEscapedState;
- else
- m_state = ScriptDataEscapedState;
- } else if (cc >= 'A' && cc <= 'Z') {
- emitCharacter(cc);
- m_temporaryBuffer.append(toLowerCase(cc));
- } else if (cc >= 'a' && cc <= 'z') {
- emitCharacter(cc);
- m_temporaryBuffer.append(cc);
- } else {
- m_state = ScriptDataEscapedState;
- continue;
- }
- break;
- }
- case ScriptDataDoubleEscapedState: {
- if (cc == '-') {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedDashState;
- } else if (cc == '<') {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedLessThanSignState;
- } else
- emitCharacter(cc);
- // FIXME: Handle EOF properly.
- break;
- }
- case ScriptDataDoubleEscapedDashState: {
- if (cc == '-') {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedDashDashState;
- } else if (cc == '<') {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedLessThanSignState;
- } else {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case ScriptDataDoubleEscapedDashDashState: {
- if (cc == '-')
- emitCharacter(cc);
- else if (cc == '<') {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedLessThanSignState;
- } else if (cc == '>') {
- emitCharacter(cc);
- m_state = ScriptDataState;
- } else {
- emitCharacter(cc);
- m_state = ScriptDataDoubleEscapedState;
- }
- // FIXME: Handle EOF properly.
- break;
+ ADVANCE_TO(ScriptDataEscapedState);
+ } else if (cc >= 'A' && cc <= 'Z') {
+ emitCharacter(cc);
+ m_temporaryBuffer.append(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataDoubleEscapeStartState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ emitCharacter(cc);
+ m_temporaryBuffer.append(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapeStartState);
+ } else
+ RECONSUME_IN(ScriptDataEscapedState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataDoubleEscapedState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedDashState);
+ } else if (cc == '<') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
+ } else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedState);
}
- case ScriptDataDoubleEscapedLessThanSignState: {
- if (cc == '/') {
- emitCharacter(cc);
- m_temporaryBuffer.clear();
- m_state = ScriptDataDoubleEscapeEndState;
- } else {
- m_state = ScriptDataDoubleEscapedState;
- continue;
- }
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataDoubleEscapedDashState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedDashDashState);
+ } else if (cc == '<') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
+ } else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedState);
}
- case ScriptDataDoubleEscapeEndState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '/' || cc == '>') {
- emitCharacter(cc);
- if (temporaryBufferIs(scriptTag.localName()))
- m_state = ScriptDataEscapedState;
- else
- m_state = ScriptDataDoubleEscapedState;
- } else if (cc >= 'A' && cc <= 'Z') {
- emitCharacter(cc);
- m_temporaryBuffer.append(toLowerCase(cc));
- } else if (cc >= 'a' && cc <= 'z') {
- emitCharacter(cc);
- m_temporaryBuffer.append(cc);
- } else {
- m_state = ScriptDataDoubleEscapedState;
- continue;
- }
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataDoubleEscapedDashDashState) {
+ if (cc == '-') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedDashDashState);
+ } else if (cc == '<') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
+ } else if (cc == '>') {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataState);
+ } else {
+ emitCharacter(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapedState);
}
- case BeforeAttributeNameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- else if (cc == '/')
- m_state = SelfClosingStartTagState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc >= 'A' && cc <= 'Z') {
- m_token->addNewAttribute();
- m_token->appendToAttributeName(toLowerCase(cc));
- m_state = AttributeNameState;
- } else {
- if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
- emitParseError();
- m_token->addNewAttribute();
- m_token->appendToAttributeName(cc);
- m_state = AttributeNameState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataDoubleEscapedLessThanSignState) {
+ if (cc == '/') {
+ emitCharacter(cc);
+ m_temporaryBuffer.clear();
+ ADVANCE_TO(ScriptDataDoubleEscapeEndState);
+ } else
+ RECONSUME_IN(ScriptDataDoubleEscapedState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(ScriptDataDoubleEscapeEndState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ' || cc == '/' || cc == '>') {
+ emitCharacter(cc);
+ if (temporaryBufferIs(scriptTag.localName()))
+ ADVANCE_TO(ScriptDataEscapedState);
+ else
+ ADVANCE_TO(ScriptDataDoubleEscapedState);
+ } else if (cc >= 'A' && cc <= 'Z') {
+ emitCharacter(cc);
+ m_temporaryBuffer.append(toLowerCase(cc));
+ ADVANCE_TO(ScriptDataDoubleEscapeEndState);
+ } else if (cc >= 'a' && cc <= 'z') {
+ emitCharacter(cc);
+ m_temporaryBuffer.append(cc);
+ ADVANCE_TO(ScriptDataDoubleEscapeEndState);
+ } else
+ RECONSUME_IN(ScriptDataDoubleEscapedState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(BeforeAttributeNameState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeAttributeNameState);
+ else if (cc == '/')
+ ADVANCE_TO(SelfClosingStartTagState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else if (cc >= 'A' && cc <= 'Z') {
+ m_token->addNewAttribute();
+ m_token->appendToAttributeName(toLowerCase(cc));
+ ADVANCE_TO(AttributeNameState);
+ } else {
+ if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
+ emitParseError();
+ m_token->addNewAttribute();
+ m_token->appendToAttributeName(cc);
+ ADVANCE_TO(AttributeNameState);
}
- case AttributeNameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = AfterAttributeNameState;
- else if (cc == '/')
- m_state = SelfClosingStartTagState;
- else if (cc == '=')
- m_state = BeforeAttributeValueState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc >= 'A' && cc <= 'Z')
- m_token->appendToAttributeName(toLowerCase(cc));
- else {
- if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
- emitParseError();
- m_token->appendToAttributeName(cc);
- m_state = AttributeNameState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AttributeNameState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || 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') {
+ m_token->appendToAttributeName(toLowerCase(cc));
+ ADVANCE_TO(AttributeNameState);
+ } else {
+ if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
+ emitParseError();
+ m_token->appendToAttributeName(cc);
+ ADVANCE_TO(AttributeNameState);
}
- case AfterAttributeNameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- else if (cc == '/')
- m_state = SelfClosingStartTagState;
- else if (cc == '=')
- m_state = BeforeAttributeValueState;
- else if (cc == '=') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc >= 'A' && cc <= 'Z') {
- m_token->addNewAttribute();
- m_token->appendToAttributeName(toLowerCase(cc));
- m_state = AttributeNameState;
- } else {
- if (cc == '"' || cc == '\'' || cc == '<')
- emitParseError();
- m_token->addNewAttribute();
- m_token->appendToAttributeName(cc);
- m_state = AttributeNameState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AfterAttributeNameState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || 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') {
+ m_token->addNewAttribute();
+ m_token->appendToAttributeName(toLowerCase(cc));
+ ADVANCE_TO(AttributeNameState);
+ } else {
+ if (cc == '"' || cc == '\'' || cc == '<')
+ emitParseError();
+ m_token->addNewAttribute();
+ m_token->appendToAttributeName(cc);
+ ADVANCE_TO(AttributeNameState);
}
- case BeforeAttributeValueState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- else if (cc == '"')
- m_state = AttributeValueDoubleQuotedState;
- else if (cc == '&') {
- m_state = AttributeValueUnquotedState;
- continue;
- } else if (cc == '\'')
- m_state = AttributeValueSingleQuotedState;
- else if (cc == '>') {
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(BeforeAttributeValueState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeAttributeValueState);
+ else if (cc == '"')
+ ADVANCE_TO(AttributeValueDoubleQuotedState);
+ else if (cc == '&')
+ RECONSUME_IN(AttributeValueUnquotedState);
+ else if (cc == '\'')
+ ADVANCE_TO(AttributeValueSingleQuotedState);
+ else if (cc == '>') {
+ emitParseError();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ if (cc == '<' || cc == '=' || cc == '`')
emitParseError();
- emitCurrentToken();
- m_state = DataState;
- } else {
- if (cc == '<' || cc == '=' || cc == '`')
- emitParseError();
- m_token->appendToAttributeValue(cc);
- m_state = AttributeValueUnquotedState;
- }
- break;
+ m_token->appendToAttributeValue(cc);
+ ADVANCE_TO(AttributeValueUnquotedState);
}
- case AttributeValueDoubleQuotedState: {
- if (cc == '"')
- m_state = AfterAttributeValueQuotedState;
- else if (cc == '&') {
- m_state = CharacterReferenceInAttributeValueState;
- m_additionalAllowedCharacter = '"';
- } else
- m_token->appendToAttributeValue(cc);
- // FIXME: Handle EOF properly.
- break;
+ }
+ END_STATE()
+
+ BEGIN_STATE(AttributeValueDoubleQuotedState) {
+ if (cc == '"')
+ ADVANCE_TO(AfterAttributeValueQuotedState);
+ else if (cc == '&') {
+ m_additionalAllowedCharacter = '"';
+ ADVANCE_TO(CharacterReferenceInAttributeValueState);
+ } else {
+ m_token->appendToAttributeValue(cc);
+ ADVANCE_TO(AttributeValueDoubleQuotedState);
+ }
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AttributeValueSingleQuotedState) {
+ if (cc == '\'')
+ ADVANCE_TO(AfterAttributeValueQuotedState);
+ else if (cc == '&') {
+ m_additionalAllowedCharacter = '\'';
+ ADVANCE_TO(CharacterReferenceInAttributeValueState);
+ } 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 == ' ')
+ ADVANCE_TO(BeforeAttributeNameState);
+ else if (cc == '&') {
+ m_additionalAllowedCharacter = '>';
+ ADVANCE_TO(CharacterReferenceInAttributeValueState);
+ } else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else {
+ if (cc == '"' || cc == '\'' || cc == '<' || cc == '=' || cc == '`')
+ emitParseError();
+ m_token->appendToAttributeValue(cc);
+ ADVANCE_TO(AttributeValueUnquotedState);
}
- case AttributeValueSingleQuotedState: {
- if (cc == '\'')
- m_state = AfterAttributeValueQuotedState;
- else if (cc == '&') {
- m_state = CharacterReferenceInAttributeValueState;
- m_additionalAllowedCharacter = '\'';
- } else
- m_token->appendToAttributeValue(cc);
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(CharacterReferenceInAttributeValueState) {
+ bool notEnoughCharacters = false;
+ unsigned value = consumeHTML5Entity(source, notEnoughCharacters, m_additionalAllowedCharacter);
+ if (notEnoughCharacters)
+ return shouldEmitBufferedCharacterToken(source);
+ if (!value)
+ m_token->appendToAttributeValue('&');
+ else if (value < 0xFFFF)
+ m_token->appendToAttributeValue(value);
+ else {
+ m_token->appendToAttributeValue(U16_LEAD(value));
+ m_token->appendToAttributeValue(U16_TRAIL(value));
+ }
+ // We're supposed to switch back to the attribute value state that
+ // we were in when we were switched into this state. Rather than
+ // keeping track of this explictly, we observe that the previous
+ // state can be determined by m_additionalAllowedCharacter.
+ if (m_additionalAllowedCharacter == '"')
+ SWITCH_TO(AttributeValueDoubleQuotedState);
+ else if (m_additionalAllowedCharacter == '\'')
+ SWITCH_TO(AttributeValueSingleQuotedState);
+ else if (m_additionalAllowedCharacter == '>')
+ SWITCH_TO(AttributeValueUnquotedState);
+ else
+ ASSERT_NOT_REACHED();
+ }
+ END_STATE()
+
+ BEGIN_STATE(AfterAttributeValueQuotedState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeAttributeNameState);
+ else if (cc == '/')
+ ADVANCE_TO(SelfClosingStartTagState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else {
+ emitParseError();
+ RECONSUME_IN(BeforeAttributeNameState);
}
- case AttributeValueUnquotedState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BeforeAttributeNameState;
- else if (cc == '&') {
- m_state = CharacterReferenceInAttributeValueState;
- m_additionalAllowedCharacter = '>';
- } else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else {
- if (cc == '"' || cc == '\'' || cc == '<' || cc == '=' || cc == '`')
- emitParseError();
- m_token->appendToAttributeValue(cc);
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(SelfClosingStartTagState) {
+ if (cc == '>') {
+ notImplemented();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ emitParseError();
+ RECONSUME_IN(BeforeAttributeNameState);
}
- case CharacterReferenceInAttributeValueState: {
- bool notEnoughCharacters = false;
- unsigned value = consumeEntity(source, notEnoughCharacters);
- if (notEnoughCharacters)
+ // 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);
+ 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.
+ }
+ m_state = DataState;
+ return true;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(MarkupDeclarationOpenState) {
+ DEFINE_STATIC_LOCAL(String, dashDashString, ("--"));
+ DEFINE_STATIC_LOCAL(String, doctypeString, ("doctype"));
+ if (cc == '-') {
+ SegmentedString::LookAheadResult result = source.lookAhead(dashDashString);
+ if (result == SegmentedString::DidMatch) {
+ source.advanceAndASSERT('-');
+ source.advanceAndASSERT('-');
+ m_token->beginComment();
+ SWITCH_TO(CommentStartState);
+ } else if (result == SegmentedString::NotEnoughCharacters)
+ return shouldEmitBufferedCharacterToken(source);
+ } else if (cc == 'D' || cc == 'd') {
+ SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(doctypeString);
+ if (result == SegmentedString::DidMatch) {
+ advanceStringAndASSERTIgnoringCase(source, "doctype");
+ SWITCH_TO(DOCTYPEState);
+ } else if (result == SegmentedString::NotEnoughCharacters)
return shouldEmitBufferedCharacterToken(source);
- if (!value)
- m_token->appendToAttributeValue('&');
- else if (value < 0xFFFF)
- m_token->appendToAttributeValue(value);
- else {
- m_token->appendToAttributeValue(U16_LEAD(value));
- m_token->appendToAttributeValue(U16_TRAIL(value));
- }
- // We're supposed to switch back to the attribute value state that
- // we were in when we were switched into this state. Rather than
- // keeping track of this explictly, we observe that the previous
- // state can be determined by m_additionalAllowedCharacter.
- if (m_additionalAllowedCharacter == '"')
- m_state = AttributeValueDoubleQuotedState;
- else if (m_additionalAllowedCharacter == '\'')
- m_state = AttributeValueSingleQuotedState;
- else if (m_additionalAllowedCharacter == '>')
- m_state = AttributeValueUnquotedState;
- else
- ASSERT_NOT_REACHED();
- continue;
}
- case AfterAttributeValueQuotedState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BeforeAttributeNameState;
- else if (cc == '/')
- m_state = SelfClosingStartTagState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- m_state = BeforeAttributeNameState;
- continue;
- }
- // FIXME: Handle EOF properly.
- break;
+ 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();
+ RECONSUME_IN(BogusCommentState);
+ }
+ END_STATE()
+
+ BEGIN_STATE(CommentStartState) {
+ if (cc == '-')
+ ADVANCE_TO(CommentStartDashState);
+ else if (cc == '>') {
+ emitParseError();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentState);
}
- case SelfClosingStartTagState: {
- if (cc == '>') {
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- m_state = BeforeAttributeNameState;
- continue;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(CommentStartDashState) {
+ if (cc == '-')
+ ADVANCE_TO(CommentEndState);
+ else if (cc == '>') {
+ emitParseError();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ m_token->appendToComment('-');
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentState);
}
- case BogusCommentState: {
- m_token->beginComment();
- while (!source.isEmpty()) {
- cc = *source;
- if (cc == '>')
- break;
- m_token->appendToComment(cc);
- source.advance();
- }
- emitCurrentToken();
- m_state = DataState;
- if (source.isEmpty())
- return true;
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(CommentState) {
+ if (cc == '-')
+ ADVANCE_TO(CommentEndDashState);
+ else {
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentState);
+ }
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(CommentEndDashState) {
+ if (cc == '-')
+ ADVANCE_TO(CommentEndState);
+ 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();
+ m_token->appendToComment('-');
+ m_token->appendToComment('-');
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentEndSpaceState);
+ } else if (cc == '!') {
+ emitParseError();
+ ADVANCE_TO(CommentEndBangState);
+ } else if (cc == '-') {
+ emitParseError();
+ m_token->appendToComment('-');
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentEndState);
+ } else {
+ emitParseError();
+ m_token->appendToComment('-');
+ m_token->appendToComment('-');
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentState);
+ }
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(CommentEndBangState) {
+ if (cc == '-') {
+ m_token->appendToComment('-');
+ m_token->appendToComment('-');
+ m_token->appendToComment('!');
+ ADVANCE_TO(CommentEndDashState);
+ } else if (cc == '>')
+ EMIT_AND_RESUME_IN(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 == ' ') {
+ m_token->appendToComment(cc);
+ ADVANCE_TO(CommentEndSpaceState);
+ } else if (cc == '-')
+ ADVANCE_TO(CommentEndDashState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(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 == ' ')
+ ADVANCE_TO(BeforeDOCTYPENameState);
+ else {
+ emitParseError();
+ RECONSUME_IN(BeforeDOCTYPENameState);
}
- case MarkupDeclarationOpenState: {
- DEFINE_STATIC_LOCAL(String, dashDashString, ("--"));
- DEFINE_STATIC_LOCAL(String, doctypeString, ("doctype"));
- if (cc == '-') {
- SegmentedString::LookAheadResult result = source.lookAhead(dashDashString);
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(BeforeDOCTYPENameState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeDOCTYPENameState);
+ else if (cc >= 'A' && cc <= 'Z') {
+ m_token->beginDOCTYPE(toLowerCase(cc));
+ ADVANCE_TO(DOCTYPENameState);
+ } else if (cc == '>') {
+ emitParseError();
+ m_token->beginDOCTYPE();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(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 == ' ')
+ ADVANCE_TO(AfterDOCTYPENameState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else if (cc >= 'A' && cc <= 'Z') {
+ m_token->appendToName(toLowerCase(cc));
+ ADVANCE_TO(DOCTYPENameState);
+ } 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 == ' ')
+ ADVANCE_TO(AfterDOCTYPENameState);
+ if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else {
+ DEFINE_STATIC_LOCAL(String, publicString, ("public"));
+ DEFINE_STATIC_LOCAL(String, systemString, ("system"));
+ if (cc == 'P' || cc == 'p') {
+ SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(publicString);
if (result == SegmentedString::DidMatch) {
- source.advanceAndASSERT('-');
- source.advanceAndASSERT('-');
- m_token->beginComment();
- m_state = CommentStartState;
- continue;
+ advanceStringAndASSERTIgnoringCase(source, "public");
+ SWITCH_TO(AfterDOCTYPEPublicKeywordState);
} else if (result == SegmentedString::NotEnoughCharacters)
return shouldEmitBufferedCharacterToken(source);
- } else if (cc == 'D' || cc == 'd') {
- SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(doctypeString);
+ } else if (cc == 'S' || cc == 's') {
+ SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(systemString);
if (result == SegmentedString::DidMatch) {
- advanceStringAndASSERTIgnoringCase(source, "doctype");
- m_state = DOCTYPEState;
- continue;
+ advanceStringAndASSERTIgnoringCase(source, "system");
+ SWITCH_TO(AfterDOCTYPESystemKeywordState);
} else if (result == SegmentedString::NotEnoughCharacters)
return shouldEmitBufferedCharacterToken(source);
}
- 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();
- m_state = BogusCommentState;
- continue;
- }
- case CommentStartState: {
- if (cc == '-')
- m_state = CommentStartDashState;
- else if (cc == '>') {
- emitParseError();
- emitCurrentToken();
- m_state = DataState;
- } else {
- m_token->appendToComment(cc);
- m_state = CommentState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case CommentStartDashState: {
- if (cc == '-')
- m_state = CommentEndState;
- else if (cc == '>') {
- emitParseError();
- emitCurrentToken();
- m_state = DataState;
- } else {
- m_token->appendToComment('-');
- m_token->appendToComment(cc);
- m_state = CommentState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case CommentState: {
- if (cc == '-')
- m_state = CommentEndDashState;
- else
- m_token->appendToComment(cc);
- // FIXME: Handle EOF properly.
- break;
- }
- case CommentEndDashState: {
- if (cc == '-')
- m_state = CommentEndState;
- else {
- m_token->appendToComment('-');
- m_token->appendToComment(cc);
- m_state = CommentState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case CommentEndState: {
- if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ') {
- emitParseError();
- m_token->appendToComment('-');
- m_token->appendToComment('-');
- m_token->appendToComment(cc);
- m_state = CommentEndSpaceState;
- } else if (cc == '!') {
- emitParseError();
- m_state = CommentEndBangState;
- } else if (cc == '-') {
- emitParseError();
- m_token->appendToComment('-');
- m_token->appendToComment(cc);
- } else {
- emitParseError();
- m_token->appendToComment('-');
- m_token->appendToComment('-');
- m_token->appendToComment(cc);
- m_state = CommentState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case CommentEndBangState: {
- if (cc == '-') {
- m_token->appendToComment('-');
- m_token->appendToComment('-');
- m_token->appendToComment('!');
- m_state = CommentEndDashState;
- } else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else {
- m_token->appendToComment('-');
- m_token->appendToComment('-');
- m_token->appendToComment('!');
- m_token->appendToComment(cc);
- m_state = CommentState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case CommentEndSpaceState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_token->appendToComment(cc);
- else if (cc == '-')
- m_state = CommentEndDashState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else {
- m_token->appendToComment(cc);
- m_state = CommentState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case DOCTYPEState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BeforeDOCTYPENameState;
- else {
- emitParseError();
- m_state = BeforeDOCTYPENameState;
- continue;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case BeforeDOCTYPENameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- else if (cc >= 'A' && cc <= 'Z') {
- m_token->beginDOCTYPE(toLowerCase(cc));
- m_state = DOCTYPENameState;
- } else if (cc == '>') {
- emitParseError();
- m_token->beginDOCTYPE();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else {
- m_token->beginDOCTYPE(cc);
- m_state = DOCTYPENameState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case DOCTYPENameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = AfterDOCTYPENameState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc >= 'A' && cc <= 'Z')
- m_token->appendToName(toLowerCase(cc));
- else
- m_token->appendToName(cc);
- // FIXME: Handle EOF properly.
- break;
- }
- case AfterDOCTYPENameState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else {
- DEFINE_STATIC_LOCAL(String, publicString, ("public"));
- DEFINE_STATIC_LOCAL(String, systemString, ("system"));
- if (cc == 'P' || cc == 'p') {
- SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(publicString);
- if (result == SegmentedString::DidMatch) {
- advanceStringAndASSERTIgnoringCase(source, "public");
- m_state = AfterDOCTYPEPublicKeywordState;
- continue;
- } else if (result == SegmentedString::NotEnoughCharacters)
- return shouldEmitBufferedCharacterToken(source);
- } else if (cc == 'S' || cc == 's') {
- SegmentedString::LookAheadResult result = source.lookAheadIgnoringCase(systemString);
- if (result == SegmentedString::DidMatch) {
- advanceStringAndASSERTIgnoringCase(source, "system");
- m_state = AfterDOCTYPESystemKeywordState;
- continue;
- } else if (result == SegmentedString::NotEnoughCharacters)
- return shouldEmitBufferedCharacterToken(source);
- }
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case AfterDOCTYPEPublicKeywordState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BeforeDOCTYPEPublicIdentifierState;
- else if (cc == '"') {
- emitParseError();
- m_token->setPublicIdentifierToEmptyString();
- m_state = DOCTYPEPublicIdentifierDoubleQuotedState;
- } else if (cc == '\'') {
- emitParseError();
- m_token->setPublicIdentifierToEmptyString();
- m_state = DOCTYPEPublicIdentifierSingleQuotedState;
- } else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case BeforeDOCTYPEPublicIdentifierState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- else if (cc == '"') {
- m_token->setPublicIdentifierToEmptyString();
- m_state = DOCTYPEPublicIdentifierDoubleQuotedState;
- } else if (cc == '\'') {
- m_token->setPublicIdentifierToEmptyString();
- m_state = DOCTYPEPublicIdentifierSingleQuotedState;
- } else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
- }
- case DOCTYPEPublicIdentifierDoubleQuotedState: {
- if (cc == '"')
- m_state = AfterDOCTYPEPublicIdentifierState;
- else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else
- m_token->appendToPublicIdentifier(cc);
- // FIXME: Handle EOF properly.
- break;
- }
- case DOCTYPEPublicIdentifierSingleQuotedState: {
- if (cc == '\'')
- m_state = AfterDOCTYPEPublicIdentifierState;
- else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else
- m_token->appendToPublicIdentifier(cc);
- // FIXME: Handle EOF properly.
- break;
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case AfterDOCTYPEPublicIdentifierState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BetweenDOCTYPEPublicAndSystemIdentifiersState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc == '"') {
- emitParseError();
- m_token->setPublicIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierDoubleQuotedState;
- } else if (cc == '\'') {
- emitParseError();
- m_token->setPublicIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierSingleQuotedState;
- } else {
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AfterDOCTYPEPublicKeywordState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeDOCTYPEPublicIdentifierState);
+ else if (cc == '"') {
+ emitParseError();
+ m_token->setPublicIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
+ } else if (cc == '\'') {
+ emitParseError();
+ m_token->setPublicIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
+ } else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ emitParseError();
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case BetweenDOCTYPEPublicAndSystemIdentifiersState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BetweenDOCTYPEPublicAndSystemIdentifiersState;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else if (cc == '"') {
- m_token->setSystemIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierDoubleQuotedState;
- } else if (cc == '\'') {
- m_token->setSystemIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierSingleQuotedState;
- } else {
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(BeforeDOCTYPEPublicIdentifierState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeDOCTYPEPublicIdentifierState);
+ else if (cc == '"') {
+ m_token->setPublicIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
+ } else if (cc == '\'') {
+ m_token->setPublicIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
+ } else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ emitParseError();
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case AfterDOCTYPESystemKeywordState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- m_state = BeforeDOCTYPESystemIdentifierState;
- else if (cc == '"') {
- emitParseError();
- m_token->setSystemIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierDoubleQuotedState;
- } else if (cc == '\'') {
- emitParseError();
- m_token->setSystemIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierSingleQuotedState;
- } else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(DOCTYPEPublicIdentifierDoubleQuotedState) {
+ if (cc == '"')
+ ADVANCE_TO(AfterDOCTYPEPublicIdentifierState);
+ else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ m_token->appendToPublicIdentifier(cc);
+ ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
}
- case BeforeDOCTYPESystemIdentifierState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- if (cc == '"') {
- m_token->setSystemIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierDoubleQuotedState;
- } else if (cc == '\'') {
- m_token->setSystemIdentifierToEmptyString();
- m_state = DOCTYPESystemIdentifierSingleQuotedState;
- } else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- notImplemented();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(DOCTYPEPublicIdentifierSingleQuotedState) {
+ if (cc == '\'')
+ ADVANCE_TO(AfterDOCTYPEPublicIdentifierState);
+ else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ m_token->appendToPublicIdentifier(cc);
+ ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
}
- case DOCTYPESystemIdentifierDoubleQuotedState: {
- if (cc == '"')
- m_state = AfterDOCTYPESystemIdentifierState;
- else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else
- m_token->appendToSystemIdentifier(cc);
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AfterDOCTYPEPublicIdentifierState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BetweenDOCTYPEPublicAndSystemIdentifiersState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else if (cc == '"') {
+ emitParseError();
+ m_token->setPublicIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
+ } else if (cc == '\'') {
+ emitParseError();
+ m_token->setPublicIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
+ } else {
+ emitParseError();
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case DOCTYPESystemIdentifierSingleQuotedState: {
- if (cc == '\'')
- m_state = AfterDOCTYPESystemIdentifierState;
- else if (cc == '>') {
- emitParseError();
- notImplemented();
- emitCurrentToken();
- m_state = DataState;
- } else
- m_token->appendToSystemIdentifier(cc);
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(BetweenDOCTYPEPublicAndSystemIdentifiersState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BetweenDOCTYPEPublicAndSystemIdentifiersState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else if (cc == '"') {
+ m_token->setSystemIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
+ } else if (cc == '\'') {
+ m_token->setSystemIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
+ } else {
+ emitParseError();
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case AfterDOCTYPESystemIdentifierState: {
- if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
- break;
- else if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- } else {
- emitParseError();
- m_state = BogusDOCTYPEState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AfterDOCTYPESystemKeywordState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeDOCTYPESystemIdentifierState);
+ else if (cc == '"') {
+ emitParseError();
+ m_token->setSystemIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
+ } else if (cc == '\'') {
+ emitParseError();
+ m_token->setSystemIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
+ } else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ emitParseError();
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case BogusDOCTYPEState: {
- if (cc == '>') {
- emitCurrentToken();
- m_state = DataState;
- }
- // FIXME: Handle EOF properly.
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(BeforeDOCTYPESystemIdentifierState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(BeforeDOCTYPESystemIdentifierState);
+ if (cc == '"') {
+ m_token->setSystemIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
+ } else if (cc == '\'') {
+ m_token->setSystemIdentifierToEmptyString();
+ ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
+ } else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ emitParseError();
+ m_token->setForceQuirks();
+ ADVANCE_TO(BogusDOCTYPEState);
}
- case CDATASectionState: {
- notImplemented();
- break;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(DOCTYPESystemIdentifierDoubleQuotedState) {
+ if (cc == '"')
+ ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
+ else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ m_token->appendToSystemIdentifier(cc);
+ ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
}
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(DOCTYPESystemIdentifierSingleQuotedState) {
+ if (cc == '\'')
+ ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
+ else if (cc == '>') {
+ emitParseError();
+ m_token->setForceQuirks();
+ EMIT_AND_RESUME_IN(DataState);
+ } else {
+ m_token->appendToSystemIdentifier(cc);
+ ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
}
- source.advance();
- if (m_emitPending) {
- m_emitPending = false;
- return true;
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(AfterDOCTYPESystemIdentifierState) {
+ if (cc == '\x09' || cc == '\x0A' || cc == '\x0C' || cc == ' ')
+ ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
+ else if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ else {
+ emitParseError();
+ ADVANCE_TO(BogusDOCTYPEState);
}
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(BogusDOCTYPEState) {
+ if (cc == '>')
+ EMIT_AND_RESUME_IN(DataState);
+ ADVANCE_TO(BogusDOCTYPEState);
+ // FIXME: Handle EOF properly.
+ }
+ END_STATE()
+
+ BEGIN_STATE(CDATASectionState) {
+ notImplemented();
+ ADVANCE_TO(CDATASectionState);
}
- // We've reached the end of the input stream. If we have a character
- // token buffered, we should emit it.
- return shouldEmitBufferedCharacterToken(source);
+ END_STATE()
+
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
}
inline bool HTML5Lexer::temporaryBufferIs(const String& expectedString)
@@ -1533,7 +1445,7 @@ inline void HTML5Lexer::addToPossibleEndTag(UChar cc)
inline bool HTML5Lexer::isAppropriateEndTag()
{
- return vectorEqualsString(m_bufferedEndTagName, m_appropriateEndTagName);
+ return m_bufferedEndTagName == m_appropriateEndTagName;
}
inline void HTML5Lexer::emitCharacter(UChar character)
@@ -1560,30 +1472,9 @@ inline void HTML5Lexer::emitParseError()
notImplemented();
}
-inline void HTML5Lexer::maybeFlushBufferedEndTag()
-{
- ASSERT(m_token->type() == HTML5Token::Character || m_token->type() == HTML5Token::Uninitialized);
- if (m_token->type() == HTML5Token::Character) {
- // We have a character token queued up. We need to emit it before we
- // can start begin the buffered end tag token.
- emitCurrentToken();
- return;
- }
- flushBufferedEndTag();
-}
-
-inline void HTML5Lexer::flushBufferedEndTag()
-{
- m_token->beginEndTag(m_bufferedEndTagName);
- m_bufferedEndTagName.clear();
- if (m_state == DataState)
- emitCurrentToken();
-}
-
inline void HTML5Lexer::emitCurrentToken()
{
ASSERT(m_token->type() != HTML5Token::Uninitialized);
- m_emitPending = true;
if (m_token->type() == HTML5Token::StartTag)
m_appropriateEndTagName = m_token->name();
}
@@ -1594,3 +1485,4 @@ inline bool HTML5Lexer::shouldEmitBufferedCharacterToken(const SegmentedString&
}
}
+
diff --git a/WebCore/html/HTML5Lexer.h b/WebCore/html/HTML5Lexer.h
index 08612e6..fe321e2 100644
--- a/WebCore/html/HTML5Lexer.h
+++ b/WebCore/html/HTML5Lexer.h
@@ -120,6 +120,9 @@ namespace WebCore {
// they call reset() first).
bool nextToken(SegmentedString&, HTML5Token&);
+ int lineNumber() const { return m_lineNumber; }
+ int columnNumber() const { return 1; } // Matches HTMLDocumentParser.h behavior.
+
void setState(State state) { m_state = state; }
// Hack to skip leading newline in <pre>/<listing> for authoring ease.
@@ -127,12 +130,65 @@ namespace WebCore {
void skipLeadingNewLineForListing() { m_skipLeadingNewLineForListing = true; }
private:
+ // http://www.whatwg.org/specs/web-apps/current-work/#preprocessing-the-input-stream
+ class InputStreamPreprocessor : public Noncopyable {
+ public:
+ InputStreamPreprocessor()
+ : m_nextInputCharacter('\0')
+ , m_skipNextNewLine(false)
+ {
+ }
+
+ UChar nextInputCharacter() const { return m_nextInputCharacter; }
+
+ // Returns whether we succeeded in peeking at the next character.
+ // The only way we can fail to peek is if there are no more
+ // characters in |source| (after collapsing \r\n, etc).
+ bool peek(SegmentedString& source, int& lineNumber)
+ {
+ m_nextInputCharacter = *source;
+ if (m_nextInputCharacter == '\n' && m_skipNextNewLine) {
+ m_skipNextNewLine = false;
+ source.advancePastNewline(lineNumber);
+ if (source.isEmpty())
+ return false;
+ m_nextInputCharacter = *source;
+ }
+ if (m_nextInputCharacter == '\r') {
+ m_nextInputCharacter = '\n';
+ m_skipNextNewLine = true;
+ } else {
+ m_skipNextNewLine = false;
+ // FIXME: The spec indicates that the surrogate pair range as well as
+ // 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')
+ m_nextInputCharacter = 0xFFFD;
+ }
+ return true;
+ }
+
+ // Returns whether there are more characters in |source| after advancing.
+ bool advance(SegmentedString& source, int& lineNumber)
+ {
+ source.advance(lineNumber);
+ if (source.isEmpty())
+ return false;
+ return peek(source, lineNumber);
+ }
+
+ private:
+ // 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);
- unsigned consumeEntity(SegmentedString&, bool& notEnoughCharacters);
inline bool processEntity(SegmentedString& source);
inline bool temporaryBufferIs(const String&);
@@ -142,21 +198,19 @@ namespace WebCore {
// functions help manage these state.
inline void addToPossibleEndTag(UChar cc);
inline bool isAppropriateEndTag();
- inline void maybeFlushBufferedEndTag();
- inline void flushBufferedEndTag();
inline bool shouldEmitBufferedCharacterToken(const SegmentedString&);
State m_state;
- AtomicString m_appropriateEndTagName;
+ Vector<UChar, 32> m_appropriateEndTagName;
// m_token is owned by the caller. If nextToken is not on the stack,
// this member might be pointing to unallocated memory.
HTML5Token* m_token;
+ int m_lineNumber;
bool m_skipLeadingNewLineForListing;
- bool m_emitPending;
// http://www.whatwg.org/specs/web-apps/current-work/#temporary-buffer
Vector<UChar, 32> m_temporaryBuffer;
@@ -168,6 +222,9 @@ namespace WebCore {
// http://www.whatwg.org/specs/web-apps/current-work/#additional-allowed-character
UChar m_additionalAllowedCharacter;
+
+ // http://www.whatwg.org/specs/web-apps/current-work/#preprocessing-the-input-stream
+ InputStreamPreprocessor m_inputStreamPreprocessor;
};
}
diff --git a/WebCore/html/HTML5ScriptRunner.cpp b/WebCore/html/HTML5ScriptRunner.cpp
index 3e0cd7f..aef5ce4 100644
--- a/WebCore/html/HTML5ScriptRunner.cpp
+++ b/WebCore/html/HTML5ScriptRunner.cpp
@@ -48,6 +48,7 @@ HTML5ScriptRunner::HTML5ScriptRunner(Document* document, HTML5ScriptRunnerHost*
, m_scriptNestingLevel(0)
, m_hasScriptsWaitingForStylesheets(false)
{
+ ASSERT(m_host);
}
HTML5ScriptRunner::~HTML5ScriptRunner()
@@ -84,8 +85,7 @@ ScriptSourceCode HTML5ScriptRunner::sourceFromPendingScript(const PendingScript&
return ScriptSourceCode(script.cachedScript.get());
}
errorOccurred = false;
- // FIXME: Line numbers are wrong.
- return ScriptSourceCode(script.element->textContent(), documentURLForScriptExecution(m_document));
+ return ScriptSourceCode(script.element->textContent(), documentURLForScriptExecution(m_document), script.startingLineNumber);
}
bool HTML5ScriptRunner::isPendingScriptReady(const PendingScript& script)
@@ -127,6 +127,10 @@ void HTML5ScriptRunner::executePendingScript()
void HTML5ScriptRunner::executeScript(Element* element, const ScriptSourceCode& sourceCode)
{
+ // FIXME: We do not block inline <script> tags on stylesheets for now.
+ // When we do, || !element->hasAttribute(srcAttr) should be removed from
+ // the ASSERT below. See https://bugs.webkit.org/show_bug.cgi?id=40047
+ ASSERT(m_document->haveStylesheetsLoaded() || !element->hasAttribute(srcAttr));
ScriptElement* scriptElement = toScriptElement(element);
ASSERT(scriptElement);
if (!scriptElement->shouldExecuteAsJavaScript())
@@ -153,26 +157,31 @@ void HTML5ScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
// This function should match 10.2.5.11 "An end tag whose tag name is 'script'"
// Script handling lives outside the tree builder to keep the each class simple.
-bool HTML5ScriptRunner::execute(PassRefPtr<Element> scriptElement)
+bool HTML5ScriptRunner::execute(PassRefPtr<Element> scriptElement, int startLine)
{
ASSERT(scriptElement);
// FIXME: If scripting is disabled, always just return true;
// Try to execute the script given to us.
- runScript(scriptElement.get());
- if (m_scriptNestingLevel)
- return false; // Don't continue parsing.
- if (!executeParsingBlockingScripts())
- return false;
+ runScript(scriptElement.get(), startLine);
- notImplemented(); // Restore insertion point?
- // FIXME: Handle re-entrant scripts and m_pendingParsingBlockinScript.
- return true;
+ if (haveParsingBlockingScript()) {
+ if (m_scriptNestingLevel)
+ return false; // Block the parser. Unwind to the outermost HTML5ScriptRunner::execute before continuing parsing.
+ if (!executeParsingBlockingScripts())
+ return false; // We still have a parsing blocking script, block the parser.
+ }
+ return true; // Scripts executed as expected, continue parsing.
+}
+
+bool HTML5ScriptRunner::haveParsingBlockingScript() const
+{
+ return !!m_parsingBlockingScript.element;
}
bool HTML5ScriptRunner::executeParsingBlockingScripts()
{
- while (m_parsingBlockingScript.element) {
+ while (haveParsingBlockingScript()) {
// We only really need to check once.
if (!isPendingScriptReady(m_parsingBlockingScript))
return false;
@@ -184,7 +193,7 @@ bool HTML5ScriptRunner::executeParsingBlockingScripts()
bool HTML5ScriptRunner::executeScriptsWaitingForLoad(CachedResource*)
{
ASSERT(!m_scriptNestingLevel);
- ASSERT(m_parsingBlockingScript.element);
+ ASSERT(haveParsingBlockingScript());
ASSERT(m_parsingBlockingScript.cachedScript->isLoaded());
return executeParsingBlockingScripts();
}
@@ -203,6 +212,10 @@ void HTML5ScriptRunner::requestScript(Element* script)
{
ASSERT(!m_parsingBlockingScript.element);
AtomicString srcValue = script->getAttribute(srcAttr);
+ // Allow the host to disllow script loads (using the XSSAuditor, etc.)
+ if (!m_host->shouldLoadExternalScriptFromSrc(srcValue))
+ return;
+
// FIXME: We need to resolve the url relative to the element.
m_parsingBlockingScript.element = script;
if (!script->dispatchBeforeLoadEvent(srcValue)) // Part of HTML5?
@@ -224,9 +237,9 @@ void HTML5ScriptRunner::requestScript(Element* script)
// This method is meant to match the HTML5 definition of "running a script"
// http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script
-void HTML5ScriptRunner::runScript(Element* script)
+void HTML5ScriptRunner::runScript(Element* script, int startingLineNumber)
{
- ASSERT(!m_parsingBlockingScript.element);
+ ASSERT(!haveParsingBlockingScript());
m_scriptNestingLevel++;
// Check script type and language, current code uses ScriptElement::shouldExecuteAsJavaScript(), but that may not be HTML5 compliant.
notImplemented(); // event for support
@@ -234,11 +247,10 @@ void HTML5ScriptRunner::runScript(Element* script)
if (script->hasAttribute(srcAttr)) {
// FIXME: Handle defer and async
requestScript(script);
- } else if (!m_document->haveStylesheetsLoaded()) {
- m_parsingBlockingScript.element = script;
} else {
- // FIXME: Need a line numbers implemenation.
- ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), 0);
+ // FIXME: We do not block inline <script> tags on stylesheets to match the
+ // old parser for now. See https://bugs.webkit.org/show_bug.cgi?id=40047
+ ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), startingLineNumber);
executeScript(script, sourceCode);
}
m_scriptNestingLevel--;
diff --git a/WebCore/html/HTML5ScriptRunner.h b/WebCore/html/HTML5ScriptRunner.h
index c6a03fb..19e70a6 100644
--- a/WebCore/html/HTML5ScriptRunner.h
+++ b/WebCore/html/HTML5ScriptRunner.h
@@ -47,7 +47,7 @@ public:
~HTML5ScriptRunner();
// Processes the passed in script and any pending scripts if possible.
- bool execute(PassRefPtr<Element> scriptToProcess);
+ bool execute(PassRefPtr<Element> scriptToProcess, int scriptStartLine);
// Processes any pending scripts.
bool executeScriptsWaitingForLoad(CachedResource*);
bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; }
@@ -59,23 +59,26 @@ private:
struct PendingScript {
PendingScript()
: watchingForLoad(false)
+ , startingLineNumber(0)
{
}
RefPtr<Element> element;
CachedResourceHandle<CachedScript> cachedScript;
bool watchingForLoad; // Did we pass the cachedScript to the HTML5ScriptRunnerHost.
+ int startingLineNumber; // Only used for inline script tags.
// HTML5 has an isReady parameter, however isReady ends up equivalent to
// m_document->haveStylesheetsLoaded() && cachedScript->isLoaded()
};
Frame* frame() const;
+ bool haveParsingBlockingScript() const;
bool executeParsingBlockingScripts();
void executePendingScript();
void requestScript(Element*);
- void runScript(Element*);
+ void runScript(Element*, int startingLineNumber);
// Helpers for dealing with HTML5ScriptRunnerHost
void watchForLoad(PendingScript&);
diff --git a/WebCore/html/HTML5ScriptRunnerHost.h b/WebCore/html/HTML5ScriptRunnerHost.h
index 730e0fc..9a77385 100644
--- a/WebCore/html/HTML5ScriptRunnerHost.h
+++ b/WebCore/html/HTML5ScriptRunnerHost.h
@@ -28,6 +28,7 @@
namespace WebCore {
+class AtomicString;
class CachedResource;
class ScriptSourceCode;
@@ -40,6 +41,8 @@ public:
// Implementors must call cachedResource->removeClient() immediately.
virtual void stopWatchingForLoad(CachedResource*) = 0;
+ // Implementors can block certain script loads (for XSSAuditor, etc.)
+ virtual bool shouldLoadExternalScriptFromSrc(const AtomicString&) = 0;
// Implementors should handle possible rentry before/after calling ScriptController::executeScript
virtual void executeScript(const ScriptSourceCode&) = 0;
};
diff --git a/WebCore/html/HTML5Token.h b/WebCore/html/HTML5Token.h
index b4188d3..6b0fdc8 100644
--- a/WebCore/html/HTML5Token.h
+++ b/WebCore/html/HTML5Token.h
@@ -50,7 +50,7 @@ public:
WTF::Vector<UChar, 32> m_value;
};
- typedef WTF::Vector<Attribute> AttributeList;
+ typedef WTF::Vector<Attribute, 10> AttributeList;
typedef WTF::Vector<UChar, 1024> DataVector;
HTML5Token() { clear(); }
@@ -64,7 +64,7 @@ public:
{
ASSERT(m_type == Uninitialized);
m_type = StartTag;
- clearData();
+ m_data.clear();
m_selfClosing = false;
m_currentAttribute = 0;
m_attributes.clear();
@@ -77,7 +77,7 @@ public:
{
ASSERT(m_type == Uninitialized);
m_type = EndTag;
- clearData();
+ m_data.clear();
m_selfClosing = false;
m_currentAttribute = 0;
m_attributes.clear();
@@ -89,7 +89,7 @@ public:
{
ASSERT(m_type == Uninitialized);
m_type = Character;
- clearData();
+ m_data.clear();
m_data.append(character);
}
@@ -97,14 +97,14 @@ public:
{
ASSERT(m_type == Uninitialized);
m_type = Comment;
- clearData();
+ m_data.clear();
}
void beginDOCTYPE()
{
ASSERT(m_type == Uninitialized);
m_type = DOCTYPE;
- clearData();
+ m_data.clear();
m_doctypeData.set(new DoctypeData());
}
@@ -166,48 +166,24 @@ public:
return m_attributes;
}
- AtomicString name()
+ const DataVector& name()
{
ASSERT(m_type == StartTag || m_type == EndTag || m_type == DOCTYPE);
- if (!m_data.isEmpty() && m_dataAsNameAtom.isEmpty())
- m_dataAsNameAtom = AtomicString(adoptDataAsStringImpl());
- return m_dataAsNameAtom;
- }
-
- PassRefPtr<StringImpl> adoptDataAsStringImpl()
- {
- ASSERT(!m_dataAsNameAtom); // An attempt to make sure this isn't called twice.
- return StringImpl::adopt(m_data);
+ return m_data;
}
const DataVector& characters()
{
ASSERT(m_type == Character);
- ASSERT(!m_dataAsNameAtom);
return m_data;
}
const DataVector& comment()
{
ASSERT(m_type == Comment);
- ASSERT(!m_dataAsNameAtom);
return m_data;
}
- // FIXME: Should be removed once we stop using the old parser.
- String takeCharacters()
- {
- ASSERT(m_type == Character);
- return String(adoptDataAsStringImpl());
- }
-
- // FIXME: Should be removed once we stop using the old parser.
- String takeComment()
- {
- ASSERT(m_type == Comment);
- return String(adoptDataAsStringImpl());
- }
-
// FIXME: Distinguish between a missing public identifer and an empty one.
const WTF::Vector<UChar>& publicIdentifier()
{
@@ -236,6 +212,18 @@ public:
m_doctypeData->m_systemIdentifier.clear();
}
+ bool forceQuirks()
+ {
+ ASSERT(m_type == DOCTYPE);
+ return m_doctypeData->m_forceQuirks;
+ }
+
+ void setForceQuirks()
+ {
+ ASSERT(m_type == DOCTYPE);
+ m_doctypeData->m_forceQuirks = true;
+ }
+
void appendToPublicIdentifier(UChar character)
{
ASSERT(m_type == DOCTYPE);
@@ -267,19 +255,12 @@ private:
WTF::Vector<UChar> m_systemIdentifier;
};
- void clearData()
- {
- m_data.clear();
- m_dataAsNameAtom = AtomicString();
- }
-
Type m_type;
// "name" for DOCTYPE, StartTag, and EndTag
// "characters" for Character
// "data" for Comment
DataVector m_data;
- AtomicString m_dataAsNameAtom;
// For DOCTYPE
OwnPtr<DoctypeData> m_doctypeData;
diff --git a/WebCore/html/HTML5Tokenizer.cpp b/WebCore/html/HTML5Tokenizer.cpp
deleted file mode 100644
index 0feace5..0000000
--- a/WebCore/html/HTML5Tokenizer.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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 APPLE 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 APPLE 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 "HTML5Tokenizer.h"
-
-#include "Element.h"
-#include "Frame.h"
-#include "HTML5Lexer.h"
-#include "HTML5ScriptRunner.h"
-#include "HTML5TreeBuilder.h"
-#include "HTMLDocument.h"
-#include "Node.h"
-#include "NotImplemented.h"
-
-namespace WebCore {
-
-HTML5Tokenizer::HTML5Tokenizer(HTMLDocument* document, bool reportErrors)
- : Tokenizer()
- , m_document(document)
- , m_lexer(new HTML5Lexer)
- , m_scriptRunner(new HTML5ScriptRunner(document, this))
- , m_treeBuilder(new HTML5TreeBuilder(m_lexer.get(), document, reportErrors))
- , m_wasWaitingOnScriptsDuringFinish(false)
-{
- begin();
-}
-
-HTML5Tokenizer::~HTML5Tokenizer()
-{
-}
-
-void HTML5Tokenizer::begin()
-{
-}
-
-void HTML5Tokenizer::pumpLexer()
-{
- ASSERT(!m_treeBuilder->isPaused());
- while (m_lexer->nextToken(m_source, m_token)) {
- m_treeBuilder->constructTreeFromToken(m_token);
- m_token.clear();
-
- if (!m_treeBuilder->isPaused())
- continue;
-
- // The parser will pause itself when waiting on a script to load or run.
- // ScriptRunner executes scripts at the right times and handles reentrancy.
- bool shouldContinueParsing = m_scriptRunner->execute(m_treeBuilder->takeScriptToProcess());
- m_treeBuilder->setPaused(!shouldContinueParsing);
- if (!shouldContinueParsing)
- return;
- }
-}
-
-void HTML5Tokenizer::write(const SegmentedString& source, bool)
-{
- // HTML5Tokenizer::executeScript is responsible for handling saving m_source before re-entry.
- m_source.append(source);
- if (!m_treeBuilder->isPaused())
- pumpLexer();
-}
-
-void HTML5Tokenizer::end()
-{
- m_source.close();
- if (!m_treeBuilder->isPaused())
- pumpLexer();
- m_treeBuilder->finished();
-}
-
-void HTML5Tokenizer::finish()
-{
- // 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 (isWaitingForScripts()) {
- // FIXME: We might want to use real state enum instead of a bool here.
- m_wasWaitingOnScriptsDuringFinish = true;
- return;
- }
- // We can't call m_source.close() yet as we may have a <script> execution
- // pending which will call document.write(). No more data off the network though.
- end();
-}
-
-int HTML5Tokenizer::executingScript() const
-{
- return m_scriptRunner->inScriptExecution();
-}
-
-bool HTML5Tokenizer::isWaitingForScripts() const
-{
- return m_treeBuilder->isPaused();
-}
-
-void HTML5Tokenizer::resumeParsingAfterScriptExecution()
-{
- ASSERT(!m_scriptRunner->inScriptExecution());
- ASSERT(!m_treeBuilder->isPaused());
- pumpLexer();
- ASSERT(m_treeBuilder->isPaused() || m_source.isEmpty());
- if (m_source.isEmpty() && m_wasWaitingOnScriptsDuringFinish)
- end(); // The document already finished parsing we were just waiting on scripts when finished() was called.
-}
-
-void HTML5Tokenizer::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);
-}
-
-void HTML5Tokenizer::stopWatchingForLoad(CachedResource* cachedScript)
-{
- cachedScript->removeClient(this);
-}
-
-void HTML5Tokenizer::executeScript(const ScriptSourceCode& sourceCode)
-{
- ASSERT(m_scriptRunner->inScriptExecution());
- if (!m_document->frame())
- return;
-
- SegmentedString oldInsertionPoint = m_source;
- m_source = SegmentedString();
- m_document->frame()->script()->executeScript(sourceCode);
- // Append oldInsertionPoint onto the new (likely empty) m_source instead of
- // oldInsertionPoint.prepent(m_source) as that would ASSERT if
- // m_source.escaped() (it had characters pushed back onto it).
- m_source.append(oldInsertionPoint);
-}
-
-void HTML5Tokenizer::notifyFinished(CachedResource* cachedResource)
-{
- ASSERT(!m_scriptRunner->inScriptExecution());
- ASSERT(m_treeBuilder->isPaused());
- bool shouldContinueParsing = m_scriptRunner->executeScriptsWaitingForLoad(cachedResource);
- m_treeBuilder->setPaused(!shouldContinueParsing);
- if (shouldContinueParsing)
- resumeParsingAfterScriptExecution();
-}
-
-void HTML5Tokenizer::executeScriptsWaitingForStylesheets()
-{
- // Ignore calls unless we have a script blocking the parser waiting on a
- // stylesheet load. Otherwise we are currently parsing and this
- // is a re-entrant call from encountering a </ style> tag.
- if (!m_scriptRunner->hasScriptsWaitingForStylesheets())
- return;
- ASSERT(!m_scriptRunner->inScriptExecution());
- ASSERT(m_treeBuilder->isPaused());
- bool shouldContinueParsing = m_scriptRunner->executeScriptsWaitingForStylesheets();
- m_treeBuilder->setPaused(!shouldContinueParsing);
- if (shouldContinueParsing)
- resumeParsingAfterScriptExecution();
-}
-
-}
diff --git a/WebCore/html/HTML5Tokenizer.h b/WebCore/html/HTML5Tokenizer.h
deleted file mode 100644
index b96866d..0000000
--- a/WebCore/html/HTML5Tokenizer.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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 APPLE 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 APPLE 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 HTML5Tokenizer_h
-#define HTML5Tokenizer_h
-
-#include "CachedResourceClient.h"
-#include "HTML5ScriptRunnerHost.h"
-#include "HTML5Token.h"
-#include "SegmentedString.h"
-#include "Tokenizer.h"
-#include <wtf/OwnPtr.h>
-
-namespace WebCore {
-
-class HTML5Lexer;
-class HTML5ScriptRunner;
-class HTML5TreeBuilder;
-class HTMLDocument;
-class ScriptSourceCode;
-
-// FIXME: The whole Tokenizer class system should be renamed "Parser"
-// or "ParserController" as the job of this class is to drive parsing process
-// but it does not itself Tokenize.
-class HTML5Tokenizer : public Tokenizer, HTML5ScriptRunnerHost, CachedResourceClient {
-public:
- HTML5Tokenizer(HTMLDocument*, bool reportErrors);
- virtual ~HTML5Tokenizer();
-
- // Tokenizer
- virtual void begin();
- virtual void write(const SegmentedString&, bool appendData);
- virtual void end();
- virtual void finish();
- virtual int executingScript() const;
- virtual bool isWaitingForScripts() const;
- virtual void executeScriptsWaitingForStylesheets();
-
- // HTML5ScriptRunnerHost
- virtual void watchForLoad(CachedResource*);
- virtual void stopWatchingForLoad(CachedResource*);
- virtual void executeScript(const ScriptSourceCode&);
-
- // CachedResourceClient
- virtual void notifyFinished(CachedResource*);
-
-private:
- void pumpLexer();
- void resumeParsingAfterScriptExecution();
-
- SegmentedString m_source;
-
- // We hold m_token here because it might be partially complete.
- HTML5Token m_token;
-
- HTMLDocument* m_document;
- OwnPtr<HTML5Lexer> m_lexer;
- OwnPtr<HTML5ScriptRunner> m_scriptRunner;
- OwnPtr<HTML5TreeBuilder> m_treeBuilder;
- bool m_wasWaitingOnScriptsDuringFinish;
-};
-
-}
-
-#endif
diff --git a/WebCore/html/HTML5TreeBuilder.cpp b/WebCore/html/HTML5TreeBuilder.cpp
index 0153e94..79e1e0e 100644
--- a/WebCore/html/HTML5TreeBuilder.cpp
+++ b/WebCore/html/HTML5TreeBuilder.cpp
@@ -31,8 +31,8 @@
#include "HTML5Token.h"
#include "HTMLDocument.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
-#include "HTMLTokenizer.h"
+#include "LegacyHTMLTreeConstructor.h"
+#include "HTMLDocumentParser.h"
#include "NotImplemented.h"
#include <wtf/UnusedParam.h>
@@ -40,12 +40,17 @@ namespace WebCore {
using namespace HTMLNames;
+static const int uninitializedLineNumberValue = -1;
+
HTML5TreeBuilder::HTML5TreeBuilder(HTML5Lexer* lexer, HTMLDocument* document, bool reportErrors)
: m_document(document)
, m_reportErrors(reportErrors)
, m_isPaused(false)
+ , m_insertionMode(Initial)
, m_lexer(lexer)
- , m_legacyHTMLParser(new HTMLParser(document, reportErrors))
+ , m_legacyTreeConstructor(new LegacyHTMLTreeConstructor(document, reportErrors))
+ , m_lastScriptElementStartLine(uninitializedLineNumberValue)
+ , m_scriptToProcessStartLine(uninitializedLineNumberValue)
{
}
@@ -68,7 +73,7 @@ static void convertToOldStyle(HTML5Token& token, Token& oldStyleToken)
case HTML5Token::EndTag: {
oldStyleToken.beginTag = (token.type() == HTML5Token::StartTag);
oldStyleToken.selfClosingTag = token.selfClosing();
- oldStyleToken.tagName = token.name();
+ oldStyleToken.tagName = AtomicString(token.name().data(), token.name().size());
HTML5Token::AttributeList& attributes = token.attributes();
for (HTML5Token::AttributeList::iterator iter = attributes.begin();
iter != attributes.end(); ++iter) {
@@ -85,11 +90,11 @@ static void convertToOldStyle(HTML5Token& token, Token& oldStyleToken)
}
case HTML5Token::Comment:
oldStyleToken.tagName = commentAtom;
- oldStyleToken.text = token.takeComment().impl();
+ oldStyleToken.text = StringImpl::create(token.comment().data(), token.comment().size());
break;
case HTML5Token::Character:
oldStyleToken.tagName = textAtom;
- oldStyleToken.text = token.takeCharacters().impl();
+ oldStyleToken.text = StringImpl::create(token.characters().data(), token.characters().size());
break;
}
}
@@ -101,23 +106,29 @@ void HTML5TreeBuilder::handleScriptStartTag()
notImplemented(); // Save insertion mode.
}
-void HTML5TreeBuilder::handleScriptEndTag(Element* scriptElement)
+void HTML5TreeBuilder::handleScriptEndTag(Element* scriptElement, int scriptStartLine)
{
ASSERT(!m_scriptToProcess); // Caller never called takeScriptToProcess!
+ ASSERT(m_scriptToProcessStartLine == uninitializedLineNumberValue); // Caller never called takeScriptToProcess!
notImplemented(); // Save insertion mode and insertion point?
// Pause ourselves so that parsing stops until the script can be processed by the caller.
m_isPaused = true;
m_scriptToProcess = scriptElement;
+ // Lexer line numbers are 0-based, ScriptSourceCode expects 1-based lines,
+ // so we convert here before passing the line number off to HTML5ScriptRunner.
+ m_scriptToProcessStartLine = scriptStartLine + 1;
}
-PassRefPtr<Element> HTML5TreeBuilder::takeScriptToProcess()
+PassRefPtr<Element> HTML5TreeBuilder::takeScriptToProcess(int& scriptStartLine)
{
// Unpause ourselves, callers may pause us again when processing the script.
// The HTML5 spec is written as though scripts are executed inside the tree
// builder. We pause the parser to exit the tree builder, and then resume
// before running scripts.
m_isPaused = false;
+ scriptStartLine = m_scriptToProcessStartLine;
+ m_scriptToProcessStartLine = uninitializedLineNumberValue;
return m_scriptToProcess.release();
}
@@ -125,11 +136,12 @@ PassRefPtr<Node> HTML5TreeBuilder::passTokenToLegacyParser(HTML5Token& token)
{
if (token.type() == HTML5Token::DOCTYPE) {
DoctypeToken doctypeToken;
- doctypeToken.m_name.append(token.name().characters(), token.name().length());
+ doctypeToken.m_name.append(token.name().data(), token.name().size());
doctypeToken.m_publicID = token.publicIdentifier();
doctypeToken.m_systemID = token.systemIdentifier();
+ doctypeToken.m_forceQuirks = token.forceQuirks();
- m_legacyHTMLParser->parseDoctypeToken(&doctypeToken);
+ m_legacyTreeConstructor->parseDoctypeToken(&doctypeToken);
return 0;
}
@@ -137,31 +149,35 @@ PassRefPtr<Node> HTML5TreeBuilder::passTokenToLegacyParser(HTML5Token& token)
Token oldStyleToken;
convertToOldStyle(token, oldStyleToken);
- RefPtr<Node> result = m_legacyHTMLParser->parseToken(&oldStyleToken);
+ RefPtr<Node> result = m_legacyTreeConstructor->parseToken(&oldStyleToken);
if (token.type() == HTML5Token::StartTag) {
// This work is supposed to be done by the parser, but
// when using the old parser for we have to do this manually.
- if (token.name() == scriptTag) {
+ if (oldStyleToken.tagName == scriptTag) {
handleScriptStartTag();
m_lastScriptElement = static_pointer_cast<Element>(result);
- } else if (token.name() == textareaTag || token.name() == titleTag)
+ m_lastScriptElementStartLine = m_lexer->lineNumber();
+ } else if (oldStyleToken.tagName == textareaTag || oldStyleToken.tagName == titleTag)
m_lexer->setState(HTML5Lexer::RCDATAState);
- else if (token.name() == styleTag || token.name() == iframeTag
- || token.name() == xmpTag || token.name() == noembedTag) {
+ else if (oldStyleToken.tagName == styleTag || oldStyleToken.tagName == iframeTag
+ || oldStyleToken.tagName == xmpTag || oldStyleToken.tagName == noembedTag) {
// FIXME: noscript and noframes may conditionally enter this state as well.
m_lexer->setState(HTML5Lexer::RAWTEXTState);
- } else if (token.name() == plaintextTag)
+ } else if (oldStyleToken.tagName == plaintextTag)
m_lexer->setState(HTML5Lexer::PLAINTEXTState);
- else if (token.name() == preTag || token.name() == listingTag)
+ else if (oldStyleToken.tagName == preTag || oldStyleToken.tagName == listingTag)
m_lexer->skipLeadingNewLineForListing();
}
if (token.type() == HTML5Token::EndTag) {
- if (token.name() == scriptTag) {
+ if (oldStyleToken.tagName == scriptTag && insertionMode() != AfterFrameset) {
if (m_lastScriptElement) {
- handleScriptEndTag(m_lastScriptElement.get());
+ ASSERT(m_lastScriptElementStartLine != uninitializedLineNumberValue);
+ handleScriptEndTag(m_lastScriptElement.get(), m_lastScriptElementStartLine);
m_lastScriptElement = 0;
+ m_lastScriptElementStartLine = uninitializedLineNumberValue;
}
- }
+ } else if (oldStyleToken.tagName == framesetTag)
+ setInsertionMode(AfterFrameset);
}
return result.release();
}
@@ -197,8 +213,8 @@ PassRefPtr<Node> HTML5TreeBuilder::processToken(HTML5Token& token, UChar current
void HTML5TreeBuilder::finished()
{
// We should call m_document->finishedParsing() here, except
- // m_legacyHTMLParser->finished() does it for us.
- m_legacyHTMLParser->finished();
+ // m_legacyTreeConstructor->finished() does it for us.
+ m_legacyTreeConstructor->finished();
}
}
diff --git a/WebCore/html/HTML5TreeBuilder.h b/WebCore/html/HTML5TreeBuilder.h
index ee5ba47..a61bb7f 100644
--- a/WebCore/html/HTML5TreeBuilder.h
+++ b/WebCore/html/HTML5TreeBuilder.h
@@ -39,7 +39,7 @@ class Frame;
class HTML5Lexer;
class HTML5Token;
class HTMLDocument;
-class HTMLParser;
+class LegacyHTMLTreeConstructor;
class Node;
class HTML5TreeBuilder : public Noncopyable {
@@ -53,29 +53,53 @@ public:
// The token really should be passed as a const& since it's never modified.
PassRefPtr<Node> constructTreeFromToken(HTML5Token&);
// Must be called when parser is paused before calling the parser again.
- PassRefPtr<Element> takeScriptToProcess();
+ PassRefPtr<Element> takeScriptToProcess(int& scriptStartLine);
// Done, close any open tags, etc.
void finished();
+ // FIXME: This is a dirty, rotten hack to keep HTMLFormControlElement happy
+ // until we stop using the legacy parser. DO NOT CALL THIS METHOD.
+ LegacyHTMLTreeConstructor* legacyTreeConstructor() const { return m_legacyTreeConstructor.get(); }
+
private:
+ // Represents HTML5 "insertion mode"
+ // http://www.w3.org/TR/html5/syntax.html#insertion-mode
+ // FIXME: Implement remainder of states.
+ enum InsertionMode {
+ Initial,
+ AfterFrameset,
+ };
+
PassRefPtr<Node> passTokenToLegacyParser(HTML5Token&);
PassRefPtr<Node> processToken(HTML5Token&, UChar currentCharacter = 0);
void handleScriptStartTag();
- void handleScriptEndTag(Element*);
+ void handleScriptEndTag(Element*, int scriptStartLine);
+
+ void setInsertionMode(InsertionMode value) { m_insertionMode = value; }
+ InsertionMode insertionMode() const { return m_insertionMode; }
Document* m_document; // This is only used by the m_legacyParser for now.
bool m_reportErrors;
bool m_isPaused;
+
+ InsertionMode m_insertionMode;
+
// HTML5 spec requires that we be able to change the state of the lexer
// from within parser actions.
HTML5Lexer* m_lexer;
- // We're re-using logic from the old HTMLParser while this class is being written.
- OwnPtr<HTMLParser> m_legacyHTMLParser;
- RefPtr<Element> m_lastScriptElement; // FIXME: This is a hack for <script> support.
- RefPtr<Element> m_scriptToProcess; // Set to a <script> tag which needs processing.
+ // We're re-using logic from the old LegacyHTMLTreeConstructor while this class is being written.
+ OwnPtr<LegacyHTMLTreeConstructor> m_legacyTreeConstructor;
+
+ // These members are intentionally duplicated as the first set is a hack
+ // on top of the legacy parser which will eventually be removed.
+ RefPtr<Element> m_lastScriptElement; // FIXME: Hack for <script> support on top of the old parser.
+ int m_lastScriptElementStartLine; // FIXME: Hack for <script> support on top of the old parser.
+
+ RefPtr<Element> m_scriptToProcess; // <script> tag which needs processing before resuming the parser.
+ int m_scriptToProcessStartLine; // Starting line number of the script tag needing processing.
};
}
diff --git a/WebCore/html/HTMLAppletElement.cpp b/WebCore/html/HTMLAppletElement.cpp
index 79fcfba..537d615 100644
--- a/WebCore/html/HTMLAppletElement.cpp
+++ b/WebCore/html/HTMLAppletElement.cpp
@@ -63,7 +63,7 @@ void HTMLAppletElement::parseMappedAttribute(Attribute* attr)
document->addNamedItem(newName);
}
m_name = newName;
- } else if (attr->name() == idAttributeName()) {
+ } else if (isIdAttributeName(attr->name())) {
const AtomicString& newId = attr->value();
if (inDocument() && document()->isHTMLDocument()) {
HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
@@ -118,7 +118,7 @@ RenderObject* HTMLAppletElement::createRenderer(RenderArena*, RenderStyle* style
if (!codeBase.isNull())
args.set("codeBase", codeBase);
- const AtomicString& name = getAttribute(document()->isHTMLDocument() ? nameAttr : idAttributeName());
+ const AtomicString& name = document()->isHTMLDocument() ? getAttribute(nameAttr) : getIdAttribute();
if (!name.isNull())
args.set("name", name);
const AtomicString& archive = getAttribute(archiveAttr);
diff --git a/WebCore/html/HTMLAttributeNames.in b/WebCore/html/HTMLAttributeNames.in
index 7cde32f..90b249a 100644
--- a/WebCore/html/HTMLAttributeNames.in
+++ b/WebCore/html/HTMLAttributeNames.in
@@ -24,6 +24,7 @@ aria-expanded
aria-flowto
aria-grabbed
aria-haspopup
+aria-help
aria-hidden
aria-label
aria-labeledby
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index c9e4620..72343aa 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -156,7 +156,11 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
}
#if ENABLE(3D_CANVAS)
Settings* settings = document()->settings();
- if (settings && settings->webGLEnabled() && settings->acceleratedCompositingEnabled()) {
+ if (settings && settings->webGLEnabled()
+#if !PLATFORM(CHROMIUM) && !PLATFORM(QT)
+ && settings->acceleratedCompositingEnabled()
+#endif
+ ) {
// Accept the legacy "webkit-3d" name as well as the provisional "experimental-webgl" name.
// Once ratified, we will also accept "webgl" as the context name.
if ((type == "webkit-3d") ||
diff --git a/WebCore/html/HTMLCanvasElement.idl b/WebCore/html/HTMLCanvasElement.idl
index 656d6ae..3a56330 100644
--- a/WebCore/html/HTMLCanvasElement.idl
+++ b/WebCore/html/HTMLCanvasElement.idl
@@ -27,7 +27,8 @@
module html {
interface [
- CustomMarkFunction
+ CustomMarkFunction,
+ GenerateNativeConverter
] HTMLCanvasElement : HTMLElement {
attribute long width;
@@ -36,10 +37,12 @@ module html {
[Custom] DOMString toDataURL(in [ConvertUndefinedOrNullToNullString] DOMString type)
raises(DOMException);
+#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
// The custom binding is needed to handle context creation attributes.
[Custom] DOMObject getContext(in DOMString contextId);
#endif
+#endif
};
diff --git a/WebCore/html/HTMLCollection.cpp b/WebCore/html/HTMLCollection.cpp
index 8a942c3..8a202ae 100644
--- a/WebCore/html/HTMLCollection.cpp
+++ b/WebCore/html/HTMLCollection.cpp
@@ -266,7 +266,7 @@ bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const A
HTMLElement* e = static_cast<HTMLElement*>(element);
if (!checkName)
- return e->getAttribute(e->idAttributeName()) == name;
+ return e->getIdAttribute() == name;
// document.all returns only images, forms, applets, objects and embeds
// by name (though everything by id)
@@ -277,7 +277,7 @@ bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const A
e->hasLocalName(selectTag)))
return false;
- return e->getAttribute(nameAttr) == name && e->getAttribute(e->idAttributeName()) != name;
+ return e->getAttribute(nameAttr) == name && e->getIdAttribute() != name;
}
Node* HTMLCollection::namedItem(const AtomicString& name) const
@@ -319,7 +319,7 @@ void HTMLCollection::updateNameCache() const
if (!element->isHTMLElement())
continue;
HTMLElement* e = static_cast<HTMLElement*>(element);
- const AtomicString& idAttrVal = e->getAttribute(e->idAttributeName());
+ const AtomicString& idAttrVal = e->getIdAttribute();
const AtomicString& nameAttrVal = e->getAttribute(nameAttr);
if (!idAttrVal.isEmpty()) {
// add to id cache
diff --git a/WebCore/html/HTMLDataGridColElement.cpp b/WebCore/html/HTMLDataGridColElement.cpp
index be2b7f2..8486d4d 100644
--- a/WebCore/html/HTMLDataGridColElement.cpp
+++ b/WebCore/html/HTMLDataGridColElement.cpp
@@ -60,7 +60,7 @@ void HTMLDataGridColElement::ensureColumn()
{
if (m_column)
return;
- m_column = DataGridColumn::create(getAttribute(idAttributeName()), label(), type(), primary(), sortable());
+ m_column = DataGridColumn::create(getIdAttribute(), label(), type(), primary(), sortable());
}
void HTMLDataGridColElement::insertedIntoTree(bool deep)
@@ -167,8 +167,8 @@ void HTMLDataGridColElement::parseMappedAttribute(Attribute* attr)
column()->setSortable(sortable());
else if (attr->name() == sortdirectionAttr)
column()->setSortDirection(sortDirection());
- else if (attr->name() == idAttributeName())
- column()->setId(getAttribute(idAttributeName()));
+ else if (isIdAttributeName(attr->name()))
+ column()->setId(getIdAttribute());
}
} // namespace WebCore
diff --git a/WebCore/html/HTMLDocument.cpp b/WebCore/html/HTMLDocument.cpp
index f060adb..b066f8a 100644
--- a/WebCore/html/HTMLDocument.cpp
+++ b/WebCore/html/HTMLDocument.cpp
@@ -64,11 +64,11 @@
#include "FrameLoader.h"
#include "FrameTree.h"
#include "FrameView.h"
-#include "HTML5Tokenizer.h"
+#include "HTML5DocumentParser.h"
#include "HTMLBodyElement.h"
#include "HTMLElementFactory.h"
#include "HTMLNames.h"
-#include "HTMLTokenizer.h"
+#include "HTMLDocumentParser.h"
#include "InspectorController.h"
#include "KURL.h"
#include "Page.h"
@@ -283,7 +283,7 @@ void HTMLDocument::releaseEvents()
{
}
-Tokenizer* HTMLDocument::createTokenizer()
+DocumentParser* HTMLDocument::createParser()
{
bool reportErrors = false;
#if ENABLE(INSPECTOR)
@@ -292,9 +292,9 @@ Tokenizer* HTMLDocument::createTokenizer()
#endif
if (settings() && settings()->html5ParserEnabled())
- return new HTML5Tokenizer(this, reportErrors);
+ return new HTML5DocumentParser(this, reportErrors);
- return new HTMLTokenizer(this, reportErrors);
+ return new HTMLDocumentParser(this, reportErrors);
}
// --------------------------------------------------------------------------
diff --git a/WebCore/html/HTMLDocument.h b/WebCore/html/HTMLDocument.h
index 55cf8ad..5b1f636 100644
--- a/WebCore/html/HTMLDocument.h
+++ b/WebCore/html/HTMLDocument.h
@@ -96,7 +96,7 @@ private:
virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
virtual bool isFrameSet() const;
- virtual Tokenizer* createTokenizer();
+ virtual DocumentParser* createParser();
virtual void determineParseMode();
void addItemToMap(HashCountedSet<AtomicStringImpl*>&, const AtomicString&);
diff --git a/WebCore/html/HTMLDocument.idl b/WebCore/html/HTMLDocument.idl
index a79b913..9684373 100644
--- a/WebCore/html/HTMLDocument.idl
+++ b/WebCore/html/HTMLDocument.idl
@@ -23,7 +23,7 @@ module html {
interface [
HasOverridingNameGetter
] HTMLDocument : Document {
- [Custom] void open();
+ [Custom, NoCPPCustom] void open();
void close();
[Custom] void write(in DOMString text);
[Custom] void writeln(in DOMString text);
diff --git a/WebCore/html/HTMLTokenizer.cpp b/WebCore/html/HTMLDocumentParser.cpp
index e3d3ce6..ba2688f 100644
--- a/WebCore/html/HTMLTokenizer.cpp
+++ b/WebCore/html/HTMLDocumentParser.cpp
@@ -26,7 +26,7 @@
*/
#include "config.h"
-#include "HTMLTokenizer.h"
+#include "HTMLDocumentParser.h"
#include "Attribute.h"
#include "CSSHelper.h"
@@ -41,7 +41,7 @@
#include "FrameView.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "HTMLScriptElement.h"
#include "HTMLViewSourceDocument.h"
#include "ImageLoader.h"
@@ -55,7 +55,7 @@
#include <wtf/ASCIICType.h>
#include <wtf/CurrentTime.h>
-#include "HTMLEntityNames.c"
+#include "HTMLEntityNames.cpp"
#ifdef ANDROID_INSTRUMENT
#include "TimeCounter.h"
@@ -70,15 +70,15 @@ namespace WebCore {
using namespace HTMLNames;
-// This value is used to define how many characters the tokenizer will process before
+// This value is used to define how many characters the parser will process before
// yeilding control.
-// To increase responsivness reduce the tokenizer chunk size.
+// To increase responsivness reduce the parser chunk size.
static const int defaultTokenizerChunkSize = 4096;
// FIXME: We would like this constant to be 200ms.
// Yielding more aggressively results in increased responsiveness and better incremental rendering.
// It slows down overall page-load on slower machines, though, so for now we set a value of 500.
-// For smaller chunks (above) decrease the value of TimerDelay as the the tokenizer should not
+// For smaller chunks (above) decrease the value of TimerDelay as the the parser should not
// yield for as long a period otherwise it will take way to long to load a page.
static const double defaultTokenizerTimeDelay = 0.500;
@@ -145,14 +145,14 @@ inline void Token::addAttribute(AtomicString& attrName, const AtomicString& attr
}
attrs->insertAttribute(a.release(), viewSourceMode);
}
-
+
attrName = emptyAtom;
}
// ----------------------------------------------------------------------------
-HTMLTokenizer::HTMLTokenizer(HTMLDocument* doc, bool reportErrors)
- : Tokenizer()
+HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* doc, bool reportErrors)
+ : DocumentParser()
, m_buffer(0)
, m_scriptCode(0)
, m_scriptCodeSize(0)
@@ -161,10 +161,10 @@ HTMLTokenizer::HTMLTokenizer(HTMLDocument* doc, bool reportErrors)
, m_executingScript(0)
, m_requestingScript(false)
, m_hasScriptsWaitingForStylesheets(false)
- , m_timer(this, &HTMLTokenizer::timerFired)
- , m_externalScriptsTimer(this, &HTMLTokenizer::executeExternalScriptsTimerFired)
+ , m_timer(this, &HTMLDocumentParser::timerFired)
+ , m_externalScriptsTimer(this, &HTMLDocumentParser::executeExternalScriptsTimerFired)
, m_doc(doc)
- , m_parser(new HTMLParser(doc, reportErrors))
+ , m_treeConstructor(new LegacyHTMLTreeConstructor(doc, reportErrors))
, m_inWrite(false)
, m_fragment(false)
, m_scriptingPermission(FragmentScriptingAllowed)
@@ -172,8 +172,8 @@ HTMLTokenizer::HTMLTokenizer(HTMLDocument* doc, bool reportErrors)
begin();
}
-HTMLTokenizer::HTMLTokenizer(HTMLViewSourceDocument* doc)
- : Tokenizer(true)
+HTMLDocumentParser::HTMLDocumentParser(HTMLViewSourceDocument* doc)
+ : DocumentParser(true)
, m_buffer(0)
, m_scriptCode(0)
, m_scriptCodeSize(0)
@@ -182,10 +182,9 @@ HTMLTokenizer::HTMLTokenizer(HTMLViewSourceDocument* doc)
, m_executingScript(0)
, m_requestingScript(false)
, m_hasScriptsWaitingForStylesheets(false)
- , m_timer(this, &HTMLTokenizer::timerFired)
- , m_externalScriptsTimer(this, &HTMLTokenizer::executeExternalScriptsTimerFired)
+ , m_timer(this, &HTMLDocumentParser::timerFired)
+ , m_externalScriptsTimer(this, &HTMLDocumentParser::executeExternalScriptsTimerFired)
, m_doc(doc)
- , m_parser(0)
, m_inWrite(false)
, m_fragment(false)
, m_scriptingPermission(FragmentScriptingAllowed)
@@ -193,7 +192,7 @@ HTMLTokenizer::HTMLTokenizer(HTMLViewSourceDocument* doc)
begin();
}
-HTMLTokenizer::HTMLTokenizer(DocumentFragment* frag, FragmentScriptingPermission scriptingPermission)
+HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* frag, FragmentScriptingPermission scriptingPermission)
: m_buffer(0)
, m_scriptCode(0)
, m_scriptCodeSize(0)
@@ -202,10 +201,10 @@ HTMLTokenizer::HTMLTokenizer(DocumentFragment* frag, FragmentScriptingPermission
, m_executingScript(0)
, m_requestingScript(false)
, m_hasScriptsWaitingForStylesheets(false)
- , m_timer(this, &HTMLTokenizer::timerFired)
- , m_externalScriptsTimer(this, &HTMLTokenizer::executeExternalScriptsTimerFired)
+ , m_timer(this, &HTMLDocumentParser::timerFired)
+ , m_externalScriptsTimer(this, &HTMLDocumentParser::executeExternalScriptsTimerFired)
, m_doc(frag->document())
- , m_parser(new HTMLParser(frag, scriptingPermission))
+ , m_treeConstructor(new LegacyHTMLTreeConstructor(frag, scriptingPermission))
, m_inWrite(false)
, m_fragment(true)
, m_scriptingPermission(scriptingPermission)
@@ -213,13 +212,12 @@ HTMLTokenizer::HTMLTokenizer(DocumentFragment* frag, FragmentScriptingPermission
begin();
}
-void HTMLTokenizer::reset()
+void HTMLDocumentParser::reset()
{
ASSERT(m_executingScript == 0);
while (!m_pendingScripts.isEmpty()) {
- CachedScript* cs = m_pendingScripts.first().get();
- m_pendingScripts.removeFirst();
+ CachedScript* cs = m_pendingScripts.takeFirst().get();
ASSERT(cache()->disabled() || cs->accessCount() > 0);
cs->removeClient(this);
}
@@ -245,7 +243,7 @@ void HTMLTokenizer::reset()
m_hasScriptsWaitingForStylesheets = false;
}
-void HTMLTokenizer::begin()
+void HTMLDocumentParser::begin()
{
m_executingScript = 0;
m_requestingScript = false;
@@ -281,12 +279,12 @@ void HTMLTokenizer::begin()
m_tokenizerChunkSize = defaultTokenizerChunkSize;
}
-void HTMLTokenizer::setForceSynchronous(bool force)
+void HTMLDocumentParser::setForceSynchronous(bool force)
{
m_state.setForceSynchronous(force);
}
-HTMLTokenizer::State HTMLTokenizer::processListing(SegmentedString list, State state)
+HTMLDocumentParser::State HTMLDocumentParser::processListing(SegmentedString list, State state)
{
// This function adds the listing 'list' as
// preformatted text-tokens to the token-collection
@@ -323,7 +321,7 @@ HTMLTokenizer::State HTMLTokenizer::processListing(SegmentedString list, State s
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseNonHTMLText(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseNonHTMLText(SegmentedString& src, State state)
{
ASSERT(state.inTextArea() || state.inTitle() || state.inIFrame() || !state.hasEntityState());
ASSERT(!state.hasTagState());
@@ -331,7 +329,7 @@ HTMLTokenizer::State HTMLTokenizer::parseNonHTMLText(SegmentedString& src, State
if (state.inScript() && !m_currentScriptTagStartLineNumber)
m_currentScriptTagStartLineNumber = m_lineNumber;
- if (state.inComment())
+ if (state.inComment())
state = parseComment(src, state);
int lastDecodedEntityPosition = -1;
@@ -357,13 +355,13 @@ HTMLTokenizer::State HTMLTokenizer::parseNonHTMLText(SegmentedString& src, State
else {
state = processListing(SegmentedString(m_scriptCode, m_scriptCodeSize), state);
processToken();
- if (state.inStyle()) {
+ if (state.inStyle()) {
m_currentToken.tagName = styleTag.localName();
m_currentToken.beginTag = false;
- } else if (state.inTextArea()) {
+ } else if (state.inTextArea()) {
m_currentToken.tagName = textareaTag.localName();
m_currentToken.beginTag = false;
- } else if (state.inTitle()) {
+ } else if (state.inTitle()) {
m_currentToken.tagName = titleTag.localName();
m_currentToken.beginTag = false;
} else if (state.inXmp()) {
@@ -419,26 +417,26 @@ HTMLTokenizer::State HTMLTokenizer::parseNonHTMLText(SegmentedString& src, State
return state;
}
-
-HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
+
+HTMLDocumentParser::State HTMLDocumentParser::scriptHandler(State state)
{
// We are inside a <script>
bool doScriptExec = false;
int startLine = m_currentScriptTagStartLineNumber + 1; // Script line numbers are 1 based, HTMLTokenzier line numbers are 0 based
-
+
// Reset m_currentScriptTagStartLineNumber to indicate that we've finished parsing the current script element
m_currentScriptTagStartLineNumber = 0;
- // (Bugzilla 3837) Scripts following a frameset element should not execute or,
+ // (Bugzilla 3837) Scripts following a frameset element should not execute or,
// in the case of extern scripts, even load.
bool followingFrameset = (m_doc->body() && m_doc->body()->hasTagName(framesetTag));
-
+
CachedScript* cs = 0;
// don't load external scripts for standalone documents (for now)
if (!inViewSourceMode()) {
if (!m_scriptTagSrcAttrValue.isEmpty() && m_doc->frame()) {
// forget what we just got; load from src url instead
- if (!m_parser->skipMode() && !followingFrameset) {
+ if (!m_treeConstructor->skipMode() && !followingFrameset) {
// The parser might have been stopped by for example a window.close call in an earlier script.
// If so, we don't want to load scripts.
if (!m_parserStopped && m_scriptNode->dispatchBeforeLoadEvent(m_scriptTagSrcAttrValue) &&
@@ -462,13 +460,13 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
state = processListing(SegmentedString(m_scriptCode, m_scriptCodeSize), state);
RefPtr<Node> node = processToken();
-
+
if (node && m_scriptingPermission == FragmentScriptingNotAllowed) {
ExceptionCode ec;
node->remove(ec);
node = 0;
}
-
+
String scriptString = node ? node->textContent() : "";
m_currentToken.tagName = scriptTag.localName();
m_currentToken.beginTag = false;
@@ -476,7 +474,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
state.setInScript(false);
m_scriptCodeSize = m_scriptCodeResync = 0;
-
+
// FIXME: The script should be syntax highlighted.
if (inViewSourceMode())
return state;
@@ -485,11 +483,15 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
SegmentedString prependingSrc;
m_currentPrependingSrc = &prependingSrc;
+<<<<<<< HEAD:WebCore/html/HTMLTokenizer.cpp
#ifdef ANDROID_INSTRUMENT
android::TimeCounter::recordNoCounter(android::TimeCounter::ParsingTimeCounter, __FUNCTION__);
#endif
if (!m_parser->skipMode() && !followingFrameset) {
+=======
+ if (!m_treeConstructor->skipMode() && !followingFrameset) {
+>>>>>>> Webkit.org at r61121:WebCore/html/HTMLDocumentParser.cpp
if (cs) {
if (savedPrependingSrc)
savedPrependingSrc->append(m_src);
@@ -544,7 +546,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
state = m_state;
}
}
-
+
#if PRELOAD_SCANNER_ENABLED
if (!m_pendingScripts.isEmpty() && !m_executingScript) {
if (!m_preloadScanner)
@@ -560,12 +562,12 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
return state;
}
-HTMLTokenizer::State HTMLTokenizer::scriptExecution(const ScriptSourceCode& sourceCode, State state)
+HTMLDocumentParser::State HTMLDocumentParser::scriptExecution(const ScriptSourceCode& sourceCode, State state)
{
if (m_fragment || !m_doc->frame())
return state;
m_executingScript++;
-
+
SegmentedString* savedPrependingSrc = m_currentPrependingSrc;
SegmentedString prependingSrc;
m_currentPrependingSrc = &prependingSrc;
@@ -579,7 +581,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptExecution(const ScriptSourceCode& sour
m_executingScript--;
if (!m_executingScript && !state.loadingExtScript()) {
- m_pendingSrc.prepend(prependingSrc);
+ m_pendingSrc.prepend(prependingSrc);
m_src.append(m_pendingSrc);
m_pendingSrc.clear();
} else if (!prependingSrc.isEmpty()) {
@@ -595,7 +597,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptExecution(const ScriptSourceCode& sour
m_currentPrependingSrc->append(prependingSrc);
else
m_pendingSrc.prepend(prependingSrc);
-
+
#if PRELOAD_SCANNER_ENABLED
// We are stuck waiting for another script. Lets check the source that
// was just document.write()n for anything to load.
@@ -612,11 +614,11 @@ HTMLTokenizer::State HTMLTokenizer::scriptExecution(const ScriptSourceCode& sour
}
m_currentPrependingSrc = savedPrependingSrc;
-
+
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseComment(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseComment(SegmentedString& src, State state)
{
// FIXME: Why does this code even run for comments inside <script> and <style>? This seems bogus.
checkScriptBuffer(src.length());
@@ -628,7 +630,7 @@ HTMLTokenizer::State HTMLTokenizer::parseComment(SegmentedString& src, State sta
int endCharsCount = 1; // start off with one for the '>' character
if (m_scriptCodeSize > 2 && m_scriptCode[m_scriptCodeSize-3] == '-' && m_scriptCode[m_scriptCodeSize-2] == '-') {
endCharsCount = 3;
- } else if (m_scriptCodeSize > 3 && m_scriptCode[m_scriptCodeSize-4] == '-' && m_scriptCode[m_scriptCodeSize-3] == '-' &&
+ } else if (m_scriptCodeSize > 3 && m_scriptCode[m_scriptCodeSize-4] == '-' && m_scriptCode[m_scriptCodeSize-3] == '-' &&
m_scriptCode[m_scriptCodeSize-2] == '!') {
// Other browsers will accept --!> as a close comment, even though it's
// not technically valid.
@@ -659,7 +661,7 @@ HTMLTokenizer::State HTMLTokenizer::parseComment(SegmentedString& src, State sta
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseServer(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseServer(SegmentedString& src, State state)
{
checkScriptBuffer(src.length());
while (!src.isEmpty()) {
@@ -676,7 +678,7 @@ HTMLTokenizer::State HTMLTokenizer::parseServer(SegmentedString& src, State stat
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseProcessingInstruction(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseProcessingInstruction(SegmentedString& src, State state)
{
UChar oldchar = 0;
while (!src.isEmpty()) {
@@ -698,11 +700,11 @@ HTMLTokenizer::State HTMLTokenizer::parseProcessingInstruction(SegmentedString&
src.advance(m_lineNumber);
oldchar = chbegin;
}
-
+
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseText(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseText(SegmentedString& src, State state)
{
while (!src.isEmpty()) {
UChar cc = *src;
@@ -730,7 +732,7 @@ HTMLTokenizer::State HTMLTokenizer::parseText(SegmentedString& src, State state)
}
-HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString& src, UChar*& dest, State state, unsigned& cBufferPos, bool start, bool parsingTag)
+HTMLDocumentParser::State HTMLDocumentParser::parseEntity(SegmentedString& src, UChar*& dest, State state, unsigned& cBufferPos, bool start, bool parsingTag)
{
if (start) {
cBufferPos = 0;
@@ -744,7 +746,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString& src, UChar*& de
case NoEntity:
ASSERT(state.entityState() != NoEntity);
return state;
-
+
case SearchEntity:
if (cc == '#') {
m_cBuffer[cBufferPos++] = cc;
@@ -782,7 +784,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString& src, UChar*& de
m_cBuffer[cBufferPos++] = cc;
src.advancePastNonNewline();
}
- if (cBufferPos == 10)
+ if (cBufferPos == 10)
state.setEntityState(SearchSemicolon);
break;
}
@@ -801,7 +803,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString& src, UChar*& de
m_cBuffer[cBufferPos++] = cc;
src.advancePastNonNewline();
}
- if (cBufferPos == 9)
+ if (cBufferPos == 9)
state.setEntityState(SearchSemicolon);
break;
}
@@ -819,7 +821,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString& src, UChar*& de
m_cBuffer[cBufferPos++] = cc;
src.advancePastNonNewline();
}
- if (cBufferPos == 9)
+ if (cBufferPos == 9)
state.setEntityState(SearchSemicolon);
if (state.entityState() == SearchSemicolon) {
if (cBufferPos > 1) {
@@ -904,7 +906,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString& src, UChar*& de
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseDoctype(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseDoctype(SegmentedString& src, State state)
{
ASSERT(state.inDoctype());
while (!src.isEmpty() && state.inDoctype()) {
@@ -1120,7 +1122,7 @@ HTMLTokenizer::State HTMLTokenizer::parseDoctype(SegmentedString& src, State sta
return state;
}
-HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
+HTMLDocumentParser::State HTMLDocumentParser::parseTag(SegmentedString& src, State state)
{
ASSERT(!state.hasEntityState());
@@ -1172,7 +1174,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
} else
searchCount = 0; // Stop looking for '<!--' sequence
}
-
+
if (m_doctypeSearchCount > 0) {
if (toASCIILower(*src) == doctypeStart[m_doctypeSearchCount]) {
m_doctypeSearchCount++;
@@ -1202,7 +1204,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
finish = true;
break;
}
-
+
// tolower() shows up on profiles. This is faster!
if (curchar >= 'A' && curchar <= 'Z' && !inViewSourceMode())
m_cBuffer[cBufferPos++] = curchar + ('a' - 'A');
@@ -1268,7 +1270,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
int ll = min(src.length(), CBUFLEN - cBufferPos);
while (ll--) {
UChar curchar = *src;
- // If we encounter a "/" when scanning an attribute name, treat it as a delimiter. This allows the
+ // If we encounter a "/" when scanning an attribute name, treat it as a delimiter. This allows the
// cases like <input type=checkbox checked/> to work (and accommodates XML-style syntax as per HTML5).
if (curchar <= '>' && (curchar >= '<' || isASCIISpace(curchar) || curchar == '/')) {
m_cBuffer[cBufferPos] = '\0';
@@ -1280,13 +1282,13 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
m_currentToken.addViewSourceChar('a');
break;
}
-
+
// tolower() shows up on profiles. This is faster!
if (curchar >= 'A' && curchar <= 'Z' && !inViewSourceMode())
m_cBuffer[cBufferPos++] = curchar + ('a' - 'A');
else
m_cBuffer[cBufferPos++] = curchar;
-
+
m_rawAttributeBeforeValue.append(curchar);
src.advance(m_lineNumber);
}
@@ -1387,7 +1389,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
tquote = NoQuote;
break;
}
-
+
if (curchar == '&') {
src.advancePastNonNewline();
state = parseEntity(src, m_dest, state, cBufferPos, true, true);
@@ -1406,9 +1408,9 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
} else if (inViewSourceMode())
m_currentToken.addViewSourceChar('v');
- if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_parser->skipMode() && m_attrName == srcAttr) {
+ if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_treeConstructor->skipMode() && m_attrName == srcAttr) {
String context(m_rawAttributeBeforeValue.data(), m_rawAttributeBeforeValue.size());
- if (m_XSSAuditor && !m_XSSAuditor->canLoadExternalScriptFromSrc(context, attributeValue))
+ if (m_XSSAuditor && !m_XSSAuditor->canLoadExternalScriptFromSrc(attributeValue))
attributeValue = blankURL().string();
}
@@ -1443,9 +1445,9 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
if (isASCIISpace(curchar) || curchar == '>') {
AtomicString attributeValue(m_buffer + 1, m_dest - m_buffer - 1);
- if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_parser->skipMode() && m_attrName == srcAttr) {
+ if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_treeConstructor->skipMode() && m_attrName == srcAttr) {
String context(m_rawAttributeBeforeValue.data(), m_rawAttributeBeforeValue.size());
- if (m_XSSAuditor && !m_XSSAuditor->canLoadExternalScriptFromSrc(context, attributeValue))
+ if (m_XSSAuditor && !m_XSSAuditor->canLoadExternalScriptFromSrc(attributeValue))
attributeValue = blankURL().string();
}
@@ -1495,7 +1497,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
// compatibility.
bool isSelfClosingScript = m_currentToken.selfClosingTag && m_currentToken.beginTag && m_currentToken.tagName == scriptTag;
bool beginTag = !m_currentToken.selfClosingTag && m_currentToken.beginTag;
- if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_parser->skipMode()) {
+ if (m_currentToken.beginTag && m_currentToken.tagName == scriptTag && !inViewSourceMode() && !m_treeConstructor->skipMode()) {
Attribute* a = 0;
m_scriptTagSrcAttrValue = String();
m_scriptTagCharsetAttrValue = String();
@@ -1590,7 +1592,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString& src, State state)
return state;
}
-inline bool HTMLTokenizer::continueProcessing(int& processedCount, double startTime, State &state)
+inline bool HTMLDocumentParser::continueProcessing(int& processedCount, double startTime, State &state)
{
// We don't want to be checking elapsed time with every character, so we only check after we've
// processed a certain number of characters.
@@ -1602,21 +1604,21 @@ inline bool HTMLTokenizer::continueProcessing(int& processedCount, double startT
/* FIXME: We'd like to yield aggressively to give stylesheets the opportunity to
load, but this hurts overall performance on slower machines. For now turn this
off.
- || (!m_doc->haveStylesheetsLoaded() &&
+ || (!m_doc->haveStylesheetsLoaded() &&
(m_doc->documentElement()->id() != ID_HTML || m_doc->body()))) {*/
// Schedule the timer to keep processing as soon as possible.
m_timer.startOneShot(0);
return false;
}
}
-
+
processedCount++;
return true;
}
// Turns the statemachine one crank using the passed in State object.
// This does not modify m_state directly in order to be reentrant.
-ALWAYS_INLINE void HTMLTokenizer::advance(State& state)
+ALWAYS_INLINE void HTMLDocumentParser::advance(State& state)
{
// do we need to enlarge the buffer?
checkBuffer();
@@ -1649,7 +1651,7 @@ ALWAYS_INLINE void HTMLTokenizer::advance(State& state)
state = parseTag(m_src, state);
else if (state.startTag()) {
state.setStartTag(false);
-
+
switch (cc) {
case '/':
break;
@@ -1724,7 +1726,7 @@ ALWAYS_INLINE void HTMLTokenizer::advance(State& state)
}
}
-void HTMLTokenizer::willWriteHTML(const SegmentedString& source)
+void HTMLDocumentParser::willWriteHTML(const SegmentedString& source)
{
#if ENABLE(INSPECTOR)
if (InspectorTimelineAgent* timelineAgent = m_doc->inspectorTimelineAgent())
@@ -1732,7 +1734,7 @@ void HTMLTokenizer::willWriteHTML(const SegmentedString& source)
#endif
}
-void HTMLTokenizer::didWriteHTML()
+void HTMLDocumentParser::didWriteHTML()
{
#if ENABLE(INSPECTOR)
if (InspectorTimelineAgent* timelineAgent = m_doc->inspectorTimelineAgent())
@@ -1740,11 +1742,11 @@ void HTMLTokenizer::didWriteHTML()
#endif
}
-void HTMLTokenizer::write(const SegmentedString& str, bool appendData)
+void HTMLDocumentParser::write(const SegmentedString& str, bool appendData)
{
if (!m_buffer)
return;
-
+
if (m_parserStopped)
return;
@@ -1765,7 +1767,7 @@ void HTMLTokenizer::write(const SegmentedString& str, bool appendData)
}
return;
}
-
+
#if PRELOAD_SCANNER_ENABLED
if (m_preloadScanner && m_preloadScanner->inProgress() && appendData)
m_preloadScanner->end();
@@ -1776,7 +1778,7 @@ void HTMLTokenizer::write(const SegmentedString& str, bool appendData)
else
setSrc(source);
- // Once a timer is set, it has control of when the tokenizer continues.
+ // Once a timer is set, it has control of when the parser continues.
if (m_timer.isActive())
return;
@@ -1811,28 +1813,29 @@ void HTMLTokenizer::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();
}
-void HTMLTokenizer::stopParsing()
+void HTMLDocumentParser::stopParsing()
{
- Tokenizer::stopParsing();
+ DocumentParser::stopParsing();
m_timer.stop();
- // The part needs to know that the tokenizer has finished with its data,
+ // FIXME: Why is HTMLDocumentParser the only DocumentParser which calls checkCompleted?
+ // The FrameLoader needs to know that the parser has finished with its data,
// regardless of whether it happened naturally or due to manual intervention.
if (!m_fragment && m_doc->frame())
- m_doc->frame()->loader()->tokenizerProcessedData();
+ m_doc->frame()->loader()->checkCompleted();
}
-bool HTMLTokenizer::processingData() const
+bool HTMLDocumentParser::processingData() const
{
return m_timer.isActive() || m_inWrite;
}
-void HTMLTokenizer::timerFired(Timer<HTMLTokenizer>*)
+void HTMLDocumentParser::timerFired(Timer<HTMLDocumentParser>*)
{
if (m_doc->view() && m_doc->view()->layoutPending() && !m_doc->minimumLayoutDelay()) {
// Restart the timer and let layout win. This is basically a way of ensuring that the layout
@@ -1845,7 +1848,7 @@ void HTMLTokenizer::timerFired(Timer<HTMLTokenizer>*)
write(SegmentedString(), true);
}
-void HTMLTokenizer::end()
+void HTMLDocumentParser::end()
{
ASSERT(!m_timer.isActive());
m_timer.stop(); // Only helps if assertion above fires, but do it anyway.
@@ -1864,12 +1867,12 @@ void HTMLTokenizer::end()
}
if (!inViewSourceMode())
- m_parser->finished();
+ m_treeConstructor->finished();
else
m_doc->finishedParsing();
}
-void HTMLTokenizer::finish()
+void HTMLDocumentParser::finish()
{
// do this as long as we don't find matching comment ends
while ((m_state.inComment() || m_state.inServer()) && m_scriptCode && m_scriptCodeSize) {
@@ -1907,7 +1910,7 @@ void HTMLTokenizer::finish()
end(); // this actually causes us to be deleted
}
-PassRefPtr<Node> HTMLTokenizer::processToken()
+PassRefPtr<Node> HTMLDocumentParser::processToken()
{
ScriptController* scriptController = (!m_fragment && m_doc->frame()) ? m_doc->frame()->script() : 0;
if (scriptController && scriptController->canExecuteScripts(NotAboutToExecuteScript))
@@ -1927,7 +1930,7 @@ PassRefPtr<Node> HTMLTokenizer::processToken()
m_dest = m_buffer;
RefPtr<Node> n;
-
+
if (!m_parserStopped) {
if (NamedNodeMap* map = m_currentToken.attrs.get())
map->shrinkToLength();
@@ -1935,7 +1938,7 @@ PassRefPtr<Node> HTMLTokenizer::processToken()
static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceToken(&m_currentToken);
else
// pass the token over to the parser, the parser DOES NOT delete the token
- n = m_parser->parseToken(&m_currentToken);
+ n = m_treeConstructor->parseToken(&m_currentToken);
}
m_currentToken.reset();
if (scriptController)
@@ -1944,22 +1947,22 @@ PassRefPtr<Node> HTMLTokenizer::processToken()
return n.release();
}
-void HTMLTokenizer::processDoctypeToken()
+void HTMLDocumentParser::processDoctypeToken()
{
if (inViewSourceMode())
static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceDoctypeToken(&m_doctypeToken);
else
- m_parser->parseDoctypeToken(&m_doctypeToken);
+ m_treeConstructor->parseDoctypeToken(&m_doctypeToken);
}
-HTMLTokenizer::~HTMLTokenizer()
+HTMLDocumentParser::~HTMLDocumentParser()
{
ASSERT(!m_inWrite);
reset();
}
-void HTMLTokenizer::enlargeBuffer(int len)
+void HTMLDocumentParser::enlargeBuffer(int len)
{
// Resize policy: Always at least double the size of the buffer each time.
int delta = max(len, m_bufferSize);
@@ -1977,7 +1980,7 @@ void HTMLTokenizer::enlargeBuffer(int len)
m_bufferSize = newSize;
}
-void HTMLTokenizer::enlargeScriptBuffer(int len)
+void HTMLDocumentParser::enlargeScriptBuffer(int len)
{
// Resize policy: Always at least double the size of the buffer each time.
int delta = max(len, m_scriptCodeCapacity);
@@ -2000,8 +2003,8 @@ void HTMLTokenizer::enlargeScriptBuffer(int len)
m_scriptCode = static_cast<UChar*>(fastRealloc(m_scriptCode, newSize * sizeof(UChar)));
m_scriptCodeCapacity = newSize;
}
-
-void HTMLTokenizer::executeScriptsWaitingForStylesheets()
+
+void HTMLDocumentParser::executeScriptsWaitingForStylesheets()
{
ASSERT(m_doc->haveStylesheetsLoaded());
@@ -2009,12 +2012,12 @@ void HTMLTokenizer::executeScriptsWaitingForStylesheets()
notifyFinished(0);
}
-void HTMLTokenizer::notifyFinished(CachedResource*)
+void HTMLDocumentParser::notifyFinished(CachedResource*)
{
executeExternalScriptsIfReady();
}
-void HTMLTokenizer::executeExternalScriptsIfReady()
+void HTMLDocumentParser::executeExternalScriptsIfReady()
{
ASSERT(!m_pendingScripts.isEmpty());
@@ -2025,14 +2028,13 @@ void HTMLTokenizer::executeExternalScriptsIfReady()
return;
bool finished = false;
-
+
double startTime = currentTime();
while (!finished && m_pendingScripts.first()->isLoaded()) {
if (!continueExecutingExternalScripts(startTime))
break;
- CachedScript* cs = m_pendingScripts.first().get();
- m_pendingScripts.removeFirst();
+ CachedScript* cs = m_pendingScripts.takeFirst().get();
ASSERT(cache()->disabled() || cs->accessCount() > 0);
setSrc(SegmentedString());
@@ -2081,7 +2083,7 @@ void HTMLTokenizer::executeExternalScriptsIfReady()
}
}
-void HTMLTokenizer::executeExternalScriptsTimerFired(Timer<HTMLTokenizer>*)
+void HTMLDocumentParser::executeExternalScriptsTimerFired(Timer<HTMLDocumentParser>*)
{
if (m_doc->view() && m_doc->view()->layoutPending() && !m_doc->minimumLayoutDelay()) {
// Restart the timer and do layout first.
@@ -2093,7 +2095,7 @@ void HTMLTokenizer::executeExternalScriptsTimerFired(Timer<HTMLTokenizer>*)
executeExternalScriptsIfReady();
}
-bool HTMLTokenizer::continueExecutingExternalScripts(double startTime)
+bool HTMLDocumentParser::continueExecutingExternalScripts(double startTime)
{
if (m_externalScriptsTimer.isActive())
return false;
@@ -2106,23 +2108,23 @@ bool HTMLTokenizer::continueExecutingExternalScripts(double startTime)
return true;
}
-bool HTMLTokenizer::isWaitingForScripts() const
+bool HTMLDocumentParser::isWaitingForScripts() const
{
return m_state.loadingExtScript();
}
-void HTMLTokenizer::setSrc(const SegmentedString& source)
+void HTMLDocumentParser::setSrc(const SegmentedString& source)
{
m_src = source;
}
void parseHTMLDocumentFragment(const String& source, DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
{
- HTMLTokenizer tok(fragment, scriptingPermission);
- tok.setForceSynchronous(true);
- tok.write(source, true);
- tok.finish();
- ASSERT(!tok.processingData()); // make sure we're done (see 3963151)
+ HTMLDocumentParser parser(fragment, scriptingPermission);
+ parser.setForceSynchronous(true);
+ parser.write(source, true);
+ parser.finish();
+ ASSERT(!parser.processingData()); // make sure we're done (see 3963151)
}
UChar decodeNamedEntity(const char* name)
diff --git a/WebCore/html/HTMLTokenizer.h b/WebCore/html/HTMLDocumentParser.h
index dc03cf2..6072a7e 100644
--- a/WebCore/html/HTMLTokenizer.h
+++ b/WebCore/html/HTMLDocumentParser.h
@@ -30,7 +30,7 @@
#include "NamedNodeMap.h"
#include "SegmentedString.h"
#include "Timer.h"
-#include "Tokenizer.h"
+#include "DocumentParser.h"
#include <wtf/Deque.h>
#include <wtf/OwnPtr.h>
#include <wtf/Vector.h>
@@ -44,7 +44,7 @@ class HTMLDocument;
class HTMLScriptElement;
class HTMLViewSourceDocument;
class FrameView;
-class HTMLParser;
+class LegacyHTMLTreeConstructor;
class Node;
class PreloadScanner;
class ScriptSourceCode;
@@ -109,7 +109,7 @@ enum DoctypeState {
class DoctypeToken {
public:
DoctypeToken() {}
-
+
void reset()
{
m_name.clear();
@@ -117,6 +117,7 @@ public:
m_systemID.clear();
m_state = DoctypeBegin;
m_source.clear();
+ m_forceQuirks = false;
}
DoctypeState state() { return m_state; }
@@ -126,8 +127,10 @@ public:
Vector<UChar> m_publicID;
Vector<UChar> m_systemID;
DoctypeState m_state;
-
+
Vector<UChar> m_source;
+
+ bool m_forceQuirks; // Used by the HTML5 parser.
};
//-----------------------------------------------------------------------------
@@ -137,12 +140,12 @@ public:
// (like dealing with <script> tags). The HTML lexer bits should be pushed
// down into a separate HTML lexer class.
-class HTMLTokenizer : public Tokenizer, public CachedResourceClient {
+class HTMLDocumentParser : public DocumentParser, public CachedResourceClient {
public:
- HTMLTokenizer(HTMLDocument*, bool reportErrors);
- HTMLTokenizer(HTMLViewSourceDocument*);
- HTMLTokenizer(DocumentFragment*, FragmentScriptingPermission = FragmentScriptingAllowed);
- virtual ~HTMLTokenizer();
+ HTMLDocumentParser(HTMLDocument*, bool reportErrors);
+ HTMLDocumentParser(HTMLViewSourceDocument*);
+ HTMLDocumentParser(DocumentFragment*, FragmentScriptingPermission = FragmentScriptingAllowed);
+ virtual ~HTMLDocumentParser();
virtual void write(const SegmentedString&, bool appendData);
virtual void finish();
@@ -157,12 +160,11 @@ public:
virtual int columnNumber() const { return 1; }
bool processingContentWrittenByScript() const { return m_src.excludeLineNumbers(); }
-
+
virtual void executeScriptsWaitingForStylesheets();
-
- virtual bool isHTMLTokenizer() const { return true; }
- virtual HTMLTokenizer* asHTMLTokenizer() { return this; }
- HTMLParser* htmlParser() const { return m_parser.get(); }
+
+ virtual LegacyHTMLTreeConstructor* htmlTreeConstructor() const { return m_treeConstructor.get(); }
+ virtual HTMLDocumentParser* asHTMLDocumentParser() { return this; }
private:
class State;
@@ -192,7 +194,7 @@ private:
State scriptHandler(State);
State scriptExecution(const ScriptSourceCode&, State);
void setSrc(const SegmentedString&);
-
+
// check if we have enough space in the buffer.
// if not enlarge it
inline void checkBuffer(int len = 10)
@@ -211,14 +213,14 @@ private:
void enlargeScriptBuffer(int len);
bool continueProcessing(int& processedCount, double startTime, State&);
- void timerFired(Timer<HTMLTokenizer>*);
+ void timerFired(Timer<HTMLDocumentParser>*);
void allDataProcessed();
// from CachedResourceClient
void notifyFinished(CachedResource*);
void executeExternalScriptsIfReady();
- void executeExternalScriptsTimerFired(Timer<HTMLTokenizer>*);
+ void executeExternalScriptsTimerFired(Timer<HTMLDocumentParser>*);
bool continueExecutingExternalScripts(double startTime);
// Internal buffers
@@ -233,7 +235,7 @@ private:
// the attribute name and the first character of the attribute value.
Vector<UChar, 32> m_rawAttributeBeforeValue;
- // Tokenizer flags
+ // DocumentParser flags
//////////////////
// are we in quotes within a html tag
enum { NoQuote, SingleQuote, DoubleQuote } tquote;
@@ -353,7 +355,7 @@ private:
};
State m_state;
-
+
DoctypeToken m_doctypeToken;
int m_doctypeSearchCount;
int m_doctypeSecondarySearchCount;
@@ -374,13 +376,13 @@ private:
// Stores characters if we are scanning for a string like "</script>"
UChar searchBuffer[10];
-
+
// Counts where we are in the string we are scanning for
int searchCount;
// the stopper string
const char* m_searchStopper;
int m_searchStopperLength;
-
+
// if no more data is coming, just parse what we have (including ext scripts that
// may be still downloading) and finish
bool m_noMoreData;
@@ -415,10 +417,10 @@ private:
int m_tokenizerChunkSize;
// The timer for continued processing.
- Timer<HTMLTokenizer> m_timer;
+ Timer<HTMLDocumentParser> m_timer;
// The timer for continued executing external scripts.
- Timer<HTMLTokenizer> m_externalScriptsTimer;
+ Timer<HTMLDocumentParser> m_externalScriptsTimer;
// This buffer can hold arbitrarily long user-defined attribute names, such as in EMBED tags.
// So any fixed number might be too small, but rather than rewriting all usage of this buffer
@@ -429,7 +431,7 @@ private:
SegmentedString m_src;
Document* m_doc;
- OwnPtr<HTMLParser> m_parser;
+ OwnPtr<LegacyHTMLTreeConstructor> m_treeConstructor;
bool m_inWrite;
bool m_fragment;
FragmentScriptingPermission m_scriptingPermission;
diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp
index d95a236..8f2bead 100644
--- a/WebCore/html/HTMLElement.cpp
+++ b/WebCore/html/HTMLElement.cpp
@@ -39,13 +39,13 @@
#include "HTMLElementFactory.h"
#include "HTMLFormElement.h"
#include "HTMLNames.h"
-#include "HTMLTokenizer.h"
+#include "HTMLDocumentParser.h"
#include "RenderWordBreak.h"
#include "ScriptEventListener.h"
#include "Settings.h"
#include "Text.h"
#include "TextIterator.h"
-#include "XMLTokenizer.h"
+#include "XMLDocumentParser.h"
#include "markup.h"
#include <wtf/StdLibExtras.h>
@@ -144,7 +144,7 @@ bool HTMLElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry
void HTMLElement::parseMappedAttribute(Attribute* attr)
{
- if (attr->name() == idAttributeName() || attr->name() == classAttr || attr->name() == styleAttr)
+ if (isIdAttributeName(attr->name()) || attr->name() == classAttr || attr->name() == styleAttr)
return StyledElement::parseMappedAttribute(attr);
String indexstring;
diff --git a/WebCore/html/HTMLEntityNames.gperf b/WebCore/html/HTMLEntityNames.gperf
index b16b3d8..c665efe 100644
--- a/WebCore/html/HTMLEntityNames.gperf
+++ b/WebCore/html/HTMLEntityNames.gperf
@@ -21,15 +21,22 @@
----------------------------------------------------------------------------
HTMLEntityNames.gperf: input file to generate a hash table for entities
- HTMLEntityNames.c: DO NOT EDIT! generated by the command
- "gperf -a -L "ANSI-C" -C -G -c -o -t -k '*' -NfindEntity -D -s 2 HTMLEntityNames.gperf > entities.c"
- from HTMLEntityNames.gperf
+ HTMLEntityNames.cpp: DO NOT EDIT! generated by WebCore/make-hash-tools.pl
*/
%}
+%struct-type
struct Entity {
const char *name;
int code;
};
+%language=ANSI-C
+%readonly-tables
+%global-table
+%compare-strncmp
+%define lookup-function-name findEntity
+%define hash-function-name entity_hash_function
+%includes
+%enum
%%
AElig, 0x00c6
AMP, 38
diff --git a/WebCore/html/HTMLFormCollection.cpp b/WebCore/html/HTMLFormCollection.cpp
index e140a03..7a2e63a 100644
--- a/WebCore/html/HTMLFormCollection.cpp
+++ b/WebCore/html/HTMLFormCollection.cpp
@@ -111,8 +111,7 @@ Element* HTMLFormCollection::getNamedFormItem(const QualifiedName& attrName, con
bool foundInputElements = false;
for (unsigned i = 0; i < form->m_associatedElements.size(); ++i) {
HTMLFormControlElement* e = form->m_associatedElements[i];
- const QualifiedName& attributeName = (attrName == idAttr) ? e->idAttributeName() : attrName;
- if (e->isEnumeratable() && e->getAttribute(attributeName) == name) {
+ if (e->isEnumeratable() && e->getAttribute(attrName) == name) {
foundInputElements = true;
if (!duplicateNumber)
return e;
@@ -123,8 +122,7 @@ Element* HTMLFormCollection::getNamedFormItem(const QualifiedName& attrName, con
if (!foundInputElements) {
for (unsigned i = 0; i < form->m_imageElements.size(); ++i) {
HTMLImageElement* e = form->m_imageElements[i];
- const QualifiedName& attributeName = (attrName == idAttr) ? e->idAttributeName() : attrName;
- if (e->getAttribute(attributeName) == name) {
+ if (e->getAttribute(attrName) == name) {
if (!duplicateNumber)
return e;
--duplicateNumber;
@@ -176,9 +174,10 @@ Node* HTMLFormCollection::nextNamedItem(const AtomicString& name) const
// checks if we are on the nameAttr half of the iteration and skips over any
// that also have the same idAttributeName.
Element* impl = nextNamedItemInternal(name);
- if (m_idsDone)
- while (impl && impl->getAttribute(impl->idAttributeName()) == name)
+ if (m_idsDone) {
+ while (impl && impl->getIdAttribute() == name)
impl = nextNamedItemInternal(name);
+ }
return impl;
}
@@ -194,7 +193,7 @@ void HTMLFormCollection::updateNameCache() const
for (unsigned i = 0; i < f->m_associatedElements.size(); ++i) {
HTMLFormControlElement* e = f->m_associatedElements[i];
if (e->isEnumeratable()) {
- const AtomicString& idAttrVal = e->getAttribute(e->idAttributeName());
+ const AtomicString& idAttrVal = e->getIdAttribute();
const AtomicString& nameAttrVal = e->getAttribute(nameAttr);
if (!idAttrVal.isEmpty()) {
// add to id cache
@@ -221,7 +220,7 @@ void HTMLFormCollection::updateNameCache() const
for (unsigned i = 0; i < f->m_imageElements.size(); ++i) {
HTMLImageElement* e = f->m_imageElements[i];
- const AtomicString& idAttrVal = e->getAttribute(e->idAttributeName());
+ const AtomicString& idAttrVal = e->getIdAttribute();
const AtomicString& nameAttrVal = e->getAttribute(nameAttr);
if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) {
// add to id cache
diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp
index fa5d957..62474cc 100644
--- a/WebCore/html/HTMLFormControlElement.cpp
+++ b/WebCore/html/HTMLFormControlElement.cpp
@@ -38,8 +38,8 @@
#include "HTMLFormElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
-#include "HTMLTokenizer.h"
+#include "LegacyHTMLTreeConstructor.h"
+#include "HTMLDocumentParser.h"
#include "LabelsNodeList.h"
#include "Page.h"
#include "RenderBox.h"
@@ -178,12 +178,11 @@ void HTMLFormControlElement::removedFromTree(bool deep)
{
// If the form and element are both in the same tree, preserve the connection to the form.
// Otherwise, null out our form and remove ourselves from the form's list of elements.
- HTMLParser* parser = 0;
- if (Tokenizer* tokenizer = document()->tokenizer())
- if (tokenizer->isHTMLTokenizer())
- parser = static_cast<HTMLTokenizer*>(tokenizer)->htmlParser();
-
- if (m_form && !(parser && parser->isHandlingResidualStyleAcrossBlocks()) && findRoot(this) != findRoot(m_form)) {
+ LegacyHTMLTreeConstructor* treeConstructor = 0;
+ if (DocumentParser* parser = document()->parser())
+ treeConstructor = parser->htmlTreeConstructor();
+
+ if (m_form && !(treeConstructor && treeConstructor->isHandlingResidualStyleAcrossBlocks()) && findRoot(this) != findRoot(m_form)) {
m_form->removeFormElement(this);
m_form = 0;
}
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index c19933a..084470c 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -209,7 +209,7 @@ PassRefPtr<FormData> HTMLFormElement::createFormData()
control->appendFormData(*domFormData, m_formDataBuilder.isMultiPartForm());
}
- RefPtr<FormData> result = (m_formDataBuilder.isMultiPartForm()) ? FormData::createMultiPart(*domFormData, document()) : FormData::create(*domFormData);
+ RefPtr<FormData> result = (m_formDataBuilder.isMultiPartForm()) ? FormData::createMultiPart(domFormData->items(), domFormData->encoding(), document()) : FormData::create(domFormData->items(), domFormData->encoding());
result->setIdentifier(generateFormDataIdentifier());
return result;
@@ -234,7 +234,7 @@ static inline HTMLFormControlElement* submitElementFromEvent(const Event* event)
bool HTMLFormElement::validateInteractively(Event* event)
{
ASSERT(event);
- if (noValidate())
+ if (!document()->inStrictMode() || noValidate())
return true;
HTMLFormControlElement* submitElement = submitElementFromEvent(event);
diff --git a/WebCore/html/HTMLFrameElementBase.cpp b/WebCore/html/HTMLFrameElementBase.cpp
index fb05e91..b21bf92 100644
--- a/WebCore/html/HTMLFrameElementBase.cpp
+++ b/WebCore/html/HTMLFrameElementBase.cpp
@@ -113,7 +113,7 @@ void HTMLFrameElementBase::parseMappedAttribute(Attribute* attr)
{
if (attr->name() == srcAttr)
setLocation(deprecatedParseURL(attr->value()));
- else if (attr->name() == idAttributeName()) {
+ else if (isIdAttributeName(attr->name())) {
// Important to call through to base for the id attribute so the hasID bit gets set.
HTMLFrameOwnerElement::parseMappedAttribute(attr);
m_frameName = attr->value();
@@ -154,7 +154,7 @@ void HTMLFrameElementBase::setName()
{
m_frameName = getAttribute(nameAttr);
if (m_frameName.isNull())
- m_frameName = getAttribute(idAttributeName());
+ m_frameName = getIdAttribute();
if (Frame* parentFrame = document()->frame())
m_frameName = parentFrame->tree()->uniqueChildName(m_frameName);
diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp
index 5dd036e..b149c95 100644
--- a/WebCore/html/HTMLImageElement.cpp
+++ b/WebCore/html/HTMLImageElement.cpp
@@ -152,7 +152,7 @@ void HTMLImageElement::parseMappedAttribute(Attribute* attr)
document->addNamedItem(newName);
}
m_name = newName;
- } else if (attr->name() == idAttributeName()) {
+ } else if (isIdAttributeName(attr->name())) {
const AtomicString& newId = attr->value();
if (inDocument() && document()->isHTMLDocument()) {
HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
diff --git a/WebCore/html/HTMLImageElement.idl b/WebCore/html/HTMLImageElement.idl
index 3862539..a5a468e 100644
--- a/WebCore/html/HTMLImageElement.idl
+++ b/WebCore/html/HTMLImageElement.idl
@@ -20,7 +20,9 @@
module html {
- interface HTMLImageElement : HTMLElement {
+ interface [
+ GenerateNativeConverter
+ ] HTMLImageElement : HTMLElement {
attribute [ConvertNullToNullString, Reflect] DOMString name;
attribute [ConvertNullToNullString, Reflect] DOMString align;
attribute [ConvertNullToNullString, Reflect] DOMString alt;
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index 9f91277..9be9bff 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -47,7 +47,7 @@
#include "HTMLImageLoader.h"
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "KeyboardEvent.h"
#include "LocalizedStrings.h"
#include "MouseEvent.h"
@@ -166,6 +166,33 @@ void HTMLInputElement::updateCheckedRadioButtons()
{
if (attached() && checked())
checkedRadioButtons(this).addButton(this);
+
+ if (form()) {
+ const Vector<HTMLFormControlElement*>& controls = form()->associatedElements();
+ for (unsigned i = 0; i < controls.size(); ++i) {
+ HTMLFormControlElement* control = controls[i];
+ if (control->name() != name())
+ continue;
+ if (control->type() != type())
+ continue;
+ control->setNeedsValidityCheck();
+ }
+ } else {
+ // FIXME: Traversing the document is inefficient.
+ for (Node* node = document()->body(); node; node = node->traverseNextNode()) {
+ if (!node->isElementNode())
+ continue;
+ Element* element = static_cast<Element*>(node);
+ if (element->formControlName() != name())
+ continue;
+ if (element->formControlType() != type())
+ continue;
+ HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(element);
+ if (control->form())
+ continue;
+ control->setNeedsValidityCheck();
+ }
+ }
if (renderer() && renderer()->style()->hasAppearance())
renderer()->theme()->stateChanged(renderer(), CheckedState);
@@ -1423,7 +1450,6 @@ void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
m_useDefaultChecked = false;
m_checked = nowChecked;
- setNeedsValidityCheck();
setNeedsStyleRecalc();
updateCheckedRadioButtons();
diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h
index 363a25f..a9a7bb0 100644
--- a/WebCore/html/HTMLInputElement.h
+++ b/WebCore/html/HTMLInputElement.h
@@ -101,6 +101,10 @@ public:
virtual bool isSearchField() const { return m_type == SEARCH; }
virtual bool isInputTypeHidden() const { return m_type == HIDDEN; }
virtual bool isPasswordField() const { return m_type == PASSWORD; }
+ bool isTelephoneField() const { return m_type == TELEPHONE; }
+ bool isNumberField() const { return m_type == NUMBER; }
+ bool isEmailField() const { return m_type == EMAIL; }
+ bool isUrlField() const { return m_type == URL; }
bool checked() const { return m_checked; }
void setChecked(bool, bool sendChangeEvent = false);
diff --git a/WebCore/html/HTMLInputElement.idl b/WebCore/html/HTMLInputElement.idl
index 83b04e7..237d4c3 100644
--- a/WebCore/html/HTMLInputElement.idl
+++ b/WebCore/html/HTMLInputElement.idl
@@ -57,7 +57,9 @@ module html {
attribute [ConvertNullToNullString, JSCCustomGetter] DOMString type; // readonly dropped as part of DOM level 2
attribute [ConvertNullToNullString] DOMString useMap;
attribute [ConvertNullToNullString] DOMString value;
+#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
attribute Date valueAsDate setter raises(DOMException);
+#endif
attribute double valueAsNumber setter raises(DOMException);
#if defined(ENABLE_DATALIST) && ENABLE_DATALIST
readonly attribute HTMLOptionElement selectedOption;
diff --git a/WebCore/html/HTMLMapElement.cpp b/WebCore/html/HTMLMapElement.cpp
index 1395cbb..07fcb5c 100644
--- a/WebCore/html/HTMLMapElement.cpp
+++ b/WebCore/html/HTMLMapElement.cpp
@@ -56,7 +56,6 @@ PassRefPtr<HTMLMapElement> HTMLMapElement::create(const QualifiedName& tagName,
HTMLMapElement::~HTMLMapElement()
{
- document()->removeImageMap(this);
}
bool HTMLMapElement::checkDTD(const Node* newChild)
@@ -104,26 +103,33 @@ HTMLImageElement* HTMLMapElement::imageElement() const
return 0;
}
-
-void HTMLMapElement::parseMappedAttribute(Attribute* attr)
+
+void HTMLMapElement::parseMappedAttribute(Attribute* attribute)
{
- const QualifiedName& attrName = attr->name();
- if (attrName == idAttributeName() || attrName == nameAttr) {
- Document* doc = document();
- if (attrName == idAttributeName()) {
+ // FIXME: This logic seems wrong for XML documents.
+ // Either the id or name will be used depending on the order the attributes are parsed.
+
+ const QualifiedName& attrName = attribute->name();
+ if (isIdAttributeName(attrName) || attrName == nameAttr) {
+ Document* document = this->document();
+ if (isIdAttributeName(attrName)) {
// Call base class so that hasID bit gets set.
- HTMLElement::parseMappedAttribute(attr);
- if (doc->isHTMLDocument())
+ HTMLElement::parseMappedAttribute(attribute);
+ if (document->isHTMLDocument())
return;
}
- doc->removeImageMap(this);
- String mapName = attr->value();
+ if (inDocument())
+ document->removeImageMap(this);
+ String mapName = attribute->value();
if (mapName[0] == '#')
mapName = mapName.substring(1);
- m_name = doc->isHTMLDocument() ? mapName.lower() : mapName;
- doc->addImageMap(this);
- } else
- HTMLElement::parseMappedAttribute(attr);
+ m_name = document->isHTMLDocument() ? mapName.lower() : mapName;
+ if (inDocument())
+ document->addImageMap(this);
+ return;
+ }
+
+ HTMLElement::parseMappedAttribute(attribute);
}
PassRefPtr<HTMLCollection> HTMLMapElement::areas()
@@ -141,4 +147,16 @@ void HTMLMapElement::setName(const String& value)
setAttribute(nameAttr, value);
}
+void HTMLMapElement::insertedIntoDocument()
+{
+ document()->addImageMap(this);
+ HTMLElement::insertedIntoDocument();
+}
+
+void HTMLMapElement::removedFromDocument()
+{
+ document()->removeImageMap(this);
+ HTMLElement::removedFromDocument();
+}
+
}
diff --git a/WebCore/html/HTMLMapElement.h b/WebCore/html/HTMLMapElement.h
index 9c8ab79..483f17b 100644
--- a/WebCore/html/HTMLMapElement.h
+++ b/WebCore/html/HTMLMapElement.h
@@ -56,6 +56,9 @@ private:
virtual void parseMappedAttribute(Attribute*);
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+
AtomicString m_name;
};
diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp
index efef1d2..34679e7 100644
--- a/WebCore/html/HTMLMediaElement.cpp
+++ b/WebCore/html/HTMLMediaElement.cpp
@@ -661,6 +661,9 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content
bool HTMLMediaElement::isSafeToLoadURL(const KURL& url, InvalidSourceAction actionIfInvalid)
{
+ if (!url.isValid())
+ return false;
+
Frame* frame = document()->frame();
FrameLoader* loader = frame ? frame->loader() : 0;
@@ -1488,7 +1491,7 @@ KURL HTMLMediaElement::selectNextSourceChild(ContentType *contentType, InvalidSo
// Is it safe to load this url?
mediaURL = source->src();
- if (!mediaURL.isValid() || !isSafeToLoadURL(mediaURL, actionIfInvalid) || !dispatchBeforeLoadEvent(mediaURL.string()))
+ if (!isSafeToLoadURL(mediaURL, actionIfInvalid) || !dispatchBeforeLoadEvent(mediaURL.string()))
goto check_again;
// Making it this far means the <source> looks reasonable
@@ -1956,7 +1959,7 @@ void HTMLMediaElement::getPluginProxyParams(KURL& url, Vector<String>& names, Ve
}
url = src();
- if (!url.isValid() || !isSafeToLoadURL(url, Complain))
+ if (!isSafeToLoadURL(url, Complain))
url = selectNextSourceChild(0, DoNothing);
m_currentSrc = url.string();
diff --git a/WebCore/html/HTMLMeterElement.cpp b/WebCore/html/HTMLMeterElement.cpp
index a1b74b2..1e8956d 100644
--- a/WebCore/html/HTMLMeterElement.cpp
+++ b/WebCore/html/HTMLMeterElement.cpp
@@ -24,10 +24,11 @@
#include "Attribute.h"
#include "EventNames.h"
+#include "ExceptionCode.h"
#include "FormDataList.h"
#include "HTMLFormElement.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "RenderMeter.h"
#include <wtf/StdLibExtras.h>
@@ -162,5 +163,38 @@ void HTMLMeterElement::setOptimum(double optimum, ExceptionCode& ec)
setAttribute(optimumAttr, String::number(optimum));
}
+HTMLMeterElement::GaugeRegion HTMLMeterElement::gaugeRegion() const
+{
+ double lowValue = low();
+ double highValue = high();
+ double theValue = value();
+ double optimumValue = optimum();
+
+ if (optimumValue <= lowValue) {
+ // The optimum range stays under low
+ if (theValue <= lowValue)
+ return GaugeRegionOptimum;
+ if (theValue <= highValue)
+ return GaugeRegionSuboptimal;
+ return GaugeRegionEvenLessGood;
+ }
+
+ if (highValue <= optimumValue) {
+ // The optimum range stays over high
+ if (highValue <= theValue)
+ return GaugeRegionOptimum;
+ if (lowValue <= theValue)
+ return GaugeRegionSuboptimal;
+ return GaugeRegionEvenLessGood;
+ }
+
+ // The optimum range stays between high and low
+ if (lowValue < highValue && theValue < highValue)
+ return GaugeRegionOptimum;
+ if (theValue == min() || max() == theValue)
+ return GaugeRegionEvenLessGood;
+ return GaugeRegionSuboptimal;
+}
+
} // namespace
#endif
diff --git a/WebCore/html/HTMLMeterElement.h b/WebCore/html/HTMLMeterElement.h
index a218584..cefad97 100644
--- a/WebCore/html/HTMLMeterElement.h
+++ b/WebCore/html/HTMLMeterElement.h
@@ -30,6 +30,12 @@ class HTMLMeterElement : public HTMLFormControlElement {
public:
static PassRefPtr<HTMLMeterElement> create(const QualifiedName&, Document*);
+ enum GaugeRegion {
+ GaugeRegionOptimum,
+ GaugeRegionSuboptimal,
+ GaugeRegionEvenLessGood
+ };
+
double min() const;
void setMin(double, ExceptionCode&);
@@ -48,6 +54,7 @@ public:
double optimum() const;
void setOptimum(double, ExceptionCode&);
+ GaugeRegion gaugeRegion() const;
private:
HTMLMeterElement(const QualifiedName&, Document*);
diff --git a/WebCore/html/HTMLMeterElement.idl b/WebCore/html/HTMLMeterElement.idl
index 2b0e03f..3398688 100644
--- a/WebCore/html/HTMLMeterElement.idl
+++ b/WebCore/html/HTMLMeterElement.idl
@@ -37,3 +37,4 @@ module html {
readonly attribute NodeList labels;
};
}
+
diff --git a/WebCore/html/HTMLNameCollection.cpp b/WebCore/html/HTMLNameCollection.cpp
index eb88c02..4075e4c 100644
--- a/WebCore/html/HTMLNameCollection.cpp
+++ b/WebCore/html/HTMLNameCollection.cpp
@@ -63,7 +63,7 @@ Element* HTMLNameCollection::itemAfter(Element* previous) const
e->hasTagName(objectTag))
if (e->getAttribute(nameAttr) == m_name)
return e;
- if (e->getAttribute(e->idAttributeName()) == m_name)
+ if (e->getIdAttribute() == m_name)
return e;
break;
case DocumentNamedItems:
@@ -74,14 +74,14 @@ Element* HTMLNameCollection::itemAfter(Element* previous) const
if (e->getAttribute(nameAttr) == m_name)
return e;
} else if (e->hasTagName(appletTag)) {
- if (e->getAttribute(nameAttr) == m_name || e->getAttribute(e->idAttributeName()) == m_name)
+ if (e->getAttribute(nameAttr) == m_name || e->getIdAttribute() == m_name)
return e;
} else if (e->hasTagName(objectTag)) {
- if ((e->getAttribute(nameAttr) == m_name || e->getAttribute(e->idAttributeName()) == m_name)
+ if ((e->getAttribute(nameAttr) == m_name || e->getIdAttribute() == m_name)
&& static_cast<HTMLObjectElement*>(e)->isDocNamedItem())
return e;
} else if (e->hasTagName(imgTag)) {
- if (e->getAttribute(nameAttr) == m_name || (e->getAttribute(e->idAttributeName()) == m_name && e->hasAttribute(nameAttr)))
+ if (e->getAttribute(nameAttr) == m_name || (e->getIdAttribute() == m_name && e->hasAttribute(nameAttr)))
return e;
}
break;
diff --git a/WebCore/html/HTMLObjectElement.cpp b/WebCore/html/HTMLObjectElement.cpp
index ea130b9..bd9fc1c 100644
--- a/WebCore/html/HTMLObjectElement.cpp
+++ b/WebCore/html/HTMLObjectElement.cpp
@@ -105,7 +105,7 @@ void HTMLObjectElement::parseMappedAttribute(Attribute* attr)
document->addNamedItem(newName);
}
m_name = newName;
- } else if (attr->name() == idAttributeName()) {
+ } else if (isIdAttributeName(attr->name())) {
const AtomicString& newId = attr->value();
if (isDocNamedItem() && inDocument() && document()->isHTMLDocument()) {
HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
diff --git a/WebCore/html/HTMLParamElement.cpp b/WebCore/html/HTMLParamElement.cpp
index ca28383..a637d5b 100644
--- a/WebCore/html/HTMLParamElement.cpp
+++ b/WebCore/html/HTMLParamElement.cpp
@@ -44,7 +44,7 @@ PassRefPtr<HTMLParamElement> HTMLParamElement::create(const QualifiedName& tagNa
void HTMLParamElement::parseMappedAttribute(Attribute* attr)
{
- if (attr->name() == idAttributeName()) {
+ if (isIdAttributeName(attr->name())) {
// Must call base class so that hasID bit gets set.
HTMLElement::parseMappedAttribute(attr);
if (document()->isHTMLDocument())
diff --git a/WebCore/html/HTMLProgressElement.cpp b/WebCore/html/HTMLProgressElement.cpp
index d275ebf..22226d9 100644
--- a/WebCore/html/HTMLProgressElement.cpp
+++ b/WebCore/html/HTMLProgressElement.cpp
@@ -24,10 +24,11 @@
#include "Attribute.h"
#include "EventNames.h"
+#include "ExceptionCode.h"
#include "FormDataList.h"
#include "HTMLFormElement.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "RenderProgress.h"
#include <wtf/StdLibExtras.h>
diff --git a/WebCore/html/HTMLVideoElement.idl b/WebCore/html/HTMLVideoElement.idl
index 1b21c54..953e447 100644
--- a/WebCore/html/HTMLVideoElement.idl
+++ b/WebCore/html/HTMLVideoElement.idl
@@ -24,7 +24,10 @@
*/
module html {
- interface [Conditional=VIDEO] HTMLVideoElement : HTMLMediaElement {
+ interface [
+ Conditional=VIDEO,
+ GenerateNativeConverter
+ ] HTMLVideoElement : HTMLMediaElement {
attribute unsigned long width;
attribute unsigned long height;
readonly attribute unsigned long videoWidth;
diff --git a/WebCore/html/HTMLViewSourceDocument.cpp b/WebCore/html/HTMLViewSourceDocument.cpp
index 196c67e..5391ddc 100644
--- a/WebCore/html/HTMLViewSourceDocument.cpp
+++ b/WebCore/html/HTMLViewSourceDocument.cpp
@@ -36,7 +36,7 @@
#include "HTMLTableElement.h"
#include "HTMLTableRowElement.h"
#include "HTMLTableSectionElement.h"
-#include "HTMLTokenizer.h"
+#include "HTMLDocumentParser.h"
#include "Text.h"
#include "TextDocument.h"
@@ -51,19 +51,19 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(Frame* frame, const String& mimeT
setUsesBeforeAfterRules(true);
}
-Tokenizer* HTMLViewSourceDocument::createTokenizer()
+DocumentParser* HTMLViewSourceDocument::createParser()
{
- // Use HTMLTokenizer if applicable, otherwise use TextTokenizer.
+ // Use HTMLDocumentParser if applicable, otherwise use TextDocumentParser.
if (m_type == "text/html" || m_type == "application/xhtml+xml" || m_type == "image/svg+xml" || DOMImplementation::isXMLMIMEType(m_type)
#if ENABLE(XHTMLMP)
|| m_type == "application/vnd.wap.xhtml+xml"
#endif
) {
// FIXME: Should respect Settings::html5ParserEnabled()
- return new HTMLTokenizer(this);
+ return new HTMLDocumentParser(this);
}
- return createTextTokenizer(this);
+ return createTextDocumentParser(this);
}
void HTMLViewSourceDocument::createContainingTable()
@@ -157,7 +157,7 @@ void HTMLViewSourceDocument::addViewSourceToken(Token* token)
} else {
const String& value = attr->value().string();
- // Compare ignoring case since HTMLTokenizer doesn't
+ // Compare ignoring case since HTMLDocumentParser doesn't
// lower names when passing in tokens to
// HTMLViewSourceDocument.
if (equalIgnoringCase(token->tagName, "base") && equalIgnoringCase(attr->name().localName(), "href")) {
@@ -244,7 +244,7 @@ void HTMLViewSourceDocument::addLine(const String& className)
m_current = m_td = td;
#ifdef DEBUG_LINE_NUMBERS
- RefPtr<Text> lineNumberText = Text::create(this, String::number(tokenizer()->lineNumber() + 1) + " ");
+ RefPtr<Text> lineNumberText = Text::create(this, String::number(parser()->lineNumber() + 1) + " ");
td->addChild(lineNumberText);
lineNumberText->attach();
#endif
diff --git a/WebCore/html/HTMLViewSourceDocument.h b/WebCore/html/HTMLViewSourceDocument.h
index e4eadb0..7de7f31 100644
--- a/WebCore/html/HTMLViewSourceDocument.h
+++ b/WebCore/html/HTMLViewSourceDocument.h
@@ -42,15 +42,15 @@ public:
return adoptRef(new HTMLViewSourceDocument(frame, mimeType));
}
- void addViewSourceToken(Token*); // Used by the HTML tokenizer.
- void addViewSourceText(const String&); // Used by the plaintext tokenizer.
+ void addViewSourceToken(Token*); // Used by the HTMLDocumentParser.
+ void addViewSourceText(const String&); // Used by the TextDocumentParser.
void addViewSourceDoctypeToken(DoctypeToken*);
private:
HTMLViewSourceDocument(Frame*, const String& mimeType);
- // Returns HTMLTokenizer or TextTokenizer based on m_type.
- virtual Tokenizer* createTokenizer();
+ // Returns HTMLDocumentParser or TextDocumentParser based on m_type.
+ virtual DocumentParser* createParser();
void createContainingTable();
PassRefPtr<Element> addSpanWithClassName(const String&);
diff --git a/WebCore/html/ImageResizerThread.cpp b/WebCore/html/ImageResizerThread.cpp
new file mode 100644
index 0000000..1bae6a0
--- /dev/null
+++ b/WebCore/html/ImageResizerThread.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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"
+#if ENABLE(IMAGE_RESIZER)
+
+#include "ImageResizerThread.h"
+
+#include "BitmapImage.h"
+#include "Image.h"
+#include "SharedBuffer.h"
+#include <utility>
+
+namespace WebCore {
+
+static void returnBlobOrError(void* callbackInformation)
+{
+ AsyncImageResizer::CallbackInfo* callbackInfo = static_cast<AsyncImageResizer::CallbackInfo*>(callbackInformation);
+ if (!callbackInfo->blob)
+ callbackInfo->asyncImageResizer->resizeError();
+ else
+ callbackInfo->asyncImageResizer->resizeComplete(callbackInfo->blob);
+ delete callbackInfo;
+}
+
+bool ImageResizerThread::start(PassRefPtr<SharedBuffer> imageData, AsyncImageResizer::CallbackInfo* callbackInfo, AsyncImageResizer::OutputType outputType, IntSize desiredBounds, float quality, AsyncImageResizer::AspectRatioOption aspectRatioOption, AsyncImageResizer::OrientationOption orientationOption)
+{
+ ImageResizerThread* imageResizerThread = new ImageResizerThread(callbackInfo, outputType, desiredBounds, quality, aspectRatioOption, orientationOption);
+
+ RefPtr<SharedBuffer> copiedImageData = imageData->copy();
+ imageResizerThread->m_image = BitmapImage::create();
+ imageResizerThread->m_image->setData(copiedImageData, true);
+
+ imageResizerThread->m_threadID = createThread(ImageResizerThread::imageResizerThreadStart, imageResizerThread, "ImageResizerThread");
+ return imageResizerThread->m_threadID;
+}
+
+ImageResizerThread::ImageResizerThread(AsyncImageResizer::CallbackInfo* callbackInfo, AsyncImageResizer::OutputType outputType, IntSize desiredBounds, float quality, AsyncImageResizer::AspectRatioOption aspectRatioOption, AsyncImageResizer::OrientationOption orientationOption)
+ : m_threadID(0)
+ , m_callbackInfo(callbackInfo)
+ , m_outputType(outputType)
+ , m_desiredBounds(desiredBounds)
+ , m_quality(quality)
+ , m_aspectRatioOption(aspectRatioOption)
+ , m_orientationOption(orientationOption)
+{
+}
+
+ImageResizerThread::~ImageResizerThread()
+{
+}
+
+void* ImageResizerThread::imageResizerThreadStart(void* thread)
+{
+ return static_cast<ImageResizerThread*>(thread)->imageResizerThread();
+}
+
+void* ImageResizerThread::imageResizerThread()
+{
+ // FIXME: Do resizing, create blob, and catch any errors.
+
+ callOnMainThread(returnBlobOrError, static_cast<void*>(m_callbackInfo));
+ detachThread(m_threadID);
+ delete this;
+ return 0;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(IMAGE_RESIZER)
diff --git a/WebCore/html/ImageResizerThread.h b/WebCore/html/ImageResizerThread.h
new file mode 100644
index 0000000..ae5ade5
--- /dev/null
+++ b/WebCore/html/ImageResizerThread.h
@@ -0,0 +1,70 @@
+/*
+ * 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 ImageResizerThread_h
+#define ImageResizerThread_h
+
+#if ENABLE(IMAGE_RESIZER)
+
+#include "AsyncImageResizer.h"
+
+namespace WebCore {
+
+class BitmapImage;
+class SharedBuffer;
+
+class ImageResizerThread {
+public:
+ static bool start(PassRefPtr<SharedBuffer> imageData, AsyncImageResizer::CallbackInfo*, AsyncImageResizer::OutputType, IntSize desiredBounds, float quality, AsyncImageResizer::AspectRatioOption, AsyncImageResizer::OrientationOption);
+ ~ImageResizerThread();
+
+private:
+ ImageResizerThread(AsyncImageResizer::CallbackInfo*, AsyncImageResizer::OutputType, IntSize desiredBounds, float quality, AsyncImageResizer::AspectRatioOption, AsyncImageResizer::OrientationOption);
+ static void* imageResizerThreadStart(void*);
+ void* imageResizerThread();
+
+ // Threading attributes.
+ ThreadIdentifier m_threadID;
+
+ // Image attributes.
+ AsyncImageResizer::CallbackInfo* m_callbackInfo;
+ RefPtr<BitmapImage> m_image;
+ AsyncImageResizer::OutputType m_outputType;
+ IntSize m_desiredBounds;
+ float m_quality;
+ AsyncImageResizer::AspectRatioOption m_aspectRatioOption;
+ AsyncImageResizer::OrientationOption m_orientationOption;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(IMAGE_RESIZER)
+
+#endif // ImageResizerThread_h
diff --git a/WebCore/html/HTMLParser.cpp b/WebCore/html/LegacyHTMLTreeConstructor.cpp
index dd822cf..1db0bb6 100644
--- a/WebCore/html/HTMLParser.cpp
+++ b/WebCore/html/LegacyHTMLTreeConstructor.cpp
@@ -23,7 +23,7 @@
*/
#include "config.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "CharacterNames.h"
#include "CSSPropertyNames.h"
@@ -52,10 +52,9 @@
#include "HTMLTableCellElement.h"
#include "HTMLTableRowElement.h"
#include "HTMLTableSectionElement.h"
-#include "HTMLTokenizer.h"
+#include "HTMLDocumentParser.h"
#include "LocalizedStrings.h"
#include "Page.h"
-#include "QualifiedName.h"
#include "Settings.h"
#include "Text.h"
#include "TreeDepthLimit.h"
@@ -141,7 +140,7 @@ struct HTMLStackElem : Noncopyable {
*
*/
-HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors)
+LegacyHTMLTreeConstructor::LegacyHTMLTreeConstructor(HTMLDocument* doc, bool reportErrors)
: m_document(doc)
, m_current(doc)
, m_didRefCurrent(false)
@@ -161,7 +160,7 @@ HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors)
{
}
-HTMLParser::HTMLParser(DocumentFragment* frag, FragmentScriptingPermission scriptingPermission)
+LegacyHTMLTreeConstructor::LegacyHTMLTreeConstructor(DocumentFragment* frag, FragmentScriptingPermission scriptingPermission)
: m_document(frag->document())
, m_current(frag)
, m_didRefCurrent(true)
@@ -183,14 +182,14 @@ HTMLParser::HTMLParser(DocumentFragment* frag, FragmentScriptingPermission scrip
frag->ref();
}
-HTMLParser::~HTMLParser()
+LegacyHTMLTreeConstructor::~LegacyHTMLTreeConstructor()
{
freeBlock();
if (m_didRefCurrent)
m_current->deref();
}
-void HTMLParser::reset()
+void LegacyHTMLTreeConstructor::reset()
{
ASSERT(!m_isParsingFragment);
@@ -215,7 +214,7 @@ void HTMLParser::reset()
m_parserQuirks->reset();
}
-void HTMLParser::setCurrent(Node* newCurrent)
+void LegacyHTMLTreeConstructor::setCurrent(Node* newCurrent)
{
bool didRefNewCurrent = newCurrent && newCurrent != m_document;
if (didRefNewCurrent)
@@ -231,7 +230,7 @@ inline static int tagPriorityOfNode(Node* n)
return n->isHTMLElement() ? static_cast<HTMLElement*>(n)->tagPriority() : 0;
}
-inline void HTMLParser::limitDepth(int tagPriority)
+inline void LegacyHTMLTreeConstructor::limitDepth(int tagPriority)
{
while (m_treeDepth >= maxDOMTreeDepth)
popBlock(m_blockStack->tagName);
@@ -241,13 +240,13 @@ inline void HTMLParser::limitDepth(int tagPriority)
}
}
-inline bool HTMLParser::insertNodeAfterLimitDepth(Node* n, bool flat)
+inline bool LegacyHTMLTreeConstructor::insertNodeAfterLimitDepth(Node* n, bool flat)
{
limitDepth(tagPriorityOfNode(n));
return insertNode(n, flat);
}
-PassRefPtr<Node> HTMLParser::parseToken(Token* t)
+PassRefPtr<Node> LegacyHTMLTreeConstructor::parseToken(Token* t)
{
if (!m_skipModeTag.isNull()) {
if (!t->beginTag && t->tagName == m_skipModeTag)
@@ -338,14 +337,16 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t)
return n;
}
-void HTMLParser::parseDoctypeToken(DoctypeToken* t)
+void LegacyHTMLTreeConstructor::parseDoctypeToken(DoctypeToken* t)
{
// Ignore any doctype after the first. Ignore doctypes in fragments.
if (m_document->doctype() || m_isParsingFragment || m_current != m_document)
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)));
+ if (t->m_forceQuirks)
+ m_document->setParseMode(Document::Compat);
}
static bool isTableSection(const Node* n)
@@ -371,7 +372,7 @@ static bool isScopingTag(const AtomicString& tagName)
|| tagName == objectTag || tagName == tableTag || tagName == htmlTag;
}
-bool HTMLParser::insertNode(Node* n, bool flat)
+bool LegacyHTMLTreeConstructor::insertNode(Node* n, bool flat)
{
RefPtr<Node> protectNode(n);
@@ -428,7 +429,7 @@ bool HTMLParser::insertNode(Node* n, bool flat)
return true;
}
-bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, int tagPriority)
+bool LegacyHTMLTreeConstructor::handleError(Node* n, bool flat, const AtomicString& localName, int tagPriority)
{
// Error handling code. This is just ad hoc handling of specific parent/child combinations.
bool handled = false;
@@ -723,22 +724,22 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
return insertNode(n);
}
-typedef bool (HTMLParser::*CreateErrorCheckFunc)(Token* t, RefPtr<Node>&);
+typedef bool (LegacyHTMLTreeConstructor::*CreateErrorCheckFunc)(Token* t, RefPtr<Node>&);
typedef HashMap<AtomicStringImpl*, CreateErrorCheckFunc> FunctionMap;
-bool HTMLParser::textCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::textCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
result = Text::create(m_document, t->text.get());
return false;
}
-bool HTMLParser::commentCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::commentCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
result = Comment::create(m_document, t->text.get());
return false;
}
-bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::headCreateErrorCheck(Token*, RefPtr<Node>& result)
{
if (!m_head || m_current->localName() == htmlTag) {
m_head = HTMLHeadElement::create(m_document);
@@ -748,7 +749,7 @@ bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result)
return false;
}
-bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::bodyCreateErrorCheck(Token*, RefPtr<Node>&)
{
// body no longer allowed if we have a frameset
if (m_haveFrameSet)
@@ -764,7 +765,7 @@ bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&)
return true;
}
-bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::framesetCreateErrorCheck(Token*, RefPtr<Node>&)
{
popBlock(headTag);
if (m_inBody && !m_haveFrameSet && !m_haveContent) {
@@ -784,7 +785,7 @@ bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&)
return true;
}
-bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
// Only create a new form if we're not already inside one.
// This is consistent with other browsers' behavior.
@@ -796,7 +797,7 @@ bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
return false;
}
-bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
RefPtr<Node> n = handleIsindex(t);
if (!m_inBody)
@@ -808,12 +809,12 @@ bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result)
return false;
}
-bool HTMLParser::selectCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::selectCreateErrorCheck(Token*, RefPtr<Node>&)
{
return true;
}
-bool HTMLParser::ddCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::ddCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
pCloserCreateErrorCheck(t, result);
popBlock(dtTag);
@@ -821,7 +822,7 @@ bool HTMLParser::ddCreateErrorCheck(Token* t, RefPtr<Node>& result)
return true;
}
-bool HTMLParser::dtCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::dtCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
pCloserCreateErrorCheck(t, result);
popBlock(ddTag);
@@ -829,46 +830,46 @@ bool HTMLParser::dtCreateErrorCheck(Token* t, RefPtr<Node>& result)
return true;
}
-bool HTMLParser::rpCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::rpCreateErrorCheck(Token*, RefPtr<Node>&)
{
popBlock(rpTag);
popBlock(rtTag);
return true;
}
-bool HTMLParser::rtCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::rtCreateErrorCheck(Token*, RefPtr<Node>&)
{
popBlock(rpTag);
popBlock(rtTag);
return true;
}
-bool HTMLParser::nestedCreateErrorCheck(Token* t, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::nestedCreateErrorCheck(Token* t, RefPtr<Node>&)
{
popBlock(t->tagName);
return true;
}
-bool HTMLParser::nestedPCloserCreateErrorCheck(Token* t, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::nestedPCloserCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
pCloserCreateErrorCheck(t, result);
popBlock(t->tagName);
return true;
}
-bool HTMLParser::nestedStyleCreateErrorCheck(Token* t, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::nestedStyleCreateErrorCheck(Token* t, RefPtr<Node>&)
{
return allowNestedRedundantTag(t->tagName);
}
-bool HTMLParser::tableCellCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::tableCellCreateErrorCheck(Token*, RefPtr<Node>&)
{
popBlock(tdTag);
popBlock(thTag);
return true;
}
-bool HTMLParser::tableSectionCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::tableSectionCreateErrorCheck(Token*, RefPtr<Node>&)
{
popBlock(theadTag);
popBlock(tbodyTag);
@@ -876,19 +877,19 @@ bool HTMLParser::tableSectionCreateErrorCheck(Token*, RefPtr<Node>&)
return true;
}
-bool HTMLParser::noembedCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::noembedCreateErrorCheck(Token*, RefPtr<Node>&)
{
setSkipMode(noembedTag);
return true;
}
-bool HTMLParser::noframesCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::noframesCreateErrorCheck(Token*, RefPtr<Node>&)
{
setSkipMode(noframesTag);
return true;
}
-bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::noscriptCreateErrorCheck(Token*, RefPtr<Node>&)
{
if (!m_isParsingFragment) {
Frame* frame = m_document->frame();
@@ -898,14 +899,14 @@ bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&)
return true;
}
-bool HTMLParser::pCloserCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::pCloserCreateErrorCheck(Token*, RefPtr<Node>&)
{
if (hasPElementInScope())
popBlock(pTag);
return true;
}
-bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&)
+bool LegacyHTMLTreeConstructor::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&)
{
if (m_document->inCompatMode())
return true;
@@ -914,7 +915,7 @@ bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&)
return true;
}
-bool HTMLParser::mapCreateErrorCheck(Token*, RefPtr<Node>& result)
+bool LegacyHTMLTreeConstructor::mapCreateErrorCheck(Token*, RefPtr<Node>& result)
{
m_currentMapElement = HTMLMapElement::create(m_document);
result = m_currentMapElement;
@@ -935,48 +936,48 @@ static void mapTagsToFunc(FunctionMap& map, QualifiedName (&names)[ArraySize], C
}
}
-PassRefPtr<Node> HTMLParser::getNode(Token* t)
+PassRefPtr<Node> LegacyHTMLTreeConstructor::getNode(Token* t)
{
// Init our error handling table.
DEFINE_STATIC_LOCAL(FunctionMap, gFunctionMap, ());
if (gFunctionMap.isEmpty()) {
QualifiedName nestedCreateErrorTags[] = { aTag, buttonTag, nobrTag, trTag };
- mapTagsToFunc(gFunctionMap, nestedCreateErrorTags, &HTMLParser::nestedCreateErrorCheck);
+ mapTagsToFunc(gFunctionMap, nestedCreateErrorTags, &LegacyHTMLTreeConstructor::nestedCreateErrorCheck);
QualifiedName nestedStyleCreateErrorTags[] = { bTag, bigTag, iTag, sTag, smallTag, strikeTag, ttTag, uTag };
- mapTagsToFunc(gFunctionMap, nestedStyleCreateErrorTags, &HTMLParser::nestedStyleCreateErrorCheck);
+ mapTagsToFunc(gFunctionMap, nestedStyleCreateErrorTags, &LegacyHTMLTreeConstructor::nestedStyleCreateErrorCheck);
QualifiedName pCloserCreateErrorTags[] = { addressTag, articleTag,
asideTag, blockquoteTag, centerTag, dirTag, divTag, dlTag,
fieldsetTag, footerTag, h1Tag, h2Tag, h3Tag, h4Tag, h5Tag, h6Tag,
headerTag, hgroupTag, hrTag, listingTag, menuTag, navTag, olTag,
pTag, plaintextTag, preTag, sectionTag, ulTag };
- mapTagsToFunc(gFunctionMap, pCloserCreateErrorTags, &HTMLParser::pCloserCreateErrorCheck);
-
- mapTagToFunc(gFunctionMap, bodyTag, &HTMLParser::bodyCreateErrorCheck);
- mapTagToFunc(gFunctionMap, ddTag, &HTMLParser::ddCreateErrorCheck);
- mapTagToFunc(gFunctionMap, dtTag, &HTMLParser::dtCreateErrorCheck);
- mapTagToFunc(gFunctionMap, formTag, &HTMLParser::formCreateErrorCheck);
- mapTagToFunc(gFunctionMap, framesetTag, &HTMLParser::framesetCreateErrorCheck);
- mapTagToFunc(gFunctionMap, headTag, &HTMLParser::headCreateErrorCheck);
- mapTagToFunc(gFunctionMap, isindexTag, &HTMLParser::isindexCreateErrorCheck);
- mapTagToFunc(gFunctionMap, mapTag, &HTMLParser::mapCreateErrorCheck);
- mapTagToFunc(gFunctionMap, liTag, &HTMLParser::nestedPCloserCreateErrorCheck);
- mapTagToFunc(gFunctionMap, noembedTag, &HTMLParser::noembedCreateErrorCheck);
- mapTagToFunc(gFunctionMap, noframesTag, &HTMLParser::noframesCreateErrorCheck);
- mapTagToFunc(gFunctionMap, noscriptTag, &HTMLParser::noscriptCreateErrorCheck);
- mapTagToFunc(gFunctionMap, tableTag, &HTMLParser::pCloserStrictCreateErrorCheck);
- mapTagToFunc(gFunctionMap, rpTag, &HTMLParser::rpCreateErrorCheck);
- mapTagToFunc(gFunctionMap, rtTag, &HTMLParser::rtCreateErrorCheck);
- mapTagToFunc(gFunctionMap, selectTag, &HTMLParser::selectCreateErrorCheck);
- mapTagToFunc(gFunctionMap, tdTag, &HTMLParser::tableCellCreateErrorCheck);
- mapTagToFunc(gFunctionMap, thTag, &HTMLParser::tableCellCreateErrorCheck);
- mapTagToFunc(gFunctionMap, tbodyTag, &HTMLParser::tableSectionCreateErrorCheck);
- mapTagToFunc(gFunctionMap, tfootTag, &HTMLParser::tableSectionCreateErrorCheck);
- mapTagToFunc(gFunctionMap, theadTag, &HTMLParser::tableSectionCreateErrorCheck);
-
- gFunctionMap.set(commentAtom.impl(), &HTMLParser::commentCreateErrorCheck);
- gFunctionMap.set(textAtom.impl(), &HTMLParser::textCreateErrorCheck);
+ mapTagsToFunc(gFunctionMap, pCloserCreateErrorTags, &LegacyHTMLTreeConstructor::pCloserCreateErrorCheck);
+
+ mapTagToFunc(gFunctionMap, bodyTag, &LegacyHTMLTreeConstructor::bodyCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, ddTag, &LegacyHTMLTreeConstructor::ddCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, dtTag, &LegacyHTMLTreeConstructor::dtCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, formTag, &LegacyHTMLTreeConstructor::formCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, framesetTag, &LegacyHTMLTreeConstructor::framesetCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, headTag, &LegacyHTMLTreeConstructor::headCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, isindexTag, &LegacyHTMLTreeConstructor::isindexCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, mapTag, &LegacyHTMLTreeConstructor::mapCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, liTag, &LegacyHTMLTreeConstructor::nestedPCloserCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, noembedTag, &LegacyHTMLTreeConstructor::noembedCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, noframesTag, &LegacyHTMLTreeConstructor::noframesCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, noscriptTag, &LegacyHTMLTreeConstructor::noscriptCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, tableTag, &LegacyHTMLTreeConstructor::pCloserStrictCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, rpTag, &LegacyHTMLTreeConstructor::rpCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, rtTag, &LegacyHTMLTreeConstructor::rtCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, selectTag, &LegacyHTMLTreeConstructor::selectCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, tdTag, &LegacyHTMLTreeConstructor::tableCellCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, thTag, &LegacyHTMLTreeConstructor::tableCellCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, tbodyTag, &LegacyHTMLTreeConstructor::tableSectionCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, tfootTag, &LegacyHTMLTreeConstructor::tableSectionCreateErrorCheck);
+ mapTagToFunc(gFunctionMap, theadTag, &LegacyHTMLTreeConstructor::tableSectionCreateErrorCheck);
+
+ gFunctionMap.set(commentAtom.impl(), &LegacyHTMLTreeConstructor::commentCreateErrorCheck);
+ gFunctionMap.set(textAtom.impl(), &LegacyHTMLTreeConstructor::textCreateErrorCheck);
}
bool proceed = true;
@@ -988,7 +989,7 @@ PassRefPtr<Node> HTMLParser::getNode(Token* t)
return result.release();
}
-bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName)
+bool LegacyHTMLTreeConstructor::allowNestedRedundantTag(const AtomicString& tagName)
{
// www.liceo.edu.mx is an example of a site that achieves a level of nesting of
// about 1500 tags, all from a bunch of <b>s. We will only allow at most 20
@@ -1000,7 +1001,7 @@ bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName)
return i != cMaxRedundantTagDepth;
}
-void HTMLParser::processCloseTag(Token* t)
+void LegacyHTMLTreeConstructor::processCloseTag(Token* t)
{
// Support for really broken html.
// we never close the body tag, since some stupid web pages close it before the actual end of the doc.
@@ -1030,7 +1031,7 @@ void HTMLParser::processCloseTag(Token* t)
}
}
-bool HTMLParser::isHeadingTag(const AtomicString& tagName)
+bool LegacyHTMLTreeConstructor::isHeadingTag(const AtomicString& tagName)
{
DEFINE_STATIC_LOCAL(TagNameSet, headingTags, ());
if (headingTags.isEmpty()) {
@@ -1040,7 +1041,7 @@ bool HTMLParser::isHeadingTag(const AtomicString& tagName)
return headingTags.contains(tagName.impl());
}
-bool HTMLParser::isInline(Node* node) const
+bool LegacyHTMLTreeConstructor::isInline(Node* node) const
{
if (node->isTextNode())
return true;
@@ -1070,7 +1071,7 @@ bool HTMLParser::isInline(Node* node) const
return false;
}
-bool HTMLParser::isResidualStyleTag(const AtomicString& tagName)
+bool LegacyHTMLTreeConstructor::isResidualStyleTag(const AtomicString& tagName)
{
DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, residualStyleTags, ());
if (residualStyleTags.isEmpty()) {
@@ -1082,7 +1083,7 @@ bool HTMLParser::isResidualStyleTag(const AtomicString& tagName)
return residualStyleTags.contains(tagName.impl());
}
-bool HTMLParser::isAffectedByResidualStyle(const AtomicString& tagName)
+bool LegacyHTMLTreeConstructor::isAffectedByResidualStyle(const AtomicString& tagName)
{
DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, unaffectedTags, ());
if (unaffectedTags.isEmpty()) {
@@ -1094,7 +1095,7 @@ bool HTMLParser::isAffectedByResidualStyle(const AtomicString& tagName)
return !unaffectedTags.contains(tagName.impl());
}
-void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
+void LegacyHTMLTreeConstructor::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
{
HTMLStackElem* maxElem = 0;
bool finished = false;
@@ -1325,7 +1326,7 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
m_handlingResidualStyleAcrossBlocks = false;
}
-void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTableParent)
+void LegacyHTMLTreeConstructor::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTableParent)
{
// Loop for each tag that needs to be reopened.
while (elem) {
@@ -1366,7 +1367,7 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
}
}
-void HTMLParser::pushBlock(const AtomicString& tagName, int level)
+void LegacyHTMLTreeConstructor::pushBlock(const AtomicString& tagName, int level)
{
m_blockStack = new HTMLStackElem(tagName, level, m_current, m_didRefCurrent, m_blockStack);
if (level >= minBlockLevelTagPriority)
@@ -1379,7 +1380,7 @@ void HTMLParser::pushBlock(const AtomicString& tagName, int level)
m_hasPElementInScope = NotInScope;
}
-void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
+void LegacyHTMLTreeConstructor::popBlock(const AtomicString& tagName, bool reportErrors)
{
HTMLStackElem* elem = m_blockStack;
@@ -1468,7 +1469,7 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
reopenResidualStyleTags(residualStyleStack, malformedTableParent);
}
-inline HTMLStackElem* HTMLParser::popOneBlockCommon()
+inline HTMLStackElem* LegacyHTMLTreeConstructor::popOneBlockCommon()
{
HTMLStackElem* elem = m_blockStack;
@@ -1497,7 +1498,7 @@ inline HTMLStackElem* HTMLParser::popOneBlockCommon()
return elem;
}
-void HTMLParser::popOneBlock()
+void LegacyHTMLTreeConstructor::popOneBlock()
{
// Store the current node before popOneBlockCommon overwrites it.
Node* lastCurrent = m_current;
@@ -1509,7 +1510,7 @@ void HTMLParser::popOneBlock()
lastCurrent->deref();
}
-void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head)
+void LegacyHTMLTreeConstructor::moveOneBlockToStack(HTMLStackElem*& head)
{
// We'll be using the stack element we're popping, but for the current node.
// See the two callers for details.
@@ -1531,7 +1532,7 @@ void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head)
head = elem;
}
-void HTMLParser::checkIfHasPElementInScope()
+void LegacyHTMLTreeConstructor::checkIfHasPElementInScope()
{
m_hasPElementInScope = NotInScope;
HTMLStackElem* elem = m_blockStack;
@@ -1546,13 +1547,13 @@ void HTMLParser::checkIfHasPElementInScope()
}
}
-void HTMLParser::popInlineBlocks()
+void LegacyHTMLTreeConstructor::popInlineBlocks()
{
while (m_blockStack && isInline(m_current))
popOneBlock();
}
-void HTMLParser::freeBlock()
+void LegacyHTMLTreeConstructor::freeBlock()
{
while (m_blockStack)
popOneBlock();
@@ -1560,7 +1561,7 @@ void HTMLParser::freeBlock()
ASSERT(!m_treeDepth);
}
-void HTMLParser::createHead()
+void LegacyHTMLTreeConstructor::createHead()
{
if (m_head)
return;
@@ -1588,7 +1589,7 @@ void HTMLParser::createHead()
}
}
-PassRefPtr<Node> HTMLParser::handleIsindex(Token* t)
+PassRefPtr<Node> LegacyHTMLTreeConstructor::handleIsindex(Token* t)
{
RefPtr<Node> n = HTMLDivElement::create(m_document);
@@ -1613,7 +1614,7 @@ PassRefPtr<Node> HTMLParser::handleIsindex(Token* t)
return n.release();
}
-void HTMLParser::startBody()
+void LegacyHTMLTreeConstructor::startBody()
{
if (m_inBody)
return;
@@ -1626,7 +1627,7 @@ void HTMLParser::startBody()
}
}
-void HTMLParser::finished()
+void LegacyHTMLTreeConstructor::finished()
{
// In the case of a completely empty document, here's the place to create the HTML element.
if (m_current && m_current->isDocumentNode() && !m_document->documentElement())
@@ -1636,18 +1637,18 @@ void HTMLParser::finished()
freeBlock();
setCurrent(0);
- // Warning, this may delete the tokenizer and parser, so don't try to do anything else after this.
+ // Warning, this may delete the parser, so don't try to do anything else after this.
if (!m_isParsingFragment)
m_document->finishedParsing();
}
-void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const AtomicString* tagName1, const AtomicString* tagName2, bool closeTags)
+void LegacyHTMLTreeConstructor::reportErrorToConsole(HTMLParserErrorCode errorCode, const AtomicString* tagName1, const AtomicString* tagName2, bool closeTags)
{
Frame* frame = m_document->frame();
if (!frame)
return;
- HTMLTokenizer* htmlTokenizer = static_cast<HTMLTokenizer*>(m_document->tokenizer());
+ HTMLDocumentParser* htmlTokenizer = static_cast<HTMLDocumentParser*>(m_document->parser());
int lineNumber = htmlTokenizer->lineNumber() + 1;
AtomicString tag1;
diff --git a/WebCore/html/HTMLParser.h b/WebCore/html/LegacyHTMLTreeConstructor.h
index 028836c..ab1f5aa 100644
--- a/WebCore/html/HTMLParser.h
+++ b/WebCore/html/LegacyHTMLTreeConstructor.h
@@ -24,12 +24,12 @@
#ifndef HTMLParser_h
#define HTMLParser_h
+#include "HTMLParserErrorCodes.h"
+#include "MappedAttributeEntry.h"
#include "QualifiedName.h"
#include <wtf/Forward.h>
#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
-#include "HTMLParserErrorCodes.h"
-#include "MappedAttributeEntry.h"
namespace WebCore {
@@ -47,14 +47,14 @@ struct HTMLStackElem;
struct Token;
/**
- * The parser for HTML. It receives a stream of tokens from the HTMLTokenizer, and
+ * The parser for HTML. It receives a stream of tokens from the HTMLDocumentParser, and
* builds up the Document structure from it.
*/
-class HTMLParser : public Noncopyable {
+class LegacyHTMLTreeConstructor : public Noncopyable {
public:
- HTMLParser(HTMLDocument*, bool reportErrors);
- HTMLParser(DocumentFragment*, FragmentScriptingPermission = FragmentScriptingAllowed);
- virtual ~HTMLParser();
+ LegacyHTMLTreeConstructor(HTMLDocument*, bool reportErrors);
+ LegacyHTMLTreeConstructor(DocumentFragment*, FragmentScriptingPermission = FragmentScriptingAllowed);
+ virtual ~LegacyHTMLTreeConstructor();
/**
* parses one token delivered by the tokenizer
diff --git a/WebCore/html/PreloadScanner.cpp b/WebCore/html/PreloadScanner.cpp
index ee7e761..d39092a 100644
--- a/WebCore/html/PreloadScanner.cpp
+++ b/WebCore/html/PreloadScanner.cpp
@@ -47,7 +47,7 @@
// Use __GNUC__ instead of PLATFORM(GCC) to stay consistent with the gperf generated c file
#ifdef __GNUC__
// The main tokenizer includes this too so we are getting two copies of the data. However, this way the code gets inlined.
-#include "HTMLEntityNames.c"
+#include "HTMLEntityNames.cpp"
#else
// Not inlined for non-GCC compilers
struct Entity {
diff --git a/WebCore/html/StepRange.cpp b/WebCore/html/StepRange.cpp
index 04f4ed3..3923abe 100644
--- a/WebCore/html/StepRange.cpp
+++ b/WebCore/html/StepRange.cpp
@@ -23,7 +23,7 @@
#include "HTMLInputElement.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "PlatformString.h"
#include <wtf/MathExtras.h>
diff --git a/WebCore/html/TextMetrics.h b/WebCore/html/TextMetrics.h
index 14cdb67..c786fca 100644
--- a/WebCore/html/TextMetrics.h
+++ b/WebCore/html/TextMetrics.h
@@ -26,6 +26,7 @@
#ifndef TextMetrics_h
#define TextMetrics_h
+#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
namespace WebCore {
diff --git a/WebCore/html/ValidityState.cpp b/WebCore/html/ValidityState.cpp
index fc60a22..7f6b8be 100644
--- a/WebCore/html/ValidityState.cpp
+++ b/WebCore/html/ValidityState.cpp
@@ -26,7 +26,7 @@
#include "HTMLInputElement.h"
#include "HTMLNames.h"
-#include "HTMLParser.h"
+#include "LegacyHTMLTreeConstructor.h"
#include "KURL.h"
#include "LocalizedStrings.h"
#include "RegularExpression.h"
diff --git a/WebCore/html/canvas/CanvasGradient.idl b/WebCore/html/canvas/CanvasGradient.idl
index 32813bc..a925a26 100644
--- a/WebCore/html/canvas/CanvasGradient.idl
+++ b/WebCore/html/canvas/CanvasGradient.idl
@@ -27,8 +27,7 @@ module html {
interface [
InterfaceUUID=bb1108ea-6b8c-4a08-894a-218628630cdb,
- ImplementationUUID=a2942ae6-2731-4286-98cc-9d5e79e20de1,
- OmitConstructor
+ ImplementationUUID=a2942ae6-2731-4286-98cc-9d5e79e20de1
] CanvasGradient {
void addColorStop(in float offset, in DOMString color)
diff --git a/WebCore/html/canvas/CanvasPattern.idl b/WebCore/html/canvas/CanvasPattern.idl
index 492c93f..1cac8f8 100644
--- a/WebCore/html/canvas/CanvasPattern.idl
+++ b/WebCore/html/canvas/CanvasPattern.idl
@@ -27,8 +27,7 @@ module html {
interface [
InterfaceUUID=c2131348-6d8c-47b5-86cc-d41aff34ce15,
- ImplementationUUID=82f5d713-3d17-44dd-aa4a-7766fe345940,
- OmitConstructor
+ ImplementationUUID=82f5d713-3d17-44dd-aa4a-7766fe345940
] CanvasPattern {
};
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 184cc14..8531bd5 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -753,6 +753,12 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei
if (!state().m_invertibleCTM)
return;
+ // from the HTML5 Canvas spec:
+ // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing
+ Gradient* gradient = c->fillGradient();
+ if (gradient && gradient->isZeroSize() && !gradient->isRadial())
+ return;
+
FloatRect rect(x, y, width, height);
willDraw(rect);
@@ -1265,10 +1271,8 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme
if (ec)
return 0;
- if (!image->complete()) {
- ec = INVALID_STATE_ERR;
+ if (!image->complete())
return 0;
- }
CachedImage* cachedImage = image->cachedImage();
if (!cachedImage || !image->cachedImage()->image())
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.idl b/WebCore/html/canvas/CanvasRenderingContext2D.idl
index da4dd72..23afc11 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.idl
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.idl
@@ -90,10 +90,12 @@ module html {
void setAlpha(in float alpha);
void setCompositeOperation(in DOMString compositeOperation);
+#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
void setLineWidth(in float width);
void setLineCap(in DOMString cap);
void setLineJoin(in DOMString join);
void setMiterLimit(in float limit);
+#endif
void clearShadow();
diff --git a/WebCore/html/canvas/FloatArray.cpp b/WebCore/html/canvas/Float32Array.cpp
index 942a123..c95fb48 100644
--- a/WebCore/html/canvas/FloatArray.cpp
+++ b/WebCore/html/canvas/Float32Array.cpp
@@ -28,33 +28,33 @@
#if ENABLE(3D_CANVAS)
-#include "FloatArray.h"
+#include "Float32Array.h"
namespace WebCore {
-PassRefPtr<FloatArray> FloatArray::create(unsigned length)
+PassRefPtr<Float32Array> Float32Array::create(unsigned length)
{
- return TypedArrayBase<float>::create<FloatArray>(length);
+ return TypedArrayBase<float>::create<Float32Array>(length);
}
-PassRefPtr<FloatArray> FloatArray::create(float* array, unsigned length)
+PassRefPtr<Float32Array> Float32Array::create(float* array, unsigned length)
{
- return TypedArrayBase<float>::create<FloatArray>(array, length);
+ return TypedArrayBase<float>::create<Float32Array>(array, length);
}
-PassRefPtr<FloatArray> FloatArray::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
+PassRefPtr<Float32Array> Float32Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
{
- return TypedArrayBase<float>::create<FloatArray>(buffer, byteOffset, length);
+ return TypedArrayBase<float>::create<Float32Array>(buffer, byteOffset, length);
}
-FloatArray::FloatArray(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
+Float32Array::Float32Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
: TypedArrayBase<float>(buffer, byteOffset, length)
{
}
-PassRefPtr<ArrayBufferView> FloatArray::slice(int start, int end) const
+PassRefPtr<ArrayBufferView> Float32Array::slice(int start, int end) const
{
- return sliceImpl<FloatArray>(start, end);
+ return sliceImpl<Float32Array>(start, end);
}
}
diff --git a/WebCore/html/canvas/FloatArray.h b/WebCore/html/canvas/Float32Array.h
index 9211a40..8112264 100644
--- a/WebCore/html/canvas/FloatArray.h
+++ b/WebCore/html/canvas/Float32Array.h
@@ -24,19 +24,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef FloatArray_h
-#define FloatArray_h
+#ifndef Float32Array_h
+#define Float32Array_h
#include "TypedArrayBase.h"
#include <wtf/MathExtras.h>
namespace WebCore {
-class FloatArray : public TypedArrayBase<float> {
+class Float32Array : public TypedArrayBase<float> {
public:
- static PassRefPtr<FloatArray> create(unsigned length);
- static PassRefPtr<FloatArray> create(float* array, unsigned length);
- static PassRefPtr<FloatArray> create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length);
+ static PassRefPtr<Float32Array> create(unsigned length);
+ static PassRefPtr<Float32Array> create(float* array, unsigned length);
+ static PassRefPtr<Float32Array> create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length);
using TypedArrayBase<float>::set;
@@ -63,7 +63,7 @@ class FloatArray : public TypedArrayBase<float> {
}
private:
- FloatArray(PassRefPtr<ArrayBuffer> buffer,
+ Float32Array(PassRefPtr<ArrayBuffer> buffer,
unsigned byteOffset,
unsigned length);
// Make constructor visible to superclass.
@@ -76,4 +76,4 @@ class FloatArray : public TypedArrayBase<float> {
} // namespace WebCore
-#endif // FloatArray_h
+#endif // Float32Array_h
diff --git a/WebCore/html/canvas/FloatArray.idl b/WebCore/html/canvas/Float32Array.idl
index 41b2c94..91a9f4e 100644
--- a/WebCore/html/canvas/FloatArray.idl
+++ b/WebCore/html/canvas/Float32Array.idl
@@ -32,8 +32,10 @@ module html {
GenerateNativeConverter,
CustomConstructor,
CustomToJS
- ] FloatArray : ArrayBufferView {
- // void set(in FloatArray array, [Optional] in unsigned long offset);
+ ] Float32Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 4;
+
+ // void set(in Float32Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
};
diff --git a/WebCore/html/canvas/Int16Array.idl b/WebCore/html/canvas/Int16Array.idl
index 2ac52fe..95c8204 100644
--- a/WebCore/html/canvas/Int16Array.idl
+++ b/WebCore/html/canvas/Int16Array.idl
@@ -32,6 +32,8 @@ module html {
CustomConstructor,
CustomToJS
] Int16Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 2;
+
// void set(in Int16Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
diff --git a/WebCore/html/canvas/Int32Array.idl b/WebCore/html/canvas/Int32Array.idl
index 80a885e..9c9a50f 100644
--- a/WebCore/html/canvas/Int32Array.idl
+++ b/WebCore/html/canvas/Int32Array.idl
@@ -33,6 +33,8 @@ module html {
CustomConstructor,
CustomToJS
] Int32Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 4;
+
// void set(in Int32Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
diff --git a/WebCore/html/canvas/Int8Array.idl b/WebCore/html/canvas/Int8Array.idl
index 1124ac1..9aefd34 100644
--- a/WebCore/html/canvas/Int8Array.idl
+++ b/WebCore/html/canvas/Int8Array.idl
@@ -33,6 +33,8 @@ module html {
CustomConstructor,
CustomToJS
] Int8Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 1;
+
// void set(in Int8Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
diff --git a/WebCore/html/canvas/Uint16Array.idl b/WebCore/html/canvas/Uint16Array.idl
index 2d5b34e..baba0d9 100644
--- a/WebCore/html/canvas/Uint16Array.idl
+++ b/WebCore/html/canvas/Uint16Array.idl
@@ -33,6 +33,8 @@ module html {
GenerateNativeConverter,
CustomToJS
] Uint16Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 2;
+
// void set(in Uint16Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
diff --git a/WebCore/html/canvas/Uint32Array.idl b/WebCore/html/canvas/Uint32Array.idl
index bab0f8d..b7573e6 100644
--- a/WebCore/html/canvas/Uint32Array.idl
+++ b/WebCore/html/canvas/Uint32Array.idl
@@ -33,6 +33,8 @@ module html {
GenerateNativeConverter,
CustomToJS
] Uint32Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 4;
+
// void set(in Uint32Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
diff --git a/WebCore/html/canvas/Uint8Array.idl b/WebCore/html/canvas/Uint8Array.idl
index 7031bfc..ea4c0f5 100644
--- a/WebCore/html/canvas/Uint8Array.idl
+++ b/WebCore/html/canvas/Uint8Array.idl
@@ -33,6 +33,8 @@ module html {
CustomConstructor,
CustomToJS
] Uint8Array : ArrayBufferView {
+ const unsigned int BYTES_PER_ELEMENT = 1;
+
// void set(in Uint8Array array, [Optional] in unsigned long offset);
// void set(in sequence<long> array, [Optional] in unsigned long offset);
[Custom] void set();
diff --git a/WebCore/html/canvas/WebGLFramebuffer.cpp b/WebCore/html/canvas/WebGLFramebuffer.cpp
index c783553..db88b1c 100644
--- a/WebCore/html/canvas/WebGLFramebuffer.cpp
+++ b/WebCore/html/canvas/WebGLFramebuffer.cpp
@@ -87,6 +87,24 @@ void WebGLFramebuffer::onAttachedObjectChange(CanvasObject* object)
initializeRenderbuffers();
}
+unsigned long WebGLFramebuffer::getColorBufferFormat()
+{
+ if (object() && m_colorAttachment && m_colorAttachment->object()) {
+ if (m_colorAttachment->isRenderbuffer()) {
+ unsigned long format = (reinterpret_cast<WebGLRenderbuffer*>(m_colorAttachment))->getInternalformat();
+ switch (format) {
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RGB5_A1:
+ return GraphicsContext3D::RGBA;
+ case GraphicsContext3D::RGB565:
+ return GraphicsContext3D::RGB;
+ }
+ } else if (m_colorAttachment->isTexture())
+ return (reinterpret_cast<WebGLTexture*>(m_colorAttachment))->getInternalformat();
+ }
+ return 0;
+}
+
void WebGLFramebuffer::_deleteObject(Platform3DObject object)
{
context()->graphicsContext3D()->deleteFramebuffer(object);
diff --git a/WebCore/html/canvas/WebGLFramebuffer.h b/WebCore/html/canvas/WebGLFramebuffer.h
index 93ab97c..ae1f4dc 100644
--- a/WebCore/html/canvas/WebGLFramebuffer.h
+++ b/WebCore/html/canvas/WebGLFramebuffer.h
@@ -57,6 +57,8 @@ namespace WebCore {
// clear un-initialized renderbuffers.
void onAttachedObjectChange(CanvasObject*);
+ unsigned long getColorBufferFormat();
+
protected:
WebGLFramebuffer(WebGLRenderingContext*);
diff --git a/WebCore/html/canvas/WebGLGetInfo.cpp b/WebCore/html/canvas/WebGLGetInfo.cpp
index d5fcd92..79fc971 100644
--- a/WebCore/html/canvas/WebGLGetInfo.cpp
+++ b/WebCore/html/canvas/WebGLGetInfo.cpp
@@ -30,7 +30,7 @@
#include "WebGLGetInfo.h"
#include "WebGLBuffer.h"
-#include "FloatArray.h"
+#include "Float32Array.h"
#include "WebGLFramebuffer.h"
#include "Int32Array.h"
#include "WebGLProgram.h"
@@ -81,7 +81,7 @@ WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLBuffer> value)
{
}
-WebGLGetInfo::WebGLGetInfo(PassRefPtr<FloatArray> value)
+WebGLGetInfo::WebGLGetInfo(PassRefPtr<Float32Array> value)
: m_type(kTypeWebGLFloatArray)
, m_webglFloatArray(value)
{
@@ -168,7 +168,7 @@ PassRefPtr<WebGLBuffer> WebGLGetInfo::getWebGLBuffer() const
return m_webglBuffer;
}
-PassRefPtr<FloatArray> WebGLGetInfo::getWebGLFloatArray() const
+PassRefPtr<Float32Array> WebGLGetInfo::getWebGLFloatArray() const
{
ASSERT(getType() == kTypeWebGLFloatArray);
return m_webglFloatArray;
diff --git a/WebCore/html/canvas/WebGLGetInfo.h b/WebCore/html/canvas/WebGLGetInfo.h
index 969e05d..b35add8 100644
--- a/WebCore/html/canvas/WebGLGetInfo.h
+++ b/WebCore/html/canvas/WebGLGetInfo.h
@@ -32,7 +32,7 @@
#include "PlatformString.h"
#include "WebGLBuffer.h"
-#include "FloatArray.h"
+#include "Float32Array.h"
#include "WebGLFramebuffer.h"
#include "Int32Array.h"
// FIXME: implement WebGLObjectArray
@@ -77,7 +77,7 @@ public:
WebGLGetInfo(const String& value);
WebGLGetInfo(unsigned long value);
WebGLGetInfo(PassRefPtr<WebGLBuffer> value);
- WebGLGetInfo(PassRefPtr<FloatArray> value);
+ WebGLGetInfo(PassRefPtr<Float32Array> value);
WebGLGetInfo(PassRefPtr<WebGLFramebuffer> value);
WebGLGetInfo(PassRefPtr<Int32Array> value);
// FIXME: implement WebGLObjectArray
@@ -97,7 +97,7 @@ public:
const String& getString() const;
unsigned long getUnsignedLong() const;
PassRefPtr<WebGLBuffer> getWebGLBuffer() const;
- PassRefPtr<FloatArray> getWebGLFloatArray() const;
+ PassRefPtr<Float32Array> getWebGLFloatArray() const;
PassRefPtr<WebGLFramebuffer> getWebGLFramebuffer() const;
PassRefPtr<Int32Array> getWebGLIntArray() const;
// FIXME: implement WebGLObjectArray
@@ -115,7 +115,7 @@ private:
String m_string;
unsigned long m_unsignedLong;
RefPtr<WebGLBuffer> m_webglBuffer;
- RefPtr<FloatArray> m_webglFloatArray;
+ RefPtr<Float32Array> m_webglFloatArray;
RefPtr<WebGLFramebuffer> m_webglFramebuffer;
RefPtr<Int32Array> m_webglIntArray;
// FIXME: implement WebGLObjectArray
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index ca1d375..82a0f8f 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -30,6 +30,8 @@
#include "WebGLRenderingContext.h"
#include "CanvasPixelArray.h"
+#include "Console.h"
+#include "DOMWindow.h"
#include "FrameView.h"
#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
@@ -50,6 +52,7 @@
#include "WebGLUniformLocation.h"
#include <wtf/ByteArray.h>
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -91,17 +94,33 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
, m_activeTextureUnit(0)
, m_packAlignment(4)
, m_unpackAlignment(4)
+ , m_unpackFlipY(false)
+ , m_unpackPremultiplyAlpha(false)
{
ASSERT(m_context);
+
+ int numCombinedTextureImageUnits = 0;
+ m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
+ m_textureUnits.resize(numCombinedTextureImageUnits);
+
int numVertexAttribs = 0;
m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs);
m_maxVertexAttribs = numVertexAttribs;
+
int implementationColorReadFormat = GraphicsContext3D::RGBA;
m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT, &implementationColorReadFormat);
m_implementationColorReadFormat = implementationColorReadFormat;
int implementationColorReadType = GraphicsContext3D::UNSIGNED_BYTE;
m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE, &implementationColorReadType);
m_implementationColorReadType = implementationColorReadType;
+
+ int maxTextureSize = 0;
+ m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
+ m_maxTextureSize = maxTextureSize;
+ int maxCubeMapTextureSize = 0;
+ m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize);
+ m_maxCubeMapTextureSize = maxCubeMapTextureSize;
+
if (!isGLES2Compliant())
createFallbackBlackTextures1x1();
m_context->reshape(canvas()->width(), canvas()->height());
@@ -433,36 +452,45 @@ void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec
void WebGLRenderingContext::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border)
{
- RefPtr<WebGLTexture> tex = 0;
- switch (target) {
- case GraphicsContext3D::TEXTURE_2D:
- tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
- break;
- case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
- tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
- break;
- }
+ if (!validateTexFuncParameters(target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
+ return;
if (!isGLES2Compliant()) {
+ if (m_framebufferBinding && m_framebufferBinding->object()
+ && !isTexInternalformatColorBufferCombinationValid(internalformat,
+ m_framebufferBinding->getColorBufferFormat())) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
if (level && WebGLTexture::isNPOT(width, height)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
+ }
+ m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ // FIXME: if the framebuffer is not complete, none of the below should be executed.
+ WebGLTexture* tex = getTextureBinding(target);
+ if (!isGLES2Compliant()) {
if (tex && !level) // only for level 0
tex->setSize(target, width, height);
+ if (tex)
+ tex->setInternalformat(internalformat);
}
- m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
if (m_framebufferBinding && tex)
- m_framebufferBinding->onAttachedObjectChange(tex.get());
+ m_framebufferBinding->onAttachedObjectChange(tex);
cleanupAfterGraphicsCall(false);
}
void WebGLRenderingContext::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height)
{
+ if (!isGLES2Compliant()) {
+ WebGLTexture* tex = getTextureBinding(target);
+ if (m_framebufferBinding && m_framebufferBinding->object() && tex
+ && !isTexInternalformatColorBufferCombinationValid(tex->getInternalformat(),
+ m_framebufferBinding->getColorBufferFormat())) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+ }
m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
cleanupAfterGraphicsCall(false);
}
@@ -731,7 +759,14 @@ bool WebGLRenderingContext::validateRenderingState(long numElementsRequired)
if (!m_currentProgram)
return false;
- // Look in each enabled vertex attrib and find the smallest buffer 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) {
+ if (m_vertexAttribState[i].enabled
+ && (!m_vertexAttribState[i].bufferBinding || !m_vertexAttribState[i].bufferBinding->object()))
+ return false;
+ }
+
+ // 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());
@@ -766,8 +801,20 @@ bool WebGLRenderingContext::validateWebGLObject(CanvasObject* object)
void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long count, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
+
+ if (!validateDrawMode(mode))
+ return;
+
+ if (first < 0 || count < 0) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (!count)
+ return;
+
// Ensure we have a valid rendering state
- if (first < 0 || count < 0 || !validateRenderingState(first + count)) {
+ if (!validateRenderingState(first + count)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -778,13 +825,34 @@ void WebGLRenderingContext::drawArrays(unsigned long mode, long first, long coun
cleanupAfterGraphicsCall(true);
}
-void WebGLRenderingContext::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset, ExceptionCode& ec)
+void WebGLRenderingContext::drawElements(unsigned long mode, long count, unsigned long type, long offset, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
+
+ if (!validateDrawMode(mode))
+ return;
+
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_BYTE:
+ case GraphicsContext3D::UNSIGNED_SHORT:
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return;
+ }
+
+ if (count < 0 || offset < 0) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ if (!count)
+ return;
+
// Ensure we have a valid rendering state
long numElements;
- if (offset < 0 || !validateElementArraySize(count, type, offset)) {
+ if (!validateElementArraySize(count, type, offset)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
@@ -946,6 +1014,10 @@ PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram
if (!m_context->getActiveUniform(program, index, info)) {
return 0;
}
+ if (!isGLES2Compliant()) {
+ if (info.size > 1 && !info.name.endsWith("[0]"))
+ info.name.append("[0]");
+ }
return WebGLActiveInfo::create(info.name, info.type, info.size);
}
@@ -1200,6 +1272,10 @@ WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionC
case GraphicsContext3D::UNPACK_ALIGNMENT:
// FIXME: should this be "long" in the spec?
return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
+ return WebGLGetInfo(m_unpackFlipY);
+ case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
+ return WebGLGetInfo(m_unpackPremultiplyAlpha);
case GraphicsContext3D::VIEWPORT:
return getWebGLIntArrayParameter(pname);
default:
@@ -1449,7 +1525,7 @@ WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG
if (length == 1)
return WebGLGetInfo(value[0]);
else
- return WebGLGetInfo(FloatArray::create(value, length));
+ return WebGLGetInfo(Float32Array::create(value, length));
}
case GraphicsContext3D::INT: {
int value[16] = {0};
@@ -1527,7 +1603,7 @@ WebGLGetInfo WebGLRenderingContext::getVertexAttrib(unsigned long index, unsigne
case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: {
float value[4] = {0};
m_context->getVertexAttribfv(index, pname, value);
- return WebGLGetInfo(FloatArray::create(value, 4));
+ return WebGLGetInfo(Float32Array::create(value, 4));
}
default: {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
@@ -1620,15 +1696,21 @@ void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec
void WebGLRenderingContext::pixelStorei(unsigned long pname, long param)
{
- m_context->pixelStorei(pname, param);
- if (param == 1 || param == 2 || param == 4 || param == 8) {
- switch (pname) {
- case GraphicsContext3D::PACK_ALIGNMENT:
- m_packAlignment = static_cast<int>(param);
- break;
- case GraphicsContext3D::UNPACK_ALIGNMENT:
- m_unpackAlignment = static_cast<int>(param);
- break;
+ if (pname == GraphicsContext3D::UNPACK_FLIP_Y_WEBGL) {
+ m_unpackFlipY = param;
+ } else if (pname == GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL) {
+ m_unpackPremultiplyAlpha = param;
+ } else {
+ m_context->pixelStorei(pname, param);
+ if (param == 1 || param == 2 || param == 4 || param == 8) {
+ switch (pname) {
+ case GraphicsContext3D::PACK_ALIGNMENT:
+ m_packAlignment = static_cast<int>(param);
+ break;
+ case GraphicsContext3D::UNPACK_ALIGNMENT:
+ m_unpackAlignment = static_cast<int>(param);
+ break;
+ }
}
}
cleanupAfterGraphicsCall(false);
@@ -1640,9 +1722,9 @@ void WebGLRenderingContext::polygonOffset(double factor, double units)
cleanupAfterGraphicsCall(false);
}
-PassRefPtr<ArrayBufferView> WebGLRenderingContext::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
+void WebGLRenderingContext::readPixels(long x, long y, long width, long height, unsigned long format, unsigned long type, ArrayBufferView* pixels)
{
- // Validate enums.
+ // Validate input parameters.
unsigned long componentsPerPixel = 0;
switch (format) {
case GraphicsContext3D::ALPHA:
@@ -1656,7 +1738,7 @@ PassRefPtr<ArrayBufferView> WebGLRenderingContext::readPixels(long x, long y, un
break;
default:
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
- return 0;
+ return;
}
unsigned long bytesPerComponent = 0;
switch (type) {
@@ -1671,11 +1753,25 @@ PassRefPtr<ArrayBufferView> WebGLRenderingContext::readPixels(long x, long y, un
break;
default:
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
- return 0;
+ return;
+ }
+ if (!pixels) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ if (width < 0 || height < 0) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
}
if (!((format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE) || (format == m_implementationColorReadFormat && type == m_implementationColorReadType))) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
- return 0;
+ return;
+ }
+ // Validate array type against pixel type.
+ if (type == GraphicsContext3D::UNSIGNED_BYTE && !pixels->isUnsignedByteArray()
+ || type != GraphicsContext3D::UNSIGNED_BYTE && !pixels->isUnsignedShortArray()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
}
// Calculate array size, taking into consideration of PACK_ALIGNMENT.
unsigned long bytesPerRow = componentsPerPixel * bytesPerComponent * width;
@@ -1688,12 +1784,11 @@ PassRefPtr<ArrayBufferView> WebGLRenderingContext::readPixels(long x, long y, un
// The last row needs no padding.
unsigned long totalBytes = bytesPerRow * height - padding;
unsigned long num = totalBytes / bytesPerComponent;
- RefPtr<ArrayBufferView> array;
- if (type == GraphicsContext3D::UNSIGNED_BYTE)
- array = Uint8Array::create(num);
- else
- array = Uint16Array::create(num);
- void* data = array->baseAddress();
+ if (pixels->length() < num) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+ void* data = pixels->baseAddress();
m_context->readPixels(x, y, width, height, format, type, data);
#if PLATFORM(CG)
// FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
@@ -1701,8 +1796,8 @@ PassRefPtr<ArrayBufferView> WebGLRenderingContext::readPixels(long x, long y, un
if ((format == GraphicsContext3D::ALPHA || format == GraphicsContext3D::RGBA) && !m_context->getContextAttributes().alpha) {
if (type == GraphicsContext3D::UNSIGNED_BYTE) {
unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
- for (unsigned long iy = 0; iy < height; ++iy) {
- for (unsigned long ix = 0; ix < width; ++ix) {
+ for (long iy = 0; iy < height; ++iy) {
+ for (long ix = 0; ix < width; ++ix) {
pixels[componentsPerPixel - 1] = 255;
pixels += componentsPerPixel;
}
@@ -1713,7 +1808,6 @@ PassRefPtr<ArrayBufferView> WebGLRenderingContext::readPixels(long x, long y, un
}
#endif
cleanupAfterGraphicsCall(false);
- return array;
}
void WebGLRenderingContext::releaseShaderCompiler()
@@ -1805,43 +1899,39 @@ void WebGLRenderingContext::texImage2DBase(unsigned target, unsigned level, unsi
unsigned width, unsigned height, unsigned border,
unsigned format, unsigned type, void* pixels, ExceptionCode& ec)
{
- RefPtr<WebGLTexture> tex = 0;
- switch (target) {
- case GraphicsContext3D::TEXTURE_2D:
- tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
- break;
- case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
- tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
- break;
- }
// FIXME: For now we ignore any errors returned
ec = 0;
+ if (!validateTexFuncParameters(target, level, internalformat, width, height, border, format, type))
+ return;
if (!isGLES2Compliant()) {
if (level && WebGLTexture::isNPOT(width, height)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- if (tex && !level) // only for level 0
- tex->setSize(target, width, height);
}
m_context->texImage2D(target, level, internalformat, width, height,
border, format, type, pixels);
+ WebGLTexture* tex = getTextureBinding(target);
+ if (!isGLES2Compliant()) {
+ if (tex && !level) // only for level 0
+ tex->setSize(target, width, height);
+ if (tex)
+ tex->setInternalformat(internalformat);
+ }
if (m_framebufferBinding && tex)
- m_framebufferBinding->onAttachedObjectChange(tex.get());
+ m_framebufferBinding->onAttachedObjectChange(tex);
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, Image* image,
- bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
+void WebGLRenderingContext::texImage2DImpl(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, Image* image,
+ bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ // FIXME: pay attention to the user's supplied internalformat, format and type
+ // FIXME: pay attention to UNPACK_ROW_WIDTH
+ UNUSED_PARAM(type);
ec = 0;
Vector<uint8_t> data;
- unsigned int format, internalformat;
if (!m_context->extractImageData(image, flipY, premultiplyAlpha, data, &format, &internalformat)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
@@ -1859,21 +1949,82 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned
format, type, pixels ? pixels->baseAddress() : 0, ec);
}
+void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, ImageData* pixels, ExceptionCode& ec)
+{
+ UNUSED_PARAM(internalformat);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ // FIXME: pay attention to the user's supplied internalformat, format and type
+ ec = 0;
+ Vector<uint8_t> data;
+ if (!m_context->extractImageData(pixels, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ texImage2DBase(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0,
+ GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec);
+}
+
+void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode& ec)
+{
+ ec = 0;
+ if (!image || !image->cachedImage()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
+ m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+
+void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode& ec)
+{
+ ec = 0;
+ if (!canvas || !canvas->buffer()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ texImage2DImpl(target, level, internalformat, format, type, canvas->buffer()->image(),
+ m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+
+void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode& ec)
+{
+ // FIXME: Need to implement this call
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(internalformat);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(video);
+
+ ec = 0;
+ cleanupAfterGraphicsCall(false);
+}
+
+// Obsolete texImage2D entry points -- to be removed shortly. (FIXME)
+
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, ImageData pixels)");
texImage2D(target, level, pixels, 0, 0, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
bool flipY, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, ImageData pixels, GLboolean flipY)");
texImage2D(target, level, pixels, flipY, 0, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels,
bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, ImageData pixels, GLboolean flipY, GLboolean premultiplyAlpha)");
ec = 0;
Vector<uint8_t> data;
if (!m_context->extractImageData(pixels, flipY, premultiplyAlpha, data)) {
@@ -1888,47 +2039,53 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageDat
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLImageElement image)");
texImage2D(target, level, image, 0, 0, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
bool flipY, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLImageElement image, GLboolean flipY)");
texImage2D(target, level, image, flipY, 0, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLImageElement image, GLboolean flipY, GLboolean premultiplyAlpha)");
ec = 0;
if (!image || !image->cachedImage()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- texImage2D(target, level, image->cachedImage()->image(), flipY, premultiplyAlpha, ec);
+ texImage2DImpl(target, level, GraphicsContext3D::RGBA, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, image->cachedImage()->image(), flipY, premultiplyAlpha, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas)");
texImage2D(target, level, canvas, 0, 0, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
bool flipY, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas, GLboolean flipY)");
texImage2D(target, level, canvas, flipY, 0, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texImage2D(GLenum target, GLint level, HTMLCanvasElement canvas, GLboolean flipY, GLboolean premultiplyAlpha)");
ec = 0;
if (!canvas || !canvas->buffer()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- texImage2D(target, level, canvas->buffer()->image(), flipY, premultiplyAlpha, ec);
+ texImage2DImpl(target, level, GraphicsContext3D::RGBA, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, canvas->buffer()->image(), flipY, premultiplyAlpha, ec);
}
void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
@@ -1957,34 +2114,59 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVide
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::texParameterf(unsigned target, unsigned pname, float param)
+void WebGLRenderingContext::texParameter(unsigned long target, unsigned long pname, float paramf, int parami, bool isFloat)
{
- m_context->texParameterf(target, pname, param);
if (!isGLES2Compliant()) {
RefPtr<WebGLTexture> tex = 0;
- if (target == GraphicsContext3D::TEXTURE_2D)
+ switch (target) {
+ case GraphicsContext3D::TEXTURE_2D:
tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
- else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
+ break;
+ case GraphicsContext3D::TEXTURE_CUBE_MAP:
tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
- if (tex)
- tex->setParameterf(pname, param);
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return;
+ }
+ switch (pname) {
+ case GraphicsContext3D::TEXTURE_MIN_FILTER:
+ case GraphicsContext3D::TEXTURE_MAG_FILTER:
+ break;
+ case GraphicsContext3D::TEXTURE_WRAP_S:
+ case GraphicsContext3D::TEXTURE_WRAP_T:
+ if (isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT
+ || !isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return;
+ }
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return;
+ }
+ if (tex) {
+ if (isFloat)
+ tex->setParameterf(pname, paramf);
+ else
+ tex->setParameteri(pname, parami);
+ }
}
+ if (isFloat)
+ m_context->texParameterf(target, pname, paramf);
+ else
+ m_context->texParameteri(target, pname, parami);
cleanupAfterGraphicsCall(false);
}
+void WebGLRenderingContext::texParameterf(unsigned target, unsigned pname, float param)
+{
+ texParameter(target, pname, param, 0, true);
+}
+
void WebGLRenderingContext::texParameteri(unsigned target, unsigned pname, int param)
{
- m_context->texParameteri(target, pname, param);
- if (!isGLES2Compliant()) {
- RefPtr<WebGLTexture> tex = 0;
- if (target == GraphicsContext3D::TEXTURE_2D)
- tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
- else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
- tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
- if (tex)
- tex->setParameteri(pname, param);
- }
- cleanupAfterGraphicsCall(false);
+ texParameter(target, pname, 0, param, false);
}
void WebGLRenderingContext::texSubImage2DBase(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
@@ -1993,16 +2175,23 @@ void WebGLRenderingContext::texSubImage2DBase(unsigned target, unsigned level, u
{
// FIXME: For now we ignore any errors returned
ec = 0;
+ if (!validateTexFuncFormatAndType(format, type))
+ return;
+
m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
- Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
+void WebGLRenderingContext::texSubImage2DImpl(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type,
+ Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ UNUSED_PARAM(type);
+ // FIXME: pay attention to the user's supplied format and type
+ // FIXME: pay attention to UNPACK_ROW_WIDTH
ec = 0;
Vector<uint8_t> data;
- unsigned int format, internalformat;
+ unsigned int internalformat;
if (!m_context->extractImageData(image, flipY, premultiplyAlpha, data, &format, &internalformat)) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
@@ -2020,20 +2209,80 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, ImageData* pixels, ExceptionCode& ec)
+{
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ // FIXME: pay attention to the user's supplied format and type
+ ec = 0;
+ Vector<uint8_t> data;
+ if (!m_context->extractImageData(pixels, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
+ GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec);
+}
+
+void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode& ec)
+{
+ ec = 0;
+ if (!image || !image->cachedImage()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
+ m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+
+void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode& ec)
+{
+ ec = 0;
+ if (!canvas || !canvas->buffer()) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+ texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->buffer()->image(),
+ m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+
+void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode& ec)
+{
+ // FIXME: Need to implement this call
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoffset);
+ UNUSED_PARAM(yoffset);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(video);
+ ec = 0;
+ cleanupAfterGraphicsCall(false);
+}
+
+// Obsolete texSubImage2D entry points -- to be removed shortly. (FIXME)
+
+void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
ImageData* pixels, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ImageData pixels)");
texSubImage2D(target, level, xoffset, yoffset, pixels, 0, 0, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
ImageData* pixels, bool flipY, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ImageData pixels, GLboolean flipY)");
texSubImage2D(target, level, xoffset, yoffset, pixels, flipY, 0, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ImageData pixels, GLboolean flipY, GLboolean premultiplyAlpha)");
ec = 0;
Vector<uint8_t> data;
if (!m_context->extractImageData(pixels, flipY, premultiplyAlpha, data)) {
@@ -2047,49 +2296,55 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
HTMLImageElement* image, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLImageElement image)");
texSubImage2D(target, level, xoffset, yoffset, image, 0, 0, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
HTMLImageElement* image, bool flipY, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLImageElement image, GLboolean flipY)");
texSubImage2D(target, level, xoffset, yoffset, image, flipY, 0, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLImageElement image, GLboolean flipY, GLboolean premultiplyAlpha)");
ec = 0;
if (!image || !image->cachedImage()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- texSubImage2D(target, level, xoffset, yoffset, image->cachedImage()->image(),
- flipY, premultiplyAlpha, ec);
+ texSubImage2DImpl(target, level, xoffset, yoffset, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, image->cachedImage()->image(),
+ flipY, premultiplyAlpha, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
HTMLCanvasElement* canvas, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLCanvasElement canvas)");
texSubImage2D(target, level, xoffset, yoffset, canvas, 0, 0, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
HTMLCanvasElement* canvas, bool flipY, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLCanvasElement canvas, GLboolean flipY)");
texSubImage2D(target, level, xoffset, yoffset, canvas, flipY, 0, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
{
+ printWarningToConsole("Calling obsolete texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, HTMLCanvasElement canvas, GLboolean flipY, GLboolean premultiplyAlpha)");
ec = 0;
if (!canvas || !canvas->buffer()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
- texSubImage2D(target, level, xoffset, yoffset, canvas->buffer()->image(),
- flipY, premultiplyAlpha, ec);
+ texSubImage2DImpl(target, level, xoffset, yoffset, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, canvas->buffer()->image(),
+ flipY, premultiplyAlpha, ec);
}
void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
@@ -2122,10 +2377,8 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2136,13 +2389,11 @@ void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, floa
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2160,10 +2411,8 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2181,10 +2430,8 @@ void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2198,10 +2445,8 @@ void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2219,10 +2464,8 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2240,10 +2483,8 @@ void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2254,13 +2495,11 @@ void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, floa
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2279,10 +2518,8 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2301,10 +2538,8 @@ void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2318,10 +2553,8 @@ void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2340,10 +2573,8 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2362,10 +2593,8 @@ void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2376,13 +2605,11 @@ void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, floa
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2401,10 +2628,8 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2423,10 +2648,8 @@ void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2440,10 +2663,8 @@ void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2462,10 +2683,8 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2484,10 +2703,8 @@ void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2498,13 +2715,11 @@ void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, floa
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2523,10 +2738,8 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Flo
void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2545,10 +2758,8 @@ void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, flo
void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2562,10 +2773,8 @@ void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, int
void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2584,10 +2793,8 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int
void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2603,13 +2810,11 @@ void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, int
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2628,10 +2833,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) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2647,13 +2850,11 @@ void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2672,10 +2873,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) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2691,13 +2890,11 @@ void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, FloatArray* v, ExceptionCode& ec)
+void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, Float32Array* v, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!location) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2716,10 +2913,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) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ if (!location)
return;
- }
if (location->program() != m_currentProgram) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
@@ -2766,7 +2961,7 @@ void WebGLRenderingContext::vertexAttrib1f(unsigned long indx, float v0)
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, FloatArray* v)
+void WebGLRenderingContext::vertexAttrib1fv(unsigned long indx, Float32Array* v)
{
// FIXME: Need to make sure array is big enough for attribute being set
m_context->vertexAttrib1fv(indx, v->data());
@@ -2788,7 +2983,7 @@ void WebGLRenderingContext::vertexAttrib2f(unsigned long indx, float v0, float v
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, FloatArray* v)
+void WebGLRenderingContext::vertexAttrib2fv(unsigned long indx, Float32Array* v)
{
// FIXME: Need to make sure array is big enough for attribute being set
m_context->vertexAttrib2fv(indx, v->data());
@@ -2810,7 +3005,7 @@ void WebGLRenderingContext::vertexAttrib3f(unsigned long indx, float v0, float v
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, FloatArray* v)
+void WebGLRenderingContext::vertexAttrib3fv(unsigned long indx, Float32Array* v)
{
// FIXME: Need to make sure array is big enough for attribute being set
m_context->vertexAttrib3fv(indx, v->data());
@@ -2832,7 +3027,7 @@ void WebGLRenderingContext::vertexAttrib4f(unsigned long indx, float v0, float v
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, FloatArray* v)
+void WebGLRenderingContext::vertexAttrib4fv(unsigned long indx, Float32Array* v)
{
// FIXME: Need to make sure array is big enough for attribute being set
m_context->vertexAttrib4fv(indx, v->data());
@@ -2872,7 +3067,8 @@ void WebGLRenderingContext::vertexAttribPointer(unsigned long indx, long size, u
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.
@@ -2995,7 +3191,7 @@ WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(unsigned long pn
default:
notImplemented();
}
- return WebGLGetInfo(FloatArray::create(value, length));
+ return WebGLGetInfo(Float32Array::create(value, length));
}
WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(unsigned long pname)
@@ -3042,8 +3238,7 @@ void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
if (isGLES2Compliant())
return;
bool resetActiveUnit = false;
- // FIXME: active texture unit limits should be queries instead of 32.
- for (unsigned long ii = 0; ii < 32; ++ii) {
+ for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()
|| m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture()) {
if (ii != m_activeTextureUnit) {
@@ -3097,6 +3292,150 @@ void WebGLRenderingContext::createFallbackBlackTextures1x1()
m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
}
+bool WebGLRenderingContext::isTexInternalformatColorBufferCombinationValid(unsigned long texInternalformat,
+ unsigned long colorBufferFormat)
+{
+ switch (colorBufferFormat) {
+ case GraphicsContext3D::ALPHA:
+ if (texInternalformat == GraphicsContext3D::ALPHA)
+ return true;
+ break;
+ case GraphicsContext3D::RGB:
+ if (texInternalformat == GraphicsContext3D::LUMINANCE
+ || texInternalformat == GraphicsContext3D::RGB)
+ return true;
+ break;
+ case GraphicsContext3D::RGBA:
+ return true;
+ }
+ return false;
+}
+
+WebGLTexture* WebGLRenderingContext::getTextureBinding(unsigned long target)
+{
+ RefPtr<WebGLTexture> tex = 0;
+ switch (target) {
+ case GraphicsContext3D::TEXTURE_2D:
+ tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
+ break;
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
+ break;
+ }
+ if (tex && tex->object())
+ return tex.get();
+ return 0;
+}
+
+bool WebGLRenderingContext::validateTexFuncFormatAndType(unsigned long format, unsigned long type)
+{
+ switch (format) {
+ case GraphicsContext3D::ALPHA:
+ case GraphicsContext3D::LUMINANCE:
+ case GraphicsContext3D::LUMINANCE_ALPHA:
+ case GraphicsContext3D::RGB:
+ case GraphicsContext3D::RGBA:
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_BYTE:
+ case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+ case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+ case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+
+ return true;
+}
+
+bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long level,
+ unsigned long internalformat,
+ long width, long height, long border,
+ unsigned long format, unsigned long type)
+{
+ if (isGLES2Compliant())
+ return true;
+
+ if (width < 0 || height < 0 || level < 0) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+
+ switch (target) {
+ case GraphicsContext3D::TEXTURE_2D:
+ if (width > m_maxTextureSize ||
+ height > m_maxTextureSize ||
+ level > log(static_cast<double>(m_maxTextureSize)) / log(2.0)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ break;
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (width != height ||
+ width > m_maxCubeMapTextureSize ||
+ level > log(static_cast<double>(m_maxCubeMapTextureSize)) / log(2.0)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+
+ if (format != internalformat) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return false;
+ }
+
+ if (border) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+
+ return validateTexFuncFormatAndType(format, type);
+}
+
+bool WebGLRenderingContext::validateDrawMode(unsigned long mode)
+{
+ switch (mode) {
+ case GraphicsContext3D::POINTS:
+ case GraphicsContext3D::LINE_STRIP:
+ case GraphicsContext3D::LINE_LOOP:
+ case GraphicsContext3D::LINES:
+ case GraphicsContext3D::TRIANGLE_STRIP:
+ case GraphicsContext3D::TRIANGLE_FAN:
+ case GraphicsContext3D::TRIANGLES:
+ return true;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return false;
+ }
+}
+
+void WebGLRenderingContext::printWarningToConsole(const String& message)
+{
+ canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel,
+ message, 0, canvas()->document()->url().string());
+}
+
} // namespace WebCore
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index d447529..552efa9 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -28,7 +28,7 @@
#include "CanvasRenderingContext.h"
#include "ExceptionCode.h"
-#include "FloatArray.h"
+#include "Float32Array.h"
#include "WebGLGetInfo.h"
#include "Int32Array.h"
#include "Uint8Array.h"
@@ -117,7 +117,7 @@ class WebKitCSSMatrix;
void disable(unsigned long cap);
void disableVertexAttribArray(unsigned long index, ExceptionCode&);
void drawArrays(unsigned long mode, long first, long count, ExceptionCode&);
- void drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset, ExceptionCode&);
+ void drawElements(unsigned long mode, long count, unsigned long type, long offset, ExceptionCode&);
void enable(unsigned long cap);
void enableVertexAttribArray(unsigned long index, ExceptionCode&);
@@ -181,9 +181,7 @@ class WebKitCSSMatrix;
void linkProgram(WebGLProgram*, ExceptionCode&);
void pixelStorei(unsigned long pname, long param);
void polygonOffset(double factor, double units);
-
- PassRefPtr<ArrayBufferView> readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type);
-
+ void readPixels(long x, long y, long width, long height, unsigned long format, unsigned long type, ArrayBufferView* pixels);
void releaseShaderCompiler();
void renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height);
void sampleCoverage(double value, bool invert);
@@ -199,6 +197,15 @@ class WebKitCSSMatrix;
void texImage2D(unsigned target, unsigned level, unsigned internalformat,
unsigned width, unsigned height, unsigned border,
unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode&);
+ void texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, ImageData* pixels, ExceptionCode&);
+ void texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode&);
+ void texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode&);
+ void texImage2D(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode&);
+ // Obsolete entry points -- to be removed shortly. (FIXME)
void texImage2D(unsigned target, unsigned level, ImageData* pixels, ExceptionCode&);
void texImage2D(unsigned target, unsigned level, ImageData* pixels, bool flipY, ExceptionCode&);
void texImage2D(unsigned target, unsigned level, ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode&);
@@ -218,6 +225,15 @@ class WebKitCSSMatrix;
void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
unsigned width, unsigned height,
unsigned format, unsigned type, ArrayBufferView* pixels, ExceptionCode&);
+ void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, ImageData* pixels, ExceptionCode&);
+ void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, HTMLImageElement* image, ExceptionCode&);
+ void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, HTMLCanvasElement* canvas, ExceptionCode&);
+ void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type, HTMLVideoElement* video, ExceptionCode&);
+ // Obsolete entry points -- to be removed shortly. (FIXME)
void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, ImageData* pixels, ExceptionCode&);
void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, ImageData* pixels, bool flipY, ExceptionCode&);
void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode&);
@@ -232,50 +248,50 @@ class WebKitCSSMatrix;
void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha, ExceptionCode&);
void uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode&);
- void uniform1fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode&);
+ void uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
void uniform1fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode&);
void uniform1i(const WebGLUniformLocation* location, int x, ExceptionCode&);
void uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
void uniform1iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode&);
void uniform2f(const WebGLUniformLocation* location, float x, float y, ExceptionCode&);
- void uniform2fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode&);
+ void uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
void uniform2fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode&);
void uniform2i(const WebGLUniformLocation* location, int x, int y, ExceptionCode&);
void uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
void uniform2iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode&);
void uniform3f(const WebGLUniformLocation* location, float x, float y, float z, ExceptionCode&);
- void uniform3fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode&);
+ void uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
void uniform3fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode&);
void uniform3i(const WebGLUniformLocation* location, int x, int y, int z, ExceptionCode&);
void uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
void uniform3iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode&);
void uniform4f(const WebGLUniformLocation* location, float x, float y, float z, float w, ExceptionCode&);
- void uniform4fv(const WebGLUniformLocation* location, FloatArray* v, ExceptionCode&);
+ void uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&);
void uniform4fv(const WebGLUniformLocation* location, float* v, int size, ExceptionCode&);
void uniform4i(const WebGLUniformLocation* location, int x, int y, int z, int w, ExceptionCode&);
void uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&);
void uniform4iv(const WebGLUniformLocation* location, int* v, int size, ExceptionCode&);
- void uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, FloatArray* value, ExceptionCode&);
+ void uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, Float32Array* value, ExceptionCode&);
void uniformMatrix2fv(const WebGLUniformLocation* location, bool transpose, float* value, int size, ExceptionCode&);
- void uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, FloatArray* value, ExceptionCode&);
+ void uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, Float32Array* value, ExceptionCode&);
void uniformMatrix3fv(const WebGLUniformLocation* location, bool transpose, float* value, int size, ExceptionCode&);
- void uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, FloatArray* value, ExceptionCode&);
+ void uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, Float32Array* value, ExceptionCode&);
void uniformMatrix4fv(const WebGLUniformLocation* location, bool transpose, float* value, int size, ExceptionCode&);
void useProgram(WebGLProgram*, ExceptionCode&);
void validateProgram(WebGLProgram*, ExceptionCode&);
void vertexAttrib1f(unsigned long indx, float x);
- void vertexAttrib1fv(unsigned long indx, FloatArray* values);
+ 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, FloatArray* values);
+ 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, FloatArray* values);
+ 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, FloatArray* values);
+ 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&);
@@ -340,6 +356,7 @@ class WebKitCSSMatrix;
VertexAttribState() : enabled(false), numElements(0) { }
bool enabled;
long numElements;
+ RefPtr<WebGLBuffer> bufferBinding;
};
Vector<VertexAttribState> m_vertexAttribState;
@@ -353,16 +370,21 @@ class WebKitCSSMatrix;
RefPtr<WebGLTexture> m_texture2DBinding;
RefPtr<WebGLTexture> m_textureCubeMapBinding;
};
- TextureUnitState m_textureUnits[32];
+ Vector<TextureUnitState> m_textureUnits;
unsigned long m_activeTextureUnit;
RefPtr<WebGLTexture> m_blackTexture2D;
RefPtr<WebGLTexture> m_blackTextureCubeMap;
+ long m_maxTextureSize;
+ long m_maxCubeMapTextureSize;
+
int m_packAlignment;
int m_unpackAlignment;
unsigned long m_implementationColorReadFormat;
unsigned long m_implementationColorReadType;
+ bool m_unpackFlipY;
+ bool m_unpackPremultiplyAlpha;
// Helpers for getParameter and others
WebGLGetInfo getBooleanParameter(unsigned long pname);
@@ -377,18 +399,50 @@ class WebKitCSSMatrix;
void texImage2DBase(unsigned target, unsigned level, unsigned internalformat,
unsigned width, unsigned height, unsigned border,
unsigned format, unsigned type, void* pixels, ExceptionCode&);
- void texImage2D(unsigned target, unsigned level, Image* image,
- bool flipY, bool premultiplyAlpha, ExceptionCode&);
+ void texImage2DImpl(unsigned target, unsigned level, unsigned internalformat,
+ unsigned format, unsigned type, Image* image,
+ bool flipY, bool premultiplyAlpha, ExceptionCode&);
void texSubImage2DBase(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
unsigned width, unsigned height,
unsigned format, unsigned type, void* pixels, ExceptionCode&);
- void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
- Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode&);
+ void texSubImage2DImpl(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned format, unsigned type,
+ Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode&);
void handleNPOTTextures(bool prepareToDraw);
void createFallbackBlackTextures1x1();
+ // Helper function for copyTex{Sub}Image, check whether the internalformat
+ // and the color buffer format of the current bound framebuffer combination
+ // is valid.
+ bool isTexInternalformatColorBufferCombinationValid(unsigned long texInternalformat,
+ unsigned long colorBufferFormat);
+
+ // Helper function to get the current bound texture.
+ 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.
+ 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.
+ 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 mode for draw{Arrays/Elements}.
+ bool validateDrawMode(unsigned long);
+
+ // Helper function for texParameterf and texParameteri.
+ void texParameter(unsigned long target, unsigned long pname, float parami, int paramf, bool isFloat);
+
+ // Helper function to print warnings to console. Currently
+ // used only to warn about use of obsolete functions.
+ void printWarningToConsole(const String& message);
+
friend class WebGLStateRestorer;
};
diff --git a/WebCore/html/canvas/WebGLRenderingContext.idl b/WebCore/html/canvas/WebGLRenderingContext.idl
index 029cae3..b3793f5 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.idl
+++ b/WebCore/html/canvas/WebGLRenderingContext.idl
@@ -459,6 +459,10 @@ module html {
const unsigned int INVALID_FRAMEBUFFER_OPERATION = 0x0506;
+ /* WebGL-specific enums */
+ const unsigned int UNPACK_FLIP_Y_WEBGL = 0x9240;
+ const unsigned int UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
+
long sizeInBytes(in unsigned long type) raises(DOMException);
void activeTexture(in unsigned long texture) raises(DOMException);
@@ -474,15 +478,9 @@ module html {
void blendFunc(in unsigned long sfactor, in unsigned long dfactor);
void blendFuncSeparate(in unsigned long srcRGB, in unsigned long dstRGB, in unsigned long srcAlpha, in unsigned long dstAlpha);
-#if defined(V8_BINDING) && V8_BINDING
void bufferData(in unsigned long target, in ArrayBufferView data, in unsigned long usage) raises (DOMException);
void bufferData(in unsigned long target, in long size, in unsigned long usage) raises (DOMException);
void bufferSubData(in unsigned long target, in long offset, in ArrayBufferView data) raises (DOMException);
-#else
- // FIXME: Unfork once JSC supports overload generation too.
- [Custom] void bufferData() raises(DOMException);
- [Custom] void bufferSubData() raises(DOMException);
-#endif
unsigned long checkFramebufferStatus(in unsigned long target);
void clear(in unsigned long mask);
@@ -521,8 +519,8 @@ module html {
void detachShader(in WebGLProgram program, in WebGLShader shader) raises(DOMException);
void disable(in unsigned long cap);
void disableVertexAttribArray(in unsigned long index) raises(DOMException);
- void drawArrays(in unsigned long mode, in long first, in unsigned long count) raises(DOMException);
- void drawElements(in unsigned long mode, in long count, in unsigned long type, in unsigned long offset) raises(DOMException);
+ void drawArrays(in unsigned long mode, in long first, in long count) raises(DOMException);
+ void drawElements(in unsigned long mode, in long count, in unsigned long type, in long offset) raises(DOMException);
void enable(in unsigned long cap);
void enableVertexAttribArray(in unsigned long index) raises(DOMException);
@@ -595,7 +593,7 @@ module html {
void pixelStorei(in unsigned long pname, in long param);
void polygonOffset(in double factor, in double units);
- ArrayBufferView readPixels(in long x, in long y, in unsigned long width, in unsigned long height, in unsigned long format, in unsigned long type);
+ void readPixels(in long x, in long y, in long width, in long height, in unsigned long format, in unsigned long type, in ArrayBufferView pixels);
void releaseShaderCompiler();
void renderbufferStorage(in unsigned long target, in unsigned long internalformat, in unsigned long width, in unsigned long height);
@@ -613,9 +611,17 @@ module html {
void texParameteri(in unsigned long target, in unsigned long pname, in long param);
// Supported forms:
-#if defined(V8_BINDING) && V8_BINDING
void texImage2D(in unsigned long target, in long level, in unsigned long internalformat, in long width, in long height,
in long border, in unsigned long format, in unsigned long type, in ArrayBufferView pixels) raises (DOMException);
+ void texImage2D(in unsigned long target, in long level, in unsigned long internalformat,
+ in unsigned long format, in unsigned long type, in ImageData pixels) raises (DOMException);
+ void texImage2D(in unsigned long target, in long level, in unsigned long internalformat,
+ in unsigned long format, in unsigned long type, in HTMLImageElement image) raises (DOMException);
+ void texImage2D(in unsigned long target, in long level, in unsigned long internalformat,
+ in unsigned long format, in unsigned long type, in HTMLCanvasElement canvas) raises (DOMException);
+ void texImage2D(in unsigned long target, in long level, in unsigned long internalformat,
+ in unsigned long format, in unsigned long type, in HTMLVideoElement video) raises (DOMException);
+ // Obsolete entry points -- to be removed shortly. (FIXME)
void texImage2D(in unsigned long target, in long level, in ImageData pixels,
in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException);
void texImage2D(in unsigned long target, in long level, in HTMLImageElement image,
@@ -629,6 +635,15 @@ module html {
in long width, in long height,
in unsigned long format, in unsigned long type, in ArrayBufferView pixels) raises (DOMException);
void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
+ in unsigned long format, in unsigned long type, in ImageData pixels) raises (DOMException);
+ void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
+ in unsigned long format, in unsigned long type, in HTMLImageElement image) raises (DOMException);
+ void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
+ in unsigned long format, in unsigned long type, in HTMLCanvasElement canvas) raises (DOMException);
+ void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
+ in unsigned long format, in unsigned long type, in HTMLVideoElement video) raises (DOMException);
+ // Obsolete entry points -- to be removed shortly. (FIXME)
+ void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
in ImageData pixels, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException);
void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
in HTMLImageElement image, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException);
@@ -636,43 +651,39 @@ module html {
in HTMLCanvasElement canvas, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException);
void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset,
in HTMLVideoElement video, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException);
-#else
- // FIXME: Unfork once JSC supports overload generation too.
- [Custom] void texImage2D();
- [Custom] void texSubImage2D();
-#endif
+
void uniform1f(in WebGLUniformLocation location, in float x) raises(DOMException);
- [Custom] void uniform1fv(in WebGLUniformLocation location, in FloatArray v) raises(DOMException);
+ [Custom] void uniform1fv(in WebGLUniformLocation location, in Float32Array v) raises(DOMException);
void uniform1i(in WebGLUniformLocation location, in long x) raises(DOMException);
[Custom] void uniform1iv(in WebGLUniformLocation location, in Int32Array v) raises(DOMException);
void uniform2f(in WebGLUniformLocation location, in float x, in float y) raises(DOMException);
- [Custom] void uniform2fv(in WebGLUniformLocation location, in FloatArray v) raises(DOMException);
+ [Custom] void uniform2fv(in WebGLUniformLocation location, in Float32Array v) raises(DOMException);
void uniform2i(in WebGLUniformLocation location, in long x, in long y) raises(DOMException);
[Custom] void uniform2iv(in WebGLUniformLocation location, in Int32Array v) raises(DOMException);
void uniform3f(in WebGLUniformLocation location, in float x, in float y, in float z) raises(DOMException);
- [Custom] void uniform3fv(in WebGLUniformLocation location, in FloatArray v) raises(DOMException);
+ [Custom] void uniform3fv(in WebGLUniformLocation location, in Float32Array v) raises(DOMException);
void uniform3i(in WebGLUniformLocation location, in long x, in long y, in long z) raises(DOMException);
[Custom] void uniform3iv(in WebGLUniformLocation location, in Int32Array v) raises(DOMException);
void uniform4f(in WebGLUniformLocation location, in float x, in float y, in float z, in float w) raises(DOMException);
- [Custom] void uniform4fv(in WebGLUniformLocation location, in FloatArray v) raises(DOMException);
+ [Custom] void uniform4fv(in WebGLUniformLocation location, in Float32Array v) raises(DOMException);
void uniform4i(in WebGLUniformLocation location, in long x, in long y, in long z, in long w) raises(DOMException);
[Custom] void uniform4iv(in WebGLUniformLocation location, in Int32Array v) raises(DOMException);
- [Custom] void uniformMatrix2fv(in WebGLUniformLocation location, in boolean transpose, in FloatArray array) raises(DOMException);
- [Custom] void uniformMatrix3fv(in WebGLUniformLocation location, in boolean transpose, in FloatArray array) raises(DOMException);
- [Custom] void uniformMatrix4fv(in WebGLUniformLocation location, in boolean transpose, in FloatArray array) raises(DOMException);
+ [Custom] void uniformMatrix2fv(in WebGLUniformLocation location, in boolean transpose, in Float32Array array) raises(DOMException);
+ [Custom] void uniformMatrix3fv(in WebGLUniformLocation location, in boolean transpose, in Float32Array array) raises(DOMException);
+ [Custom] void uniformMatrix4fv(in WebGLUniformLocation location, in boolean transpose, in Float32Array array) raises(DOMException);
void useProgram(in WebGLProgram program) raises(DOMException);
void validateProgram(in WebGLProgram program) raises(DOMException);
void vertexAttrib1f(in unsigned long indx, in float x);
- [Custom] void vertexAttrib1fv(in unsigned long indx, in FloatArray values);
+ [Custom] void vertexAttrib1fv(in unsigned long indx, in Float32Array values);
void vertexAttrib2f(in unsigned long indx, in float x, in float y);
- [Custom] void vertexAttrib2fv(in unsigned long indx, in FloatArray values);
+ [Custom] void vertexAttrib2fv(in unsigned long indx, in Float32Array values);
void vertexAttrib3f(in unsigned long indx, in float x, in float y, in float z);
- [Custom] void vertexAttrib3fv(in unsigned long indx, in FloatArray values);
+ [Custom] void vertexAttrib3fv(in unsigned long indx, in Float32Array values);
void vertexAttrib4f(in unsigned long indx, in float x, in float y, in float z, in float w);
- [Custom] void vertexAttrib4fv(in unsigned long indx, in FloatArray values);
+ [Custom] void vertexAttrib4fv(in unsigned long indx, in Float32Array values);
void vertexAttribPointer(in unsigned long indx, in long size, in unsigned long type, in boolean normalized,
in long stride, in unsigned long offset) raises(DOMException);
diff --git a/WebCore/html/canvas/WebGLTexture.cpp b/WebCore/html/canvas/WebGLTexture.cpp
index 4e4096b..d24405a 100644
--- a/WebCore/html/canvas/WebGLTexture.cpp
+++ b/WebCore/html/canvas/WebGLTexture.cpp
@@ -45,6 +45,7 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx)
, m_magFilter(GraphicsContext3D::LINEAR)
, m_wrapS(GraphicsContext3D::REPEAT)
, m_wrapT(GraphicsContext3D::REPEAT)
+ , m_internalformat(0)
, m_isNPOT(false)
, m_needToUseBlackTexture(false)
{
diff --git a/WebCore/html/canvas/WebGLTexture.h b/WebCore/html/canvas/WebGLTexture.h
index 864533e..889e902 100644
--- a/WebCore/html/canvas/WebGLTexture.h
+++ b/WebCore/html/canvas/WebGLTexture.h
@@ -52,6 +52,9 @@ namespace WebCore {
void setParameterf(unsigned long pname, float param);
void setSize(unsigned long target, unsigned width, unsigned height);
+ void setInternalformat(unsigned long internalformat) { m_internalformat = internalformat; }
+ unsigned long getInternalformat() const { return m_internalformat; }
+
static bool isNPOT(unsigned, unsigned);
bool isNPOT() const { return m_isNPOT; }
@@ -77,6 +80,8 @@ namespace WebCore {
int m_wrapS;
int m_wrapT;
+ unsigned long m_internalformat;
+
unsigned m_width[6];
unsigned m_height[6];