Diff
Modified: trunk/LayoutTests/ChangeLog (118954 => 118955)
--- trunk/LayoutTests/ChangeLog 2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/LayoutTests/ChangeLog 2012-05-30 19:44:22 UTC (rev 118955)
@@ -1,3 +1,16 @@
+2012-05-30 Ulan Degenbaev <[email protected]>
+
+ [v8] Crash after redefining setter on typed array to a number
+ https://bugs.webkit.org/show_bug.cgi?id=87862
+
+ Reviewed by Kenneth Russell.
+
+ Remove calls to typed array set() method from C++.
+ Store the copying script as a hidden property of a typed array prototype.
+
+ * fast/canvas/webgl/array-override-set-expected.txt: Added.
+ * fast/canvas/webgl/array-override-set.html: Added.
+
2012-05-30 Stephen Chenney <[email protected]>
http/tests/cache/subresource-expiration-2.html is slow on Linux
Added: trunk/LayoutTests/fast/canvas/webgl/array-override-set-expected.txt (0 => 118955)
--- trunk/LayoutTests/fast/canvas/webgl/array-override-set-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/array-override-set-expected.txt 2012-05-30 19:44:22 UTC (rev 118955)
@@ -0,0 +1,27 @@
+Test overriding the set method of WebGL array
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+Regression test for ????
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/canvas/webgl/array-override-set.html (0 => 118955)
--- trunk/LayoutTests/fast/canvas/webgl/array-override-set.html (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/array-override-set.html 2012-05-30 19:44:22 UTC (rev 118955)
@@ -0,0 +1,47 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Test overriding the set method of WebGL array");
+
+debug('Regression test for ????');
+
+var array;
+var typeNames = ['Float32Array', 'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array',
+ 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array']
+
+function overrideSetWithNumberAndConstruct(typeName) {
+ var type = window[typeName];
+ type.prototype.set = 0x3ffff;
+ array = new type([0], function() {});
+ shouldBe("array[0]", "0");
+}
+
+for (var i = 0; i < typeNames.length; i++) {
+ overrideSetWithNumberAndConstruct(typeNames[i]);
+}
+
+function overrideSetWithNumberAndSet(typeName) {
+ var type = window[typeName];
+ array = new type(10);
+ type.prototype.set = 0x3ffff;
+ array[0] = 8;
+ array.set([0], function() {});
+ shouldBe("array[0]", "0");
+}
+
+for (var i = 0; i < typeNames.length; i++) {
+ overrideSetWithNumberAndConstruct(typeNames[i]);
+}
+
+</script>
+
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (118954 => 118955)
--- trunk/Source/WebCore/ChangeLog 2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/ChangeLog 2012-05-30 19:44:22 UTC (rev 118955)
@@ -1,3 +1,26 @@
+2012-05-30 Ulan Degenbaev <[email protected]>
+
+ [v8] Crash after redefining setter on typed array to a number
+ https://bugs.webkit.org/show_bug.cgi?id=87862
+
+ Reviewed by Kenneth Russell.
+
+ Remove calls to typed array set() method from C++.
+ Store the copying script as a hidden property of a typed array prototype.
+
+ Test: fast/canvas/webgl/array-override-set.html
+
+ * bindings/v8/custom/V8ArrayBufferViewCustom.cpp:
+ (WebCore):
+ (WebCore::getHiddenCopyMethod):
+ (WebCore::installHiddenCopyMethod):
+ (WebCore::copyElements):
+ * bindings/v8/custom/V8ArrayBufferViewCustom.h:
+ (WebCore):
+ (WebCore::constructWebGLArray):
+ (WebCore::setWebGLArrayHelper):
+ * bindings/v8/custom/V8ArrayBufferViewCustomScript.js:
+
2012-05-30 David Hyatt <[email protected]>
https://bugs.webkit.org/show_bug.cgi?id=87882
Modified: trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.cpp (118954 => 118955)
--- trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.cpp 2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.cpp 2012-05-30 19:44:22 UTC (rev 118955)
@@ -27,51 +27,51 @@
#include "V8ArrayBufferViewCustom.h"
#include "V8ArrayBufferViewCustomScript.h"
+
#include <v8.h>
namespace WebCore {
// The random suffix helps to avoid name collision.
-const char fastSetFlagName[] = "TypedArray::FastSet::8NkZVq";
+const char hiddenCopyMethodName[] = "TypedArray::HiddenCopy::8NkZVq";
-bool fastSetInstalled(v8::Handle<v8::Object> array)
+v8::Handle<v8::Value> getHiddenCopyMethod(v8::Handle<v8::Object> prototype)
{
- // Use a hidden flag in the global object an indicator of whether the fast
- // 'set' is installed or not.
- v8::Handle<v8::Object> global = array->CreationContext()->Global();
- v8::Handle<v8::String> key = v8::String::New(fastSetFlagName);
- v8::Handle<v8::Value> fastSetFlag = global->GetHiddenValue(key);
- return !fastSetFlag.IsEmpty();
+ v8::Handle<v8::String> key = v8::String::New(hiddenCopyMethodName);
+ return prototype->GetHiddenValue(key);
}
-void installFastSet(v8::Handle<v8::Object> array)
-{
+v8::Handle<v8::Value> installHiddenCopyMethod(v8::Handle<v8::Object> prototype) {
v8::TryCatch tryCatch;
tryCatch.SetVerbose(true);
- v8::Handle<v8::Object> global = array->CreationContext()->Global();
- v8::Handle<v8::String> key = v8::String::New(fastSetFlagName);
- global->SetHiddenValue(key, v8::Boolean::New(true));
-
String source(reinterpret_cast<const char*>(V8ArrayBufferViewCustomScript_js),
sizeof(V8ArrayBufferViewCustomScript_js));
v8::Handle<v8::Script> script = v8::Script::Compile(v8String(source));
- script->Run();
+ v8::Handle<v8::Value> value = script->Run();
+ v8::Handle<v8::String> key = v8::String::New(hiddenCopyMethodName);
+ prototype->SetHiddenValue(key, value);
+ return value;
}
-
-void copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t offset)
+bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t length, uint32_t offset)
{
- v8::Handle<v8::String> key = v8::String::New("set");
- v8::Handle<v8::Function> set = destArray->Get(key).As<v8::Function>();
- v8::Handle<v8::Value> arguments[2];
- int numberOfArguments = 1;
+ v8::Handle<v8::Value> prototype_value = destArray->GetPrototype();
+ if (prototype_value.IsEmpty() || !prototype_value->IsObject())
+ return false;
+ v8::Handle<v8::Object> prototype = prototype_value.As<v8::Object>();
+ v8::Handle<v8::Value> value = getHiddenCopyMethod(prototype);
+ if (value.IsEmpty())
+ value = installHiddenCopyMethod(prototype);
+ if (value.IsEmpty() || !value->IsFunction())
+ return false;
+ v8::Handle<v8::Function> copy_method = value.As<v8::Function>();
+ v8::Handle<v8::Value> arguments[3];
arguments[0] = srcArray;
- if (offset) {
- arguments[1] = v8::Uint32::New(offset);
- numberOfArguments = 2;
- }
- set->Call(destArray, numberOfArguments, arguments);
+ arguments[1] = v8::Uint32::New(length);
+ arguments[2] = v8::Uint32::New(offset);
+ copy_method->Call(destArray, 3, arguments);
+ return true;
}
}
Modified: trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h (118954 => 118955)
--- trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h 2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h 2012-05-30 19:44:22 UTC (rev 118955)
@@ -40,20 +40,11 @@
namespace WebCore {
+// Copy the elements from the source array to the typed destination array.
+// Returns true if it succeeded, otherwise returns false.
+bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t length, uint32_t offset);
-// Check if the _javascript_ 'set' method was already installed
-// on the prototype of the given typed array.
-bool fastSetInstalled(v8::Handle<v8::Object> array);
-// Install the _javascript_ 'set' method on the prototype of
-// the given typed array.
-void installFastSet(v8::Handle<v8::Object> array);
-
-// Copy the elements from the source array to the typed destination array by
-// invoking the 'set' method of the destination array in JS.
-void copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t offset);
-
-
// Template function used by the ArrayBufferView*Constructor callbacks.
template<class ArrayClass, class ElementType>
v8::Handle<v8::Value> constructWebGLArrayWithArrayBufferArgument(const v8::Arguments& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool hasIndexer)
@@ -173,8 +164,13 @@
V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get());
args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length());
- if (!srcArray.IsEmpty())
- copyElements(args.Holder(), srcArray, 0);
+ if (!srcArray.IsEmpty()) {
+ bool copied = copyElements(args.Holder(), srcArray, len, 0);
+ if (!copied) {
+ for (unsigned i = 0; i < len; i++)
+ array->set(i, srcArray->Get(i)->NumberValue());
+ }
+ }
v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::New(args.Holder());
wrapper.MarkIndependent();
@@ -214,11 +210,8 @@
// Out of range offset or overflow
return V8Proxy::setDOMException(INDEX_SIZE_ERR, args.GetIsolate());
}
-
- if (!fastSetInstalled(args.Holder())) {
- installFastSet(args.Holder());
- copyElements(args.Holder(), array, offset);
- } else {
+ bool copied = copyElements(args.Holder(), array, length, offset);
+ if (!copied) {
for (uint32_t i = 0; i < length; i++)
impl->set(offset + i, array->Get(i)->NumberValue());
}
Modified: trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustomScript.js (118954 => 118955)
--- trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustomScript.js 2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustomScript.js 2012-05-30 19:44:22 UTC (rev 118955)
@@ -23,42 +23,14 @@
*/
(function() {
-
-var optimizeSetMethod = function(type)
-{
- if (typeof type === 'function' &&
- typeof type.prototype !== 'undefined' &&
- typeof type.prototype.set === 'function') {
- type.prototype.set = (function() {
- var nativeSet = type.prototype.set;
- var f = function(source, offset)
- {
- if (source.constructor === Array) {
- var length = source.length;
- offset = offset || 0;
- if (offset < 0 || offset + length > this.length) {
- return nativeSet.call(this, source, offset);
- }
- for (var i = 0; i < length; i++)
- this[i + offset] = source[i];
- } else
- return nativeSet.call(this, source, offset);
- }
- f.name = "set";
- return f;
- })();
+ return function(source, length, offset) {
+ if (offset == 0) {
+ for (var i = 0; i < length; i++)
+ this[i] = source[i];
+ } else {
+ for (var i = 0; i < length; i++)
+ this[i + offset] = source[i];
+ }
}
-};
-
-optimizeSetMethod(Float32Array);
-optimizeSetMethod(Float64Array);
-optimizeSetMethod(Int8Array);
-optimizeSetMethod(Int16Array);
-optimizeSetMethod(Int32Array);
-optimizeSetMethod(Uint8Array);
-optimizeSetMethod(Uint8ClampedArray);
-optimizeSetMethod(Uint16Array);
-optimizeSetMethod(Uint32Array);
-
})();