summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/FileAPI/blob
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/FileAPI/blob
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/FileAPI/blob')
-rw-r--r--testing/web-platform/tests/FileAPI/blob/Blob-XHR-revoke.html28
-rw-r--r--testing/web-platform/tests/FileAPI/blob/Blob-close.html39
-rw-r--r--testing/web-platform/tests/FileAPI/blob/Blob-constructor.html495
-rw-r--r--testing/web-platform/tests/FileAPI/blob/Blob-in-worker.worker.js14
-rw-r--r--testing/web-platform/tests/FileAPI/blob/Blob-slice-overflow.html42
-rw-r--r--testing/web-platform/tests/FileAPI/blob/Blob-slice.html214
6 files changed, 832 insertions, 0 deletions
diff --git a/testing/web-platform/tests/FileAPI/blob/Blob-XHR-revoke.html b/testing/web-platform/tests/FileAPI/blob/Blob-XHR-revoke.html
new file mode 100644
index 000000000..fea313eee
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/blob/Blob-XHR-revoke.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>Revoking blob URL used with XMLHttpRequest</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+async_test(function(t) {
+ var blob = new Blob(["test"]);
+ var url = URL.createObjectURL(blob);
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+
+ // Revoke the object URL. XHR should take a reference to the blob as soon as
+ // it receives it in open(), so the request succeeds even though we revoke the
+ // URL before calling send().
+ URL.revokeObjectURL(url);
+
+ xhr.send();
+
+ xhr.onload = t.step_func(function() {
+ assert_equals(xhr.response, "test");
+ t.done();
+ })
+ xhr.onerror = t.step_func(function() {
+ assert_unreached("Got unexpected error event");
+ })
+});
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/FileAPI/blob/Blob-close.html b/testing/web-platform/tests/FileAPI/blob/Blob-close.html
new file mode 100644
index 000000000..45df1e211
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/blob/Blob-close.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob.close</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-close">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/Blob.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var blob = new Blob(["TEST"]);
+ var sliced = blob.slice();
+ blob.close();
+
+ async_test(function(t) {
+ var reader = new FileReader();
+
+ reader.onload = t.step_func(function(evt) {
+ assert_unreached("Should not dispatch the load event");
+ });
+
+ reader.onerror = t.step_func(function(e) {
+ assert_equals(reader.result, null);
+ assert_equals(reader.error.code, DOMException.INVALID_STATE_ERR);
+ t.done();
+ });
+
+ reader.readAsText(blob, "UTF-8");
+ }, "Closed Blob");
+
+ test_blob(function() {
+ return sliced;
+ }, {
+ expected: "TEST",
+ type: "",
+ desc: "Slice should still have the data."
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/FileAPI/blob/Blob-constructor.html b/testing/web-platform/tests/FileAPI/blob/Blob-constructor.html
new file mode 100644
index 000000000..d8375c2a6
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/blob/Blob-constructor.html
@@ -0,0 +1,495 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob constructor</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob">
+<link rel=help href="https://heycam.github.io/webidl/#es-union">
+<link rel=help href="https://heycam.github.io/webidl/#es-dictionary">
+<link rel=help href="https://heycam.github.io/webidl/#es-sequence">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/Blob.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_true("Blob" in window, "window should have a Blob property.");
+ assert_equals(Blob.length, 0, "Blob.length should be 0.");
+ assert_true(Blob instanceof Function, "Blob should be a function.");
+}, "Blob interface object");
+
+// Step 1.
+test(function() {
+ var blob = new Blob();
+ assert_true(blob instanceof Blob);
+ assert_equals(String(blob), '[object Blob]');
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+}, "Blob constructor with no arguments");
+test(function() {
+ assert_throws(new TypeError(), function() { var blob = Blob(); });
+}, "Blob constructor with no arguments, without 'new'");
+test(function() {
+ var blob = new Blob;
+ assert_true(blob instanceof Blob);
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+}, "Blob constructor without brackets");
+test(function() {
+ var blob = new Blob(undefined);
+ assert_true(blob instanceof Blob);
+ assert_equals(String(blob), '[object Blob]');
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+}, "Blob constructor with undefined as first argument");
+
+// blobParts argument (WebIDL).
+test(function() {
+ var args = [
+ null,
+ true,
+ false,
+ 0,
+ 1,
+ 1.5,
+ "FAIL",
+ new Date(),
+ new RegExp(),
+ {},
+ { 0: "FAIL", length: 1 },
+ document.createElement("div"),
+ window,
+ ];
+ args.forEach(function(arg) {
+ assert_throws(new TypeError(), function() {
+ new Blob(arg);
+ }, "Should throw for argument " + format_value(arg) + ".");
+ });
+}, "Passing non-objects, Dates and RegExps for blobParts should throw a TypeError.");
+
+test_blob(function() {
+ return new Blob({
+ [Symbol.iterator]: Array.prototype[Symbol.iterator],
+ });
+}, {
+ expected: "",
+ type: "",
+ desc: "A plain object with @@iterator should be treated as a sequence for the blobParts argument."
+});
+test_blob(function() {
+ return new Blob({
+ [Symbol.iterator]: Array.prototype[Symbol.iterator],
+ 0: "PASS",
+ length: 1
+ });
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "A plain object with @@iterator and a length property should be treated as a sequence for the blobParts argument."
+});
+test_blob(function() {
+ return new Blob(new String("xyz"));
+}, {
+ expected: "xyz",
+ type: "",
+ desc: "A String object should be treated as a sequence for the blobParts argument."
+});
+test_blob(function() {
+ return new Blob(new Uint8Array([1, 2, 3]));
+}, {
+ expected: "123",
+ type: "",
+ desc: "A Uint8Array object should be treated as a sequence for the blobParts argument."
+});
+
+var test_error = {
+ name: "test",
+ message: "test error",
+};
+
+test(function() {
+ var obj = {
+ [Symbol.iterator]: Array.prototype[Symbol.iterator],
+ get length() { throw test_error; }
+ };
+ assert_throws(test_error, function() {
+ new Blob(obj);
+ });
+}, "The length getter should be invoked and any exceptions should be propagated.");
+
+test(function() {
+ var element = document.createElement("div");
+ element.appendChild(document.createElement("div"));
+ element.appendChild(document.createElement("p"));
+ var list = element.children;
+ Object.defineProperty(list, "length", {
+ get: function() { throw test_error; }
+ });
+ assert_throws(test_error, function() {
+ new Blob(list);
+ });
+}, "A platform object that supports indexed properties should be treated as a sequence for the blobParts argument (overwritten 'length'.)");
+
+test(function() {
+ assert_throws(test_error, function() {
+ var obj = {
+ [Symbol.iterator]: Array.prototype[Symbol.iterator],
+ length: {
+ valueOf: null,
+ toString: function() { throw test_error; }
+ }
+ };
+ new Blob(obj);
+ });
+ assert_throws(test_error, function() {
+ var obj = {
+ [Symbol.iterator]: Array.prototype[Symbol.iterator],
+ length: { valueOf: function() { throw test_error; } }
+ };
+ new Blob(obj);
+ });
+}, "ToUint32 should be applied to the length and any exceptions should be propagated.");
+
+test(function() {
+ var received = [];
+ var obj = {
+ get [Symbol.iterator]() {
+ received.push("Symbol.iterator");
+ return Array.prototype[Symbol.iterator];
+ },
+ get length() {
+ received.push("length getter");
+ return {
+ valueOf: function() {
+ received.push("length valueOf");
+ return 3;
+ }
+ };
+ },
+ get 0() {
+ received.push("0 getter");
+ return {
+ toString: function() {
+ received.push("0 toString");
+ return "a";
+ }
+ };
+ },
+ get 1() {
+ received.push("1 getter");
+ throw test_error;
+ },
+ get 2() {
+ received.push("2 getter");
+ assert_unreached("Should not call the getter for 2 if the getter for 1 threw.");
+ }
+ };
+ assert_throws(test_error, function() {
+ new Blob(obj);
+ });
+ assert_array_equals(received, [
+ "Symbol.iterator",
+ "length getter",
+ "length valueOf",
+ "0 getter",
+ "0 toString",
+ "length getter",
+ "length valueOf",
+ "1 getter",
+ ]);
+}, "Getters and value conversions should happen in order until an exception is thrown.");
+
+// XXX should add tests edge cases of ToLength(length)
+
+test(function() {
+ assert_throws(test_error, function() {
+ new Blob([{ toString: function() { throw test_error; } }]);
+ }, "Throwing toString");
+ assert_throws(test_error, function() {
+ new Blob([{ toString: undefined, valueOf: function() { throw test_error; } }]);
+ }, "Throwing valueOf");
+ assert_throws(test_error, function() {
+ new Blob([{
+ toString: function() { throw test_error; },
+ valueOf: function() { assert_unreached("Should not call valueOf if toString is present."); }
+ }]);
+ }, "Throwing toString and valueOf");
+ assert_throws(new TypeError(), function() {
+ new Blob([{toString: null, valueOf: null}]);
+ }, "Null toString and valueOf");
+}, "ToString should be called on elements of the blobParts array and any exceptions should be propagated.");
+
+test_blob(function() {
+ var arr = [
+ { toString: function() { arr.pop(); return "PASS"; } },
+ { toString: function() { assert_unreached("Should have removed the second element of the array rather than called toString() on it."); } }
+ ];
+ return new Blob(arr);
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "Changes to the blobParts array should be reflected in the returned Blob (pop)."
+});
+
+test_blob(function() {
+ var arr = [
+ {
+ toString: function() {
+ if (arr.length === 3) {
+ return "A";
+ }
+ arr.unshift({
+ toString: function() {
+ assert_unreached("Should only access index 0 once.");
+ }
+ });
+ return "P";
+ }
+ },
+ {
+ toString: function() {
+ return "SS";
+ }
+ }
+ ];
+ return new Blob(arr);
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "Changes to the blobParts array should be reflected in the returned Blob (unshift)."
+});
+
+test_blob(function() {
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17652
+ return new Blob([
+ null,
+ undefined,
+ true,
+ false,
+ 0,
+ 1,
+ new String("stringobject"),
+ [],
+ ['x', 'y'],
+ {},
+ { 0: "FAIL", length: 1 },
+ { toString: function() { return "stringA"; } },
+ { toString: undefined, valueOf: function() { return "stringB"; } },
+ { valueOf: function() { assert_unreached("Should not call valueOf if toString is present on the prototype."); } }
+ ]);
+}, {
+ expected: "nullundefinedtruefalse01stringobjectx,y[object Object][object Object]stringAstringB[object Object]",
+ type: "",
+ desc: "ToString should be called on elements of the blobParts array."
+});
+
+test_blob(function() {
+ return new Blob([
+ new ArrayBuffer(8)
+ ]);
+}, {
+ expected: "\0\0\0\0\0\0\0\0",
+ type: "",
+ desc: "ArrayBuffer elements of the blobParts array should be supported."
+});
+
+test_blob(function() {
+ return new Blob([
+ new Uint8Array([0x50, 0x41, 0x53, 0x53]),
+ new Int8Array([0x50, 0x41, 0x53, 0x53]),
+ new Uint16Array([0x4150, 0x5353]),
+ new Int16Array([0x4150, 0x5353]),
+ new Uint32Array([0x53534150]),
+ new Int32Array([0x53534150]),
+ new Float32Array([0xD341500000])
+ ]);
+}, {
+ expected: "PASSPASSPASSPASSPASSPASSPASS",
+ type: "",
+ desc: "Passing typed arrays as elements of the blobParts array should work."
+});
+test_blob(function() {
+ return new Blob([
+ // 0x535 3415053534150
+ // 0x535 = 0b010100110101 -> Sign = +, Exponent = 1333 - 1023 = 310
+ // 0x13415053534150 * 2**(-52)
+ // ==> 0x13415053534150 * 2**258 = 2510297372767036725005267563121821874921913208671273727396467555337665343087229079989707079680
+ new Float64Array([2510297372767036725005267563121821874921913208671273727396467555337665343087229079989707079680])
+ ]);
+}, {
+ expected: "PASSPASS",
+ type: "",
+ desc: "Passing a Float64Array as element of the blobParts array should work."
+});
+
+test_blob(function() {
+ var select = document.createElement("select");
+ select.appendChild(document.createElement("option"));
+ return new Blob(select);
+}, {
+ expected: "[object HTMLOptionElement]",
+ type: "",
+ desc: "Passing an platform object that supports indexed properties as the blobParts array should work (select)."
+});
+
+test_blob(function() {
+ var elm = document.createElement("div");
+ elm.setAttribute("foo", "bar");
+ return new Blob(elm.attributes);
+}, {
+ expected: "[object Attr]",
+ type: "",
+ desc: "Passing an platform object that supports indexed properties as the blobParts array should work (attributes)."
+});
+
+var t_ports = async_test("Passing a FrozenArray as the blobParts array should work (FrozenArray<MessagePort>).");
+t_ports.step(function() {
+ var channel = new MessageChannel();
+ channel.port2.onmessage = this.step_func(function(e) {
+ var b_ports = new Blob(e.ports);
+ assert_equals(b_ports.size, "[object MessagePort]".length);
+ this.done();
+ });
+ var channel2 = new MessageChannel();
+ channel.port1.postMessage('', [channel2.port1]);
+});
+
+test_blob(function() {
+ var blob = new Blob(['foo']);
+ return new Blob([blob, blob]);
+}, {
+ expected: "foofoo",
+ type: "",
+ desc: "Array with two blobs"
+});
+
+test_blob_binary(function() {
+ var view = new Uint8Array([0, 255, 0]);
+ return new Blob([view.buffer, view.buffer]);
+}, {
+ expected: [0, 255, 0, 0, 255, 0],
+ type: "",
+ desc: "Array with two buffers"
+});
+
+test_blob_binary(function() {
+ var view = new Uint8Array([0, 255, 0, 4]);
+ var blob = new Blob([view, view]);
+ assert_equals(blob.size, 8);
+ var view1 = new Uint16Array(view.buffer, 2);
+ return new Blob([view1, view.buffer, view1]);
+}, {
+ expected: [0, 4, 0, 255, 0, 4, 0, 4],
+ type: "",
+ desc: "Array with two bufferviews"
+});
+
+test_blob(function() {
+ var view = new Uint8Array([0]);
+ var blob = new Blob(["fo"]);
+ return new Blob([view.buffer, blob, "foo"]);
+}, {
+ expected: "\0fofoo",
+ type: "",
+ desc: "Array with mixed types"
+});
+
+// options argument
+test(function() {
+ new Blob([], { endings: "invalidEnumValue" });
+ new Blob([], { endings: null });
+ new Blob([], { endings: undefined });
+ new Blob([], { endings: 0 });
+ new Blob([], { get endings() { assert_unreached("Should not call getter"); } });
+}, "The 'endings' property should be ignored.");
+
+test(function() {
+ assert_throws(test_error, function() {
+ new Blob([], {
+ get type() { throw test_error; }
+ });
+ });
+ assert_throws(test_error, function() {
+ new Blob([], {
+ type: { toString: function() { throw test_error; } }
+ });
+ });
+}, "options properties should be accessed in lexicographic order.");
+
+test(function() {
+ assert_throws(test_error, function() {
+ new Blob(
+ [{ toString: function() { throw test_error } }],
+ {
+ get type() { assert_unreached("type getter should not be called."); }
+ }
+ );
+ });
+}, "Arguments should be evaluated from left to right.");
+
+[
+ null,
+ undefined,
+ {},
+ { unrecognized: true },
+ /regex/,
+ function() {}
+].forEach(function(arg, idx) {
+ test_blob(function() {
+ return new Blob([], arg);
+ }, {
+ expected: "",
+ type: "",
+ desc: "Passing " + format_value(arg) + " (index " + idx + ") for options should use the defaults."
+ });
+ test_blob(function() {
+ return new Blob(["\na\r\nb\n\rc\r"], arg);
+ }, {
+ expected: "\na\r\nb\n\rc\r",
+ type: "",
+ desc: "Passing " + format_value(arg) + " (index " + idx + ") for options should use the defaults (with newlines)."
+ });
+});
+
+test_blob(function() {
+ return new Blob(["\na\r\nb\n\rc\r"], { endings: "transparent" });
+}, {
+ expected: "\na\r\nb\n\rc\r",
+ type: "",
+ desc: "Newlines should not change when endings is 'transparent'."
+});
+test_blob(function() {
+ return new Blob(["\na\r\nb\n\rc\r"], { endings: "native" });
+}, {
+ expected: "\na\r\nb\n\rc\r",
+ type: "",
+ desc: "Newlines should not change when endings is 'native'."
+});
+
+var type_tests = [
+ // blobParts, type, expected type
+ [[], '', ''],
+ [[], 'a', 'a'],
+ [[], 'A', 'a'],
+ [[], 'text/html', 'text/html'],
+ [[], 'TEXT/HTML', 'text/html'],
+ [[], '\u00E5', ''],
+ [[], '\uD801\uDC7E', ''], // U+1047E
+ [[], ' image/gif ', ' image/gif '],
+ [[], '\timage/gif\t', ''],
+ [[], 'image/gif;\u007f', ''],
+ [[], '\u0130mage/gif', ''], // uppercase i with dot
+ [[], '\u0131mage/gif', ''], // lowercase dotless i
+ [[], 'image/gif\u0000', ''],
+ // check that type isn't changed based on sniffing
+ [[0x3C, 0x48, 0x54, 0x4D, 0x4C, 0x3E], 'unknown/unknown', 'unknown/unknown'], // "<HTML>"
+ [[0x00, 0xFF], 'text/plain', 'text/plain'],
+ [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], 'image/png', 'image/png'], // "GIF89a"
+];
+
+type_tests.forEach(function(t) {
+ test(function() {
+ var arr = new Uint8Array([t[0]]).buffer;
+ var b = new Blob([arr], {type:t[1]});
+ assert_equals(b.type, t[2]);
+ }, "Blob with type " + format_value(t[1]));
+});
+</script>
diff --git a/testing/web-platform/tests/FileAPI/blob/Blob-in-worker.worker.js b/testing/web-platform/tests/FileAPI/blob/Blob-in-worker.worker.js
new file mode 100644
index 000000000..a67060e7b
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/blob/Blob-in-worker.worker.js
@@ -0,0 +1,14 @@
+importScripts("/resources/testharness.js");
+
+async_test(function() {
+ var data = "TEST";
+ var blob = new Blob([data], {type: "text/plain"});
+ var reader = new FileReader();
+ reader.onload = this.step_func_done(function() {
+ assert_equals(reader.result, data);
+ });
+ reader.onerror = this.unreached_func("Unexpected error event");
+ reader.readAsText(blob);
+}, "Create Blob in Worker");
+
+done();
diff --git a/testing/web-platform/tests/FileAPI/blob/Blob-slice-overflow.html b/testing/web-platform/tests/FileAPI/blob/Blob-slice-overflow.html
new file mode 100644
index 000000000..56891af5f
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/blob/Blob-slice-overflow.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Blob slice overflow</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://w3c.github.io/FileAPI/#dfn-slice">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+var text = '';
+
+for (var i = 0; i < 2000; ++i) {
+ text += 'A';
+}
+
+test(function() {
+ var blob = new Blob([text]);
+ var sliceBlob = blob.slice(-1, 2000);
+ assert_equals(sliceBlob.size, 2000-(2000-1), "Bolb slice size");
+}, "slice start is negative, relativeStart will be max((size + start), 0)");
+
+test(function() {
+ var blob = new Blob([text]);
+ var sliceBlob = blob.slice(2001, 2000);
+ assert_equals(sliceBlob.size, 0, "Bolb slice size");
+}, "slice start is greater than blob size, relativeStart will be min(start, size)");
+
+test(function() {
+ var blob = new Blob([text]);
+ var sliceBlob = blob.slice(1998, -1);
+ assert_equals(sliceBlob.size, (2000-1)-1998, "Bolb slice size");
+}, "slice end is negative, relativeEnd will be max((size + end), 0)");
+
+test(function() {
+ var blob = new Blob([text]);
+ var sliceBlob = blob.slice(1998, 2999);
+ assert_equals(sliceBlob.size, 2000-1998, "Bolb slice size");
+}, "slice end is greater than blob size, relativeEnd will be min(end, size)");
+
+</script>
+
diff --git a/testing/web-platform/tests/FileAPI/blob/Blob-slice.html b/testing/web-platform/tests/FileAPI/blob/Blob-slice.html
new file mode 100644
index 000000000..0ecea79c8
--- /dev/null
+++ b/testing/web-platform/tests/FileAPI/blob/Blob-slice.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob slice</title>
+<link rel=help href="https://w3c.github.io/FileAPI/#slice-method-algo">
+<link rel=author title="Saurabh Anand" href="mailto:saurabhanandiit@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/Blob.js"></script>
+<div id="log"></div>
+<script>
+test_blob(function() {
+ var blobTemp = new Blob(["PASS"]);
+ return blobTemp.slice();
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "no-argument Blob slice"
+});
+
+test(function() {
+ var blob1, blob2;
+
+ test_blob(function() {
+ return blob1 = new Blob(["squiggle"]);
+ }, {
+ expected: "squiggle",
+ type: "",
+ desc: "blob1."
+ });
+
+ test_blob(function() {
+ return blob2 = new Blob(["steak"], {type: "content/type"});
+ }, {
+ expected: "steak",
+ type: "content/type",
+ desc: "blob2."
+ });
+
+ var arrayBuffer = new ArrayBuffer(16);
+ var int8View = new Int8Array(arrayBuffer);
+ for (var i = 0; i < 16; i++) {
+ int8View[i] = i + 65;
+ }
+
+ var testData = [
+ [
+ ["PASSSTRING"],
+ [{start: -6, contents: "STRING"},
+ {start: -12, contents: "PASSSTRING"},
+ {start: 4, contents: "STRING"},
+ {start: 12, contents: ""},
+ {start: 0, end: -6, contents: "PASS"},
+ {start: 0, end: -12, contents: ""},
+ {start: 0, end: 4, contents: "PASS"},
+ {start: 0, end: 12, contents: "PASSSTRING"},
+ {start: 7, end: 4, contents: ""}]
+ ],
+
+ // Test 3 strings
+ [
+ ["foo", "bar", "baz"],
+ [{start: 0, end: 9, contents: "foobarbaz"},
+ {start: 0, end: 3, contents: "foo"},
+ {start: 3, end: 9, contents: "barbaz"},
+ {start: 6, end: 9, contents: "baz"},
+ {start: 6, end: 12, contents: "baz"},
+ {start: 0, end: 9, contents: "foobarbaz"},
+ {start: 0, end: 11, contents: "foobarbaz"},
+ {start: 10, end: 15, contents: ""}]
+ ],
+
+ // Test string, Blob, string
+ [
+ ["foo", blob1, "baz"],
+ [{start: 0, end: 3, contents: "foo"},
+ {start: 3, end: 11, contents: "squiggle"},
+ {start: 2, end: 4, contents: "os"},
+ {start: 10, end: 12, contents: "eb"}]
+ ],
+
+ // Test blob, string, blob
+ [
+ [blob1, "foo", blob1],
+ [{start: 0, end: 8, contents: "squiggle"},
+ {start: 7, end: 9, contents: "ef"},
+ {start: 10, end: 12, contents: "os"},
+ {start: 1, end: 4, contents: "qui"},
+ {start: 12, end: 15, contents: "qui"},
+ {start: 40, end: 60, contents: ""}]
+ ],
+
+ // Test blobs all the way down
+ [
+ [blob2, blob1, blob2],
+ [{start: 0, end: 5, contents: "steak"},
+ {start: 5, end: 13, contents: "squiggle"},
+ {start: 13, end: 18, contents: "steak"},
+ {start: 1, end: 3, contents: "te"},
+ {start: 6, end: 10, contents: "quig"}]
+ ],
+
+ // Test an ArrayBufferView
+ [
+ [int8View, blob1, "foo"],
+ [{start: 0, end: 8, contents: "ABCDEFGH"},
+ {start: 8, end: 18, contents: "IJKLMNOPsq"},
+ {start: 17, end: 20, contents: "qui"},
+ {start: 4, end: 12, contents: "EFGHIJKL"}]
+ ],
+
+ // Test a partial ArrayBufferView
+ [
+ [new Uint8Array(arrayBuffer, 3, 5), blob1, "foo"],
+ [{start: 0, end: 8, contents: "DEFGHsqu"},
+ {start: 8, end: 18, contents: "igglefoo"},
+ {start: 4, end: 12, contents: "Hsquiggl"}]
+ ],
+
+ // Test type coercion of a number
+ [
+ [3, int8View, "foo"],
+ [{start: 0, end: 8, contents: "3ABCDEFG"},
+ {start: 8, end: 18, contents: "HIJKLMNOPf"},
+ {start: 17, end: 21, contents: "foo"},
+ {start: 4, end: 12, contents: "DEFGHIJK"}]
+ ],
+
+ [
+ [(new Uint8Array([0, 255, 0])).buffer,
+ new Blob(['abcd']),
+ 'efgh',
+ 'ijklmnopqrstuvwxyz'],
+ [{start: 1, end: 4, contents: "\uFFFD\u0000a"},
+ {start: 4, end: 8, contents: "bcde"},
+ {start: 8, end: 12, contents: "fghi"},
+ {start: 1, end: 12, contents: "\uFFFD\u0000abcdefghi"}]
+ ]
+ ];
+
+ testData.forEach(function(data, i) {
+ var blobs = data[0];
+ var tests = data[1];
+ tests.forEach(function(expectations, j) {
+ test(function() {
+ var blob = new Blob(blobs);
+ assert_true(blob instanceof Blob);
+ assert_false(blob instanceof File);
+
+ test_blob(function() {
+ return expectations.end === undefined
+ ? blob.slice(expectations.start)
+ : blob.slice(expectations.start, expectations.end);
+ }, {
+ expected: expectations.contents,
+ type: "",
+ desc: "Slicing test: slice (" + i + "," + j + ")."
+ });
+ }, "Slicing test (" + i + "," + j + ").");
+ });
+ });
+}, "Slices");
+
+var invalidTypes = [
+ "\xFF",
+ "te\x09xt/plain",
+ "te\x00xt/plain",
+ "te\x1Fxt/plain",
+ "te\x7Fxt/plain"
+];
+invalidTypes.forEach(function(type) {
+ test_blob(function() {
+ var blob = new Blob(["PASS"]);
+ return blob.slice(0, 4, type);
+ }, {
+ expected: "PASS",
+ type: "",
+ desc: "Invalid contentType (" + format_value(type) + ")"
+ });
+});
+
+var validTypes = [
+ "te(xt/plain",
+ "te)xt/plain",
+ "te<xt/plain",
+ "te>xt/plain",
+ "te@xt/plain",
+ "te,xt/plain",
+ "te;xt/plain",
+ "te:xt/plain",
+ "te\\xt/plain",
+ "te\"xt/plain",
+ "te/xt/plain",
+ "te[xt/plain",
+ "te]xt/plain",
+ "te?xt/plain",
+ "te=xt/plain",
+ "te{xt/plain",
+ "te}xt/plain",
+ "te\x20xt/plain",
+ "TEXT/PLAIN",
+ "text/plain;charset = UTF-8",
+ "text/plain;charset=UTF-8"
+];
+validTypes.forEach(function(type) {
+ test_blob(function() {
+ var blob = new Blob(["PASS"]);
+ return blob.slice(0, 4, type);
+ }, {
+ expected: "PASS",
+ type: type.toLowerCase(),
+ desc: "Valid contentType (" + format_value(type) + ")"
+ });
+});
+</script>