worker_fileReader.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. var testRanCounter = 0;
  2. var expectedTestCount = 0;
  3. var testSetupFinished = false;
  4. function ok(a, msg) {
  5. postMessage({type: 'check', status: !!a, msg: msg });
  6. }
  7. function is(a, b, msg) {
  8. ok(a === b, msg);
  9. }
  10. function finish() {
  11. postMessage({type: 'finish'});
  12. }
  13. function convertToUTF16(s) {
  14. res = "";
  15. for (var i = 0; i < s.length; ++i) {
  16. c = s.charCodeAt(i);
  17. res += String.fromCharCode(c & 255, c >>> 8);
  18. }
  19. return res;
  20. }
  21. function convertToUTF8(s) {
  22. return unescape(encodeURIComponent(s));
  23. }
  24. function convertToDataURL(s) {
  25. return "data:application/octet-stream;base64," + btoa(s);
  26. }
  27. onmessage = function(message) {
  28. is(FileReader.EMPTY, 0, "correct EMPTY value");
  29. is(FileReader.LOADING, 1, "correct LOADING value");
  30. is(FileReader.DONE, 2, "correct DONE value");
  31. // List of blobs.
  32. var asciiFile = message.data.blobs.shift();
  33. var binaryFile = message.data.blobs.shift();
  34. var nonExistingFile = message.data.blobs.shift();
  35. var utf8TextFile = message.data.blobs.shift();
  36. var utf16TextFile = message.data.blobs.shift();
  37. var emptyFile = message.data.blobs.shift();
  38. var dataUrlFile0 = message.data.blobs.shift();
  39. var dataUrlFile1 = message.data.blobs.shift();
  40. var dataUrlFile2 = message.data.blobs.shift();
  41. // List of buffers for testing.
  42. var testTextData = message.data.testTextData;
  43. var testASCIIData = message.data.testASCIIData;
  44. var testBinaryData = message.data.testBinaryData;
  45. var dataurldata0 = message.data.dataurldata0;
  46. var dataurldata1 = message.data.dataurldata1;
  47. var dataurldata2 = message.data.dataurldata2;
  48. // Test that plain reading works and fires events as expected, both
  49. // for text and binary reading
  50. var onloadHasRunText = false;
  51. var onloadStartHasRunText = false;
  52. r = new FileReader();
  53. is(r.readyState, FileReader.EMPTY, "correct initial text readyState");
  54. r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "plain reading");
  55. r.addEventListener("load", function() { onloadHasRunText = true }, false);
  56. r.addEventListener("loadstart", function() { onloadStartHasRunText = true }, false);
  57. r.readAsText(asciiFile);
  58. is(r.readyState, FileReader.LOADING, "correct loading text readyState");
  59. is(onloadHasRunText, false, "text loading must be async");
  60. is(onloadStartHasRunText, true, "text loadstart should fire sync");
  61. expectedTestCount++;
  62. var onloadHasRunBinary = false;
  63. var onloadStartHasRunBinary = false;
  64. r = new FileReader();
  65. is(r.readyState, FileReader.EMPTY, "correct initial binary readyState");
  66. r.addEventListener("load", function() { onloadHasRunBinary = true }, false);
  67. r.addEventListener("loadstart", function() { onloadStartHasRunBinary = true }, false);
  68. r.readAsBinaryString(binaryFile);
  69. r.onload = getLoadHandler(testBinaryData, testBinaryData.length, "binary reading");
  70. is(r.readyState, FileReader.LOADING, "correct loading binary readyState");
  71. is(onloadHasRunBinary, false, "binary loading must be async");
  72. is(onloadStartHasRunBinary, true, "binary loadstart should fire sync");
  73. expectedTestCount++;
  74. var onloadHasRunArrayBuffer = false;
  75. var onloadStartHasRunArrayBuffer = false;
  76. r = new FileReader();
  77. is(r.readyState, FileReader.EMPTY, "correct initial arrayBuffer readyState");
  78. r.addEventListener("load", function() { onloadHasRunArrayBuffer = true }, false);
  79. r.addEventListener("loadstart", function() { onloadStartHasRunArrayBuffer = true }, false);
  80. r.readAsArrayBuffer(binaryFile);
  81. r.onload = getLoadHandlerForArrayBuffer(testBinaryData, testBinaryData.length, "array buffer reading");
  82. is(r.readyState, FileReader.LOADING, "correct loading arrayBuffer readyState");
  83. is(onloadHasRunArrayBuffer, false, "arrayBuffer loading must be async");
  84. is(onloadStartHasRunArrayBuffer, true, "arrayBuffer loadstart should fire sync");
  85. expectedTestCount++;
  86. // Test a variety of encodings, and make sure they work properly
  87. r = new FileReader();
  88. r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "no encoding reading");
  89. r.readAsText(asciiFile, "");
  90. expectedTestCount++;
  91. r = new FileReader();
  92. r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "iso8859 reading");
  93. r.readAsText(asciiFile, "iso-8859-1");
  94. expectedTestCount++;
  95. r = new FileReader();
  96. r.onload = getLoadHandler(testTextData,
  97. convertToUTF8(testTextData).length,
  98. "utf8 reading");
  99. r.readAsText(utf8TextFile, "utf8");
  100. expectedTestCount++;
  101. r = new FileReader();
  102. r.readAsText(utf16TextFile, "utf-16");
  103. r.onload = getLoadHandler(testTextData,
  104. convertToUTF16(testTextData).length,
  105. "utf16 reading");
  106. expectedTestCount++;
  107. // Test get result without reading
  108. r = new FileReader();
  109. is(r.readyState, FileReader.EMPTY,
  110. "readyState in test reader get result without reading");
  111. is(r.error, null,
  112. "no error in test reader get result without reading");
  113. is(r.result, null,
  114. "result in test reader get result without reading");
  115. // Test loading an empty file works (and doesn't crash!)
  116. r = new FileReader();
  117. r.onload = getLoadHandler("", 0, "empty no encoding reading");
  118. r.readAsText(emptyFile, "");
  119. expectedTestCount++;
  120. r = new FileReader();
  121. r.onload = getLoadHandler("", 0, "empty utf8 reading");
  122. r.readAsText(emptyFile, "utf8");
  123. expectedTestCount++;
  124. r = new FileReader();
  125. r.onload = getLoadHandler("", 0, "empty utf16 reading");
  126. r.readAsText(emptyFile, "utf-16");
  127. expectedTestCount++;
  128. r = new FileReader();
  129. r.onload = getLoadHandler("", 0, "empty binary string reading");
  130. r.readAsBinaryString(emptyFile);
  131. expectedTestCount++;
  132. r = new FileReader();
  133. r.onload = getLoadHandlerForArrayBuffer("", 0, "empty array buffer reading");
  134. r.readAsArrayBuffer(emptyFile);
  135. expectedTestCount++;
  136. r = new FileReader();
  137. r.onload = getLoadHandler(convertToDataURL(""), 0, "empt binary string reading");
  138. r.readAsDataURL(emptyFile);
  139. expectedTestCount++;
  140. // Test reusing a FileReader to read multiple times
  141. r = new FileReader();
  142. r.onload = getLoadHandler(testASCIIData,
  143. testASCIIData.length,
  144. "to-be-reused reading text")
  145. var makeAnotherReadListener = function(event) {
  146. r = event.target;
  147. r.removeEventListener("load", makeAnotherReadListener, false);
  148. r.onload = getLoadHandler(testASCIIData,
  149. testASCIIData.length,
  150. "reused reading text");
  151. r.readAsText(asciiFile);
  152. };
  153. r.addEventListener("load", makeAnotherReadListener, false);
  154. r.readAsText(asciiFile);
  155. expectedTestCount += 2;
  156. r = new FileReader();
  157. r.onload = getLoadHandler(testBinaryData,
  158. testBinaryData.length,
  159. "to-be-reused reading binary")
  160. var makeAnotherReadListener2 = function(event) {
  161. r = event.target;
  162. r.removeEventListener("load", makeAnotherReadListener2, false);
  163. r.onload = getLoadHandler(testBinaryData,
  164. testBinaryData.length,
  165. "reused reading binary");
  166. r.readAsBinaryString(binaryFile);
  167. };
  168. r.addEventListener("load", makeAnotherReadListener2, false);
  169. r.readAsBinaryString(binaryFile);
  170. expectedTestCount += 2;
  171. r = new FileReader();
  172. r.onload = getLoadHandler(convertToDataURL(testBinaryData),
  173. testBinaryData.length,
  174. "to-be-reused reading data url")
  175. var makeAnotherReadListener3 = function(event) {
  176. r = event.target;
  177. r.removeEventListener("load", makeAnotherReadListener3, false);
  178. r.onload = getLoadHandler(convertToDataURL(testBinaryData),
  179. testBinaryData.length,
  180. "reused reading data url");
  181. r.readAsDataURL(binaryFile);
  182. };
  183. r.addEventListener("load", makeAnotherReadListener3, false);
  184. r.readAsDataURL(binaryFile);
  185. expectedTestCount += 2;
  186. r = new FileReader();
  187. r.onload = getLoadHandlerForArrayBuffer(testBinaryData,
  188. testBinaryData.length,
  189. "to-be-reused reading arrayBuffer")
  190. var makeAnotherReadListener4 = function(event) {
  191. r = event.target;
  192. r.removeEventListener("load", makeAnotherReadListener4, false);
  193. r.onload = getLoadHandlerForArrayBuffer(testBinaryData,
  194. testBinaryData.length,
  195. "reused reading arrayBuffer");
  196. r.readAsArrayBuffer(binaryFile);
  197. };
  198. r.addEventListener("load", makeAnotherReadListener4, false);
  199. r.readAsArrayBuffer(binaryFile);
  200. expectedTestCount += 2;
  201. // Test first reading as ArrayBuffer then read as something else
  202. // (BinaryString) and doesn't crash
  203. r = new FileReader();
  204. r.onload = getLoadHandlerForArrayBuffer(testBinaryData,
  205. testBinaryData.length,
  206. "to-be-reused reading arrayBuffer")
  207. var makeAnotherReadListener5 = function(event) {
  208. r = event.target;
  209. r.removeEventListener("load", makeAnotherReadListener5, false);
  210. r.onload = getLoadHandler(testBinaryData,
  211. testBinaryData.length,
  212. "reused reading binary string");
  213. r.readAsBinaryString(binaryFile);
  214. };
  215. r.addEventListener("load", makeAnotherReadListener5, false);
  216. r.readAsArrayBuffer(binaryFile);
  217. expectedTestCount += 2;
  218. //Test data-URI encoding on differing file sizes
  219. is(dataurldata0.length % 3, 0, "Want to test data with length % 3 == 0");
  220. r = new FileReader();
  221. r.onload = getLoadHandler(convertToDataURL(dataurldata0),
  222. dataurldata0.length,
  223. "dataurl reading, %3 = 0");
  224. r.readAsDataURL(dataUrlFile0);
  225. expectedTestCount++;
  226. is(dataurldata1.length % 3, 1, "Want to test data with length % 3 == 1");
  227. r = new FileReader();
  228. r.onload = getLoadHandler(convertToDataURL(dataurldata1),
  229. dataurldata1.length,
  230. "dataurl reading, %3 = 1");
  231. r.readAsDataURL(dataUrlFile1);
  232. expectedTestCount++;
  233. is(dataurldata2.length % 3, 2, "Want to test data with length % 3 == 2");
  234. r = new FileReader();
  235. r.onload = getLoadHandler(convertToDataURL(dataurldata2),
  236. dataurldata2.length,
  237. "dataurl reading, %3 = 2");
  238. r.readAsDataURL(dataUrlFile2),
  239. expectedTestCount++;
  240. // Test abort()
  241. var abortHasRun = false;
  242. var loadEndHasRun = false;
  243. r = new FileReader();
  244. r.onabort = function (event) {
  245. is(abortHasRun, false, "abort should only fire once");
  246. is(loadEndHasRun, false, "loadend shouldn't have fired yet");
  247. abortHasRun = true;
  248. is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort");
  249. is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads");
  250. is(event.target.result, null, "file data should be null on aborted reads");
  251. }
  252. r.onloadend = function (event) {
  253. is(abortHasRun, true, "abort should fire before loadend");
  254. is(loadEndHasRun, false, "loadend should only fire once");
  255. loadEndHasRun = true;
  256. is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort");
  257. is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads");
  258. is(event.target.result, null, "file data should be null on aborted reads");
  259. }
  260. r.onload = function() { ok(false, "load should not fire for aborted reads") };
  261. r.onerror = function() { ok(false, "error should not fire for aborted reads") };
  262. r.onprogress = function() { ok(false, "progress should not fire for aborted reads") };
  263. var abortThrew = false;
  264. try {
  265. r.abort();
  266. } catch(e) {
  267. abortThrew = true;
  268. }
  269. is(abortThrew, true, "abort() must throw if not loading");
  270. is(abortHasRun, false, "abort() is a no-op unless loading");
  271. r.readAsText(asciiFile);
  272. r.abort();
  273. is(abortHasRun, true, "abort should fire sync");
  274. is(loadEndHasRun, true, "loadend should fire sync");
  275. // Test calling readAsX to cause abort()
  276. var reuseAbortHasRun = false;
  277. r = new FileReader();
  278. r.onabort = function (event) {
  279. is(reuseAbortHasRun, false, "abort should only fire once");
  280. reuseAbortHasRun = true;
  281. is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort");
  282. is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads");
  283. is(event.target.result, null, "file data should be null on aborted reads");
  284. }
  285. r.onload = function() { ok(false, "load should not fire for aborted reads") };
  286. var abortThrew = false;
  287. try {
  288. r.abort();
  289. } catch(e) {
  290. abortThrew = true;
  291. }
  292. is(abortThrew, true, "abort() must throw if not loading");
  293. is(reuseAbortHasRun, false, "abort() is a no-op unless loading");
  294. r.readAsText(asciiFile);
  295. r.readAsText(asciiFile);
  296. is(reuseAbortHasRun, true, "abort should fire sync");
  297. r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "reuse-as-abort reading");
  298. expectedTestCount++;
  299. // Test reading from nonexistent files
  300. r = new FileReader();
  301. var didThrow = false;
  302. r.onerror = function (event) {
  303. is(event.target.readyState, FileReader.DONE, "should be DONE while firing onerror");
  304. is(event.target.error.name, "NotFoundError", "error set to NotFoundError for nonexistent files");
  305. is(event.target.result, null, "file data should be null on aborted reads");
  306. testHasRun();
  307. };
  308. r.onload = function (event) {
  309. is(false, "nonexistent file shouldn't load! (FIXME: bug 1122788)");
  310. testHasRun();
  311. };
  312. try {
  313. r.readAsDataURL(nonExistingFile);
  314. expectedTestCount++;
  315. } catch(ex) {
  316. didThrow = true;
  317. }
  318. // Once this test passes, we should test that onerror gets called and
  319. // that the FileReader object is in the right state during that call.
  320. is(didThrow, false, "shouldn't throw when opening nonexistent file, should fire error instead");
  321. function getLoadHandler(expectedResult, expectedLength, testName) {
  322. return function (event) {
  323. is(event.target.readyState, FileReader.DONE,
  324. "readyState in test " + testName);
  325. is(event.target.error, null,
  326. "no error in test " + testName);
  327. is(event.target.result, expectedResult,
  328. "result in test " + testName);
  329. is(event.lengthComputable, true,
  330. "lengthComputable in test " + testName);
  331. is(event.loaded, expectedLength,
  332. "loaded in test " + testName);
  333. is(event.total, expectedLength,
  334. "total in test " + testName);
  335. testHasRun();
  336. }
  337. }
  338. function getLoadHandlerForArrayBuffer(expectedResult, expectedLength, testName) {
  339. return function (event) {
  340. is(event.target.readyState, FileReader.DONE,
  341. "readyState in test " + testName);
  342. is(event.target.error, null,
  343. "no error in test " + testName);
  344. is(event.lengthComputable, true,
  345. "lengthComputable in test " + testName);
  346. is(event.loaded, expectedLength,
  347. "loaded in test " + testName);
  348. is(event.total, expectedLength,
  349. "total in test " + testName);
  350. is(event.target.result.byteLength, expectedLength,
  351. "array buffer size in test " + testName);
  352. var u8v = new Uint8Array(event.target.result);
  353. is(String.fromCharCode.apply(String, u8v), expectedResult,
  354. "array buffer contents in test " + testName);
  355. u8v = null;
  356. is(event.target.result.byteLength, expectedLength,
  357. "array buffer size after gc in test " + testName);
  358. u8v = new Uint8Array(event.target.result);
  359. is(String.fromCharCode.apply(String, u8v), expectedResult,
  360. "array buffer contents after gc in test " + testName);
  361. testHasRun();
  362. }
  363. }
  364. function testHasRun() {
  365. //alert(testRanCounter);
  366. ++testRanCounter;
  367. if (testRanCounter == expectedTestCount) {
  368. is(testSetupFinished, true, "test setup should have finished; check for exceptions");
  369. is(onloadHasRunText, true, "onload text should have fired by now");
  370. is(onloadHasRunBinary, true, "onload binary should have fired by now");
  371. finish();
  372. }
  373. }
  374. testSetupFinished = true;
  375. }