pluotsorbet/classes.js

193 строки
5.8 KiB
JavaScript
Исходник Обычный вид История

2014-07-06 12:29:36 +04:00
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
'use strict';
var Classes = function() {
if (this instanceof Classes) {
this.classfiles = [];
this.mainclass = [];
this.classes = {};
} else {
return new Classes();
}
}
Classes.ClassNotFoundException = function(message) {
this.message = message;
};
2014-08-05 23:15:13 +04:00
Classes.ClassNotFoundException.prototype = Object.create(Error.prototype);
Classes.ClassNotFoundException.prototype.name = "ClassNotFoundException";
Classes.ClassNotFoundException.prototype.constructor = Classes.ClassNotFoundException;
2014-07-26 02:06:21 +04:00
2014-07-06 12:29:36 +04:00
Classes.prototype.addPath = function(name, data) {
if (name.substr(-4) === ".jar") {
data = new ZipFile(data);
}
this.classfiles[name] = data;
}
2014-08-03 04:25:00 +04:00
Classes.prototype.loadFileFromJar = function(jar, fileName) {
var classfiles = this.classfiles;
var zip = classfiles[jar];
if (!zip)
return null;
if (!(fileName in zip.directory))
return null;
var bytes = zip.read(fileName);
return bytes.buffer.slice(0, bytes.length);
}
2014-07-06 12:29:36 +04:00
Classes.prototype.loadFile = function(fileName) {
2014-07-06 13:03:36 +04:00
var classfiles = this.classfiles;
var data = classfiles[fileName];
2014-07-06 12:29:36 +04:00
if (data)
return data;
2014-07-06 13:03:36 +04:00
Object.keys(classfiles).every(function (name) {
2014-07-06 12:29:36 +04:00
if (name.substr(-4) !== ".jar")
return true;
2014-07-06 13:03:36 +04:00
var zip = classfiles[name];
if (fileName in zip.directory) {
var bytes = zip.read(fileName);
data = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
}
return !data;
2014-07-06 12:29:36 +04:00
});
2014-08-06 04:08:59 +04:00
if (data)
classfiles[fileName] = data;
2014-07-06 12:29:36 +04:00
return data;
}
Classes.prototype.loadClassBytes = function(bytes) {
2014-07-13 03:42:01 +04:00
var classInfo = new ClassInfo(bytes);
this.classes[classInfo.className] = classInfo;
2014-07-13 03:42:01 +04:00
return classInfo;
2014-07-06 12:29:36 +04:00
}
Classes.prototype.loadClassFile = function(fileName) {
var bytes = this.loadFile(fileName);
2014-07-26 02:06:21 +04:00
if (!bytes)
throw new (Classes.ClassNotFoundException)(fileName);
2014-07-18 10:26:34 +04:00
var self = this;
2014-07-13 03:42:01 +04:00
var classInfo = this.loadClassBytes(bytes);
if (classInfo.superClassName)
2014-07-18 13:00:10 +04:00
classInfo.superClass = this.loadClass(classInfo.superClassName);
2014-07-18 10:26:34 +04:00
var classes = classInfo.classes;
classes.forEach(function (c, n) {
classes[n] = self.loadClass(c);
});
2014-07-13 03:42:01 +04:00
return classInfo;
2014-07-06 12:29:36 +04:00
}
2014-07-18 13:00:10 +04:00
Classes.prototype.loadClass = function(className) {
var classInfo = this.classes[className];
if (classInfo)
return classInfo;
return this.loadClassFile(className + ".class");
}
2014-07-17 12:14:18 +04:00
Classes.prototype.getEntryPoint = function(classInfo) {
var methods = classInfo.methods;
for (var i=0; i<methods.length; i++) {
var method = methods[i];
if (method.isPublic && method.isStatic && !method.isNative &&
method.name === "main" &&
method.signature === "([Ljava/lang/String;)V") {
return method;
2014-07-06 12:29:36 +04:00
}
2014-07-12 20:48:05 +04:00
}
2014-07-06 12:29:36 +04:00
}
Classes.prototype.getClass = function(className) {
2014-07-13 03:42:01 +04:00
var classInfo = this.classes[className];
2014-07-17 12:37:35 +04:00
if (!classInfo) {
if (className[0] === "[") {
classInfo = this.initArrayClass(className);
2014-07-18 13:00:10 +04:00
} else {
classInfo = this.loadClass(className);
2014-07-17 12:37:35 +04:00
}
if (!classInfo)
return null;
2014-07-09 11:12:58 +04:00
}
2014-07-17 12:37:35 +04:00
return classInfo;
2014-07-06 12:29:36 +04:00
};
Classes.prototype.initArrayClass = function(typeName) {
2014-07-14 03:31:36 +04:00
var elementType = typeName.substr(1);
2014-07-18 12:20:06 +04:00
var constructor = ARRAYS[elementType];
if (constructor)
return this.classes[typeName] = this.initPrimitiveArrayType(typeName, constructor);
2014-07-18 13:00:10 +04:00
if (elementType[0] === "L")
elementType = elementType.substr(1).replace(";", "");
2014-07-18 12:25:12 +04:00
var classInfo = new ArrayClass(typeName, this.getClass(elementType));
2014-07-21 04:10:12 +04:00
classInfo.superClass = this.java_lang_Object;
2014-07-14 04:02:57 +04:00
classInfo.constructor = function (size) {
var array = new Array(size);
array.class = classInfo;
return array;
}
2014-07-18 13:00:10 +04:00
return this.classes[typeName] = classInfo;
2014-07-14 03:31:36 +04:00
}
Classes.prototype.initPrimitiveArrayType = function(typeName, constructor) {
var classInfo = new ArrayClass(typeName);
2014-07-21 04:10:12 +04:00
classInfo.superClass = this.java_lang_Object;
2014-07-14 04:02:57 +04:00
constructor.prototype.class = classInfo;
classInfo.constructor = constructor;
return classInfo;
2014-07-14 03:31:36 +04:00
}
Classes.prototype.getField = function(classInfo, fieldKey) {
if (classInfo.vfc[fieldKey]) {
2014-09-25 23:52:38 +04:00
return classInfo.vfc[fieldKey];
}
2014-07-20 02:53:58 +04:00
do {
var fields = classInfo.fields;
for (var i=0; i<fields.length; ++i) {
var field = fields[i];
2014-09-25 23:52:38 +04:00
if (!field.key) {
2014-09-26 22:48:06 +04:00
field.key = (ACCESS_FLAGS.isStatic(field.access_flags) ? "S" : "I") + "." + field.name + "." + field.signature;
2014-09-25 23:52:38 +04:00
}
if (field.key === fieldKey) {
return classInfo.vfc[fieldKey] = field;
2014-07-20 02:53:58 +04:00
}
}
2014-09-25 23:52:38 +04:00
2014-09-26 22:48:06 +04:00
if (fieldKey[0] === 'S') {
for (var n = 0; n < classInfo.interfaces.length; ++n) {
var field = this.getField(classInfo.interfaces[n], fieldKey);
2014-09-25 23:52:38 +04:00
if (field) {
return classInfo.vfc[fieldKey] = field;
2014-09-25 23:52:38 +04:00
}
}
}
2014-09-25 23:52:38 +04:00
2014-07-20 02:53:58 +04:00
classInfo = classInfo.superClass;
} while (classInfo);
};
Classes.prototype.getMethod = function(classInfo, methodKey) {
2014-08-01 06:42:36 +04:00
var c = classInfo;
do {
2014-08-01 06:42:36 +04:00
var methods = c.methods;
2014-07-20 02:53:58 +04:00
for (var i=0; i<methods.length; ++i) {
var method = methods[i];
if (method.key === methodKey) {
return classInfo.vmc[methodKey] = method;
2014-07-10 09:23:17 +04:00
}
2014-07-06 12:29:36 +04:00
}
2014-08-01 06:42:36 +04:00
c = c.superClass;
} while (c);
2014-08-01 06:42:36 +04:00
if (ACCESS_FLAGS.isInterface(classInfo.access_flags)) {
for (var n = 0; n < classInfo.interfaces.length; ++n) {
var method = this.getMethod(classInfo.interfaces[n], methodKey);
if (method) {
return classInfo.vmc[methodKey] = method;
}
2014-08-01 06:42:36 +04:00
}
}
2014-07-06 12:29:36 +04:00
};