All files / src/fsa CoreFileSystemSyncAccessHandle.ts

7.4% Statements 4/54
0% Branches 0/27
0% Functions 0/8
7.4% Lines 4/54

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132    4x   4x 4x         4x                                                                                                                                                                                                                                                  
import type { IFileSystemSyncAccessHandle, FileSystemReadWriteOptions, CoreFsaContext } from './types';
import type { Superblock } from '../core/Superblock';
import { Buffer } from '../internal/buffer';
import { ERROR_CODE } from '../core/constants';
import { newNotAllowedError } from './util';
import { FLAGS } from '../node/constants';
 
/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle
 */
export class CoreFileSystemSyncAccessHandle implements IFileSystemSyncAccessHandle {
  private _fd: number | null = null;
  private _closed = false;
 
  constructor(
    private readonly _core: Superblock,
    private readonly _path: string,
    private readonly _ctx: CoreFsaContext,
  ) {}
 
  private _ensureOpen(): number {
    Iif (this._closed) {
      throw new DOMException('The file handle is closed.', 'InvalidStateError');
    }
    Iif (this._fd === null) {
      // Open file for read/write
      const flags = this._ctx.mode === 'readwrite' ? FLAGS['r+'] : FLAGS.r;
      this._fd = this._core.open(this._path, flags, 0o644);
    }
    return this._fd;
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/close
   */
  public async close(): Promise<void> {
    Iif (this._fd !== null) {
      this._core.close(this._fd);
      this._fd = null;
    }
    this._closed = true;
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/flush
   */
  public async flush(): Promise<void> {
    const fd = this._ensureOpen();
    // Core doesn't have an explicit flush method, but we can try to sync if available
    // For now, this is a no-op as the core writes are synchronous
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/getSize
   */
  public async getSize(): Promise<number> {
    try {
      const link = this._core.getResolvedLinkOrThrow(this._path);
      const node = link.getNode();
      return node.getSize();
    } catch (error) {
      Iif (error && typeof error === 'object' && error.code === ERROR_CODE.EACCES) {
        throw newNotAllowedError();
      }
      throw error;
    }
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/read
   */
  public async read(buffer: ArrayBuffer | ArrayBufferView, options: FileSystemReadWriteOptions = {}): Promise<number> {
    const fd = this._ensureOpen();
    const { at: position = 0 } = options;
 
    const buf = Buffer.from(buffer);
    try {
      return this._core.read(fd, buf, 0, buf.length, position);
    } catch (error) {
      Iif (error && typeof error === 'object' && error.code === ERROR_CODE.EACCES) {
        throw newNotAllowedError();
      }
      throw error;
    }
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/truncate
   */
  public async truncate(newSize: number): Promise<void> {
    Iif (this._ctx.mode !== 'readwrite') {
      throw newNotAllowedError();
    }
 
    try {
      const link = this._core.getResolvedLinkOrThrow(this._path);
      const node = link.getNode();
      node.truncate(newSize);
    } catch (error) {
      Iif (error && typeof error === 'object' && error.code === ERROR_CODE.EACCES) {
        throw newNotAllowedError();
      }
      throw error;
    }
  }
 
  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle/write
   */
  public async write(
    buffer: ArrayBuffer | ArrayBufferView | DataView,
    options: FileSystemReadWriteOptions = {},
  ): Promise<number> {
    Iif (this._ctx.mode !== 'readwrite') {
      throw newNotAllowedError();
    }
 
    const fd = this._ensureOpen();
    const { at: position = 0 } = options;
 
    const buf = Buffer.from(buffer);
    try {
      return this._core.write(fd, buf, 0, buf.length, position);
    } catch (error) {
      Iif (error && typeof error === 'object' && error.code === ERROR_CODE.EACCES) {
        throw newNotAllowedError();
      }
      throw error;
    }
  }
}