tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FileSystemWritableFileStream-write.js (13720B)


      1 'use strict';
      2 
      3 directory_test(async (t, root) => {
      4  const handle = await createEmptyFile('empty_blob', root);
      5  const stream = await handle.createWritable();
      6 
      7  await stream.write(new Blob([]));
      8  await stream.close();
      9 
     10  assert_equals(await getFileContents(handle), '');
     11  assert_equals(await getFileSize(handle), 0);
     12 }, 'write() with an empty blob to an empty file');
     13 
     14 directory_test(async (t, root) => {
     15  const handle = await createEmptyFile('valid_blob', root);
     16  const stream = await handle.createWritable();
     17 
     18  await stream.write(new Blob(['1234567890']));
     19  await stream.close();
     20 
     21  assert_equals(await getFileContents(handle), '1234567890');
     22  assert_equals(await getFileSize(handle), 10);
     23 }, 'write() a blob to an empty file');
     24 
     25 directory_test(async (t, root) => {
     26  const handle = await createEmptyFile('write_param_empty', root);
     27  const stream = await handle.createWritable();
     28 
     29  await stream.write({type: 'write', data: '1234567890'});
     30  await stream.close();
     31 
     32  assert_equals(await getFileContents(handle), '1234567890');
     33  assert_equals(await getFileSize(handle), 10);
     34 }, 'write() with WriteParams without position to an empty file');
     35 
     36 directory_test(async (t, root) => {
     37  const handle = await createEmptyFile('string_zero_offset', root);
     38  const stream = await handle.createWritable();
     39 
     40  await stream.write({type: 'write', position: 0, data: '1234567890'});
     41  await stream.close();
     42 
     43  assert_equals(await getFileContents(handle), '1234567890');
     44  assert_equals(await getFileSize(handle), 10);
     45 }, 'write() a string to an empty file with zero offset');
     46 
     47 directory_test(async (t, root) => {
     48  const handle = await createEmptyFile('blob_zero_offset', root);
     49  const stream = await handle.createWritable();
     50 
     51  await stream.write(
     52      {type: 'write', position: 0, data: new Blob(['1234567890'])});
     53  await stream.close();
     54 
     55  assert_equals(await getFileContents(handle), '1234567890');
     56  assert_equals(await getFileSize(handle), 10);
     57 }, 'write() a blob to an empty file with zero offset');
     58 
     59 directory_test(async (t, root) => {
     60  const handle = await createEmptyFile('write_appends', root);
     61  const stream = await handle.createWritable();
     62 
     63  await stream.write('12345');
     64  await stream.write('67890');
     65  await stream.close();
     66 
     67  assert_equals(await getFileContents(handle), '1234567890');
     68  assert_equals(await getFileSize(handle), 10);
     69 }, 'write() called consecutively appends');
     70 
     71 directory_test(async (t, root) => {
     72  const handle = await createEmptyFile('write_appends_object_string', root);
     73  const stream = await handle.createWritable();
     74 
     75  await stream.write('12345');
     76  await stream.write({type: 'write', data: '67890'});
     77  await stream.close();
     78 
     79  assert_equals(await getFileContents(handle), '1234567890');
     80  assert_equals(await getFileSize(handle), 10);
     81 }, 'write() WriteParams without position and string appends');
     82 
     83 directory_test(async (t, root) => {
     84  const handle = await createEmptyFile('write_appends_object_blob', root);
     85  const stream = await handle.createWritable();
     86 
     87  await stream.write('12345');
     88  await stream.write({type: 'write', data: new Blob(['67890'])});
     89  await stream.close();
     90 
     91  assert_equals(await getFileContents(handle), '1234567890');
     92  assert_equals(await getFileSize(handle), 10);
     93 }, 'write() WriteParams without position and blob appends');
     94 
     95 directory_test(async (t, root) => {
     96  const handle = await createEmptyFile('string_with_offset', root);
     97  const stream = await handle.createWritable();
     98 
     99  await stream.write('1234567890');
    100  await stream.write({type: 'write', position: 4, data: 'abc'});
    101  await stream.close();
    102 
    103  assert_equals(await getFileContents(handle), '1234abc890');
    104  assert_equals(await getFileSize(handle), 10);
    105 }, 'write() called with a string and a valid offset');
    106 
    107 directory_test(async (t, root) => {
    108  const handle =
    109      await createEmptyFile('write_string_with_offset_after_seek', root);
    110  const stream = await handle.createWritable();
    111 
    112  await stream.write('1234567890');
    113  await stream.write({type: 'seek', position: 0});
    114  await stream.write({type: 'write', position: 4, data: 'abc'});
    115  await stream.close();
    116 
    117  assert_equals(await getFileContents(handle), '1234abc890');
    118  assert_equals(await getFileSize(handle), 10);
    119 }, 'write() called with a string and a valid offset after seek');
    120 
    121 directory_test(async (t, root) => {
    122  const handle = await createEmptyFile('blob_with_offset', root);
    123  const stream = await handle.createWritable();
    124 
    125  await stream.write('1234567890');
    126  await stream.write({type: 'write', position: 4, data: new Blob(['abc'])});
    127  await stream.close();
    128 
    129  assert_equals(await getFileContents(handle), '1234abc890');
    130  assert_equals(await getFileSize(handle), 10);
    131 }, 'write() called with a blob and a valid offset');
    132 
    133 directory_test(async (t, root) => {
    134  const handle = await createEmptyFile('bad_offset', root);
    135  const stream = await handle.createWritable();
    136 
    137  await stream.write({type: 'write', position: 4, data: new Blob(['abc'])});
    138  await stream.close();
    139 
    140  assert_equals(await getFileContents(handle), '\0\0\0\0abc');
    141  assert_equals(await getFileSize(handle), 7);
    142 }, 'write() called with an offset beyond the end of the file');
    143 
    144 directory_test(async (t, root) => {
    145  const handle = await createEmptyFile('empty_string', root);
    146  const stream = await handle.createWritable();
    147 
    148  await stream.write('');
    149  await stream.close();
    150  assert_equals(await getFileContents(handle), '');
    151  assert_equals(await getFileSize(handle), 0);
    152 }, 'write() with an empty string to an empty file');
    153 
    154 directory_test(async (t, root) => {
    155  const handle = await createEmptyFile('valid_utf8_string', root);
    156  const stream = await handle.createWritable();
    157 
    158  await stream.write('foo🤘');
    159  await stream.close();
    160  assert_equals(await getFileContents(handle), 'foo🤘');
    161  assert_equals(await getFileSize(handle), 7);
    162 }, 'write() with a valid utf-8 string');
    163 
    164 directory_test(async (t, root) => {
    165  const handle = await createEmptyFile('string_with_unix_line_ending', root);
    166  const stream = await handle.createWritable();
    167 
    168  await stream.write('foo\n');
    169  await stream.close();
    170  assert_equals(await getFileContents(handle), 'foo\n');
    171  assert_equals(await getFileSize(handle), 4);
    172 }, 'write() with a string with unix line ending preserved');
    173 
    174 directory_test(async (t, root) => {
    175  const handle = await createEmptyFile('string_with_windows_line_ending', root);
    176  const stream = await handle.createWritable();
    177 
    178  await stream.write('foo\r\n');
    179  await stream.close();
    180  assert_equals(await getFileContents(handle), 'foo\r\n');
    181  assert_equals(await getFileSize(handle), 5);
    182 }, 'write() with a string with windows line ending preserved');
    183 
    184 directory_test(async (t, root) => {
    185  const handle = await createEmptyFile('empty_array_buffer', root);
    186  const stream = await handle.createWritable();
    187 
    188  const buf = new ArrayBuffer(0);
    189  await stream.write(buf);
    190  await stream.close();
    191  assert_equals(await getFileContents(handle), '');
    192  assert_equals(await getFileSize(handle), 0);
    193 }, 'write() with an empty array buffer to an empty file');
    194 
    195 directory_test(async (t, root) => {
    196  const handle = await createEmptyFile('valid_string_typed_byte_array', root);
    197  const stream = await handle.createWritable();
    198 
    199  const buf = new ArrayBuffer(3);
    200  const intView = new Uint8Array(buf);
    201  intView[0] = 0x66;
    202  intView[1] = 0x6f;
    203  intView[2] = 0x6f;
    204  await stream.write(buf);
    205  await stream.close();
    206  assert_equals(await getFileContents(handle), 'foo');
    207  assert_equals(await getFileSize(handle), 3);
    208 }, 'write() with a valid typed array buffer');
    209 
    210 directory_test(async (t, root) => {
    211  const handle = await createEmptyFile('atomic_writes.txt', root);
    212  const stream = await handle.createWritable();
    213  await stream.write('foox');
    214 
    215  const stream2 = await cleanup_writable(t, await handle.createWritable());
    216  await stream2.write('bar');
    217 
    218  assert_equals(await getFileSize(handle), 0);
    219 
    220  await stream2.close();
    221  assert_equals(await getFileContents(handle), 'bar');
    222  assert_equals(await getFileSize(handle), 3);
    223 
    224  await stream.close();
    225  assert_equals(await getFileContents(handle), 'foox');
    226  assert_equals(await getFileSize(handle), 4);
    227 }, 'atomic writes: writable file streams make atomic changes on close');
    228 
    229 directory_test(async (t, root) => {
    230  const handle = await createEmptyFile('atomic_write_after_close.txt', root);
    231  const stream = await handle.createWritable();
    232  await stream.write('foo');
    233 
    234  await stream.close();
    235  assert_equals(await getFileContents(handle), 'foo');
    236  assert_equals(await getFileSize(handle), 3);
    237 
    238  await promise_rejects_js(t, TypeError, stream.write('abc'));
    239 }, 'atomic writes: write() after close() fails');
    240 
    241 directory_test(async (t, root) => {
    242  const handle = await createEmptyFile('atomic_truncate_after_close.txt', root);
    243  const stream = await handle.createWritable();
    244  await stream.write('foo');
    245 
    246  await stream.close();
    247  assert_equals(await getFileContents(handle), 'foo');
    248  assert_equals(await getFileSize(handle), 3);
    249 
    250  await promise_rejects_js(t, TypeError, stream.truncate(0));
    251 }, 'atomic writes: truncate() after close() fails');
    252 
    253 directory_test(async (t, root) => {
    254  const handle = await createEmptyFile('atomic_close_after_close.txt', root);
    255  const stream = await handle.createWritable();
    256  await stream.write('foo');
    257 
    258  await stream.close();
    259  assert_equals(await getFileContents(handle), 'foo');
    260  assert_equals(await getFileSize(handle), 3);
    261 
    262  await promise_rejects_js(t, TypeError, stream.close());
    263 }, 'atomic writes: close() after close() fails');
    264 
    265 directory_test(async (t, root) => {
    266  const handle = await createEmptyFile('there_can_be_only_one.txt', root);
    267  const stream = await handle.createWritable();
    268  await stream.write('foo');
    269 
    270  // This test might be flaky if there is a race condition allowing
    271  // close() to be called multiple times.
    272  const success_promises =
    273      [...Array(100)].map(() => stream.close().then(() => 1).catch(() => 0));
    274  const close_attempts = await Promise.all(success_promises);
    275  const success_count = close_attempts.reduce((x, y) => x + y);
    276  assert_equals(success_count, 1);
    277 }, 'atomic writes: only one close() operation may succeed');
    278 
    279 directory_test(async (t, root) => {
    280  const handle = await createEmptyFile('writer_written', root);
    281  const stream = await handle.createWritable();
    282  assert_false(stream.locked);
    283  const writer = stream.getWriter();
    284  assert_true(stream.locked);
    285 
    286  await writer.write('foo');
    287  await writer.write(new Blob(['bar']));
    288  await writer.write({type: 'seek', position: 0});
    289  await writer.write({type: 'write', data: 'baz'});
    290  await writer.close();
    291 
    292  assert_equals(await getFileContents(handle), 'bazbar');
    293  assert_equals(await getFileSize(handle), 6);
    294 }, 'getWriter() can be used');
    295 
    296 directory_test(async (t, root) => {
    297  const handle =
    298      await createFileWithContents('content.txt', 'very long string', root);
    299  const stream = await handle.createWritable();
    300 
    301  await promise_rejects_dom(
    302      t, 'SyntaxError', stream.write({type: 'truncate'}),
    303      'truncate without size');
    304 }, 'WriteParams: truncate missing size param');
    305 
    306 directory_test(async (t, root) => {
    307  const handle = await createEmptyFile('content.txt', root);
    308  const stream = await handle.createWritable();
    309 
    310  await promise_rejects_dom(
    311      t, 'SyntaxError', stream.write({type: 'write'}), 'write without data');
    312 }, 'WriteParams: write missing data param');
    313 
    314 directory_test(async (t, root) => {
    315  const handle = await createEmptyFile('content.txt', root);
    316  const stream = await handle.createWritable();
    317 
    318  await promise_rejects_js(
    319      t, TypeError, stream.write({type: 'write', data: null}),
    320      'write with null data');
    321 }, 'WriteParams: write null data param');
    322 
    323 directory_test(async (t, root) => {
    324  const handle = await createFileWithContents('content.txt', 'seekable', root);
    325  const stream = await handle.createWritable();
    326 
    327  await promise_rejects_dom(
    328      t, 'SyntaxError', stream.write({type: 'seek'}), 'seek without position');
    329 }, 'WriteParams: seek missing position param');
    330 
    331 directory_test(async (t, root) => {
    332  const source_file =
    333      await createFileWithContents('source_file', 'source data', root);
    334  const source_blob = await source_file.getFile();
    335  await root.removeEntry(source_file.name);
    336 
    337  const handle = await createEmptyFile('invalid_blob_test', root);
    338  const stream = await handle.createWritable();
    339  await promise_rejects_dom(t, "NotFoundError", stream.write(source_blob));
    340  await promise_rejects_js(t, TypeError, stream.close());
    341 
    342  assert_equals(await getFileContents(handle), '');
    343  assert_equals(await getFileSize(handle), 0);
    344 }, 'write() with an invalid blob to an empty file should reject');
    345 
    346 directory_test(async (t, root) => {
    347  const handle = await createFileWithContents('file.txt', 'contents', root);
    348  const stream = await handle.createWritable({mode: 'exclusive'});
    349 
    350  await stream.write('12345');
    351  await promise_rejects_js(
    352      t, TypeError, stream.write({type: 'write', data: null}),
    353      'write with null data');
    354 
    355  // The file contents should not have been changed.
    356  assert_equals(await getFileContents(handle), 'contents');
    357 
    358  // The file's lock was released.
    359  const newStream = await handle.createWritable({mode: 'exclusive'});
    360  await newStream.close();
    361 }, 'an errored writable stream releases its lock');
    362 
    363 directory_test(async (t, root) => {
    364  const handle = await createFileWithContents('file.txt', 'contents', root);
    365  const stream = await handle.createWritable({mode: 'exclusive'});
    366 
    367  const writer = stream.getWriter();
    368 
    369  await promise_rejects_js(t, TypeError, writer.write(null), 'write with null data');
    370  await promise_rejects_js(t, TypeError, writer.write("foo"), 'write with text data');
    371 }, 'an errored writable stream should reject the next write call');