зеркало из https://github.com/mozilla/pluotsorbet.git
214 строки
5.6 KiB
JavaScript
214 строки
5.6 KiB
JavaScript
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
|
|
|
'use strict';
|
|
|
|
var JARStore = (function() {
|
|
var DATABASE = "JARStore";
|
|
var VERSION = 2;
|
|
var OBJECT_STORE_OLD = "files";
|
|
var OBJECT_STORE_WITH_UNCOMPRESSED_LEN = "files_v2"
|
|
var KEY_PATH = "jarName";
|
|
|
|
var database;
|
|
var jars = new Map();
|
|
var jad;
|
|
|
|
var upgrade = {
|
|
"0to1": function(database, transaction, next) {
|
|
database.createObjectStore(OBJECT_STORE_OLD, { keyPath: KEY_PATH });
|
|
next();
|
|
},
|
|
"1to2": function(database, transaction, next) {
|
|
database.deleteObjectStore(OBJECT_STORE_OLD);
|
|
// We don't migrate data from the old format to the new one, but
|
|
// rely on JARStore users to recreate the needed data.
|
|
database.createObjectStore(OBJECT_STORE_WITH_UNCOMPRESSED_LEN, { keyPath: KEY_PATH });
|
|
next();
|
|
},
|
|
};
|
|
|
|
var openDatabase = new Promise(function(resolve, reject) {
|
|
var request = indexedDB.open(DATABASE, VERSION);
|
|
|
|
request.onerror = function() {
|
|
console.error("error opening database: " + request.error.name);
|
|
reject(request.error.name);
|
|
};
|
|
|
|
request.onupgradeneeded = function(event) {
|
|
var database = request.result;
|
|
var transaction = request.transaction;
|
|
|
|
var version = event.oldVersion;
|
|
(function next() {
|
|
if (version < event.newVersion) {
|
|
upgrade[version + "to" + ++version](database, transaction, next);
|
|
}
|
|
})();
|
|
};
|
|
|
|
request.onsuccess = function() {
|
|
database = request.result;
|
|
resolve();
|
|
};
|
|
});
|
|
|
|
function addBuiltIn(jarName, jarData) {
|
|
var zip = new ZipFile(jarData, false);
|
|
|
|
jars.set(jarName, {
|
|
directory: zip.directory,
|
|
isBuiltIn: true,
|
|
});
|
|
}
|
|
|
|
function installJAR(jarName, jarData, jadData) {
|
|
return openDatabase.then(function() {
|
|
return new Promise(function(resolve, reject) {
|
|
var zip = new ZipFile(jarData, true);
|
|
|
|
var transaction = database.transaction(OBJECT_STORE_WITH_UNCOMPRESSED_LEN, "readwrite");
|
|
var objectStore = transaction.objectStore(OBJECT_STORE_WITH_UNCOMPRESSED_LEN);
|
|
var request = objectStore.put({
|
|
jarName: jarName,
|
|
jar: zip.directory,
|
|
jad: jadData || null,
|
|
});
|
|
|
|
request.onerror = function() {
|
|
console.error("Error installing " + jarName + ": " + request.error.name);
|
|
reject(request.error.name);
|
|
};
|
|
|
|
transaction.oncomplete = function() {
|
|
jars.set(jarName, {
|
|
directory: zip.directory,
|
|
isBuiltIn: false,
|
|
});
|
|
resolve();
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
function loadJAR(jarName) {
|
|
return openDatabase.then(function() {
|
|
return new Promise(function(resolve, reject) {
|
|
var transaction = database.transaction(OBJECT_STORE_WITH_UNCOMPRESSED_LEN, "readonly");
|
|
var objectStore = transaction.objectStore(OBJECT_STORE_WITH_UNCOMPRESSED_LEN);
|
|
var request = objectStore.get(jarName);
|
|
|
|
request.onerror = function() {
|
|
console.error("Error loading " + jarName + ": " + request.error.name);
|
|
reject(request.error.name);
|
|
};
|
|
|
|
transaction.oncomplete = function() {
|
|
if (request.result) {
|
|
jars.set(jarName, {
|
|
directory: request.result.jar,
|
|
isBuiltIn: false,
|
|
});
|
|
|
|
if (request.result.jad) {
|
|
jad = request.result.jad;
|
|
}
|
|
|
|
resolve(true);
|
|
} else {
|
|
resolve(false);
|
|
}
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
function loadFileFromJAR(jarName, fileName) {
|
|
var jar = jars.get(jarName);
|
|
if (!jar) {
|
|
return null;
|
|
}
|
|
|
|
var entry = jar.directory[fileName];
|
|
|
|
if (!entry) {
|
|
return null;
|
|
}
|
|
|
|
var bytes;
|
|
if (entry.compression_method === 0) {
|
|
bytes = entry.compressed_data;
|
|
} else if (entry.compression_method === 8) {
|
|
bytes = inflate(entry.compressed_data, entry.uncompressed_len);
|
|
} else {
|
|
return null;
|
|
}
|
|
|
|
if (!jar.isBuiltIn && fileName.endsWith(".class")) {
|
|
// Classes are loaded just once and then are cached in ClassRegistry::classes
|
|
delete jar.directory[fileName];
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
function loadFile(fileName) {
|
|
for (var jarName of jars.keys()) {
|
|
var data = loadFileFromJAR(jarName, fileName);
|
|
if (data) {
|
|
return data;
|
|
}
|
|
}
|
|
}
|
|
|
|
function getJAD() {
|
|
return jad;
|
|
}
|
|
|
|
function clear() {
|
|
return openDatabase.then(function() {
|
|
return new Promise(function(resolve, reject) {
|
|
jars.clear();
|
|
|
|
var transaction = database.transaction(OBJECT_STORE_WITH_UNCOMPRESSED_LEN, "readwrite");
|
|
var objectStore = transaction.objectStore(OBJECT_STORE_WITH_UNCOMPRESSED_LEN);
|
|
var request = objectStore.clear();
|
|
|
|
request.onerror = function() {
|
|
console.error("Error clearing: " + request.error.name);
|
|
reject(request.error.name);
|
|
};
|
|
|
|
request.onsuccess = function() {
|
|
resolve();
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
function deleteDatabase() {
|
|
return new Promise(function(resolve, reject) {
|
|
database = null;
|
|
var request = indexedDB.deleteDatabase(DATABASE);
|
|
request.onsuccess = resolve;
|
|
request.onerror = function() { reject(request.error.name) };
|
|
});
|
|
}
|
|
|
|
return {
|
|
addBuiltIn: addBuiltIn,
|
|
installJAR: installJAR,
|
|
loadJAR: loadJAR,
|
|
loadFileFromJAR: loadFileFromJAR,
|
|
loadFile: loadFile,
|
|
getJAD: getJAD,
|
|
clear: clear,
|
|
deleteDatabase: deleteDatabase,
|
|
};
|
|
})();
|
|
|
|
if (typeof module === 'object') {
|
|
module.exports.JARStore = JARStore;
|
|
}
|