The FileSystem API defines functionality on a local sandboxed file system within the same origin of the Web Application that created it. It exposes standard file system operations to Web Applications, such as creation of files and directories, and reading, writing, and copying files and directories. It builds on top of the [[!FileAPI]] and uses Promises for asynchronous functionality [[!ECMAScript]].

Portions of this specification are in flux, and are likely to be re-written; where appropriate, these have been marked as ISSUES by the editor. Implementors are encouraged to contribute to discussions on the public-webapps@w3.org mailing list. This work uses the "File API: Directories and System" W3C Note as a starting point.

Introduction

The FileSystem API is for Web applications that have client-side storage needs not readily addressed by database APIs such as [[IndexedDB]]. Such applications need to handle common file types that end users typically link with logical directory structures in a file system, and generally involve binary data that may be shared with other applications. The API is designed to be asynchronous using Promises [[!ECMAScript]].

The FileSystem API is a virtual file system, and thus user agents are responsible for allocating space for the creation of a sandboxed file system and for imposing storage quotas on that virtual file system.

Use Cases

  1. Persistent uploader
    • When a file or directory is selected for upload, it copies it into a local sandbox and uploads a chunk at a time.
    • It can restart uploads after browser crashes, network interruptions, etc.
  2. Video game or other app with lots of media assets
    • It downloads one or several large tarballs, and expands them locally into a directory structure.
    • The same download should work on any operating system.
    • It can manage prefetching just the next-to-be-needed assets in the background, so going to the next game level or activating a new feature doesn't require waiting for a download.
    • It uses those assets directly from its local cache, by direct file reads or by handing local URLs to image or video tags, WebGL asset loaders, etc.
    • The files may be of arbitrary binary format.
  3. Audio/Photo editor with offline access or local cache for speed
    • Data here is potentially quite large, and is read-write.
    • It may want to do partial writes to files (ovewriting just the ID3/EXIF tags, for example).
    • The ability to organize project files by creating directories would be useful.
  4. Offline video viewer
    • It downloads large files (>1GB) for later viewing.
    • It needs efficient seek + streaming.
    • It must be able to hand a URL to the video tag.
    • It should enable access to partly-downloaded files e.g. to let you watch the first episode of the DVD even if your download didn't complete before you got on the plane.
    • It should be able to pull a single episode out of the middle of a download and give just that to the video tag; this can be accomplished by a URL scheme that works with a filesystem path.
  5. Offline Web Mail Client
    • Downloads attachments and stores them locally.
    • Caches user-selected attachments for later upload.
    • Needs to be able to refer to cached attachments and image thumbnails for display and upload.
    • Should be able to trigger the UA's download manager just as if talking to a server.
    • Should be able to upload an email with attachments as a multipart post, rather than sending a file at a time in an XHR.

Conformance

Everything in this specification is normative except for examples and sections marked as being informative.

The keywords “MUST”,
“MUST NOT”,
“REQUIRED”,
“SHALL”,
“SHALL NOT”,
“RECOMMENDED”,
“MAY” and
“OPTIONAL” in this document are to be interpreted as described in
Key words for use in RFCs to Indicate Requirement Levels [[!RFC2119]].

The following conformance classes are defined by this specification:

conforming user agent

A user agent is considered to be a conforming user agent if it satisfies all of the MUST-, REQUIRED- and SHALL-level criteria in this specification that apply to implementations. This specification uses both the terms "conforming user agent" and "user agent" to refer to this product class.

User agents may implement algorithms in this specifications in any way desired, so long as the end result is indistinguishable from the result that would be obtained from the specification's algorithms.

User agents that use ECMAScript to implement the APIs defined in this specification must implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]] as this specification uses that specification and terminology.

Terminology

The terms Blob, File, Unix Epoch, and File Constructor Steps are as defined by the [[!FileAPI]] specification.

The terms scheme, scheme data, and URL are as defined by the [[!URL]] specification.

The term origin is used as defined by the Web Origin Specification [[!ORIGIN]].

The term worker is defined by the WebWorkers specification [[!WEBWORKERS]].

The terms context object, strictly split a string, and document are defined by the HTML specification [[!HTML]].

Model

Directory, File, Root, and Path

A directory is a logical organizing storage unit with a distinct name which contains files and/or one or more subdirectory units (which are themselves directory units). The directory is organized by a hierarchical containment structure, which can also be represented by a string, called a path; the path string uses the U+002F SOLIDUS character ("/") to denote directories within the Directory Tree. A file in this specification is as defined in the [[!FileAPI]], and is represented by a File object. Files, like directories, have distinct names which identify them on the Directory Tree.

The top-most containing directory, which contains all directories and files, if any exist, is called the root directory, and has the following properties:

Each origin has one root directory.

The Directory Tree

User agents must maintain an internal per-origin Directory Tree of directories and files, along with the affiliated path from root for each directory and file; each directory or file must correspond to a node in the Directory Tree, with the root directory being the root of the Directory Tree.

The corollary to this is that for each file or directory, user agents are required to maintain the position of that file or directory on the Directory Tree.

A Directory Pointer is a pointer to a position in the Directory Tree; unless specified otherwise, it initally points to the root of the Directory Tree.

The present working directory is the node on the Directory Tree that represents the current directory from which an operation is taking place. In this specification, this is the context object from which a Directory operation is called.

A path to a given directory from the root directory is said to be a path from root and always begins with a leading U+002F SOLIDUS ("/"). A path that is relative only from the present working directory is said to be a relative path, and does not begin with a U+002F SOLIDUS ("/").

The present working directory may also be the root Directory, in which case the path does not need to begin with a leading U+002F SOLIDUS ("/"). If the present working Directory is the root directory, then all paths to other directories or files can be represented by relative paths.

var path = "/music/genres/jazz"; // path from root to jazz Directory

// set genres directory to the present working Directory:

var pathToJazz = "jazz"; // relative path from within genres to jazz Directory 

Should additional definition be added to allow for "../.../myDir/yourDir" style path navigation under relative paths? Currently, we only allow forward path navigation; allowing "../../" will allow backward path navigation.

A child is a node on the Directory Tree with a position that is below a given position on the Directory Tree for a given directory; a subdirectory of the present working directory is a child of the present working directory; a subdirectory of that subdirectory is also a child of the present working directory. An immediate child corresponds to a node on the Directory Tree that is either a subdirectory that is the next position on the path, or a file that is next on the path. A parent is a directory that contains a file or another directory; in particular, the directory that contains the present working directory is its parent. The root directory is the parent of all other nodes in the Directory Tree.

When this specification says to add d to the Directory Tree, where d is either a file or a directory, a user agent must add d to the Directory Tree, along with its path from root.

Adding to the Directory Tree involves allocating storage for a new directory or a file, but not necessarily allocating storage for a pre-existing one, which can be added to the Directory Tree through a transfer operation. Failure to allocate storage owing to disk quota issues causes promises in this specification to get rejected with a QuotaExceededError.

When this specification says to remove d from the Directory Tree, where d is either a file or a directory, a user agent must remove d from the Directory Tree; in particular, this removes the path that d had and removes data associated with d. If d has files or subdirectories these must also be recursively removed, including the storage affiliated with each child.

User agents should determine if the storage can be reallocated for subsequent operations.

When this specification says to remove the path for a particular node, which is either a file or a directory, a user agent must remove the path from root for that node, without removing the storage allocated to that node or removing its data. This includes recursively removing the path from root for any child of that node, which applies only to directories.

When this specification says to transfer e to directory d, where e is either a file or a directory, the following steps must be followed, taking care to check for illegal transfers:

  1. Remove the path for e.

  2. If there is already a file or directory o with the identical name as e in d, run the following substeps:

    1. Remove o from the Directory Tree.

      This includes recursively removing any child nodes of o.

    2. Add e to the Directory Tree such that e is an immediate child of d. If e is directory, it becomes a subdirectory of d. If e is a file, it becomes a file contained by d.

  3. If e and d are identical, then terminate this algorithm, unless it is a renaming operation.

  4. Otherwise add e to the Directory Tree such that e is an immediate child of d. If e is directory, it becomes a subdirectory of d. If e is a file, it becomes a file contained by d.

Like adding to the Directory Tree, a transfer may generate storage quota errors.

The set of illegal transfers which methods invoking the transfer algorithm must prevent are:

TODO: See if there is a cohesive algorithm which results in better promise rejection messages for the move operation.

When this specification says to do a renaming operation with a new name on a node e on the Directory Tree, where e is either a file or a directory, user agents must change the name of e to the new name. If a transfer is invoked on two nodes, e and d, that identify the same node on the Directory Tree, unless d is supplied with a new name, the transfer is considered an illegal transfer. If the method invoking the transfer is supplied a new name, then it can perform a renaming operation.

The change to the underlying model's node e will result in a new object, or invalidate existing File and Directory objects referring to the underlying resource with the old name, which no longer exists.

When this specification says to crawl the entire path for a given path p, the following steps must be run:

  1. Let input be set to path, position be a pointer to input, initially set to the first character of input, and tokens be a list of tokens, initially empty. If input is a single U+002F SOLIDUS character, set the Directory Pointer to the root directory and terminate this algorithm.

  2. If the character at position is a U+002F SOLIDUS character ("/"), set the Directory Pointer to root; this represents a path from root. Otherwise, set it to the present working directory. Strictly split input on the U+002F SOLIDUS character.

  3. For each token in tokens, if the next position of the Directory Pointer strictly matches the name of a directory or a file, advance the Directory Pointer to that directory or file. If it does not strictly match, return failure.

When this specification says to crawl the path until node n for a given path p and value for n, the following steps must be run:

  1. Let input be set to path, position be a pointer to input, initially set to the first character of input, and tokens be a list of tokens, initially empty. If input is a single U+002F SOLIDUS character, set the Directory Pointer to the root directory and terminate this algorithm.

  2. If the character at position is a U+002F SOLIDUS character ("/"), set the Directory Pointer to root; this represents a path from root. Otherwise, set it to the present working directory. Strictly split input on the U+002F SOLIDUS character.

  3. If n ≥ the number of tokens in tokens, run the crawl the entire path algorithm and terminate this algorithm.

  4. Otherwise, for each token in tokens up to the nth token, if the next position of the Directory Pointer strictly matches the name of a directory, advance the Directory Pointer to that directory. If it does not strictly match, return failure.

Extensions to Existing Objects

The FileSystem API is exposed to the Web via an extension to the window.navigator object [[!HTML]]. A URL-generating method for individual files within the virtualized filesystem is generated via an extension to the window.URL object [[!URL]].

Extension to Navigator

Promise<Directory?> getFileSystem()

The getFileSystem method returns a Promise that is either fulfilled with the root Directory object or fulfilled with null if the root Directory object cannot be returned. The getFileSystem method must act as follows:

  1. Let promise be a new promise and run the next steps asynchronously.

  2. Resolve or reject promise according to the Directory Creation Steps with no value given for path.

  3. Return promise.

Extension to URL

static DOMString? getFileSystemURL(File file)

This method must return a FileSystem URL according to the URL generation steps for the File argument.

The Directory Interface

Directory objects represent a directory in the Directory Tree, and allow for API operations on that directory or on other parts of the Directory Tree, which may affect other directories. The root Directory object represents the root directory. Each Directory object must refer to the present working directory, unless any method called on that Directory uses a path argument that refers to another directory or file.

Origin of a Directory

The origin of a Directory is the same as the origin of the document or worker. Each origin has one root Directory.

The origin of the root Directory is not affected by changes to document.domain.

Origin may be redefined in terms of Script Realm; open bugs include 27203, 27204, and 26603.

Resolving or Rejecting a Directory-Creating Promise

When this specification says to resolve or reject a promise p according to the Directory Creation Steps, a conforming implementation must run the following steps within the asynchronous block that invoked this algorithm, and return control back to the invoking algorithm after resolving or rejecting p:

  1. If the method was invoked without a path argument, run the following root Directory substeps:

    1. If the root Directory cannot be returned by the implementation, resolve p with null.

      The invocation without a path argument occurs from navigator.getFileSystem(). In practice, there are few reasons for a user agent to not return a root Directory object; various errors may arise from Directory operations on the root Directory, but failure to create a root Directory should fulfill a Promise with null.

    2. Otherwise, resolve p with the root Directory.
  2. Otherwise the method was invoked with a path argument. Run the following Directory creation for a path argument steps:

    1. If the path argument is the empty string, then reject p with an InvalidStateError.

    2. If the path argument is a single U+002F SOLIDUS character ("/") then resolve p with the root Directory.

    3. Otherwise let input be set to the path argument, and let position be a pointer to input, initially pointing to the first character of input. Let dirname initially be set to the empty string, and let tokens be an ordered list of tokens, initally empty. If the character at position is a U+002F SOLIDUS character ("/"), set the Directory Pointer to the root of the Directory Tree, and advance position by one character. If not, set the Directory Pointer to the present working directory. Strictly split input on the U+002F SOLIDUS character ("/").

    4. While there are tokens in tokens, set dirname to initially equal the first token in tokens, moving to the next one at each iteration, and run the following substeps:

      1. If dirname strictly matches a subdirectory name that is the next position of the Directory Pointer, advance the Directory Pointer to the position on the Directory Tree that corresponds to the directory named dirname and reset dirname to the empty string.
      2. If dirname does not strictly match the next position of the Directory Pointer, then add to the Directory Tree a Directory called dirname and advance the Directory Pointer to the newly created Directory and reset dirname to the empty string. If adding to the Directory Tree raises any error, reject p with the most appropriate error from the Directory Promise Rejection Error Table.

    5. If all values of dirname strictly match the name of nodes on the Directory Tree, and no new directories are added to the Directory Tree, reject p with an InvalidModificationError.

    6. Otherwise, resolve p with a new Directory d with the following properties:

Directory Promise Rejection Error Table

Rejection of Directory-creation promises occur with the errors and reasons shown in the Directory Promise Rejection Error Table below.

Type Description and Failure Reason
QuotaExceededError

If no storage space exists for a directory creation operation.

SecurityError

If the user agent determines that the directory creation operation causes a security risk.

Directory WebIDL

readonly attribute DOMString name

On getting, this must be the name of the underlying directory.

Promise<File> createFile(DOMString path, CreateFileOptions options)

When the createFile(path, options) method is run, the user agents must run the steps below:

  1. Let p be a new promise.

  2. Run the following steps asynchronously:

    1. Strictly split the path argument on the U+002F SOLIDUS character. Let n be the total number of resulting tokens.

    2. If crawling the path until node n-1 for the path argument returns failure, reject p with an InvalidStateError.

    3. If the nth token in tokens identifies a directory, reject p with an InvalidStateError.

      The path argument must identify a file.

    4. Otherwise, if the nth token in tokens strictly matches the name of a pre-existing file at the next position of the Directory Pointer, run the following substeps:

      1. If the CreateIfExistsMode ifExists dictionary member of the options argument is "fail" then reject p with a NoModificationAllowedError.

      2. If the CreateIfExistsMode ifExists dictionary member of the options argument is "replace" then run the following substeps:

        1. Let f be a new File constructed according to running the File Constructor Steps with the following modifications:

          • Treat the data member of the options dictionary as if it was a single element in the fileBits sequence, and follow the step for that type from the File Constructor Steps.

          • Replace the fileName parameter with the nth token in tokens, and normalize it according to the File Constructor Steps.

          • Set f.lastModifiedDate to the current date and time represented as the number of milliseconds since the Unix Epoch (which is the equivalent of Date.now() [[!ECMAScript]]).

          • This API gives no way to configure the type of a File since filesystems do not store the type of a file. But the File constructor steps allow developers to mint File object with a type.

        2. Remove the file at the at the next position of the Directory Pointer which strictly matches the name of the nth token in tokens.

        3. Add the file represented by f to the next position of the Directory Pointer and advance the Directory Pointer to point to f. If adding to the Directory Tree raises any error, reject p with the most appropriate error from the Directory Promise Rejection Error Table.

        4. Otherwise, resolve p with f.

    5. If the nth token does not strictly match the name of a pre-existing file at the next position of the Directory Pointer run the following substeps:

      1. Let f be a new File constructed according to the File Constructor Steps with the following modifications:

        • Treat the data member of the options dictionary as if it was a single element in the fileBits sequence, and follow the step for that type from the File Constructor Steps.

        • Replace the fileName parameter with the nth token in tokens, and normalize it according to the File Constructor Steps.

        • Set f.lastModifiedDate to the current date and time represented as the number of milliseconds since the Unix Epoch (which is the equivalent of Date.now() [[!ECMAScript]).

        • This API gives no way to configure the type of a File since filesystems do not store the type of a file. But the File constructor steps allow developers to mint File object with a type.

      2. Add the file represented by f to the next position of the Directory Pointer and advance the Directory Pointer to point to f. If adding to the Directory Tree raises any error, reject p with the most appropriate error from the Directory Promise Rejection Error Table

        .

        Rejection in this algorithm occurs at a later stage than may be desirable; "short-circuiting" this might be good.

      3. Otherwise, resolve p with f.

  3. Return p

Promise<Directory> createDirectory(DOMString path)

When the createDirectory(path) method is called, the user agent must run the steps below:

  1. Let p be a new promise and run the next step asynchronously.
  2. Resolve or reject p according to the Directory Creation Steps, using the path argument.
  3. Return p
DOMString path
This parameter represents the path; user agents must interpret it as a path from root or a relative path.
Promise<(File or Directory)> get(DOMString path)

When the get(path) method is called, the user agent must run the steps below:

  1. Let p be a new promise.

  2. Run the following steps asynchronously:

    1. If crawling the entire path represented by the path argument returns failure, reject p with an InvalidStateError.

    2. Otherwise, set d to the node at the position the Directory Pointer is pointing to, and run the following substeps:

      1. If d is a file, resolve p with a new File representing d.

      2. If d is a directory, resolve p with a new Directory representing d.

  3. Return p.

CancelablePromise<void> move((DOMString or File or Directory) path, (DOMString or Directory or DestinationDict) dest)

When the move(path, dest) method is called, the user agent must run the steps below:

  1. Let p be a new CancelablePromise.

    The web does not have a CancelablePromise type yet.

  2. Run the following steps asynchronously:

    1. If path is a DOMString, then crawl the entire path represented by path. If it returns failure, then reject p with an InvalidStateError.

    2. If dest is a DOMString, then run the following substeps:

      1. Crawl the entire path represented by dest as a path. If it returns failure, then reject p with an InvalidStateError.

      2. If the path represented by dest is a File, reject p with an InvalidStateError.

        It is an error to move a directory or a file to the location of another file; dest must represent a directory, either through a valid path string, a Directory object, or the DestinationDict dictionary argument.

    3. If the node that corresponds to dest is a child of path, then reject p with an InvalidStateError.

      This is an illegal transfer.

    4. If path and dest both represent directories and are at the identical position on the Directory Tree, run the following substeps:

      1. If dest is not a DestinationDict with a name member that has a value different than the name of the directory represented by path, then reject p with an InvalidStateError.

        This is an illegal transfer; only a DestinationDict allows for a renaming operation.

      2. Otherwise:

        1. if dest is a DestinationDict with a name member that has a value different than the name of the directory represented by path, conduct a renaming operation on the directory identified by path

        2. resolve p with undefined.

        This may have implications for Directory objects that exist with the old name of the underlying directory.

    5. If path is a child of dest and dest has an immediate child which is a parent of path with the same name as the node identified by path, then reject p with an InvalidStateError.

      This is an illegal transfer.

    6. Otherwise:

      1. transfer path to dest. If there were errors in the transfer, reject p with the most appropriate error from the Directory Promise Rejection Error Table.

      2. If there were no errors, resolve p with undefined.

  3. Return p.

Promise<boolean> remove((DOMString or File or Directory) path)

When the remove(path) method is called, the user agent must run the steps below:

Is it better to take advantage of boolean semantics and ONLY resolve this promise with true or false (never reject) or to reject this promise, like other Directory operation promises get rejected? #bikeshed?

  1. Let p be a new promise.

  2. Run the following steps asynchronously:

    1. If path is a DOMString crawl the entire path. If it returns failure, resolve p with false.

    2. If path is a File then run the following substeps:

      1. Remove from the Directory Tree the node identified by the path argument.

        Error conditions could arise with removal. This should generate a fulfillment with false.

      2. Resolve p with true.

      This has implications for existing File object references. The "lock" problem needs to be solved.

    3. If path represents a directory run the following substeps:

      1. If path has one or more child nodes, resolve p with false.

      2. Otherwise, run the following substeps:

        1. Remove from the Directory Tree the node identified by the path argument.

          This has implications for existing Directory object references. The "lock" problem needs to be solved.

          Error conditions could arise with removal. This should generate a fulfillment with false.

        2. Resolve p with true.

  3. Return p.
Promise<boolean> removeDeep((DOMString or File or Directory) path)

When the removeDeep(path) method is called, the user agent must run the steps below:

Is it better to take advantage of boolean semantics and ONLY resolve this promise with true or false (never reject) or to reject this promise, like other Directory operation promises get rejected? #bikeshed?

  1. Let p be a new promise.

  2. Run the following steps asynchronously:

    1. If path is a DOMString crawl the entire path. If it returns failure, resolve p with false.

    2. If path is a File then run the following substeps:

      1. Remove from the Directory Tree the node identified by the path argument.

      2. Resolve p with true.

      This has implications for existing File object references. The "lock" problem needs to be solved.

    3. If path represents a directory run the following substeps:

      1. If path has no child nodes, run the following substeps:

        1. remove from the Directory Tree the node identifed by the path argument.

          Error conditions could arise with removal. This should generate a fulfillment with false.

        2. Resolve p with true
      2. If path has one or more child nodes, run the following substeps:

        1. Recursively remove from the Directory Tree the node identified by the path argument, including all child nodes.

          This has implications for existing Directory object references, for both the present working directory and all child nodes. The "lock" problem needs to be solved.

          Error conditions could arise with removal. This should generate a fulfillment with false.

        2. Resolve p with true.

  3. Return p.
Promise<FileHandle> openRead((DOMString or File) path)

When the openRead(path) method is called, the user agent must run the steps below:

  1. Let p be a new promise.
  2. Run the following steps asynchronously:

    1. If path is a DOMString, run the following substeps:

      1. Crawl the entire path. If it returns failure, then reject p with an InvalidStateError.

      2. If path represents a directory node and not a file node, reject p with an InvalidStateError.
      3. Otherwise, resolve p with a new FileHandle set to refer to the file at path.

    2. Return p.
Promise<FileHandleWritable> openWrite((DOMString or File) path, OpenWriteOptions options)

When the openWrite(path, options) method is called, the user agent must run the steps below:

  1. Let p be a new promise, and filename a string, initially empty.
  2. Run the following steps asynchronously:

    1. If the path argument is a DOMString, then run the substeps below:

      1. Strictly split the path argument on the U+002F SOLIDUS character. Let n be the total number of resulting tokens.

      2. If crawling the path until node n-1 for the path argument returns failure, reject p with an InvalidStateError.

      3. If the node identified by the token at n is a directory, reject p with an InvalidStateError.

        If a DOMString is used for path, it must point to a file in the Directory Tree, or be a the name of a potential new file.

      4. Otherwise, set filename to the nth token.
    2. If path is a File then set filename to path.name.

    3. If path is a File and filename corresponds to an existing file's name in the present working directory OR path is a DOMString and filename corresponds to a file's name in the directory identified by the n-1th token, then run the following substeps:

      If path is a File, then this method applies to the present working directory; if path is a DOMString, then this method applies to the directory identified by path's n-1th token.

      1. If the optional OpenWriteOptions dictionary argument is used, and the OpenIfExistsMode ifExists member is "fail" then reject p with an InvalidStateError.

      2. Otherwise, if the OpenIfExistsMode ifExists dictionary member is "open" then run the substeps below:

        This enum value is set to "open" by default.

        1. If the Flush dictionary member is set to true, resolve p with a flushing FileHandleWritable object set to the file corresponding to path.

        2. If the Flush dictionary member is set to false, resolve p with a non-flushing FileHandleWritable object set to the file corresponding to path.

          This value is set to false by default.

      3. Otherwise, if path is a File and filename does NOT correspond to an existing file's name in the present working directory OR path is a DOMString and filename does NOT correspond to a file's name in the directory identified by the n-1th token, then run the following substeps:

        1. If the optional OpenWriteOptions dictionary argument is used, and the OpenIfNotExistsMode ifNotExists member is "fail" then reject p with an InvalidStateError.

        2. Otherwise, if the OpenIfNotExistsMode ifNotExists dictionary member is "create" then run the substeps below:

          This enum value is set to "create" by default.

          1. If the Flush dictionary member is set to true, resolve p with a flushing FileHandleWritable object set to the file corresponding to path.

          2. If the Flush dictionary member is set to false, resolve p with a non-flushing FileHandleWritable object set to the file corresponding to path.

            This value is set to false by default.

  3. Return p
Observable<(File or Directory)> enumerate(optional DOMString path)

The Observable async generator and semantics around it are not well-defined yet. This is a general platform problem; Observable currently is a proposal within TC-39, and this should be considered "placeholder" semantics till the proposal becomes a language formalism.

When the enumerate(path) method is called, the user agent must run the steps below:

  1. If no parameter is provided, set the Directory Pointer to the present working directory. For each immediate child, emit a corresponding object (File or Directory) until done; when done, invoke this Observable's final state.

    If there are no immediate child nodes, this becomes the empty Observable.

  2. If a parameter is provided, and crawling the entire path returns failure, invoke the Observable's rejection path with an InvalidStateError.
  3. If crawling the entire path does not return failure, run the substeps below:
    1. If the Directory Pointer points to a file, emit a File corresponding to the file; when done, invoke this Observable's final state.
    2. If the Directory Pointer points to a directory, for each immediate child, emit a corresponding object (File or Directory) until done; when done, invoke this Observable's final state.
Observable<(File)> enumerateDeep(optional DOMString path)

The Observable async generator and semantics around it are not well-defined yet. This is a general platform problem; Observable currently is a proposal within TC-39, and this should be considered "placeholder" semantics till the proposal becomes a language formalism.

When the enumerateDeep(path) method is called, the user agent must run the steps below:

  1. If no parameter is provided, set the Directory Pointer to the present working directory and run the following substeps:
    1. If there are immediate child nodes and they are files, emit a corresponding File object.

      If there are no immediate child nodes, this becomes the empty Observable.

    2. If any immediate child is a directory, run the following substeps for all child nodes of that directory:

      1. Set the Directory Pointer to the directory and emit a corresponding File object for any immediate child nodes that are files.

      2. If any immediate child nodes are directories, run the step above on them.
    3. When done, invoke this Observable's final state.

  2. If a parameter is provided, and crawling the entire path returns failure, invoke the Observable's rejection path with an InvalidStateError.

  3. If crawling the entire path above does not return failure, run the substeps below:

    1. If the Directory Pointer points to a file, emit a File corresponding to the file; when done, invoke this Observable's final state.

    2. If the Directory Pointer points to a directory, run the following substeps:
      1. If there are immediate child nodes and they are files, emit a corresponding File object.

        If there are no immediate child nodes, this becomes the empty Observable.

      2. If any immediate child is a directory, run the following substeps for all child nodes of that directory:

        1. Set the Directory Pointer to the directory and emit a corresponding File object for any immediate child nodes that are files.

        2. If any immediate child nodes are directories, run the step above on them.
      3. When done, invoke this Observable's final state.

The FileHandle interface

FileHandle WebIDL

readonly attribute FileOpenMode mode

TBD

readonly attribute boolean active

TBD

attribute long long? offset

TBD

Promise<File> getFile()

TBD

CancelablePromise<ArrayBuffer> read(unsigned long long size)

TBD

void cancel()

TBD

The FileHandleWritable Interface

FileHandleWritable WebIDL

CancelablePromise<void> write((DOMString or ArrayBuffer or ArrayBufferView or Blob) value)

TBD

Promise<void> setSize(optional unsigned long long size)

TBD

FileSystem Configuration Parameters

CreateIfExistsMode ifExists = "fail"

This enum value indicates whether to write over a pre-existing file or to fail the attempt to write over a pre-existing file.

(DOMString or Blob or ArrayBuffer or ArrayBufferView) data

OpenIfNotExistsMode ifNotExists = "create"

TBD

OpenIfExistsMode ifExists = "open"

TBD

boolean Flush = false

TBD

replace

This value, if set, replaces a File by removing it and writing a new File over it.

fail

This is the default; by default, a file cannot be replaced.

open

TBD

fail

TBD

create

TBD

fail

TBD

Directory dir

TBD

DOMString name

TBD

readonly

TBD

readwrite

TBD

FileSystem URLs

Acknowledgements

Jonas Sicking, Mounir Lamouri, Ben Turner, Jan Varga, Andrea Marchesini, Doug Turner, Maciej Stachowiak