Diff
Modified: trunk/LayoutTests/ChangeLog (159274 => 159275)
--- trunk/LayoutTests/ChangeLog 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/ChangeLog 2013-11-14 05:46:10 UTC (rev 159275)
@@ -1,3 +1,20 @@
+2013-11-13 Victor Costan <[email protected]>
+
+ Blob constructor accepts a sequence (array-like object) as first arg.
+ https://bugs.webkit.org/show_bug.cgi?id=124175
+
+ Reviewed by Christophe Dumez.
+
+
+ * crypto/subtle/argument-conversion-expected.txt: Updated sequence error expectations.
+ * fast/dom/Window/window-postmessage-args-expected.txt: Updated sequence error expectations.
+ * fast/events/constructors/message-event-constructor-expected.txt: Updated sequence error expectations.
+ * fast/events/message-port-multi-expected.txt: Updated sequence error expectations.
+ * fast/files/blob-constructor-expected.txt: Updated error text and added expectations.
+ * fast/files/script-tests/blob-constructor.js: Added sequence test cases.
+ * fast/workers/worker-context-multi-port-expected.txt: Updated sequence error expectations.
+ * fast/workers/worker-multi-port-expected.txt: Updated sequence error expectations.
+
2013-11-13 Sun-woo Nam <[email protected]>
[EFL] Layout tests with css3 selectors3 properties need to be rebaselined.
Modified: trunk/LayoutTests/crypto/subtle/argument-conversion-expected.txt (159274 => 159275)
--- trunk/LayoutTests/crypto/subtle/argument-conversion-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/crypto/subtle/argument-conversion-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -17,8 +17,8 @@
Passing invalid data to digest()
PASS crypto.subtle.digest({name: 'sha-1'}) threw exception TypeError: Not enough arguments.
-PASS crypto.subtle.digest({name: 'sha-1'}, null) threw exception TypeError: Type error.
-PASS crypto.subtle.digest({name: 'sha-1'}, 10) threw exception TypeError: Type error.
+PASS crypto.subtle.digest({name: 'sha-1'}, null) threw exception TypeError: Value is not a sequence.
+PASS crypto.subtle.digest({name: 'sha-1'}, 10) threw exception TypeError: Value is not a sequence.
PASS crypto.subtle.digest({name: 'sha-1'}, [10]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be part of CryptoOperationData sequence.
PASS crypto.subtle.digest({name: 'sha-1'}, new Uint8Array([0])) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be part of CryptoOperationData sequence.
Modified: trunk/LayoutTests/fast/dom/Window/window-postmessage-args-expected.txt (159274 => 159275)
--- trunk/LayoutTests/fast/dom/Window/window-postmessage-args-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/dom/Window/window-postmessage-args-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -1,8 +1,8 @@
Test that the second argument of window.postMessage is ignored or triggers an error if it is not a message port. You should see PASS message '1' through '7', followed by 'done', with messages 4-7 received below.
-PASS: Posting message ('1', 1): threw exception TypeError: Type error
-PASS: Posting message ('2', c): threw exception TypeError: Type error
-PASS: Posting message ('3', [object Object]): threw exception TypeError: Type error
+PASS: Posting message ('1', 1): threw exception TypeError: Value is not a sequence
+PASS: Posting message ('2', c): threw exception TypeError: Value is not a sequence
+PASS: Posting message ('3', [object Object]): threw exception TypeError: Value is not a sequence
PASS: Posting message ('4', [object Window]) did not throw an exception
PASS: Posting message ('4a', *) did not throw an exception
PASS: Posting message ('5', null) did not throw an exception
Modified: trunk/LayoutTests/fast/events/constructors/message-event-constructor-expected.txt (159274 => 159275)
--- trunk/LayoutTests/fast/events/constructors/message-event-constructor-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/events/constructors/message-event-constructor-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -83,18 +83,18 @@
PASS new MessageEvent('eventType', { ports: undefined }).ports is []
PASS new MessageEvent('eventType', { ports: null }).ports is []
PASS new MessageEvent('eventType', { ports: [1, 2, 3] }).ports[2] threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: test_object }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: document }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: false }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: true }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: '' }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: 'chocolate' }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: 12345 }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: 18446744073709551615 }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { ports: NaN }).ports threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { get ports() { return 123; } }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: test_object }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: document }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: false }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: true }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: '' }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: 'chocolate' }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: 12345 }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: 18446744073709551615 }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { ports: NaN }).ports threw exception TypeError: Value is not a sequence.
+PASS new MessageEvent('eventType', { get ports() { return 123; } }).ports threw exception TypeError: Value is not a sequence.
PASS new MessageEvent('eventType', { get ports() { throw 'MessageEvent Error'; } }) threw exception MessageEvent Error.
-PASS new MessageEvent('eventType', { ports: {valueOf: function () { return [channel.port1, channel.port2, channel.port2]; } } }).ports[0] threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: {valueOf: function () { return [channel.port1, channel.port2, channel.port2]; } } }).ports[0] threw exception TypeError: Value is not a sequence.
PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel2.port1] }).bubbles is true
PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel2.port1] }).cancelable is true
PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel2.port1] }).data is test_object
Modified: trunk/LayoutTests/fast/events/message-port-multi-expected.txt (159274 => 159275)
--- trunk/LayoutTests/fast/events/message-port-multi-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/events/message-port-multi-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -8,7 +8,7 @@
PASS channel.port1.postMessage("null port", [channel3.port1, null, channel3.port2]) threw exception Error: InvalidStateError: DOM Exception 11.
PASS channel.port1.postMessage("notAPort", [channel3.port1, {}, channel3.port2]) threw exception TypeError: Type error.
PASS channel.port1.postMessage("duplicate port", [channel3.port1, channel3.port1]) threw exception Error: InvalidStateError: DOM Exception 11.
-PASS channel.port1.postMessage("notAnArray", channel3.port1) threw exception TypeError: Type error.
+PASS channel.port1.postMessage("notAnArray", channel3.port1) threw exception TypeError: Value is not a sequence.
PASS channel.port1.postMessage("notASequence", [{length: 3}]) threw exception TypeError: Type error.
PASS channel.port1.postMessage("largeSequence", largePortArray) threw exception Error: InvalidStateError: DOM Exception 11.
PASS event.ports is non-null and zero length when no port sent
Modified: trunk/LayoutTests/fast/files/blob-constructor-expected.txt (159274 => 159275)
--- trunk/LayoutTests/fast/files/blob-constructor-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/files/blob-constructor-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -10,8 +10,8 @@
PASS (new Blob(['hello'], {type:'text/html'})) instanceof window.Blob is true
PASS (new Blob(['hello'], {type:'text/html', endings:'native'})) instanceof window.Blob is true
PASS (new Blob(['hello'], {type:'text/html', endings:'transparent'})) instanceof window.Blob is true
-PASS new Blob('hello') threw exception TypeError: First argument of the constructor is not of type Array.
-PASS new Blob(0) threw exception TypeError: First argument of the constructor is not of type Array.
+PASS new Blob('hello') threw exception TypeError: Value is not a sequence.
+PASS new Blob(0) threw exception TypeError: Value is not a sequence.
PASS (new Blob([])) instanceof window.Blob is true
PASS (new Blob(['stringPrimitive'])) instanceof window.Blob is true
PASS (new Blob([String('stringObject')])) instanceof window.Blob is true
@@ -72,6 +72,12 @@
PASS new Blob([(new Float64Array(100)).buffer]).size is 800
PASS new Blob([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size is 1400
PASS new Blob([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size is 1000
+PASS new Blob({length: 0}) instanceof window.Blob is true
+PASS new Blob({length: 0}).size is 0
+PASS new Blob({length: 1, 0: 'string'}).size is 6
+PASS new Blob({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}).size is 300
+PASS new Blob({length: 1, 0: 'string'}, {type: 'text/html'}).type is 'text/html'
+PASS new Blob({length: 0}, {endings:'illegal'}) threw exception TypeError: The endings property must be either "transparent" or "native".
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/files/script-tests/blob-constructor.js (159274 => 159275)
--- trunk/LayoutTests/fast/files/script-tests/blob-constructor.js 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/files/script-tests/blob-constructor.js 2013-11-14 05:46:10 UTC (rev 159275)
@@ -10,8 +10,8 @@
shouldBeTrue("(new Blob(['hello'], {type:'text/html', endings:'transparent'})) instanceof window.Blob");
// Test invalid blob parts
-shouldThrow("new Blob('hello')", "'TypeError: First argument of the constructor is not of type Array'");
-shouldThrow("new Blob(0)", "'TypeError: First argument of the constructor is not of type Array'");
+shouldThrow("new Blob('hello')", "'TypeError: Value is not a sequence'");
+shouldThrow("new Blob(0)", "'TypeError: Value is not a sequence'");
// Test valid blob parts.
shouldBeTrue("(new Blob([])) instanceof window.Blob");
@@ -98,3 +98,11 @@
shouldBe("new Blob([(new Float64Array(100)).buffer]).size", "800");
shouldBe("new Blob([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1400");
shouldBe("new Blob([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1000");
+
+// Test passing blob parts in sequences.
+shouldBeTrue("new Blob({length: 0}) instanceof window.Blob");
+shouldBe("new Blob({length: 0}).size", "0");
+shouldBe("new Blob({length: 1, 0: 'string'}).size", "6");
+shouldBe("new Blob({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}).size", "300");
+shouldBe("new Blob({length: 1, 0: 'string'}, {type: 'text/html'}).type", "'text/html'");
+shouldThrow("new Blob({length: 0}, {endings:'illegal'})", "'TypeError: The endings property must be either \"transparent\" or \"native\"'");
Modified: trunk/LayoutTests/fast/workers/worker-context-multi-port-expected.txt (159274 => 159275)
--- trunk/LayoutTests/fast/workers/worker-context-multi-port-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/workers/worker-context-multi-port-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -9,7 +9,7 @@
PASS posting a null port did throw: Error: InvalidStateError: DOM Exception 11
PASS posting a non-port did throw: TypeError: Type error
PASS event.ports contains two ports when two ports re-sent after error
-PASS posting a non-array did throw: TypeError: Type error
+PASS posting a non-array did throw: TypeError: Value is not a sequence
PASS posting a non-sequence did throw: TypeError: Type error
TEST COMPLETE
Modified: trunk/LayoutTests/fast/workers/worker-multi-port-expected.txt (159274 => 159275)
--- trunk/LayoutTests/fast/workers/worker-multi-port-expected.txt 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/LayoutTests/fast/workers/worker-multi-port-expected.txt 2013-11-14 05:46:10 UTC (rev 159275)
@@ -5,7 +5,7 @@
PASS worker.postMessage("null port", [channel3.port1, null, channel3.port2]) threw exception Error: InvalidStateError: DOM Exception 11.
PASS worker.postMessage("notAPort", [channel3.port1, {}, channel3.port2]) threw exception TypeError: Type error.
-PASS worker.postMessage("notAnArray", channel3.port1) threw exception TypeError: Type error.
+PASS worker.postMessage("notAnArray", channel3.port1) threw exception TypeError: Value is not a sequence.
PASS worker.postMessage("notASequence", [{length: 3}]) threw exception TypeError: Type error.
PASS event.ports is non-null and zero length when no port sent
PASS event.ports is non-null and zero length when empty array sent
Modified: trunk/Source/WebCore/ChangeLog (159274 => 159275)
--- trunk/Source/WebCore/ChangeLog 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/Source/WebCore/ChangeLog 2013-11-14 05:46:10 UTC (rev 159275)
@@ -1,3 +1,19 @@
+2013-11-13 Victor Costan <[email protected]>
+
+ Blob constructor accepts a sequence (array-like object) as first arg.
+ https://bugs.webkit.org/show_bug.cgi?id=124175
+
+ Reviewed by Christophe Dumez.
+
+ Added test cases to fast/files/script-tests/blob-constructor.js.
+
+ * bindings/js/JSBlobCustom.cpp: Make the constructor work with sequences.
+ (WebCore::JSBlobConstructor::constructJSBlob):
+ * bindings/js/JSDOMBinding.h:
+ (WebCore::toJSSequence): Slightly better error message when conversion fails.
+ (WebCore::toJS): Whitespace.
+ (WebCore::jsArray): Whitespace.
+
2013-11-13 Joseph Pecoraro <[email protected]>
Web Inspector: InspectorBackendDispatcher improvements
Modified: trunk/Source/WebCore/bindings/js/JSBlobCustom.cpp (159274 => 159275)
--- trunk/Source/WebCore/bindings/js/JSBlobCustom.cpp 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/Source/WebCore/bindings/js/JSBlobCustom.cpp 2013-11-14 05:46:10 UTC (rev 159275)
@@ -71,9 +71,11 @@
return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get()));
}
- JSValue firstArg = exec->argument(0);
- if (!isJSArray(firstArg))
- return throwVMError(exec, createTypeError(exec, "First argument of the constructor is not of type Array"));
+ unsigned blobPartsLength = 0;
+ JSObject* blobParts = toJSSequence(exec, exec->argument(0), blobPartsLength);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ ASSERT(blobParts);
String type;
String endings = ASCIILiteral("transparent");
@@ -110,11 +112,8 @@
BlobBuilder blobBuilder;
- JSArray* array = asArray(firstArg);
- unsigned length = array->length();
-
- for (unsigned i = 0; i < length; ++i) {
- JSValue item = array->getIndex(exec, i);
+ for (unsigned i = 0; i < blobPartsLength; ++i) {
+ JSValue item = blobParts->get(exec, i);
#if ENABLE(BLOB)
if (item.inherits(JSArrayBuffer::info()))
blobBuilder.append(toArrayBuffer(item));
Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (159274 => 159275)
--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h 2013-11-14 05:06:00 UTC (rev 159274)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h 2013-11-14 05:46:10 UTC (rev 159275)
@@ -119,7 +119,7 @@
{
return static_cast<WebCoreTypedArrayController*>(world.vm()->m_typedArrayController.get())->wrapperOwner();
}
-
+
inline void* wrapperContext(DOMWrapperWorld& world, JSC::ArrayBuffer*)
{
return &world;
@@ -197,7 +197,7 @@
return;
weakRemove(world.m_wrappers, (void*)domObject, wrapper);
}
-
+
#define CREATE_DOM_WRAPPER(exec, globalObject, className, object) createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
template<class WrapperClass, class DOMClass> inline JSDOMWrapper* createWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
{
@@ -251,7 +251,7 @@
{
return jsStringWithCache(exec, s.string());
}
-
+
JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null
JSC::JSValue jsStringOrNull(JSC::ExecState*, const URL&); // null if the URL is null
@@ -325,7 +325,7 @@
{
JSC::JSObject* object = value.getObject();
if (!object) {
- throwTypeError(exec);
+ throwVMError(exec, createTypeError(exec, "Value is not a sequence"));
return 0;
}
@@ -334,7 +334,7 @@
return 0;
if (lengthValue.isUndefinedOrNull()) {
- throwTypeError(exec);
+ throwVMError(exec, createTypeError(exec, "Value is not a sequence"));
return 0;
}
@@ -374,10 +374,10 @@
inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Vector<T> vector)
{
JSC::JSArray* array = constructEmptyArray(exec, 0, vector.size());
-
+
for (size_t i = 0; i < vector.size(); ++i)
array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i]));
-
+
return array;
}
@@ -385,10 +385,10 @@
inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Vector<RefPtr<T>> vector)
{
JSC::JSArray* array = constructEmptyArray(exec, 0, vector.size());
-
+
for (size_t i = 0; i < vector.size(); ++i)
array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i].get()));
-
+
return array;
}
@@ -428,7 +428,7 @@
JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& iterator)
{
JSC::MarkedArgumentBuffer list;
- typename Vector<T, inlineCapacity>::const_iterator end = iterator.end();
+ typename Vector<T, inlineCapacity>::const_iterator end = iterator.end();
typedef JSValueTraits<T> TraitsType;
for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter)