diff --git a/src/NativeFileSystem.js b/src/NativeFileSystem.js index 1cf5f369f57..65ee52def5f 100644 --- a/src/NativeFileSystem.js +++ b/src/NativeFileSystem.js @@ -8,12 +8,12 @@ define(function (require, exports, module) { 'use strict'; - // TODO: Determine proper public/private API for this module, splitting into separate modules as needed - var NativeFileSystem = { - /** Amount of time we wait for async calls to return (in milliseconds) - * TODO: Not all async calls are wrapped with something that times out and calls the error callback + /** + * Amount of time we wait for async calls to return (in milliseconds) + * Not all async calls are wrapped with something that times out and + * calls the error callback. Timeouts are not specified in the W3C spec. * @const * @type {number} */ @@ -66,6 +66,7 @@ define(function (require, exports, module) { requestNativeFileSystem: function (path, successCallback, errorCallback) { brackets.fs.stat(path, function (err, data) { if (!err) { + // FIXME (issue #247): return a NativeFileSystem object var root = new NativeFileSystem.DirectoryEntry(path); successCallback(root); } else if (errorCallback) { @@ -122,8 +123,6 @@ define(function (require, exports, module) { NativeFileSystem.Entry = function (fullPath, isDirectory) { this.isDirectory = isDirectory; this.isFile = !isDirectory; - - // TODO (jasonsj): PATH_SEPARATOR per native OS this.fullPath = fullPath; // Extract name from fullPath @@ -135,33 +134,48 @@ define(function (require, exports, module) { } } - this.getMetadata = function (successCallBack, errorCallback) { - brackets.fs.stat(this.fullPath, function (err, stat) { - if (err === brackets.fs.NO_ERROR) { - var metadata = new NativeFileSystem.Metadata(stat.mtime); - successCallBack(metadata); - } else { - errorCallback(NativeFileSystem._nativeToFileError(err)); - } - }); - - }; - - - // IMPLEMENT LATER copyTo(parent, newName, successCallBack, errorCallback) - // IMPLEMENT LATER getParent(successCallBack, errorCallback) - // IMPLEMENT LATER moveTo(parent, newName, successCallBack, errorCallback) - // IMPLEMENT LATER remove(successCallBack, errorCallback) - // IMPLEMENT LATER toURL() - - // IMPLEMENT LATER var filesystem; - // IMPLEMENT LATER void moveTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback); - // IMPLEMENT LATER void copyTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback); - // IMPLEMENT LATER DOMString toURL (optional DOMString mimeType); - // IMPLEMENT LATER void remove (VoidCallback successCallback, optional ErrorCallback errorCallback); - // IMPLEMENT LATER void getParent (EntryCallback successCallback, optional ErrorCallback errorCallback); + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-filesystem + this.filesystem = null; + }; + + NativeFileSystem.Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-moveTo + }; + + NativeFileSystem.Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-copyTo + }; + + NativeFileSystem.Entry.prototype.toURL = function (mimeType) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-toURL + }; + + NativeFileSystem.Entry.prototype.remove = function (successCallback, errorCallback) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-remove + }; + + NativeFileSystem.Entry.prototype.getParent = function (successCallback, errorCallback) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-Entry-remove + }; + + NativeFileSystem.Entry.prototype.getMetadata = function (successCallBack, errorCallback) { + brackets.fs.stat(this.fullPath, function (err, stat) { + if (err === brackets.fs.NO_ERROR) { + var metadata = new NativeFileSystem.Metadata(stat.mtime); + successCallBack(metadata); + } else { + errorCallback(NativeFileSystem._nativeToFileError(err)); + } + }); }; + /** * Stores information about a FileEntry */ @@ -170,7 +184,6 @@ define(function (require, exports, module) { this.modificationTime = modificationTime; }; - /** class: FileEntry * This interface represents a file on a file system. * @@ -179,10 +192,9 @@ define(function (require, exports, module) { * @extends {Entry} */ NativeFileSystem.FileEntry = function (name) { - this.prototype = new NativeFileSystem.Entry(); NativeFileSystem.Entry.call(this, name, false); - }; + NativeFileSystem.FileEntry.prototype = new NativeFileSystem.Entry(); /** * Creates a new FileWriter associated with the file that this FileEntry represents. @@ -201,21 +213,6 @@ define(function (require, exports, module) { // FileWriter private memeber vars this._length = 0; this._position = 0; - - // initialize file length - // TODO (jasonsj): handle async - var self = this; - - brackets.fs.readFile(fileEntry.fullPath, "utf8", function (err, contents) { - // Ignore "file not found" errors. It's okay if the file doesn't exist yet. - if (err !== brackets.fs.ERR_NOT_FOUND) { - self._err = err; - } - - if (contents) { - self._length = contents.length; - } - }); }; FileWriter.prototype.length = function () { @@ -226,7 +223,7 @@ define(function (require, exports, module) { return this._position; }; - // TODO (jasonsj): handle Blob data instead of string + // TODO (issue #241): handle Blob data instead of string FileWriter.prototype.write = function (data) { if (!data) { throw new Error(); @@ -239,7 +236,7 @@ define(function (require, exports, module) { this._readyState = NativeFileSystem.FileSaver.WRITING; if (this.onwritestart) { - // TODO (jasonsj): progressevent + // TODO (issue #241): progressevent this.onwritestart(); } @@ -250,14 +247,14 @@ define(function (require, exports, module) { if ((err !== brackets.fs.NO_ERROR) && self.onerror) { var fileError = NativeFileSystem._nativeToFileError(err); - // TODO (jasonsj): set readonly FileSaver.error attribute + // TODO (issue #241): set readonly FileSaver.error attribute // self._error = fileError; self.onerror(fileError); - // TODO (jasonsj): partial write, update length and position + // TODO (issue #241): partial write, update length and position } // else { - // TODO (jasonsj): After changing data argument to Blob, use + // TODO (issue #241): After changing data argument to Blob, use // Blob.size to update position and length upon successful // completion of a write. @@ -269,12 +266,12 @@ define(function (require, exports, module) { self._readyState = NativeFileSystem.FileSaver.DONE; if (self.onwrite) { - // TODO (jasonsj): progressevent + // TODO (issue #241): progressevent self.onwrite(); } if (self.onwriteend) { - // TODO (jasonsj): progressevent + // TODO (issue #241): progressevent self.onwriteend(); } }); @@ -288,14 +285,42 @@ define(function (require, exports, module) { var fileWriter = new FileWriter(); - if (fileWriter._err && (errorCallback !== undefined)) { - errorCallback(NativeFileSystem._nativeToFileError(fileWriter._err)); - } else if (successCallback !== undefined) { - successCallback(fileWriter); - } + // initialize file length + var result = new $.Deferred(); + brackets.fs.readFile(fileEntry.fullPath, "utf8", function (err, contents) { + // Ignore "file not found" errors. It's okay if the file doesn't exist yet. + if (err !== brackets.fs.ERR_NOT_FOUND) { + fileWriter._err = err; + } + + if (contents) { + fileWriter._length = contents.length; + } + + result.resolve(); + }); + + result.done(function () { + if (fileWriter._err && (errorCallback !== undefined)) { + errorCallback(NativeFileSystem._nativeToFileError(fileWriter._err)); + } else if (successCallback !== undefined) { + successCallback(fileWriter); + } + }); }; + /** + * Obtains the File objecte for a FileEntry object + * + * @param {function(...)} successCallback + * @param {function(...)} errorCallback + */ + NativeFileSystem.FileEntry.prototype.file = function (successCallback, errorCallback) { + var newFile = new NativeFileSystem.File(this); + successCallback(newFile); + // TODO (issue #241): errorCallback + }; /** * This interface extends the FileException interface described in to add @@ -363,14 +388,14 @@ define(function (require, exports, module) { return this._readyState; }; - // TODO (jasonsj): http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void + // TODO (issue #241): http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void NativeFileSystem.FileSaver.prototype.abort = function () { // If readyState is DONE or INIT, terminate this overall series of steps without doing anything else.. if (this._readyState === NativeFileSystem.FileSaver.INIT || this._readyState === NativeFileSystem.FileSaver.DONE) { return; } - // Terminate any steps having to do with writing a file. + // TODO (issue #241): Terminate any steps having to do with writing a file. // Set the error attribute to a FileError object with the code ABORT_ERR. this._error = new NativeFileSystem.FileError(FileError.ABORT_ERR); @@ -378,32 +403,15 @@ define(function (require, exports, module) { // Set readyState to DONE. this._readyState = NativeFileSystem.FileSaver.DONE; - // Dispatch a progress event called abort - // Dispatch a progress event called writeend - // Stop dispatching any further progress events. - // Terminate this overall set of steps. - }; - - /** - * Obtains the File objecte for a FileEntry object - * - * @param {function(...)} successCallback - * @param {function(...)} errorCallback - */ - NativeFileSystem.FileEntry.prototype.file = function (successCallback, errorCallback) { - var newFile = new NativeFileSystem.File(this); - successCallback(newFile); - - // TODO Ty: error handling - // errorCallback + /* + TODO (issue #241): + Dispatch a progress event called abort + Dispatch a progress event called writeend + Stop dispatching any further progress events. + Terminate this overall set of steps. + */ }; - /* - TODO Jason - NativeFileSystem.FileEntry.prototype.createfileerror = function (successCallback, errorCallback) { - }; - */ - /** * This interface represents a directory on a file system. * @@ -414,12 +422,19 @@ define(function (require, exports, module) { NativeFileSystem.DirectoryEntry = function (name) { NativeFileSystem.Entry.call(this, name, true); - // TODO: make DirectoryEntry actually inherit from Entry by modifying prototype. I don't know how to do this yet. - - // IMPLEMENT LATERvoid getDirectory (DOMString path, optional Flags options, optional EntryCallback successCallback, optional ErrorCallback errorCallback); - // IMPLEMENT LATERvoid removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback); + // TODO (issue #241): void removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback); + }; + NativeFileSystem.DirectoryEntry.prototype = new NativeFileSystem.Entry(); + + NativeFileSystem.DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-DirectoryEntry-getDirectory + }; + + NativeFileSystem.DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) { + // TODO (issue #241) + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-DirectoryEntry-removeRecursively }; - NativeFileSystem.DirectoryEntry.prototype.createReader = function () { var dirReader = new NativeFileSystem.DirectoryReader(); @@ -513,14 +528,12 @@ define(function (require, exports, module) { }); }; - /** class: DirectoryReader */ NativeFileSystem.DirectoryReader = function () { }; - /** readEntries * * @param {function(...)} successCallback @@ -566,7 +579,7 @@ define(function (require, exports, module) { statEntry(rootPath + "/" + filelist[i], d); } - // FIXME: (joelrbrandt or pflynn) -- once we have an async library, it would be good + // FIXME (issue #213): -- once we have an async library, it would be good // to replace the code below with a library call. // Get a Promise that depennds on all the individual deferreds finishing. @@ -621,14 +634,7 @@ define(function (require, exports, module) { * @extends {EventTarget} */ NativeFileSystem.FileReader = function () { - // Todo Ty: this classes should extend EventTarget - - // async read methods - // IMPLEMENT LATER void readAsArrayBuffer(Blob blob); - // IMPLEMENT LATER void readAsBinaryString(Blob blob); - // IMPLEMENT LATER void readAsDataURL(Blob blob); - - // IMPLEMENT LATER void abort(); + // TODO (issue #241): this classes should extend EventTarget // states this.EMPTY = 0; @@ -639,8 +645,8 @@ define(function (require, exports, module) { this.readyState = this.EMPTY; // File or Blob data - // IMPLEMENT LATER readonly attribute any result; - // IMPLEMENT LATER readonly attribute DOMError error; + // TODO (issue #241): readonly attribute any result; + // TODO (issue #241): readonly attribute DOMError error; // event handler attributes this.onloadstart = null; @@ -649,10 +655,30 @@ define(function (require, exports, module) { this.onabort = null; this.onerror = null; this.onloadend = null; - - }; - + // TODO (issue #241): extend EventTarget (draft status, not implememnted in webkit) + // NativeFileSystem.FileReader.prototype = new NativeFileSystem.EventTarget() + + NativeFileSystem.FileReader.prototype.readAsArrayBuffer = function (blob) { + // TODO (issue #241): implement + // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsArrayBuffer + }; + + NativeFileSystem.FileReader.prototype.readAsBinaryString = function (blob) { + // TODO (issue #241): implement + // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsBinaryStringAsync + }; + + NativeFileSystem.FileReader.prototype.readAsDataURL = function (blob) { + // TODO (issue #241): implement + // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-readAsDataURL + }; + + NativeFileSystem.FileReader.prototype.abort = function () { + // TODO (issue #241): implement + // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-abort + }; + /** readAsText * * @param {Blob} blob @@ -672,12 +698,12 @@ define(function (require, exports, module) { this.readyState = this.LOADING; if (this.onloadstart) { - this.onloadstart(); // todo params + this.onloadstart(); // TODO (issue #241): progressevent } brackets.fs.readFile(blob._fullPath, encoding, function (err, data) { - // TODO: the event objects passed to these event handlers is fake and incomplete right now + // TODO (issue #241): the event objects passed to these event handlers is fake and incomplete right now var fakeEvent = { loaded: 0, total: 0 @@ -696,7 +722,7 @@ define(function (require, exports, module) { } else { self.readyState = self.DONE; - // TODO: this should be the file/blob size, but we don't have code to get that yet, so for know assume a file size of 1 + // TODO (issue #241): this should be the file/blob size, but we don't have code to get that yet, so for know assume a file size of 1 // and since we read the file in one go, assume 100% after the first read fakeEvent.loaded = 1; fakeEvent.total = 1; @@ -705,7 +731,7 @@ define(function (require, exports, module) { self.onprogress(fakeEvent); } - // TODO: onabort not currently supported since our native implementation doesn't support it + // TODO (issue #241): onabort not currently supported since our native implementation doesn't support it // if (self.onabort) // self.onabort(fakeEvent); @@ -728,17 +754,19 @@ define(function (require, exports, module) { */ NativeFileSystem.Blob = function (fullPath) { this._fullPath = fullPath; - - // IMPLEMENT LATER readonly attribute unsigned long long size; - // IMPLEMENT LATER readonly attribute DOMString type; - - //slice Blob into byte-ranged chunks - - // IMPLEMENT LATER Blob slice(optional long long start, - // optional long long end, - // optional DOMString contentType); + + // TODO (issue #241): implement, readonly + this.size = 0; + + // TODO (issue #241): implement, readonly + this.type = null; }; - + + NativeFileSystem.Blob.prototype.slice = function (start, end, contentType) { + // TODO (issue #241): implement + // http://www.w3.org/TR/2011/WD-FileAPI-20111020/#dfn-slice + }; + /** class: File * * @constructor @@ -747,9 +775,12 @@ define(function (require, exports, module) { */ NativeFileSystem.File = function (entry) { NativeFileSystem.Blob.call(this, entry.fullPath); - - // IMPLEMENT LATER get name() { return this.entry.name; } - + + // TODO (issue #241): implement, readonly + this.name = ""; + + // TODO (issue #241): implement, readonly + this.lastModifiedDate = null; }; /** class: FileError diff --git a/test/spec/NativeFileSystem-test.js b/test/spec/NativeFileSystem-test.js index 9bd4b63af3e..7e3e6733f05 100644 --- a/test/spec/NativeFileSystem-test.js +++ b/test/spec/NativeFileSystem-test.js @@ -125,7 +125,8 @@ define(function (require, exports, module) { }); it("can read an empty folder", function () { - // FIXME: (joelrbrandt) We need an empty folder for testing in this spec. Unfortunately, it's impossible + // TODO: (issue #241): Implement DirectoryEntry.getDirectory() and remove this empty folder workaround. + // We need an empty folder for testing in this spec. Unfortunately, it's impossible // to check an empty folder in to git, and we don't have low level fs calls to create an emtpy folder. // So, for now, we have a folder called "emptydir" which contains a single 0-length file called // "placeholder". We delete that file at the beginning of each test, and then recreate it at the end. @@ -165,7 +166,8 @@ define(function (require, exports, module) { function deletePlaceholder(successCallback) { - // FIXME: (joelrbrandt) once NativeFileSystem has a delete/unlink, should use that + // TODO: (issue #241): implement FileEntry.remove() + // once NativeFileSystem has a delete/unlink, should use that brackets.fs.unlink(placeholderPath, function (err) { if (!err) { placeholderDeleted = true; @@ -407,7 +409,7 @@ define(function (require, exports, module) { writeComplete = true; }; - // FIXME (jasonsj): NativeFileSystem.root is missing + // FIXME (issue #247): NativeFileSystem.root is missing this.nfs.getFile("new-zero-length-file.txt", { create: true, exclusive: true }, successCallback, errorCallback); }); @@ -461,7 +463,7 @@ define(function (require, exports, module) { writeComplete = true; }; - // FIXME (jasonsj): NativeFileSystem.root is missing + // FIXME (issue #247): NativeFileSystem.root is missing this.nfs.getFile("does-not-exist.txt", { create: false }, successCallback, errorCallback); }); @@ -490,7 +492,7 @@ define(function (require, exports, module) { writeComplete = true; }; - // FIXME (jasonsj): NativeFileSystem.root is missing + // FIXME (issue #247): NativeFileSystem.root is missing this.nfs.getFile("file1", { create: true, exclusive: true }, successCallback, errorCallback); }); @@ -522,7 +524,7 @@ define(function (require, exports, module) { writeComplete = true; }; - // FIXME (jasonsj): NativeFileSystem.root is missing + // FIXME (issue #247): NativeFileSystem.root is missing this.nfs.getFile("dir1", { create: false }, successCallback, errorCallback); }); @@ -555,7 +557,7 @@ define(function (require, exports, module) { writeComplete = true; }; - // TODO (jasonsj): BlobBulder + // TODO (issue #241): BlobBulder fileWriter.write("FileWriter.write"); }); }; @@ -626,7 +628,7 @@ define(function (require, exports, module) { error = err; }; - // TODO (jasonsj): BlobBulder + // TODO (issue #241): BlobBulder fileWriter.write("FileWriter.write"); }); }; @@ -649,15 +651,15 @@ define(function (require, exports, module) { }); xit("should append to existing files", function () { - this.fail("TODO (jasonsj): not supported for sprint 1"); + this.fail("TODO (issue #241): not supported for sprint 1"); }); xit("should seek into a file before writing", function () { - this.fail("TODO (jasonsj): not supported for sprint 1"); + this.fail("TODO (issue #241): not supported for sprint 1"); }); xit("should truncate files", function () { - this.fail("TODO (jasonsj): not supported for sprint 1"); + this.fail("TODO (issue #241): not supported for sprint 1"); }); }); });