forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			848 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			848 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
function test_setup() {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    const minFileSize = 20000;
 | 
						|
 | 
						|
    // Create strings containing data we'll test with. We'll want long
 | 
						|
    // strings to ensure they span multiple buffers while loading
 | 
						|
    let testTextData = "asd b\tlah\u1234w\u00a0r";
 | 
						|
    while (testTextData.length < minFileSize) {
 | 
						|
      testTextData = testTextData + testTextData;
 | 
						|
    }
 | 
						|
 | 
						|
    let testASCIIData = "abcdef 123456\n";
 | 
						|
    while (testASCIIData.length < minFileSize) {
 | 
						|
      testASCIIData = testASCIIData + testASCIIData;
 | 
						|
    }
 | 
						|
 | 
						|
    let testBinaryData = "";
 | 
						|
    for (let i = 0; i < 256; i++) {
 | 
						|
      testBinaryData += String.fromCharCode(i);
 | 
						|
    }
 | 
						|
    while (testBinaryData.length < minFileSize) {
 | 
						|
      testBinaryData = testBinaryData + testBinaryData;
 | 
						|
    }
 | 
						|
 | 
						|
    let dataurldata0 = testBinaryData.substr(
 | 
						|
      0,
 | 
						|
      testBinaryData.length - (testBinaryData.length % 3)
 | 
						|
    );
 | 
						|
    let dataurldata1 = testBinaryData.substr(
 | 
						|
      0,
 | 
						|
      testBinaryData.length - 2 - (testBinaryData.length % 3)
 | 
						|
    );
 | 
						|
    let dataurldata2 = testBinaryData.substr(
 | 
						|
      0,
 | 
						|
      testBinaryData.length - 1 - (testBinaryData.length % 3)
 | 
						|
    );
 | 
						|
 | 
						|
    //Set up files for testing
 | 
						|
    let openerURL = SimpleTest.getTestFileURL("fileapi_chromeScript.js");
 | 
						|
    let opener = SpecialPowers.loadChromeScript(openerURL);
 | 
						|
 | 
						|
    opener.addMessageListener("files.opened", message => {
 | 
						|
      let [
 | 
						|
        asciiFile,
 | 
						|
        binaryFile,
 | 
						|
        nonExistingFile,
 | 
						|
        utf8TextFile,
 | 
						|
        utf16TextFile,
 | 
						|
        emptyFile,
 | 
						|
        dataUrlFile0,
 | 
						|
        dataUrlFile1,
 | 
						|
        dataUrlFile2,
 | 
						|
      ] = message;
 | 
						|
 | 
						|
      resolve({
 | 
						|
        blobs: {
 | 
						|
          asciiFile,
 | 
						|
          binaryFile,
 | 
						|
          nonExistingFile,
 | 
						|
          utf8TextFile,
 | 
						|
          utf16TextFile,
 | 
						|
          emptyFile,
 | 
						|
          dataUrlFile0,
 | 
						|
          dataUrlFile1,
 | 
						|
          dataUrlFile2,
 | 
						|
        },
 | 
						|
        data: {
 | 
						|
          text: testTextData,
 | 
						|
          ascii: testASCIIData,
 | 
						|
          binary: testBinaryData,
 | 
						|
          url0: dataurldata0,
 | 
						|
          url1: dataurldata1,
 | 
						|
          url2: dataurldata2,
 | 
						|
        },
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    opener.sendAsyncMessage("files.open", [
 | 
						|
      testASCIIData,
 | 
						|
      testBinaryData,
 | 
						|
      null,
 | 
						|
      convertToUTF8(testTextData),
 | 
						|
      convertToUTF16(testTextData),
 | 
						|
      "",
 | 
						|
      dataurldata0,
 | 
						|
      dataurldata1,
 | 
						|
      dataurldata2,
 | 
						|
    ]);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function runBasicTests(data) {
 | 
						|
  return test_basic()
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsText(data.blobs.asciiFile, data.data.ascii);
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsBinaryString(data.blobs.binaryFile, data.data.binary);
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsArrayBuffer(data.blobs.binaryFile, data.data.binary);
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function runEncodingTests(data) {
 | 
						|
  return test_readAsTextWithEncoding(
 | 
						|
    data.blobs.asciiFile,
 | 
						|
    data.data.ascii,
 | 
						|
    data.data.ascii.length,
 | 
						|
    ""
 | 
						|
  )
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsTextWithEncoding(
 | 
						|
        data.blobs.asciiFile,
 | 
						|
        data.data.ascii,
 | 
						|
        data.data.ascii.length,
 | 
						|
        "iso8859-1"
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsTextWithEncoding(
 | 
						|
        data.blobs.utf8TextFile,
 | 
						|
        data.data.text,
 | 
						|
        convertToUTF8(data.data.text).length,
 | 
						|
        "utf8"
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsTextWithEncoding(
 | 
						|
        data.blobs.utf16TextFile,
 | 
						|
        data.data.text,
 | 
						|
        convertToUTF16(data.data.text).length,
 | 
						|
        "utf-16"
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsTextWithEncoding(data.blobs.emptyFile, "", 0, "");
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsTextWithEncoding(data.blobs.emptyFile, "", 0, "utf8");
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsTextWithEncoding(data.blobs.emptyFile, "", 0, "utf-16");
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function runEmptyTests(data) {
 | 
						|
  return test_onlyResult()
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsText(data.blobs.emptyFile, "");
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsBinaryString(data.blobs.emptyFile, "");
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsArrayBuffer(data.blobs.emptyFile, "");
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsDataURL(data.blobs.emptyFile, convertToDataURL(""), 0);
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function runTwiceTests(data) {
 | 
						|
  return test_readAsTextTwice(data.blobs.asciiFile, data.data.ascii)
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsBinaryStringTwice(
 | 
						|
        data.blobs.binaryFile,
 | 
						|
        data.data.binary
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsDataURLTwice(
 | 
						|
        data.blobs.binaryFile,
 | 
						|
        convertToDataURL(data.data.binary),
 | 
						|
        data.data.binary.length
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsArrayBufferTwice(
 | 
						|
        data.blobs.binaryFile,
 | 
						|
        data.data.binary
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsArrayBufferTwice2(
 | 
						|
        data.blobs.binaryFile,
 | 
						|
        data.data.binary
 | 
						|
      );
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function runOtherTests(data) {
 | 
						|
  return test_readAsDataURL_customLength(
 | 
						|
    data.blobs.dataUrlFile0,
 | 
						|
    convertToDataURL(data.data.url0),
 | 
						|
    data.data.url0.length,
 | 
						|
    0
 | 
						|
  )
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsDataURL_customLength(
 | 
						|
        data.blobs.dataUrlFile1,
 | 
						|
        convertToDataURL(data.data.url1),
 | 
						|
        data.data.url1.length,
 | 
						|
        1
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_readAsDataURL_customLength(
 | 
						|
        data.blobs.dataUrlFile2,
 | 
						|
        convertToDataURL(data.data.url2),
 | 
						|
        data.data.url2.length,
 | 
						|
        2
 | 
						|
      );
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_abort(data.blobs.asciiFile);
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_abort_readAsX(data.blobs.asciiFile, data.data.ascii);
 | 
						|
    })
 | 
						|
    .then(() => {
 | 
						|
      return test_nonExisting(data.blobs.nonExistingFile);
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function convertToUTF16(s) {
 | 
						|
  let res = "";
 | 
						|
  for (let i = 0; i < s.length; ++i) {
 | 
						|
    c = s.charCodeAt(i);
 | 
						|
    res += String.fromCharCode(c & 255, c >>> 8);
 | 
						|
  }
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
function convertToUTF8(s) {
 | 
						|
  return unescape(encodeURIComponent(s));
 | 
						|
}
 | 
						|
 | 
						|
function convertToDataURL(s) {
 | 
						|
  return "data:application/octet-stream;base64," + btoa(s);
 | 
						|
}
 | 
						|
 | 
						|
function loadEventHandler_string(
 | 
						|
  event,
 | 
						|
  resolve,
 | 
						|
  reader,
 | 
						|
  data,
 | 
						|
  dataLength,
 | 
						|
  testName
 | 
						|
) {
 | 
						|
  is(event.target, reader, "Correct target.");
 | 
						|
  is(
 | 
						|
    event.target.readyState,
 | 
						|
    FileReader.DONE,
 | 
						|
    "readyState in test " + testName
 | 
						|
  );
 | 
						|
  is(event.target.error, null, "no error in test " + testName);
 | 
						|
  is(event.target.result, data, "result in test " + testName);
 | 
						|
  is(event.lengthComputable, true, "lengthComputable in test " + testName);
 | 
						|
  is(event.loaded, dataLength, "loaded in test " + testName);
 | 
						|
  is(event.total, dataLength, "total in test " + testName);
 | 
						|
  resolve();
 | 
						|
}
 | 
						|
 | 
						|
function loadEventHandler_arrayBuffer(event, resolve, reader, data, testName) {
 | 
						|
  is(
 | 
						|
    event.target.readyState,
 | 
						|
    FileReader.DONE,
 | 
						|
    "readyState in test " + testName
 | 
						|
  );
 | 
						|
  is(event.target.error, null, "no error in test " + testName);
 | 
						|
  is(event.lengthComputable, true, "lengthComputable in test " + testName);
 | 
						|
  is(event.loaded, data.length, "loaded in test " + testName);
 | 
						|
  is(event.total, data.length, "total in test " + testName);
 | 
						|
  is(
 | 
						|
    event.target.result.byteLength,
 | 
						|
    data.length,
 | 
						|
    "array buffer size in test " + testName
 | 
						|
  );
 | 
						|
 | 
						|
  let u8v = new Uint8Array(event.target.result);
 | 
						|
  is(
 | 
						|
    String.fromCharCode.apply(String, u8v),
 | 
						|
    data,
 | 
						|
    "array buffer contents in test " + testName
 | 
						|
  );
 | 
						|
  u8v = null;
 | 
						|
 | 
						|
  if ("SpecialPowers" in self) {
 | 
						|
    SpecialPowers.gc();
 | 
						|
 | 
						|
    is(
 | 
						|
      event.target.result.byteLength,
 | 
						|
      data.length,
 | 
						|
      "array buffer size after gc in test " + testName
 | 
						|
    );
 | 
						|
    u8v = new Uint8Array(event.target.result);
 | 
						|
    is(
 | 
						|
      String.fromCharCode.apply(String, u8v),
 | 
						|
      data,
 | 
						|
      "array buffer contents after gc in test " + testName
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  resolve();
 | 
						|
}
 | 
						|
 | 
						|
function test_basic() {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    is(FileReader.EMPTY, 0, "correct EMPTY value");
 | 
						|
    is(FileReader.LOADING, 1, "correct LOADING value");
 | 
						|
    is(FileReader.DONE, 2, "correct DONE value");
 | 
						|
    resolve();
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsText(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let onloadHasRun = false;
 | 
						|
    let onloadStartHasRun = false;
 | 
						|
 | 
						|
    let r = new FileReader();
 | 
						|
    is(r.readyState, FileReader.EMPTY, "correct initial text readyState");
 | 
						|
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        resolve,
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        text.length,
 | 
						|
        "readAsText"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    r.addEventListener("load", () => {
 | 
						|
      onloadHasRun = true;
 | 
						|
    });
 | 
						|
    r.addEventListener("loadstart", () => {
 | 
						|
      onloadStartHasRun = true;
 | 
						|
    });
 | 
						|
 | 
						|
    r.readAsText(blob);
 | 
						|
 | 
						|
    is(r.readyState, FileReader.LOADING, "correct loading text readyState");
 | 
						|
    is(onloadHasRun, false, "text loading must be async");
 | 
						|
    is(onloadStartHasRun, false, "text loadstart should fire async");
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsBinaryString(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let onloadHasRun = false;
 | 
						|
    let onloadStartHasRun = false;
 | 
						|
 | 
						|
    let r = new FileReader();
 | 
						|
    is(r.readyState, FileReader.EMPTY, "correct initial binary readyState");
 | 
						|
 | 
						|
    r.addEventListener("load", function() {
 | 
						|
      onloadHasRun = true;
 | 
						|
    });
 | 
						|
    r.addEventListener("loadstart", function() {
 | 
						|
      onloadStartHasRun = true;
 | 
						|
    });
 | 
						|
 | 
						|
    r.readAsBinaryString(blob);
 | 
						|
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        resolve,
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        text.length,
 | 
						|
        "readAsBinaryString"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    is(r.readyState, FileReader.LOADING, "correct loading binary readyState");
 | 
						|
    is(onloadHasRun, false, "binary loading must be async");
 | 
						|
    is(onloadStartHasRun, false, "binary loadstart should fire async");
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsArrayBuffer(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let onloadHasRun = false;
 | 
						|
    let onloadStartHasRun = false;
 | 
						|
 | 
						|
    r = new FileReader();
 | 
						|
    is(
 | 
						|
      r.readyState,
 | 
						|
      FileReader.EMPTY,
 | 
						|
      "correct initial arrayBuffer readyState"
 | 
						|
    );
 | 
						|
 | 
						|
    r.addEventListener("load", function() {
 | 
						|
      onloadHasRun = true;
 | 
						|
    });
 | 
						|
    r.addEventListener("loadstart", function() {
 | 
						|
      onloadStartHasRun = true;
 | 
						|
    });
 | 
						|
 | 
						|
    r.readAsArrayBuffer(blob);
 | 
						|
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_arrayBuffer(
 | 
						|
        event,
 | 
						|
        resolve,
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        "readAsArrayBuffer"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    is(
 | 
						|
      r.readyState,
 | 
						|
      FileReader.LOADING,
 | 
						|
      "correct loading arrayBuffer readyState"
 | 
						|
    );
 | 
						|
    is(onloadHasRun, false, "arrayBuffer loading must be async");
 | 
						|
    is(onloadStartHasRun, false, "arrayBuffer loadstart should fire sync");
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test a variety of encodings, and make sure they work properly
 | 
						|
function test_readAsTextWithEncoding(blob, text, length, charset) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        resolve,
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        length,
 | 
						|
        "readAsText-" + charset
 | 
						|
      );
 | 
						|
    };
 | 
						|
    r.readAsText(blob, charset);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test get result without reading
 | 
						|
function test_onlyResult() {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    is(
 | 
						|
      r.readyState,
 | 
						|
      FileReader.EMPTY,
 | 
						|
      "readyState in test reader get result without reading"
 | 
						|
    );
 | 
						|
    is(r.error, null, "no error in test reader get result without reading");
 | 
						|
    is(r.result, null, "result in test reader get result without reading");
 | 
						|
    resolve();
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsDataURL(blob, text, length) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(event, resolve, r, text, length, "readAsDataURL");
 | 
						|
    };
 | 
						|
    r.readAsDataURL(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test reusing a FileReader to read multiple times
 | 
						|
function test_readAsTextTwice(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        () => {},
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        text.length,
 | 
						|
        "readAsText-reused-once"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    let anotherListener = event => {
 | 
						|
      let r1 = event.target;
 | 
						|
      r1.removeEventListener("load", anotherListener);
 | 
						|
      r1.onload = evt => {
 | 
						|
        loadEventHandler_string(
 | 
						|
          evt,
 | 
						|
          resolve,
 | 
						|
          r1,
 | 
						|
          text,
 | 
						|
          text.length,
 | 
						|
          "readAsText-reused-twice"
 | 
						|
        );
 | 
						|
      };
 | 
						|
      r1.readAsText(blob);
 | 
						|
    };
 | 
						|
 | 
						|
    r.addEventListener("load", anotherListener);
 | 
						|
    r.readAsText(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test reusing a FileReader to read multiple times
 | 
						|
function test_readAsBinaryStringTwice(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        () => {},
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        text.length,
 | 
						|
        "readAsBinaryString-reused-once"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    let anotherListener = event => {
 | 
						|
      let r1 = event.target;
 | 
						|
      r1.removeEventListener("load", anotherListener);
 | 
						|
      r1.onload = evt => {
 | 
						|
        loadEventHandler_string(
 | 
						|
          evt,
 | 
						|
          resolve,
 | 
						|
          r1,
 | 
						|
          text,
 | 
						|
          text.length,
 | 
						|
          "readAsBinaryString-reused-twice"
 | 
						|
        );
 | 
						|
      };
 | 
						|
      r1.readAsBinaryString(blob);
 | 
						|
    };
 | 
						|
 | 
						|
    r.addEventListener("load", anotherListener);
 | 
						|
    r.readAsBinaryString(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsDataURLTwice(blob, text, length) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        () => {},
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        length,
 | 
						|
        "readAsDataURL-reused-once"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    let anotherListener = event => {
 | 
						|
      let r1 = event.target;
 | 
						|
      r1.removeEventListener("load", anotherListener);
 | 
						|
      r1.onload = evt => {
 | 
						|
        loadEventHandler_string(
 | 
						|
          evt,
 | 
						|
          resolve,
 | 
						|
          r1,
 | 
						|
          text,
 | 
						|
          length,
 | 
						|
          "readAsDataURL-reused-twice"
 | 
						|
        );
 | 
						|
      };
 | 
						|
      r1.readAsDataURL(blob);
 | 
						|
    };
 | 
						|
 | 
						|
    r.addEventListener("load", anotherListener);
 | 
						|
    r.readAsDataURL(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsArrayBufferTwice(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_arrayBuffer(
 | 
						|
        event,
 | 
						|
        () => {},
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        "readAsArrayBuffer-reused-once"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    let anotherListener = event => {
 | 
						|
      let r1 = event.target;
 | 
						|
      r1.removeEventListener("load", anotherListener);
 | 
						|
      r1.onload = evt => {
 | 
						|
        loadEventHandler_arrayBuffer(
 | 
						|
          evt,
 | 
						|
          resolve,
 | 
						|
          r1,
 | 
						|
          text,
 | 
						|
          "readAsArrayBuffer-reused-twice"
 | 
						|
        );
 | 
						|
      };
 | 
						|
      r1.readAsArrayBuffer(blob);
 | 
						|
    };
 | 
						|
 | 
						|
    r.addEventListener("load", anotherListener);
 | 
						|
    r.readAsArrayBuffer(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test first reading as ArrayBuffer then read as something else (BinaryString)
 | 
						|
// and doesn't crash
 | 
						|
function test_readAsArrayBufferTwice2(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_arrayBuffer(
 | 
						|
        event,
 | 
						|
        () => {},
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        "readAsArrayBuffer-reused-once2"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    let anotherListener = event => {
 | 
						|
      let r1 = event.target;
 | 
						|
      r1.removeEventListener("load", anotherListener);
 | 
						|
      r1.onload = evt => {
 | 
						|
        loadEventHandler_string(
 | 
						|
          evt,
 | 
						|
          resolve,
 | 
						|
          r1,
 | 
						|
          text,
 | 
						|
          text.length,
 | 
						|
          "readAsArrayBuffer-reused-twice2"
 | 
						|
        );
 | 
						|
      };
 | 
						|
      r1.readAsBinaryString(blob);
 | 
						|
    };
 | 
						|
 | 
						|
    r.addEventListener("load", anotherListener);
 | 
						|
    r.readAsArrayBuffer(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function test_readAsDataURL_customLength(blob, text, length, numb) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    is(length % 3, numb, "Want to test data with length %3 == " + numb);
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        resolve,
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        length,
 | 
						|
        "dataurl reading, %3 = " + numb
 | 
						|
      );
 | 
						|
    };
 | 
						|
    r.readAsDataURL(blob);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test abort()
 | 
						|
function test_abort(blob) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let abortHasRun = false;
 | 
						|
    let loadEndHasRun = false;
 | 
						|
 | 
						|
    let r = new FileReader();
 | 
						|
 | 
						|
    r.onabort = function(event) {
 | 
						|
      is(abortHasRun, false, "abort should only fire once");
 | 
						|
      is(loadEndHasRun, false, "loadend shouldn't have fired yet");
 | 
						|
      abortHasRun = true;
 | 
						|
      is(
 | 
						|
        event.target.readyState,
 | 
						|
        FileReader.DONE,
 | 
						|
        "should be DONE while firing onabort"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.error.name,
 | 
						|
        "AbortError",
 | 
						|
        "error set to AbortError for aborted reads"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.result,
 | 
						|
        null,
 | 
						|
        "file data should be null on aborted reads"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    r.onloadend = function(event) {
 | 
						|
      is(abortHasRun, true, "abort should fire before loadend");
 | 
						|
      is(loadEndHasRun, false, "loadend should only fire once");
 | 
						|
      loadEndHasRun = true;
 | 
						|
      is(
 | 
						|
        event.target.readyState,
 | 
						|
        FileReader.DONE,
 | 
						|
        "should be DONE while firing onabort"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.error.name,
 | 
						|
        "AbortError",
 | 
						|
        "error set to AbortError for aborted reads"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.result,
 | 
						|
        null,
 | 
						|
        "file data should be null on aborted reads"
 | 
						|
      );
 | 
						|
    };
 | 
						|
 | 
						|
    r.onload = function() {
 | 
						|
      ok(false, "load should not fire for aborted reads");
 | 
						|
    };
 | 
						|
    r.onerror = function() {
 | 
						|
      ok(false, "error should not fire for aborted reads");
 | 
						|
    };
 | 
						|
    r.onprogress = function() {
 | 
						|
      ok(false, "progress should not fire for aborted reads");
 | 
						|
    };
 | 
						|
 | 
						|
    let abortThrew = false;
 | 
						|
    try {
 | 
						|
      r.abort();
 | 
						|
    } catch (e) {
 | 
						|
      abortThrew = true;
 | 
						|
    }
 | 
						|
 | 
						|
    is(abortThrew, false, "abort() doesn't throw");
 | 
						|
    is(abortHasRun, false, "abort() is a no-op unless loading");
 | 
						|
 | 
						|
    r.readAsText(blob);
 | 
						|
    r.abort();
 | 
						|
 | 
						|
    is(abortHasRun, true, "abort should fire sync");
 | 
						|
    is(loadEndHasRun, true, "loadend should fire sync");
 | 
						|
 | 
						|
    resolve();
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test calling readAsX to cause abort()
 | 
						|
function test_abort_readAsX(blob, text) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let reuseAbortHasRun = false;
 | 
						|
 | 
						|
    let r = new FileReader();
 | 
						|
    r.onabort = function(event) {
 | 
						|
      is(reuseAbortHasRun, false, "abort should only fire once");
 | 
						|
      reuseAbortHasRun = true;
 | 
						|
      is(
 | 
						|
        event.target.readyState,
 | 
						|
        FileReader.DONE,
 | 
						|
        "should be DONE while firing onabort"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.error.name,
 | 
						|
        "AbortError",
 | 
						|
        "error set to AbortError for aborted reads"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.result,
 | 
						|
        null,
 | 
						|
        "file data should be null on aborted reads"
 | 
						|
      );
 | 
						|
    };
 | 
						|
    r.onload = function() {
 | 
						|
      ok(false, "load should fire for nested reads");
 | 
						|
    };
 | 
						|
 | 
						|
    let abortThrew = false;
 | 
						|
    try {
 | 
						|
      r.abort();
 | 
						|
    } catch (e) {
 | 
						|
      abortThrew = true;
 | 
						|
    }
 | 
						|
 | 
						|
    is(abortThrew, false, "abort() should not throw");
 | 
						|
    is(reuseAbortHasRun, false, "abort() is a no-op unless loading");
 | 
						|
    r.readAsText(blob);
 | 
						|
 | 
						|
    let readThrew = false;
 | 
						|
    try {
 | 
						|
      r.readAsText(blob);
 | 
						|
    } catch (e) {
 | 
						|
      readThrew = true;
 | 
						|
    }
 | 
						|
 | 
						|
    is(readThrew, true, "readAsText() must throw if loading");
 | 
						|
    is(reuseAbortHasRun, false, "abort should not fire");
 | 
						|
 | 
						|
    r.onload = event => {
 | 
						|
      loadEventHandler_string(
 | 
						|
        event,
 | 
						|
        resolve,
 | 
						|
        r,
 | 
						|
        text,
 | 
						|
        text.length,
 | 
						|
        "reuse-as-abort reading"
 | 
						|
      );
 | 
						|
    };
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Test reading from nonexistent files
 | 
						|
function test_nonExisting(blob) {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    let r = new FileReader();
 | 
						|
 | 
						|
    r.onerror = function(event) {
 | 
						|
      is(
 | 
						|
        event.target.readyState,
 | 
						|
        FileReader.DONE,
 | 
						|
        "should be DONE while firing onerror"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.error.name,
 | 
						|
        "NotFoundError",
 | 
						|
        "error set to NotFoundError for nonexistent files"
 | 
						|
      );
 | 
						|
      is(
 | 
						|
        event.target.result,
 | 
						|
        null,
 | 
						|
        "file data should be null on aborted reads"
 | 
						|
      );
 | 
						|
      resolve();
 | 
						|
    };
 | 
						|
    r.onload = function(event) {
 | 
						|
      is(false, "nonexistent file shouldn't load! (FIXME: bug 1122788)");
 | 
						|
    };
 | 
						|
 | 
						|
    let didThrow = false;
 | 
						|
    try {
 | 
						|
      r.readAsDataURL(blob);
 | 
						|
    } catch (ex) {
 | 
						|
      didThrow = true;
 | 
						|
    }
 | 
						|
 | 
						|
    // Once this test passes, we should test that onerror gets called and
 | 
						|
    // that the FileReader object is in the right state during that call.
 | 
						|
    is(
 | 
						|
      didThrow,
 | 
						|
      false,
 | 
						|
      "shouldn't throw when opening nonexistent file, should fire error instead"
 | 
						|
    );
 | 
						|
  });
 | 
						|
}
 |