Diff
Modified: trunk/Source/WebCore/ChangeLog (99323 => 99324)
--- trunk/Source/WebCore/ChangeLog 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/ChangeLog 2011-11-04 21:43:56 UTC (rev 99324)
@@ -1,3 +1,39 @@
+2011-11-04 Dmitry Lomov <dslo...@google.com>
+
+ Add the ability to transfer ArrayBuffer and "neuter" it.
+ https://bugs.webkit.org/show_bug.cgi?id=71535
+
+ Reviewed by David Levin.
+
+ * html/canvas/ArrayBuffer.cpp:
+ (WebCore::ArrayBuffer::create):
+ (WebCore::ArrayBuffer::ArrayBuffer):
+ (WebCore::ArrayBuffer::data):
+ (WebCore::ArrayBuffer::byteLength):
+ (WebCore::ArrayBuffer::transfer):
+ (WebCore::ArrayBufferContents::~ArrayBufferContents):
+ (WebCore::ArrayBufferContents::tryAllocate):
+ (WebCore::ArrayBuffer::addView):
+ (WebCore::ArrayBuffer::removeView):
+ * html/canvas/ArrayBuffer.h:
+ (WebCore::ArrayBufferContents::ArrayBufferContents):
+ (WebCore::ArrayBufferContents::data):
+ (WebCore::ArrayBufferContents::sizeInBytes):
+ (WebCore::ArrayBufferContents::release):
+ (WebCore::ArrayBuffer::~ArrayBuffer):
+ * html/canvas/ArrayBufferView.cpp:
+ (WebCore::ArrayBufferView::ArrayBufferView):
+ (WebCore::ArrayBufferView::~ArrayBufferView):
+ (WebCore::ArrayBufferView::neuter):
+ * html/canvas/ArrayBufferView.h:
+ * html/canvas/DataView.cpp:
+ (WebCore::DataView::neuter):
+ (WebCore::DataView::neuterBinding):
+ * html/canvas/DataView.h:
+ * html/canvas/TypedArrayBase.h:
+ (WebCore::TypedArrayBase::neuter):
+ (WebCore::TypedArrayBase::neuterBinding):
+
2011-11-04 Noel Gordon <noel.gor...@gmail.com>
[Chromium] Implement canvas.toDataURL("image/webp")
Modified: trunk/Source/WebCore/html/canvas/ArrayBuffer.cpp (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/ArrayBuffer.cpp 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBuffer.cpp 2011-11-04 21:43:56 UTC (rev 99324)
@@ -25,6 +25,7 @@
#include "config.h"
#include "ArrayBuffer.h"
+#include "ArrayBufferView.h"
#include <wtf/RefPtr.h>
@@ -42,10 +43,11 @@
PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
{
- void* data = "" elementByteSize);
- if (!data)
+ ArrayBufferContents contents;
+ ArrayBufferContents::tryAllocate(numElements, elementByteSize, contents);
+ if (!contents.m_data)
return 0;
- return adoptRef(new ArrayBuffer(data, numElements * elementByteSize));
+ return adoptRef(new ArrayBuffer(contents));
}
PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
@@ -55,33 +57,39 @@
PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
{
- void* data = "" 1);
- if (!data)
+ ArrayBufferContents contents;
+ ArrayBufferContents::tryAllocate(byteLength, 1, contents);
+ if (!contents.m_data)
return 0;
- RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(data, byteLength));
+ RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(contents));
memcpy(buffer->data(), source, byteLength);
return buffer.release();
}
-ArrayBuffer::ArrayBuffer(void* data, unsigned sizeInBytes)
- : m_sizeInBytes(sizeInBytes)
- , m_data(data)
+PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents& contents)
{
+ return adoptRef(new ArrayBuffer(contents));
}
+ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents)
+ : m_firstView(0)
+{
+ contents.transfer(m_contents);
+}
+
void* ArrayBuffer::data()
{
- return m_data;
+ return m_contents.m_data;
}
const void* ArrayBuffer::data() const
{
- return m_data;
+ return m_contents.m_data;
}
unsigned ArrayBuffer::byteLength() const
{
- return m_sizeInBytes;
+ return m_contents.m_sizeInBytes;
}
PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const
@@ -108,26 +116,70 @@
return clampValue(index, 0, currentLength);
}
-ArrayBuffer::~ArrayBuffer()
+void ArrayBuffer::transfer(ScriptExecutionContext* context, ArrayBufferContents& result, ExceptionCode& ec)
{
+ RefPtr<ArrayBuffer> keepAlive(this);
+
+ if (!m_contents.m_data) {
+ ec = INVALID_STATE_ERR;
+ result.m_data = 0;
+ return;
+ }
+
+ m_contents.transfer(result);
+
+ while (m_firstView) {
+ ArrayBufferView* current = m_firstView;
+ removeView(current);
+ current->neuter(context);
+ }
+}
+
+ArrayBufferContents::~ArrayBufferContents()
+{
WTF::fastFree(m_data);
}
-void* ArrayBuffer::tryAllocate(unsigned numElements, unsigned elementByteSize)
+void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents& result)
{
- void* result;
// Do not allow 32-bit overflow of the total size.
// FIXME: Why not? The tryFastCalloc function already checks its arguments,
// and will fail if there is any overflow, so why should we include a
// redudant unnecessarily restrictive check here?
if (numElements) {
unsigned totalSize = numElements * elementByteSize;
- if (totalSize / numElements != elementByteSize)
- return 0;
+ if (totalSize / numElements != elementByteSize) {
+ result.m_data = 0;
+ return;
+ }
}
- if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result))
- return result;
- return 0;
+ if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data)) {
+ result.m_sizeInBytes = numElements * elementByteSize;
+ return;
+ }
+ result.m_data = 0;
}
+void ArrayBuffer::addView(ArrayBufferView* view)
+{
+ view->m_buffer = this;
+ view->m_prevView = 0;
+ view->m_nextView = m_firstView;
+ if (m_firstView)
+ m_firstView->m_prevView = view;
+ m_firstView = view;
}
+
+void ArrayBuffer::removeView(ArrayBufferView* view)
+{
+ ASSERT(this == view->m_buffer);
+ if (view->m_nextView)
+ view->m_nextView->m_prevView = view->m_prevView;
+ if (view->m_prevView)
+ view->m_prevView->m_nextView = view->m_nextView;
+ if (m_firstView == view)
+ m_firstView = view->m_nextView;
+ view->m_prevView = view->m_nextView = 0;
+}
+
+}
Modified: trunk/Source/WebCore/html/canvas/ArrayBuffer.h (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/ArrayBuffer.h 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBuffer.h 2011-11-04 21:43:56 UTC (rev 99324)
@@ -26,16 +26,57 @@
#ifndef ArrayBuffer_h
#define ArrayBuffer_h
+#include "ExceptionCode.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
namespace WebCore {
+class ArrayBuffer;
+class ArrayBufferView;
+class ScriptExecutionContext;
+
+class ArrayBufferContents {
+ WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
+public:
+ ArrayBufferContents()
+ : m_data(0)
+ , m_sizeInBytes(0)
+ { }
+
+ ~ArrayBufferContents();
+
+ void* data() { return m_data; }
+ unsigned sizeInBytes() { return m_sizeInBytes; }
+
+private:
+ ArrayBufferContents(void* data, unsigned sizeInBytes)
+ : m_data(data)
+ , m_sizeInBytes(sizeInBytes)
+ { }
+
+ friend class ArrayBuffer;
+
+ static void tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents&);
+ void transfer(ArrayBufferContents& other)
+ {
+ ASSERT(!other.m_data);
+ other.m_data = m_data;
+ other.m_sizeInBytes = m_sizeInBytes;
+ m_data = 0;
+ m_sizeInBytes = 0;
+ }
+
+ void* m_data;
+ unsigned m_sizeInBytes;
+};
+
class ArrayBuffer : public RefCounted<ArrayBuffer> {
- public:
+public:
static PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
static PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
static PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
+ static PassRefPtr<ArrayBuffer> create(ArrayBufferContents&);
void* data();
const void* data() const;
@@ -44,17 +85,20 @@
PassRefPtr<ArrayBuffer> slice(int begin, int end) const;
PassRefPtr<ArrayBuffer> slice(int begin) const;
- ~ArrayBuffer();
+ void addView(ArrayBufferView*);
+ void removeView(ArrayBufferView*);
- private:
- ArrayBuffer(void* data, unsigned sizeInBytes);
- ArrayBuffer(unsigned numElements, unsigned elementByteSize);
- static void* tryAllocate(unsigned numElements, unsigned elementByteSize);
+ void transfer(ScriptExecutionContext*, ArrayBufferContents&, ExceptionCode&);
+
+ ~ArrayBuffer() { }
+
+private:
+ ArrayBuffer(ArrayBufferContents&);
PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
unsigned clampIndex(int index) const;
- unsigned m_sizeInBytes;
- void* m_data;
+ ArrayBufferContents m_contents;
+ ArrayBufferView* m_firstView;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/canvas/ArrayBufferView.cpp (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/ArrayBufferView.cpp 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBufferView.cpp 2011-11-04 21:43:56 UTC (rev 99324)
@@ -36,10 +36,14 @@
, m_buffer(buffer)
{
m_baseAddress = m_buffer ? (static_cast<char*>(m_buffer->data()) + m_byteOffset) : 0;
+ if (m_buffer)
+ m_buffer->addView(this);
}
ArrayBufferView::~ArrayBufferView()
{
+ if (m_buffer)
+ m_buffer->removeView(this);
}
void ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset, ExceptionCode& ec)
@@ -101,4 +105,10 @@
*length = static_cast<unsigned>(end - start);
}
+void ArrayBufferView::neuter(ScriptExecutionContext*)
+{
+ m_buffer = 0;
+ m_byteOffset = 0;
}
+
+}
Modified: trunk/Source/WebCore/html/canvas/ArrayBufferView.h (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/ArrayBufferView.h 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBufferView.h 2011-11-04 21:43:56 UTC (rev 99324)
@@ -119,13 +119,18 @@
*numElements = std::min(remainingElements, *numElements);
}
+ virtual void neuter(ScriptExecutionContext*);
+
// This is the address of the ArrayBuffer's storage, plus the byte offset.
void* m_baseAddress;
unsigned m_byteOffset;
private:
+ friend class ArrayBuffer;
RefPtr<ArrayBuffer> m_buffer;
+ ArrayBufferView* m_prevView;
+ ArrayBufferView* m_nextView;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/canvas/DataView.cpp (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/DataView.cpp 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/DataView.cpp 2011-11-04 21:43:56 UTC (rev 99324)
@@ -235,4 +235,16 @@
setData<double>(byteOffset, value, littleEndian, ec);
}
+void DataView::neuter(ScriptExecutionContext* context)
+{
+ ArrayBufferView::neuter(context);
+ m_byteLength = 0;
+ neuterBinding(context);
}
+
+void DataView::neuterBinding(ScriptExecutionContext*)
+{
+ // FIXME https://bugs.webkit.org/show_bug.cgi?id=71534
+}
+
+}
Modified: trunk/Source/WebCore/html/canvas/DataView.h (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/DataView.h 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/DataView.h 2011-11-04 21:43:56 UTC (rev 99324)
@@ -72,6 +72,10 @@
void setFloat64(unsigned byteOffset, double value, ExceptionCode& ec) { setFloat64(byteOffset, value, false, ec); }
void setFloat64(unsigned byteOffset, double value, bool littleEndian, ExceptionCode&);
+protected:
+ virtual void neuter(ScriptExecutionContext*);
+ virtual void neuterBinding(ScriptExecutionContext*);
+
private:
DataView(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength);
Modified: trunk/Source/WebCore/html/canvas/TypedArrayBase.h (99323 => 99324)
--- trunk/Source/WebCore/html/canvas/TypedArrayBase.h 2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/TypedArrayBase.h 2011-11-04 21:43:56 UTC (rev 99324)
@@ -112,6 +112,18 @@
return create<Subclass>(buffer(), offset, length);
}
+ virtual void neuter(ScriptExecutionContext* context)
+ {
+ ArrayBufferView::neuter(context);
+ m_length = 0;
+ neuterBinding(context);
+ }
+
+ virtual void neuterBinding(ScriptExecutionContext*)
+ {
+ // FIXME https://bugs.webkit.org/show_bug.cgi?id=71534
+ }
+
// We do not want to have to access this via a virtual function in subclasses,
// which is why it is protected rather than private.
unsigned m_length;