| Index: runtime/bin/file_impl.dart
|
| diff --git a/runtime/bin/file_impl.dart b/runtime/bin/file_impl.dart
|
| index 6db8e1e41b22a55183793ba9b869e3dc79001ac1..479cea36b0a2fd12c872def397baff59ed31c39c 100644
|
| --- a/runtime/bin/file_impl.dart
|
| +++ b/runtime/bin/file_impl.dart
|
| @@ -7,7 +7,7 @@ class _FileInputStream extends _BaseDataInputStream implements InputStream {
|
| _file = new File(name);
|
| _data = [];
|
| _position = 0;
|
| - _file.onError = (String s) {
|
| + _file.onError = (e) {
|
| if (_clientErrorHandler != null) {
|
| _clientErrorHandler();
|
| }
|
| @@ -26,7 +26,7 @@ class _FileInputStream extends _BaseDataInputStream implements InputStream {
|
| }
|
|
|
| void _readDataFromFile(RandomAccessFile openedFile) {
|
| - openedFile.onError = (String s) {
|
| + openedFile.onError = (e) {
|
| if (_clientErrorHandler != null) {
|
| _clientErrorHandler();
|
| }
|
| @@ -224,6 +224,10 @@ class _FileUtils {
|
| static final kWriteListRequest = 15;
|
| static final kWriteStringRequest = 16;
|
|
|
| + static final kSuccessResponse = 0;
|
| + static final kIllegalArgumentResponse = 1;
|
| + static final kOSErrorResponse = 2;
|
| +
|
| static List ensureFastAndSerializableBuffer(
|
| List buffer, int offset, int bytes) {
|
| // When using the Dart C API to access raw data, using a ByteArray is
|
| @@ -250,12 +254,12 @@ class _FileUtils {
|
| return [outBuffer, outOffset];
|
| }
|
|
|
| - static bool exists(String name) native "File_Exists";
|
| - static int open(String name, int mode) native "File_Open";
|
| - static bool create(String name) native "File_Create";
|
| - static bool delete(String name) native "File_Delete";
|
| - static String fullPath(String name) native "File_FullPath";
|
| - static String directory(String name) native "File_Directory";
|
| + static exists(String name) native "File_Exists";
|
| + static open(String name, int mode) native "File_Open";
|
| + static create(String name) native "File_Create";
|
| + static delete(String name) native "File_Delete";
|
| + static fullPath(String name) native "File_FullPath";
|
| + static directory(String name) native "File_Directory";
|
| static int close(int id) native "File_Close";
|
| static int readByte(int id) native "File_ReadByte";
|
| static int readList(int id, List<int> buffer, int offset, int bytes)
|
| @@ -279,24 +283,70 @@ class _FileUtils {
|
| static int openStdio(int fd) native "File_OpenStdio";
|
| static SendPort newServicePort() native "File_NewServicePort";
|
|
|
| + static bool checkedExists(String name) {
|
| + if (name is !String) {
|
| + throw new IllegalArgumentException();
|
| + }
|
| + var result = exists(name);
|
| + if (result is OSError) {
|
| + throw new FileIOException("Cannot check existence of file", result);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| static int checkedOpen(String name, int mode) {
|
| - if (name is !String || mode is !int) return 0;
|
| - return open(name, mode);
|
| + if (name is !String || mode is !int) {
|
| + throw new IllegalArgumentException();
|
| + };
|
| + var result = open(name, mode);
|
| + if (result is OSError) {
|
| + throw new FileIOException("Cannot open file", result);
|
| + }
|
| + return result;
|
| }
|
|
|
| static bool checkedCreate(String name) {
|
| - if (name is !String) return false;
|
| - return create(name);
|
| + if (name is !String) {
|
| + throw new IllegalArgumentException();
|
| + };
|
| + var result = create(name);
|
| + if (result is OSError) {
|
| + throw new FileIOException("Cannot create file", result);
|
| + }
|
| + return true;
|
| }
|
|
|
| static bool checkedDelete(String name) {
|
| - if (name is !String) return false;
|
| - return delete(name);
|
| + if (name is !String) {
|
| + throw new IllegalArgumentException();
|
| + };
|
| + var result = delete(name);
|
| + if (result is OSError) {
|
| + throw new FileIOException("Cannot delete file", result);
|
| + }
|
| + return true;
|
| }
|
|
|
| static String checkedFullPath(String name) {
|
| - if (name is !String) return null;
|
| - return fullPath(name);
|
| + if (name is !String) {
|
| + throw new IllegalArgumentException();
|
| + };
|
| + var result = fullPath(name);
|
| + if (result is OSError) {
|
| + throw new FileIOException("Cannot retrieve full path", result);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + static String checkedDirectory(String name) {
|
| + if (name is !String) {
|
| + throw new IllegalArgumentException();
|
| + }
|
| + var result = directory(name);
|
| + if (result is OSError) {
|
| + throw new FileIOException("Cannot retrieve directory for file", result);
|
| + }
|
| + return result;
|
| }
|
|
|
| static int checkReadWriteListArguments(int length, int offset, int bytes) {
|
| @@ -310,6 +360,7 @@ class _FileUtils {
|
| if (string is !String) return -1;
|
| return writeString(id, string);
|
| }
|
| +
|
| }
|
|
|
|
|
| @@ -321,17 +372,15 @@ class _File implements File {
|
| void exists(void callback(bool exists)) {
|
| _ensureFileService();
|
| _asyncUsed = true;
|
| - if (_name is !String) {
|
| - if (_onError != null) {
|
| - _onError('File name is not a string: $_name');
|
| - }
|
| - return;
|
| - }
|
| List request = new List(2);
|
| request[0] = _FileUtils.kExistsRequest;
|
| request[1] = _name;
|
| - _fileService.call(request).then((exists) {
|
| - callback(exists);
|
| + _fileService.call(request).then((response) {
|
| + if (_isErrorResponse(response)) {
|
| + _reportError(response, "Cannot open file");
|
| + } else {
|
| + callback(response);
|
| + }
|
| });
|
| }
|
|
|
| @@ -340,10 +389,7 @@ class _File implements File {
|
| throw new FileIOException(
|
| "Mixed use of synchronous and asynchronous API");
|
| }
|
| - if (_name is !String) {
|
| - throw new FileIOException('File name is not a string: $_name');
|
| - }
|
| - return _FileUtils.exists(_name);
|
| + return _FileUtils.checkedExists(_name);
|
| }
|
|
|
| void create(void callback()) {
|
| @@ -352,11 +398,11 @@ class _File implements File {
|
| List request = new List(2);
|
| request[0] = _FileUtils.kCreateRequest;
|
| request[1] = _name;
|
| - _fileService.call(request).then((created) {
|
| - if (created) {
|
| + _fileService.call(request).then((response) {
|
| + if (_isErrorResponse(response)) {
|
| + _reportError(response, "Cannot create file");
|
| + } else {
|
| callback();
|
| - } else if (_onError != null) {
|
| - _onError("Cannot create file: $_name");
|
| }
|
| });
|
| }
|
| @@ -378,11 +424,11 @@ class _File implements File {
|
| List request = new List(2);
|
| request[0] = _FileUtils.kDeleteRequest;
|
| request[1] = _name;
|
| - _fileService.call(request).then((deleted) {
|
| - if (deleted) {
|
| + _fileService.call(request).then((response) {
|
| + if (_isErrorResponse(response)) {
|
| + _reportError(response, "Cannot delete file");
|
| + } else {
|
| callback();
|
| - } else if (_onError != null) {
|
| - _onError("Cannot delete file: $_name");
|
| }
|
| });
|
| }
|
| @@ -392,10 +438,7 @@ class _File implements File {
|
| throw new FileIOException(
|
| "Mixed use of synchronous and asynchronous API");
|
| }
|
| - bool deleted = _FileUtils.checkedDelete(_name);
|
| - if (!deleted) {
|
| - throw new FileIOException("Cannot delete file: $_name");
|
| - }
|
| + _FileUtils.checkedDelete(_name);
|
| }
|
|
|
| void directory(void callback(Directory dir)) {
|
| @@ -404,11 +447,11 @@ class _File implements File {
|
| List request = new List(2);
|
| request[0] = _FileUtils.kDirectoryRequest;
|
| request[1] = _name;
|
| - _fileService.call(request).then((path) {
|
| - if (path != null) {
|
| - callback(new Directory(path));
|
| - } else if (_onError != null) {
|
| - _onError("Cannot get directory for: ${_name}");
|
| + _fileService.call(request).then((response) {
|
| + if (_isErrorResponse(response)) {
|
| + _reportError(response, "Cannot retrieve directory for file");
|
| + } else {
|
| + callback(new Directory(response));
|
| }
|
| });
|
| }
|
| @@ -418,9 +461,7 @@ class _File implements File {
|
| throw new FileIOException(
|
| "Mixed use of synchronous and asynchronous API");
|
| }
|
| - if (!existsSync()) {
|
| - throw new FileIOException("Cannot get directory for: $_name");
|
| - }
|
| + _FileUtils.checkedDirectory(_name);
|
| return new Directory(_FileUtils.directory(_name));
|
| }
|
|
|
| @@ -431,8 +472,7 @@ class _File implements File {
|
| mode != FileMode.WRITE &&
|
| mode != FileMode.APPEND) {
|
| if (_onError != null) {
|
| - _onError("Unknown file mode. Use FileMode.READ, FileMode.WRITE " +
|
| - "or FileMode.APPEND.");
|
| + _onError(new IllegalArgumentException());
|
| return;
|
| }
|
| }
|
| @@ -440,11 +480,11 @@ class _File implements File {
|
| request[0] = _FileUtils.kOpenRequest;
|
| request[1] = _name;
|
| request[2] = mode._mode; // Direct int value for serialization.
|
| - _fileService.call(request).then((id) {
|
| - if (id != 0) {
|
| - callback(new _RandomAccessFile(id, _name));
|
| - } else if (_onError != null) {
|
| - _onError("Cannot open file: $_name");
|
| + _fileService.call(request).then((response) {
|
| + if (_isErrorResponse(response)) {
|
| + _reportError(response, "Cannot open file");
|
| + } else {
|
| + callback(new _RandomAccessFile(response, _name));
|
| }
|
| });
|
| }
|
| @@ -461,9 +501,7 @@ class _File implements File {
|
| "FileMode.WRITE or FileMode.APPEND.");
|
| }
|
| var id = _FileUtils.checkedOpen(_name, mode._mode);
|
| - if (id == 0) {
|
| - throw new FileIOException("Cannot open file: $_name");
|
| - }
|
| + assert(id != 0);
|
| return new _RandomAccessFile(id, _name);
|
| }
|
|
|
| @@ -481,11 +519,11 @@ class _File implements File {
|
| List request = new List(2);
|
| request[0] = _FileUtils.kFullPathRequest;
|
| request[1] = _name;
|
| - _fileService.call(request).then((result) {
|
| - if (result != null) {
|
| - callback(result);
|
| - } else if (_onError != null) {
|
| - _onError("fullPath failed");
|
| + _fileService.call(request).then((response) {
|
| + if (_isErrorResponse(response)) {
|
| + _reportError(response, "Cannot retrieve full path");
|
| + } else {
|
| + callback(response);
|
| }
|
| });
|
| }
|
| @@ -495,11 +533,7 @@ class _File implements File {
|
| throw new FileIOException(
|
| "Mixed use of synchronous and asynchronous API");
|
| }
|
| - String result = _FileUtils.checkedFullPath(_name);
|
| - if (result == null) {
|
| - throw new FileIOException("fullPath failed");
|
| - }
|
| - return result;
|
| + return _FileUtils.checkedFullPath(_name);
|
| }
|
|
|
| InputStream openInputStream() {
|
| @@ -528,7 +562,7 @@ class _File implements File {
|
| };
|
| stream.onError = () {
|
| if (_onError != null) {
|
| - _onError("Failed to read file as bytes: $_name");
|
| + _onError("Failed to read file");
|
| }
|
| };
|
| }
|
| @@ -543,7 +577,7 @@ class _File implements File {
|
| var result = new ByteArray(length);
|
| var read = opened.readListSync(result, 0, length);
|
| if (read != length) {
|
| - throw new FileIOException("Failed reading file as bytes: $_name");
|
| + throw new FileIOException("Failed to read file");
|
| }
|
| opened.closeSync();
|
| return result;
|
| @@ -631,6 +665,27 @@ class _File implements File {
|
| }
|
| }
|
|
|
| + bool _isErrorResponse(response) {
|
| + return response is List && response[0] != _FileUtils.kSuccessResponse;
|
| + }
|
| +
|
| + bool _reportError(response, String message) {
|
| + assert(_isErrorResponse(response));
|
| + if (_onError != null) {
|
| + switch (response[0]) {
|
| + case _FileUtils.kIllegalArgumentResponse:
|
| + _onError(new IllegalArgumentException());
|
| + break;
|
| + case _FileUtils.kOSErrorResponse:
|
| + _onError(new FileIOException(message,
|
| + new OSError(response[2], response[1])));
|
| + break;
|
| + default:
|
| + _onError(new Exception("Unknown error"));
|
| + }
|
| + }
|
| + }
|
| +
|
| String _name;
|
| bool _asyncUsed;
|
|
|
|
|