зеркало из https://github.com/mozilla/pluotsorbet.git
Merge pull request #640 from mykmelez/fs-perf
improve fs perf with in-memory cache, synchronous calls
This commit is contained in:
Коммит
2929e3c7e7
|
@ -1,179 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This module defines an asynchronous version of the localStorage API, backed by
|
|
||||||
* an IndexedDB database. It creates a global asyncStorage object that has
|
|
||||||
* methods like the localStorage object.
|
|
||||||
*
|
|
||||||
* To store a value use setItem:
|
|
||||||
*
|
|
||||||
* asyncStorage.setItem('key', 'value');
|
|
||||||
*
|
|
||||||
* If you want confirmation that the value has been stored, pass a callback
|
|
||||||
* function as the third argument:
|
|
||||||
*
|
|
||||||
* asyncStorage.setItem('key', 'newvalue', function() {
|
|
||||||
* console.log('new value stored');
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* To read a value, call getItem(), but note that you must supply a callback
|
|
||||||
* function that the value will be passed to asynchronously:
|
|
||||||
*
|
|
||||||
* asyncStorage.getItem('key', function(value) {
|
|
||||||
* console.log('The value of key is:', value);
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* Note that unlike localStorage, asyncStorage does not allow you to store and
|
|
||||||
* retrieve values by setting and querying properties directly. You cannot just
|
|
||||||
* write asyncStorage.key; you have to explicitly call setItem() or getItem().
|
|
||||||
*
|
|
||||||
* removeItem(), clear(), length(), and key() are like the same-named methods of
|
|
||||||
* localStorage, but, like getItem() and setItem() they take a callback
|
|
||||||
* argument.
|
|
||||||
*
|
|
||||||
* The asynchronous nature of getItem() makes it tricky to retrieve multiple
|
|
||||||
* values. But unlike localStorage, asyncStorage does not require the values you
|
|
||||||
* store to be strings. So if you need to save multiple values and want to
|
|
||||||
* retrieve them together, in a single asynchronous operation, just group the
|
|
||||||
* values into a single object. The properties of this object may not include
|
|
||||||
* DOM elements, but they may include things like Blobs and typed arrays.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var asyncStorage = (function() {
|
|
||||||
var indexedDB = window.indexedDB || window.webkitIndexedDB ||
|
|
||||||
window.mozIndexedDB || window.msIndexedDB;
|
|
||||||
|
|
||||||
var DBNAME = 'asyncStorage';
|
|
||||||
var DBVERSION = 1;
|
|
||||||
var STORENAME = 'keyvaluepairs';
|
|
||||||
var db = null;
|
|
||||||
|
|
||||||
function withDatabase(f) {
|
|
||||||
if (db) {
|
|
||||||
f();
|
|
||||||
} else {
|
|
||||||
var openreq = indexedDB.open(DBNAME, DBVERSION);
|
|
||||||
openreq.onerror = function withStoreOnError() {
|
|
||||||
console.error('asyncStorage: can\'t open database:',
|
|
||||||
openreq.error.name);
|
|
||||||
};
|
|
||||||
openreq.onupgradeneeded = function withStoreOnUpgradeNeeded() {
|
|
||||||
// First time setup: create an empty object store
|
|
||||||
openreq.result.createObjectStore(STORENAME);
|
|
||||||
};
|
|
||||||
openreq.onsuccess = function withStoreOnSuccess() {
|
|
||||||
db = openreq.result;
|
|
||||||
f();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function withStore(type, callback, oncomplete) {
|
|
||||||
withDatabase(function() {
|
|
||||||
var transaction = db.transaction(STORENAME, type);
|
|
||||||
if (oncomplete) {
|
|
||||||
transaction.oncomplete = oncomplete;
|
|
||||||
}
|
|
||||||
callback(transaction.objectStore(STORENAME));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItem(key, callback) {
|
|
||||||
var req;
|
|
||||||
withStore('readonly', function getItemBody(store) {
|
|
||||||
req = store.get(key);
|
|
||||||
req.onerror = function getItemOnError() {
|
|
||||||
console.error('Error in asyncStorage.getItem(): ', req.error.name);
|
|
||||||
};
|
|
||||||
}, function onComplete() {
|
|
||||||
var value = req.result;
|
|
||||||
if (value === undefined) {
|
|
||||||
value = null;
|
|
||||||
}
|
|
||||||
callback(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setItem(key, value, callback) {
|
|
||||||
withStore('readwrite', function setItemBody(store) {
|
|
||||||
var req = store.put(value, key);
|
|
||||||
req.onerror = function setItemOnError() {
|
|
||||||
console.error('Error in asyncStorage.setItem(): ', req.error.name);
|
|
||||||
};
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeItem(key, callback) {
|
|
||||||
withStore('readwrite', function removeItemBody(store) {
|
|
||||||
var req = store.delete(key);
|
|
||||||
req.onerror = function removeItemOnError() {
|
|
||||||
console.error('Error in asyncStorage.removeItem(): ', req.error.name);
|
|
||||||
};
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear(callback) {
|
|
||||||
withStore('readwrite', function clearBody(store) {
|
|
||||||
var req = store.clear();
|
|
||||||
req.onerror = function clearOnError() {
|
|
||||||
console.error('Error in asyncStorage.clear(): ', req.error.name);
|
|
||||||
};
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function length(callback) {
|
|
||||||
var req;
|
|
||||||
withStore('readonly', function lengthBody(store) {
|
|
||||||
req = store.count();
|
|
||||||
req.onerror = function lengthOnError() {
|
|
||||||
console.error('Error in asyncStorage.length(): ', req.error.name);
|
|
||||||
};
|
|
||||||
}, function onComplete() {
|
|
||||||
callback(req.result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function key(n, callback) {
|
|
||||||
if (n < 0) {
|
|
||||||
callback(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var req;
|
|
||||||
withStore('readonly', function keyBody(store) {
|
|
||||||
var advanced = false;
|
|
||||||
req = store.openCursor();
|
|
||||||
req.onsuccess = function keyOnSuccess() {
|
|
||||||
var cursor = req.result;
|
|
||||||
if (!cursor) {
|
|
||||||
// this means there weren't enough keys
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (n === 0 || advanced) {
|
|
||||||
// Either 1) we have the first key, return it if that's what they
|
|
||||||
// wanted, or 2) we've got the nth key.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, ask the cursor to skip ahead n records
|
|
||||||
advanced = true;
|
|
||||||
cursor.advance(n);
|
|
||||||
};
|
|
||||||
req.onerror = function keyOnError() {
|
|
||||||
console.error('Error in asyncStorage.key(): ', req.error.name);
|
|
||||||
};
|
|
||||||
}, function onComplete() {
|
|
||||||
var cursor = req.result;
|
|
||||||
callback(cursor ? cursor.key : null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getItem: getItem,
|
|
||||||
setItem: setItem,
|
|
||||||
removeItem: removeItem,
|
|
||||||
clear: clear,
|
|
||||||
length: length,
|
|
||||||
key: key
|
|
||||||
};
|
|
||||||
})();
|
|
249
libs/fs.js
249
libs/fs.js
|
@ -1,6 +1,88 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var DEBUG_FS = false;
|
||||||
|
|
||||||
var fs = (function() {
|
var fs = (function() {
|
||||||
|
var Store = function() {
|
||||||
|
this.map = new Map();
|
||||||
|
this.db = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Store.DBNAME = "asyncStorage";
|
||||||
|
Store.DBVERSION = 1;
|
||||||
|
Store.DBSTORENAME = "keyvaluepairs";
|
||||||
|
|
||||||
|
Store.prototype.init = function(cb) {
|
||||||
|
var openreq = indexedDB.open(Store.DBNAME, Store.DBVERSION);
|
||||||
|
openreq.onerror = function() {
|
||||||
|
console.error("error opening database: " + openreq.error.name);
|
||||||
|
};
|
||||||
|
openreq.onupgradeneeded = function() {
|
||||||
|
openreq.result.createObjectStore(Store.DBSTORENAME);
|
||||||
|
};
|
||||||
|
openreq.onsuccess = (function() {
|
||||||
|
this.db = openreq.result;
|
||||||
|
cb();
|
||||||
|
}).bind(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Store.prototype.getItem = function(key, cb) {
|
||||||
|
if (this.map.has(key)) {
|
||||||
|
var value = this.map.get(key);
|
||||||
|
window.setZeroTimeout(function() { cb(value) });
|
||||||
|
} else {
|
||||||
|
var transaction = this.db.transaction(Store.DBSTORENAME, "readonly");
|
||||||
|
var objectStore = transaction.objectStore(Store.DBSTORENAME);
|
||||||
|
var req = objectStore.get(key);
|
||||||
|
req.onerror = function() {
|
||||||
|
console.error("Error getting " + key + ": " + req.error.name);
|
||||||
|
};
|
||||||
|
transaction.oncomplete = (function() {
|
||||||
|
var value = req.result;
|
||||||
|
if (value === undefined) {
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
this.map.set(key, value);
|
||||||
|
cb(value);
|
||||||
|
}).bind(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Store.prototype.setItem = function(key, value) {
|
||||||
|
this.map.set(key, value);
|
||||||
|
|
||||||
|
var transaction = this.db.transaction(Store.DBSTORENAME, "readwrite");
|
||||||
|
var objectStore = transaction.objectStore(Store.DBSTORENAME);
|
||||||
|
var req = objectStore.put(value, key);
|
||||||
|
req.onerror = function() {
|
||||||
|
console.error("Error putting " + key + ": " + req.error.name);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Store.prototype.removeItem = function(key) {
|
||||||
|
this.map.delete(key);
|
||||||
|
|
||||||
|
var transaction = this.db.transaction(Store.DBSTORENAME, "readwrite");
|
||||||
|
var objectStore = transaction.objectStore(Store.DBSTORENAME);
|
||||||
|
var req = objectStore.delete(key);
|
||||||
|
req.onerror = function() {
|
||||||
|
console.error("Error deleting " + key + ": " + req.error.name);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Store.prototype.clear = function() {
|
||||||
|
this.map.clear();
|
||||||
|
|
||||||
|
var transaction = this.db.transaction(Store.DBSTORENAME, "readwrite");
|
||||||
|
var objectStore = transaction.objectStore(Store.DBSTORENAME);
|
||||||
|
var req = objectStore.clear();
|
||||||
|
req.onerror = function() {
|
||||||
|
console.error("Error clearing store: " + req.error.name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var store = new Store();
|
||||||
|
|
||||||
var FileBuffer = function(array) {
|
var FileBuffer = function(array) {
|
||||||
this.array = array;
|
this.array = array;
|
||||||
this.contentSize = array.byteLength;
|
this.contentSize = array.byteLength;
|
||||||
|
@ -75,25 +157,31 @@ var fs = (function() {
|
||||||
return path.slice(path.lastIndexOf("/") + 1);
|
return path.slice(path.lastIndexOf("/") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(cb) {
|
function initRootDir(cb) {
|
||||||
asyncStorage.getItem("/", function(data) {
|
store.getItem("/", function(data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
cb();
|
cb();
|
||||||
} else {
|
} else {
|
||||||
asyncStorage.setItem("/", [], function() {
|
store.setItem("/", []);
|
||||||
setStat("/", { mtime: Date.now(), isDir: true }, cb);
|
setStat("/", { mtime: Date.now(), isDir: true });
|
||||||
});
|
cb();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function init(cb) {
|
||||||
|
store.init(function() {
|
||||||
|
initRootDir(cb || function() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var openedFiles = [null, null, null];
|
var openedFiles = [null, null, null];
|
||||||
var fileStats = {};
|
|
||||||
|
|
||||||
function open(path, cb) {
|
function open(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs open " + path); }
|
||||||
|
|
||||||
asyncStorage.getItem(path, function(blob) {
|
store.getItem(path, function(blob) {
|
||||||
if (blob == null || !(blob instanceof Blob)) {
|
if (blob == null || !(blob instanceof Blob)) {
|
||||||
cb(-1);
|
cb(-1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -112,20 +200,11 @@ var fs = (function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function close(fd, cb) {
|
function close(fd) {
|
||||||
if (fd >= 0 && openedFiles[fd]) {
|
if (fd >= 0 && openedFiles[fd]) {
|
||||||
flush(fd, function() {
|
if (DEBUG_FS) { console.log("fs close " + openedFiles[fd].path); }
|
||||||
// Replace descriptor object with null value instead of removing it from
|
flush(fd);
|
||||||
// the array so we don't change the indexes of the other objects.
|
openedFiles.splice(fd, 1, null);
|
||||||
openedFiles.splice(fd, 1, null);
|
|
||||||
if (cb) {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (cb) {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +212,7 @@ var fs = (function() {
|
||||||
if (!openedFiles[fd]) {
|
if (!openedFiles[fd]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (DEBUG_FS) { console.log("fs read " + openedFiles[fd].path); }
|
||||||
|
|
||||||
var buffer = openedFiles[fd].buffer;
|
var buffer = openedFiles[fd].buffer;
|
||||||
|
|
||||||
|
@ -153,6 +233,8 @@ var fs = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function write(fd, data, from) {
|
function write(fd, data, from) {
|
||||||
|
if (DEBUG_FS) { console.log("fs write " + openedFiles[fd].path); }
|
||||||
|
|
||||||
if (typeof from == "undefined") {
|
if (typeof from == "undefined") {
|
||||||
from = openedFiles[fd].position;
|
from = openedFiles[fd].position;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +255,6 @@ var fs = (function() {
|
||||||
file.position = from + data.byteLength;
|
file.position = from + data.byteLength;
|
||||||
file.stat = { mtime: Date.now(), isDir: false, size: buffer.contentSize };
|
file.stat = { mtime: Date.now(), isDir: false, size: buffer.contentSize };
|
||||||
file.dirty = true;
|
file.dirty = true;
|
||||||
fileStats[file.path] = file.stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getpos(fd) {
|
function getpos(fd) {
|
||||||
|
@ -192,22 +273,22 @@ var fs = (function() {
|
||||||
return openedFiles[fd].buffer.contentSize;
|
return openedFiles[fd].buffer.contentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
function flush(fd, cb) {
|
function flush(fd) {
|
||||||
|
if (DEBUG_FS) { console.log("fs flush " + openedFiles[fd].path); }
|
||||||
|
|
||||||
|
var openedFile = openedFiles[fd];
|
||||||
|
|
||||||
// Bail early if the file has not been modified.
|
// Bail early if the file has not been modified.
|
||||||
if (!openedFiles[fd].dirty) {
|
if (!openedFile.dirty) {
|
||||||
cb();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var blob = new Blob([openedFiles[fd].buffer.getContent()]);
|
var blob = new Blob([openedFile.buffer.getContent()]);
|
||||||
asyncStorage.setItem(openedFiles[fd].path, blob, function() {
|
store.setItem(openedFile.path, blob);
|
||||||
openedFiles[fd].dirty = false;
|
openedFile.dirty = false;
|
||||||
if (openedFiles[fd].stat) {
|
if (openedFile.stat) {
|
||||||
setStat(openedFiles[fd].path, openedFiles[fd].stat, cb);
|
setStat(openedFile.path, openedFile.stat);
|
||||||
} else {
|
}
|
||||||
cb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function flushAll() {
|
function flushAll() {
|
||||||
|
@ -230,8 +311,9 @@ var fs = (function() {
|
||||||
|
|
||||||
function list(path, cb) {
|
function list(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs list " + path); }
|
||||||
|
|
||||||
asyncStorage.getItem(path, function(files) {
|
store.getItem(path, function(files) {
|
||||||
if (files == null || files instanceof Blob) {
|
if (files == null || files instanceof Blob) {
|
||||||
cb(null);
|
cb(null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,6 +324,7 @@ var fs = (function() {
|
||||||
|
|
||||||
function exists(path, cb) {
|
function exists(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs exists " + path); }
|
||||||
|
|
||||||
stat(path, function(stat) {
|
stat(path, function(stat) {
|
||||||
cb(stat ? true : false);
|
cb(stat ? true : false);
|
||||||
|
@ -250,13 +333,13 @@ var fs = (function() {
|
||||||
|
|
||||||
function truncate(path, cb) {
|
function truncate(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs truncate " + path); }
|
||||||
|
|
||||||
stat(path, function(stat) {
|
stat(path, function(stat) {
|
||||||
if (stat && !stat.isDir) {
|
if (stat && !stat.isDir) {
|
||||||
asyncStorage.setItem(path, new Blob(), function() {
|
store.setItem(path, new Blob());
|
||||||
setStat(path, { mtime: Date.now(), isDir: false, size: 0 });
|
setStat(path, { mtime: Date.now(), isDir: false, size: 0 });
|
||||||
cb(true);
|
cb(true);
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
cb(false);
|
cb(false);
|
||||||
}
|
}
|
||||||
|
@ -264,16 +347,19 @@ var fs = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ftruncate(fd, size) {
|
function ftruncate(fd, size) {
|
||||||
|
if (DEBUG_FS) { console.log("fs ftruncate " + openedFiles[fd].path); }
|
||||||
|
|
||||||
var file = openedFiles[fd];
|
var file = openedFiles[fd];
|
||||||
if (size != file.buffer.contentSize) {
|
if (size != file.buffer.contentSize) {
|
||||||
file.buffer.setSize(size);
|
file.buffer.setSize(size);
|
||||||
file.dirty = true;
|
file.dirty = true;
|
||||||
fileStats[file.path] = file.stat = { mtime: Date.now(), isDir: false, size: size };
|
file.stat = { mtime: Date.now(), isDir: false, size: size };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(path, cb) {
|
function remove(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs remove " + path); }
|
||||||
|
|
||||||
if (openedFiles.findIndex(function(file) { return file && file.path === path; }) != -1) {
|
if (openedFiles.findIndex(function(file) { return file && file.path === path; }) != -1) {
|
||||||
setZeroTimeout(function() { cb(false); });
|
setZeroTimeout(function() { cb(false); });
|
||||||
|
@ -298,13 +384,10 @@ var fs = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
files.splice(index, 1);
|
files.splice(index, 1);
|
||||||
asyncStorage.setItem(dir, files, function() {
|
store.setItem(dir, files);
|
||||||
asyncStorage.removeItem(path, function() {
|
store.removeItem(path);
|
||||||
removeStat(path, function() {
|
removeStat(path);
|
||||||
cb(true);
|
cb(true);
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -320,43 +403,39 @@ var fs = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
files.push(name);
|
files.push(name);
|
||||||
asyncStorage.setItem(dir, files, function() {
|
store.setItem(dir, files);
|
||||||
asyncStorage.setItem(path, data, function() {
|
store.setItem(path, data);
|
||||||
cb(true);
|
cb(true);
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function create(path, blob, cb) {
|
function create(path, blob, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs create " + path); }
|
||||||
|
|
||||||
createInternal(path, blob, function(created) {
|
createInternal(path, blob, function(created) {
|
||||||
if (created) {
|
if (created) {
|
||||||
setStat(path, { mtime: Date.now(), isDir: false, size: blob.size }, function() {
|
setStat(path, { mtime: Date.now(), isDir: false, size: blob.size });
|
||||||
cb(created);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cb(created);
|
|
||||||
}
|
}
|
||||||
|
cb(created);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkdir(path, cb) {
|
function mkdir(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs mkdir " + path); }
|
||||||
|
|
||||||
createInternal(path, [], function(created) {
|
createInternal(path, [], function(created) {
|
||||||
if (created) {
|
if (created) {
|
||||||
setStat(path, { mtime: Date.now(), isDir: true }, function() {
|
setStat(path, { mtime: Date.now(), isDir: true });
|
||||||
cb(created);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cb(created);
|
|
||||||
}
|
}
|
||||||
|
cb(created);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function mkdirp(path, cb) {
|
function mkdirp(path, cb) {
|
||||||
|
if (DEBUG_FS) { console.log("fs mkdirp " + path); }
|
||||||
|
|
||||||
if (path[0] !== "/") {
|
if (path[0] !== "/") {
|
||||||
console.error("mkdirp called on relative path: " + path);
|
console.error("mkdirp called on relative path: " + path);
|
||||||
cb(false);
|
cb(false);
|
||||||
|
@ -400,19 +479,12 @@ var fs = (function() {
|
||||||
|
|
||||||
function size(path, cb) {
|
function size(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs size " + path); }
|
||||||
|
|
||||||
if (fileStats[path] && typeof fileStats[path].size != "undefined") {
|
store.getItem(path, function(blob) {
|
||||||
cb(fileStats[path].size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
asyncStorage.getItem(path, function(blob) {
|
|
||||||
if (blob == null || !(blob instanceof Blob)) {
|
if (blob == null || !(blob instanceof Blob)) {
|
||||||
cb(-1);
|
cb(-1);
|
||||||
} else {
|
} else {
|
||||||
if (fileStats[path]) {
|
|
||||||
fileStats[path].size = blob.size;
|
|
||||||
}
|
|
||||||
cb(blob.size);
|
cb(blob.size);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -423,6 +495,7 @@ var fs = (function() {
|
||||||
function rename(oldPath, newPath, cb) {
|
function rename(oldPath, newPath, cb) {
|
||||||
oldPath = normalizePath(oldPath);
|
oldPath = normalizePath(oldPath);
|
||||||
newPath = normalizePath(newPath);
|
newPath = normalizePath(newPath);
|
||||||
|
if (DEBUG_FS) { console.log("fs rename " + oldPath + " -> " + newPath); }
|
||||||
|
|
||||||
if (openedFiles.findIndex(function(file) { return file && file.path === oldPath; }) != -1) {
|
if (openedFiles.findIndex(function(file) { return file && file.path === oldPath; }) != -1) {
|
||||||
setZeroTimeout(function() { cb(false); });
|
setZeroTimeout(function() { cb(false); });
|
||||||
|
@ -435,7 +508,7 @@ var fs = (function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncStorage.getItem(oldPath, function(data) {
|
store.getItem(oldPath, function(data) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
cb(false);
|
cb(false);
|
||||||
return;
|
return;
|
||||||
|
@ -457,24 +530,21 @@ var fs = (function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setStat(path, stat, cb) {
|
function setStat(path, stat) {
|
||||||
fileStats[path] = stat;
|
if (DEBUG_FS) { console.log("fs setStat " + path); }
|
||||||
asyncStorage.setItem("!" + path, stat, cb);
|
|
||||||
|
store.setItem("!" + path, stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeStat(path, cb) {
|
function removeStat(path) {
|
||||||
delete fileStats[path];
|
if (DEBUG_FS) { console.log("fs removeStat " + path); }
|
||||||
asyncStorage.removeItem("!" + path, cb);
|
|
||||||
|
store.removeItem("!" + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stat(path, cb) {
|
function stat(path, cb) {
|
||||||
path = normalizePath(path);
|
path = normalizePath(path);
|
||||||
|
if (DEBUG_FS) { console.log("fs stat " + path); }
|
||||||
var stat = fileStats[path];
|
|
||||||
if (stat) {
|
|
||||||
setZeroTimeout(function() { cb(stat); });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var file = openedFiles.find(function (file) { return file && file.stat && file.path === path });
|
var file = openedFiles.find(function (file) { return file && file.stat && file.path === path });
|
||||||
if (file) {
|
if (file) {
|
||||||
|
@ -482,12 +552,12 @@ var fs = (function() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncStorage.getItem("!" + path, function(stat) {
|
store.getItem("!" + path, cb);
|
||||||
if (stat) {
|
}
|
||||||
fileStats[path] = stat;
|
|
||||||
}
|
function clear(cb) {
|
||||||
cb(stat);
|
store.clear();
|
||||||
});
|
initRootDir(cb || function() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -512,5 +582,6 @@ var fs = (function() {
|
||||||
size: size,
|
size: size,
|
||||||
rename: rename,
|
rename: rename,
|
||||||
stat: stat,
|
stat: stat,
|
||||||
|
clear: clear,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
<script type="text/javascript" src="jvm.js" defer></script>
|
<script type="text/javascript" src="jvm.js" defer></script>
|
||||||
<script type="text/javascript" src="libs/zipfile.js" defer></script>
|
<script type="text/javascript" src="libs/zipfile.js" defer></script>
|
||||||
<script type="text/javascript" src="libs/long.js" defer></script>
|
<script type="text/javascript" src="libs/long.js" defer></script>
|
||||||
<script type="text/javascript" src="libs/async_storage.js" defer></script>
|
|
||||||
<script type="text/javascript" src="libs/encoding.js" defer></script>
|
<script type="text/javascript" src="libs/encoding.js" defer></script>
|
||||||
<script type="text/javascript" src="libs/fs.js" defer></script>
|
<script type="text/javascript" src="libs/fs.js" defer></script>
|
||||||
<script type="text/javascript" src="libs/rusha.js" defer></script>
|
<script type="text/javascript" src="libs/rusha.js" defer></script>
|
||||||
|
|
41
main.js
41
main.js
|
@ -63,7 +63,7 @@ if (urlParams.pushConn && urlParams.pushMidlet) {
|
||||||
var initFS = new Promise(function(resolve, reject) {
|
var initFS = new Promise(function(resolve, reject) {
|
||||||
fs.init(resolve);
|
fs.init(resolve);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
return Promise.all([
|
var fsPromises = [
|
||||||
new Promise(function(resolve, reject) {
|
new Promise(function(resolve, reject) {
|
||||||
fs.mkdir("/Persistent", resolve);
|
fs.mkdir("/Persistent", resolve);
|
||||||
}),
|
}),
|
||||||
|
@ -81,7 +81,27 @@ var initFS = new Promise(function(resolve, reject) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if (MIDP.midletClassName == "RunTests") {
|
||||||
|
fsPromises.push(
|
||||||
|
new Promise(function(resolve, reject) {
|
||||||
|
fs.exists("/_test.ks", function(exists) {
|
||||||
|
if (exists) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
load("certs/_test.ks", "blob").then(function(data) {
|
||||||
|
fs.create("/_test.ks", data, function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(fsPromises);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mobile info gets accessed a lot, so we cache it on startup.
|
// Mobile info gets accessed a lot, so we cache it on startup.
|
||||||
|
@ -120,21 +140,6 @@ if (MIDP.midletClassName == "RunTests") {
|
||||||
loadingPromises.push(loadScript("tests/native.js"),
|
loadingPromises.push(loadScript("tests/native.js"),
|
||||||
loadScript("tests/override.js"),
|
loadScript("tests/override.js"),
|
||||||
loadScript("tests/mozactivitymock.js"));
|
loadScript("tests/mozactivitymock.js"));
|
||||||
loadingPromises.push(
|
|
||||||
new Promise(function(resolve, reject) {
|
|
||||||
fs.exists("/_test.ks", function(exists) {
|
|
||||||
if (exists) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
load("certs/_test.ks", "blob").then(function(data) {
|
|
||||||
fs.create("/_test.ks", data, function() {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(loadingPromises).then(function() {
|
Promise.all(loadingPromises).then(function() {
|
||||||
|
@ -152,7 +157,7 @@ function toggle(button) {
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
document.getElementById("clearstorage").onclick = function() {
|
document.getElementById("clearstorage").onclick = function() {
|
||||||
asyncStorage.clear();
|
fs.clear();
|
||||||
};
|
};
|
||||||
document.getElementById("trace").onclick = function() {
|
document.getElementById("trace").onclick = function() {
|
||||||
VM.DEBUG = !VM.DEBUG;
|
VM.DEBUG = !VM.DEBUG;
|
||||||
|
|
49
midp/fs.js
49
midp/fs.js
|
@ -109,25 +109,17 @@ Native.create("com/sun/midp/rms/RecordStoreFile.writeBytes.(I[BII)V", function(h
|
||||||
});
|
});
|
||||||
|
|
||||||
Native.create("com/sun/midp/rms/RecordStoreFile.commitWrite.(I)V", function(handle) {
|
Native.create("com/sun/midp/rms/RecordStoreFile.commitWrite.(I)V", function(handle) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.flush(handle);
|
||||||
fs.flush(handle, resolve);
|
});
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Native.create("com/sun/midp/rms/RecordStoreFile.closeFile.(I)V", function(handle) {
|
Native.create("com/sun/midp/rms/RecordStoreFile.closeFile.(I)V", function(handle) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.close(handle);
|
||||||
fs.close(handle, resolve);
|
});
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Native.create("com/sun/midp/rms/RecordStoreFile.truncateFile.(II)V", function(handle, size) {
|
Native.create("com/sun/midp/rms/RecordStoreFile.truncateFile.(II)V", function(handle, size) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.flush(handle);
|
||||||
fs.flush(handle, function() {
|
fs.ftruncate(handle, size);
|
||||||
fs.ftruncate(handle, size);
|
});
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
MIDP.RecordStoreCache = [];
|
MIDP.RecordStoreCache = [];
|
||||||
|
|
||||||
|
@ -442,7 +434,8 @@ Native.create("com/ibm/oti/connection/file/Connection.truncateImpl.([BJ)V", func
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.ftruncate(fd, newLength.toNumber());
|
fs.ftruncate(fd, newLength.toNumber());
|
||||||
fs.close(fd, resolve);
|
fs.close(fd);
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, true);
|
}, true);
|
||||||
|
@ -500,10 +493,8 @@ Native.create("com/ibm/oti/connection/file/FCInputStream.closeImpl.(I)V", functi
|
||||||
});
|
});
|
||||||
|
|
||||||
Native.create("com/ibm/oti/connection/file/FCOutputStream.closeImpl.(I)V", function(fd) {
|
Native.create("com/ibm/oti/connection/file/FCOutputStream.closeImpl.(I)V", function(fd) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.close(fd);
|
||||||
fs.close(fd, resolve);
|
});
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Native.create("com/ibm/oti/connection/file/FCOutputStream.openImpl.([B)I", function(jPath) {
|
Native.create("com/ibm/oti/connection/file/FCOutputStream.openImpl.([B)I", function(jPath) {
|
||||||
var path = util.decodeUtf8(jPath);
|
var path = util.decodeUtf8(jPath);
|
||||||
|
@ -559,10 +550,8 @@ Native.create("com/ibm/oti/connection/file/FCOutputStream.openOffsetImpl.([BJ)I"
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
Native.create("com/ibm/oti/connection/file/FCOutputStream.syncImpl.(I)V", function(fd) {
|
Native.create("com/ibm/oti/connection/file/FCOutputStream.syncImpl.(I)V", function(fd) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.flush(fd);
|
||||||
fs.flush(fd, resolve);
|
});
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Native.create("com/ibm/oti/connection/file/FCOutputStream.writeByteImpl.(II)V", function(val, fd) {
|
Native.create("com/ibm/oti/connection/file/FCOutputStream.writeByteImpl.(II)V", function(val, fd) {
|
||||||
var buf = new Uint8Array(1);
|
var buf = new Uint8Array(1);
|
||||||
|
@ -630,10 +619,8 @@ function(handle, buffer, offset, length) {
|
||||||
});
|
});
|
||||||
|
|
||||||
Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.commitWrite.(I)V", function(handle) {
|
Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.commitWrite.(I)V", function(handle) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.flush(handle);
|
||||||
fs.flush(handle, resolve);
|
});
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.position.(II)V", function(handle, position) {
|
Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.position.(II)V", function(handle, position) {
|
||||||
fs.setpos(handle, position);
|
fs.setpos(handle, position);
|
||||||
|
@ -650,10 +637,8 @@ Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.sizeOf.(I)I", fun
|
||||||
});
|
});
|
||||||
|
|
||||||
Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.close.(I)V", function(handle) {
|
Native.create("com/sun/midp/io/j2me/storage/RandomAccessStream.close.(I)V", function(handle) {
|
||||||
return new Promise(function(resolve, reject) {
|
fs.close(handle);
|
||||||
fs.close(handle, resolve);
|
});
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Native.create("javax/microedition/io/file/FileSystemRegistry.getRootsImpl.()[Ljava/lang/String;", function() {
|
Native.create("javax/microedition/io/file/FileSystemRegistry.getRootsImpl.()[Ljava/lang/String;", function() {
|
||||||
var array = util.newArray("[Ljava/lang/String;", 1);
|
var array = util.newArray("[Ljava/lang/String;", 1);
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import javax.microedition.io.*;
|
||||||
|
import javax.microedition.io.file.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class TestFileSystemPerf {
|
||||||
|
public static void main(String args[]) {
|
||||||
|
try {
|
||||||
|
String dirPath = System.getProperty("fileconn.dir.private");
|
||||||
|
long then;
|
||||||
|
|
||||||
|
String str = "I am the very model of a modern major general.";
|
||||||
|
byte[] bytes = str.getBytes();
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
FileConnection file = (FileConnection)Connector.open(dirPath + "test.txt");
|
||||||
|
System.out.println("Time to open file: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
file.create();
|
||||||
|
System.out.println("Time to create file: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
OutputStream out = file.openOutputStream();
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
out.write(bytes);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
System.out.println("Time to write/flush to output stream: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
out.close();
|
||||||
|
System.out.println("Time to close output stream: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
file.delete();
|
||||||
|
System.out.println("Time to delete file: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
file.close();
|
||||||
|
System.out.println("Time to close file: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
file = (FileConnection)Connector.open(dirPath + "test.txt");
|
||||||
|
System.out.println("Time to reopen file: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
then = System.currentTimeMillis();
|
||||||
|
file = (FileConnection)Connector.open(dirPath + "test2.txt");
|
||||||
|
file.create();
|
||||||
|
out = file.openOutputStream();
|
||||||
|
out.write(bytes);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
file.delete();
|
||||||
|
file.close();
|
||||||
|
System.out.println("Time to access another file: " + (System.currentTimeMillis() - then) + "ms");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Unexpected exception: " + e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ var gfxTests = [
|
||||||
];
|
];
|
||||||
|
|
||||||
var expectedUnitTestResults = [
|
var expectedUnitTestResults = [
|
||||||
{ name: "pass", number: 71128 },
|
{ name: "pass", number: 71126 },
|
||||||
{ name: "fail", number: 0 },
|
{ name: "fail", number: 0 },
|
||||||
{ name: "known fail", number: 180 },
|
{ name: "known fail", number: 180 },
|
||||||
{ name: "unknown pass", number: 0 }
|
{ name: "unknown pass", number: 0 }
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="initial-scale=1.0">
|
<meta name="viewport" content="initial-scale=1.0">
|
||||||
<script type="text/javascript" src="../libs/async_storage.js" defer></script>
|
|
||||||
<script type="text/javascript" src="../libs/fs.js" defer></script>
|
<script type="text/javascript" src="../libs/fs.js" defer></script>
|
||||||
<script type="text/javascript" src="../timer.js" defer></script>
|
<script type="text/javascript" src="../timer.js" defer></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var passed = 0, failed = 0;
|
var passed = 0, failed = 0, then = performance.now();
|
||||||
function is(a, b, msg) {
|
function is(a, b, msg) {
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
++passed;
|
++passed;
|
||||||
|
@ -30,7 +30,8 @@ var fd;
|
||||||
function next() {
|
function next() {
|
||||||
if (tests.length == 0) {
|
if (tests.length == 0) {
|
||||||
ok(true, "TESTS COMPLETED");
|
ok(true, "TESTS COMPLETED");
|
||||||
console.log("DONE: " + passed + " PASS, " + failed + " FAIL");
|
console.log("DONE: " + passed + " PASS, " + failed + " FAIL, " +
|
||||||
|
(Math.round(performance.now() - then)) + " TIME");
|
||||||
} else {
|
} else {
|
||||||
var test = tests.shift();
|
var test = tests.shift();
|
||||||
test();
|
test();
|
||||||
|
@ -67,15 +68,18 @@ tests.push(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.close(-1, next);
|
fs.close(-1);
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.close(0, next);
|
fs.close(0);
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.close(1, next);
|
fs.close(1);
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
|
@ -331,7 +335,8 @@ tests.push(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.close(3, next);
|
fs.close(3);
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
|
@ -494,16 +499,15 @@ tests.push(function() {
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.size("/tmp/tmp.txt", function(size) {
|
fs.size("/tmp/tmp.txt", function(size) {
|
||||||
is(size, 12, "unflushed file's size is 12");
|
is(size, 0, "unflushed file's size is 0");
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.flush(fd, function() {
|
fs.flush(fd);
|
||||||
ok(true, "file data flushed");
|
ok(true, "file data flushed");
|
||||||
next();
|
next();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
|
@ -549,7 +553,8 @@ tests.push(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
fs.close(fd, next);
|
fs.close(fd);
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
|
@ -676,12 +681,11 @@ tests.push(function() {
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
fs.flush(fd, function() {
|
fs.flush(fd);
|
||||||
fs.stat("/tmp/stat.txt", function(stat) {
|
fs.stat("/tmp/stat.txt", function(stat) {
|
||||||
is(stat.mtime, lastTime, "flush on just opened file doesn't update mtime");
|
is(stat.mtime, lastTime, "flush on just opened file doesn't update mtime");
|
||||||
lastTime = stat.mtime;
|
lastTime = stat.mtime;
|
||||||
next();
|
next();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
@ -700,24 +704,22 @@ tests.push(function() {
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
fs.write(fd, new TextEncoder().encode("sc"));
|
fs.write(fd, new TextEncoder().encode("sc"));
|
||||||
fs.flush(fd, function() {
|
fs.flush(fd);
|
||||||
fs.stat("/tmp/stat.txt", function(stat) {
|
fs.stat("/tmp/stat.txt", function(stat) {
|
||||||
ok(stat.mtime > lastTime, "write and then flush updates mtime");
|
ok(stat.mtime > lastTime, "write and then flush updates mtime");
|
||||||
lastTime = stat.mtime;
|
lastTime = stat.mtime;
|
||||||
next();
|
next();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
fs.flush(fd, function() {
|
fs.flush(fd);
|
||||||
fs.stat("/tmp/stat.txt", function(stat) {
|
fs.stat("/tmp/stat.txt", function(stat) {
|
||||||
is(stat.mtime, lastTime, "flush on non-dirty file doesn't change mtime");
|
is(stat.mtime, lastTime, "flush on non-dirty file doesn't change mtime");
|
||||||
lastTime = stat.mtime;
|
lastTime = stat.mtime;
|
||||||
next();
|
next();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
@ -757,13 +759,11 @@ tests.push(function() {
|
||||||
|
|
||||||
tests.push(function() {
|
tests.push(function() {
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
fs.flush(fd, function() {
|
fs.flush(fd);
|
||||||
fs.close(fd, function() {
|
fs.close(fd);
|
||||||
fs.stat("/tmp/stat.txt", function(stat) {
|
fs.stat("/tmp/stat.txt", function(stat) {
|
||||||
is(stat.mtime, lastTime, "close doesn't update mtime");
|
is(stat.mtime, lastTime, "close doesn't update mtime");
|
||||||
next();
|
next();
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
@ -808,8 +808,8 @@ tests.push(function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncStorage.clear(function() {
|
fs.init(function() {
|
||||||
fs.init(function() {
|
fs.clear(function() {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -61,6 +61,12 @@ public class TestMediaImage implements Testlet, PlayerListener {
|
||||||
|
|
||||||
player.start();
|
player.start();
|
||||||
|
|
||||||
|
// We have to remove the listener now that we're done testing.
|
||||||
|
// Otherwise, it could receive additional calls to playerUpdate,
|
||||||
|
// including after we've returned, and the harness has tallied
|
||||||
|
// our total number of passed tests!
|
||||||
|
player.removePlayerListener(this);
|
||||||
|
|
||||||
file.delete();
|
file.delete();
|
||||||
file.close();
|
file.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче