/// import { Flags } from './util'; import { ConstantPool, ClassReference, MethodHandle, IConstantPoolItem } from './ConstantPool'; import { IAttribute } from './attributes'; import { JVMThread } from './threading'; import { Method, Field } from './methods'; import { ClassLoader } from './ClassLoader'; import { ClassState } from './enums'; import StringOutputStream from './StringOutputStream'; import * as JVMTypes from '../includes/JVMTypes'; export interface IJVMConstructor { /** * Constructs a new object in the same manner as the JVM's "new" opcode. * Does *NOT* run the JVM constructor! * @param jvm The thread that is constructing the object. * @param lengths... If this is an array type, the length of each dimension of the array. (Required if an array type.) */ new (thread: JVMThread, lengths?: number[] | number): T; } /** * Represents a single class in the JVM. */ export declare abstract class ClassData { protected loader: ClassLoader; accessFlags: Flags; /** * We make this private to *enforce* call sites to use our getter functions. * The actual state of this class depends on the state of its parents, and * parents do not inform their children when they change state. */ private state; private jco; /** * The class's canonical name, in internal form. * Ljava/lang/Foo; */ protected className: string; protected superClass: ReferenceClassData; /** * Responsible for setting up all of the fields that are guaranteed to be * present on any ClassData object. */ constructor(loader: ClassLoader); /** * Get the external form of this class's name (e.g. java.lang.String). */ getExternalName(): string; /** * Get the internal form of this class's name (e.g. Ljava/lang/String;). */ getInternalName(): string; /** * Get the name of the package that this class belongs to (e.g. java.lang). */ getPackageName(): string; /** * Returns the ClassLoader object of the classloader that initialized this * class. Returns null for the default classloader. */ getLoader(): ClassLoader; /** * Get the class's super class, which is always going to be a reference * class. */ getSuperClass(): ReferenceClassData; /** * Get all of the interfaces that the class implements. */ getInterfaces(): ReferenceClassData[]; /** * Get all of the injected fields for this class. The value for each field * in the returned map is its type. */ getInjectedFields(): { [fieldName: string]: string; }; /** * Get all of the injected methods for this class. The value for each method * in the returned map is its type. */ getInjectedMethods(): { [methodName: string]: string; }; /** * Get all of the injected static methods for this class. The value for each * method in the returned map is its type. */ getInjectedStaticMethods(): { [methodName: string]: string; }; /** * Get a java.lang.Class object corresponding to this class. */ getClassObject(thread: JVMThread): JVMTypes.java_lang_Class; /** * Get the protection domain of this class. * This value is NULL for all but reference classes loaded by app classloaders. */ getProtectionDomain(): JVMTypes.java_security_ProtectionDomain; /** * Retrieves the method defined in this particular class by the given method * signature *without* invoking method lookup. * @param methodSignature The method's full signature, e.g. ()V */ getMethod(methodSignature: string): Method; /** * Retrieve all of the methods defined on this class. */ getMethods(): Method[]; /** * Retrieve the set of fields defined on this class. */ getFields(): Field[]; /** * Attempt to synchronously resolve this class using its loader. Should only * be called on ClassData in the LOADED state. */ abstract tryToResolve(): boolean; /** * Attempt to synchronously initialize this class. */ abstract tryToInitialize(): boolean; /** * Set the state of this particular class to LOADED/RESOLVED/INITIALIZED. */ setState(state: ClassState): void; /** * Gets the current state of this class. */ protected getState(): ClassState; /** * Check if the class is initialized. * @param thread The thread that is performing the check. If initialization * is in progress on that thread, then the class is, for all intents and * purposes, initialized. */ isInitialized(thread: JVMThread): boolean; isResolved(): boolean; isSubinterface(target: ClassData): boolean; isSubclass(target: ClassData): boolean; abstract isCastable(target: ClassData): boolean; resolve(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; initialize(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; protected outputInjectedMethods(jsClassName: string, outputStream: StringOutputStream): void; } export declare class PrimitiveClassData extends ClassData { constructor(className: string, loader: ClassLoader); /** * Returns a boolean indicating if this class is an instance of the target class. * "target" is a ClassData object. * The ClassData objects do not need to be initialized; just loaded. */ isCastable(target: ClassData): boolean; /** * Returns the internal class name for the corresponding boxed type. */ boxClassName(): string; /** * Returns a boxed version of the given primitive. */ createWrapperObject(thread: JVMThread, value: any): JVMTypes.java_lang_Object; tryToResolve(): boolean; tryToInitialize(): boolean; /** * Primitive classes are already resolved. */ resolve(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; } export declare class ArrayClassData extends ClassData { private componentClassName; private componentClass; private _constructor; constructor(componentType: string, loader: ClassLoader); /** * Looks up a method with the given signature. Returns null if no method * found. */ methodLookup(signature: string): Method; fieldLookup(name: string): Field; /** * Resolve the class. */ resolve(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; getComponentClass(): ClassData; /** * Resolved and initialized are the same for array types. */ setResolved(super_class_cdata: ReferenceClassData, component_class_cdata: ClassData): void; tryToResolve(): boolean; tryToInitialize(): boolean; /** * Returns a boolean indicating if this class is an instance of the target class. * "target" is a ClassData object. * The ClassData objects do not need to be initialized; just loaded. * See §2.6.7 for casting rules. */ isCastable(target: ClassData): boolean; initialize(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; /** * Get the array constructor for this particular JVM array class. * Uses typed arrays when available for primitive arrays. */ private getJSArrayConstructor(); /** * Get the initial value placed into each array element. */ private getJSDefaultArrayElement(); /** * Creates a specialized `slice` method that creates a shallow slice of this * array. Specialized to the type of array (JS or Typed). */ private _getSliceMethod(); private _constructConstructor(thread); getConstructor(thread: JVMThread): IJVMConstructor>; } /** * Represents a "reference" Class -- that is, a class that neither represents a * primitive nor an array. */ export declare class ReferenceClassData extends ClassData { private minorVersion; majorVersion: number; constantPool: ConstantPool; /** * All of the fields directly defined by this class. */ private fields; /** * All of the methods directly defined by this class. */ private methods; private attrs; private interfaceClasses; private superClassRef; private interfaceRefs; /** * Initialization lock. */ private initLock; /** * Stores the JavaScript constructor for this class. */ private _constructor; /** * Virtual field table */ private _fieldLookup; /** * All fields in object instantiations. Fields from super classes are in front * of fields from this class. A field's offset in the array is its *vmindex*. */ protected _objectFields: Field[]; /** * All static fields in this particular class. The field's offset in this * array is its *vmindex*. */ protected _staticFields: Field[]; /** * Virtual method table, keyed by method signature. Unlike _vmTable, * _methodLookup contains static methods and constructors, too. */ private _methodLookup; /** * Virtual method table, keyed by vmindex. Methods originally defined by * super classes are in front of methods defined in this class. Overriding * methods are placed into the vmindex of the originating method. */ protected _vmTable: Method[]; /** * Default method implementations that this class did *not* inherit, but are * still invocable in the class via their full name (e.g. through an * invokespecial bytecode). */ protected _uninheritedDefaultMethods: Method[]; /** * The ProtectionDomain for this class, specified by the application class * loader. NULL for bootstrap classloaded items. */ protected _protectionDomain: JVMTypes.java_security_ProtectionDomain; constructor(buffer: Buffer, protectionDomain?: JVMTypes.java_security_ProtectionDomain, loader?: ClassLoader, cpPatches?: JVMTypes.JVMArray); getSuperClassReference(): ClassReference; getInterfaceClassReferences(): ClassReference[]; /** * Retrieve the set of interfaces that this class implements. * DO NOT MUTATE! */ getInterfaces(): ReferenceClassData[]; /** * The set of fields that this class has. * DO NOT MUTATE! */ getFields(): Field[]; /** * Get the Virtual Method table for this class. */ getVMTable(): Method[]; /** * Returns the VM index for the given method. Returns -1 if not present in the * virtual method table (e.g. is static or a constructor). */ getVMIndexForMethod(m: Method): number; /** * Returns the method corresponding to the given VMIndex. */ getMethodFromVMIndex(i: number): Method; /** * Get the VM index for the given field * NOTE: A static and non-static field can have the same vmindex! Caller must * be able to differentiate between static and non-static behavior! */ getVMIndexForField(f: Field): number; getStaticFieldFromVMIndex(index: number): Field; getObjectFieldFromVMIndex(index: number): Field; /** * Get a field from its "slot". A "slot" is just the field's index in its * defining class's field array. */ getFieldFromSlot(slot: number): Field; /** * Get a method from its "slot". A "slot" is just the method's index in its * defining class's method array. */ getMethodFromSlot(slot: number): Method; /** * Retrieve a method with the given signature from this particular class. * Does not search superclasses / interfaces. */ getMethod(sig: string): Method; getSpecificMethod(definingCls: string, sig: string): Method; /** * Get the methods belonging to this particular class. * DO NOT MUTATE! */ getMethods(): Method[]; /** * Get the set of default methods that are invocable on this object, but were * not inherited in the virtual method table. * DO NOT MUTATE! */ getUninheritedDefaultMethods(): Method[]; getProtectionDomain(): JVMTypes.java_security_ProtectionDomain; /** * Resolves this class's virtual method table according to the JVM * specification: * http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3 */ private _resolveMethods(); /** * Resolves all of the fields for this class according to the JVM * specification: * http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.2 */ private _resolveFields(); /** * Looks up a method with the given signature. Returns null if no method * found. */ methodLookup(signature: string): Method; /** * Performs method lookup, and includes signature polymorphic results if * the method is signature polymorphic. */ signaturePolymorphicAwareMethodLookup(signature: string): Method; /** * Looks up a field with the given name. Returns null if no method found. */ fieldLookup(name: string): Field; getAttribute(name: string): IAttribute; getAttributes(name: string): IAttribute[]; /** * Get the bootstrap method information for an InvokeDynamic opcode. */ getBootstrapMethod(idx: number): [MethodHandle, IConstantPoolItem[]]; /** * Returns the initial value for a given static field in the class. Should * only be called when the constructor is created. */ private _getInitialStaticFieldValue(thread, name); setResolved(superClazz: ReferenceClassData, interfaceClazzes: ReferenceClassData[]): void; tryToResolve(): boolean; /** * Attempt to synchronously initialize. This is possible if there is no * static initializer, and the parent classes are properly initialized. */ tryToInitialize(): boolean; /** * Returns a boolean indicating if this class is an instance of the target class. * "target" is a ClassData object. * The ClassData objects do not need to be initialized; just loaded. * See §2.6.7 for casting rules. * @todo Determine this statically to make this a constant time operation. */ isCastable(target: ClassData): boolean; /** * Returns 'true' if I implement the target interface. */ isSubinterface(target: ClassData): boolean; /** * Asynchronously *initializes* the class and its super classes. * Throws a Java exception on the thread if initialization fails. * @param thread The thread that is performing the initialization. * @param cb Callback to invoke when completed. Contains a reference to the * class if it succeeds, or NULL if a failure occurs. * @param [explicit] Defaults to true. If true, this class is being * *explicitly* initialized by a user. If false, the JVM is implicitly * initializing the class. */ initialize(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; /** * Helper function. Initializes this class alone. Assumes super class is * already initialized. */ private _initialize(thread, cb); /** * A reference class can be treated as initialized in a thread if that thread * is in the process of initializing it. */ isInitialized(thread: JVMThread): boolean; /** * Resolve the class. */ resolve(thread: JVMThread, cb: (cdata: ClassData) => void, explicit?: boolean): void; /** * Find Miranda and default interface methods in this class. These * methods manifest as new vmindices in the virtual method table compared with * the superclass, and are not defined in this class itself. */ getMirandaAndDefaultMethods(): Method[]; outputInjectedFields(outputStream: StringOutputStream): void; protected _constructConstructor(thread: JVMThread): IJVMConstructor; getConstructor(thread: JVMThread): IJVMConstructor; }