@awayfl/avm2
Version:
Virtual machine for executing AS3 code
133 lines (111 loc) • 3.66 kB
text/typescript
import { MethodTraitInfo } from './MethodTraitInfo';
import { MethodBodyInfo } from './MethodBodyInfo';
import { AXClass } from '../../run/AXClass';
import { ABCFile } from './ABCFile';
import { ParameterInfo } from './ParameterInfo';
import { MetadataInfo } from './MetadataInfo';
import { TRAIT } from './TRAIT';
import { InstanceInfo } from './InstanceInfo';
import { ClassInfo } from './ClassInfo';
import { METHOD } from './METHOD';
import { Multiname } from './Multiname';
import { ScriptInfo } from './ScriptInfo';
import { COMPILATION_STATE, COMPILATION_FAIL_REASON } from '../../flags';
import { IMethodReadableMeta } from '../../utils/reconstructMetadata';
export class MethodInfo {
public meta: IMethodReadableMeta;
public parentInfo?: MethodInfo;
public trait: MethodTraitInfo = null;
public minArgs: number;
private _body: MethodBodyInfo;
private _returnType: AXClass;
public scriptInfo: ScriptInfo = null;
public classInfo: ClassInfo = null;
public instanceInfo: InstanceInfo = null;
public isConstructor: boolean = false;
public compiled: Function = null;
public names: Multiname[];
public error: {message: string, reason: COMPILATION_FAIL_REASON} = null;
public useCount: number = 0;
public get state(): COMPILATION_STATE {
if (this.error || this.getBody() == null) {
return COMPILATION_STATE.FAILED;
}
if (this.compiled) {
return COMPILATION_STATE.COMPILLED;
}
return COMPILATION_STATE.PENDING;
}
constructor(
public abc: ABCFile,
private _index: number,
public readonly name: string,
public readonly typeName: Multiname,
public readonly parameters: ParameterInfo [],
public readonly optionalCount: number,
public readonly flags: number
) {
this._body = null;
this.minArgs = parameters.length - optionalCount;
}
public getNativeMetadata(): MetadataInfo {
const metadata = this.trait?.metadata;
if (!metadata)
return null;
for (let i = 0; i < metadata.length; i++)
if (metadata[i].name === 'native')
return metadata[i];
return null;
}
public getBody(): MethodBodyInfo {
return this._body || (this._body = this.abc.getMethodBodyInfo(this._index));
}
public index(): number {
return this._index;
}
getType(): AXClass {
if (this._returnType !== undefined)
return this._returnType;
this._returnType = this.typeName ? this.abc.applicationDomain.getClass(this.typeName) : null;
return this._returnType;
}
toString() {
let str = this.name;
str += ' (' + this.parameters.join(', ') + ')';
if (this.typeName) {
str += ': ' + this.typeName.name;
}
return str;
}
toFlashlogString(): string {
const trait = this.trait;
let prefix = trait.kind === TRAIT.Getter ? 'get ' :
trait.kind === TRAIT.Setter ? 'set ' : '';
let name = trait.multiname.toFlashlogString();
const holder = trait.holder;
let holderName;
if (holder && holder instanceof InstanceInfo) {
holderName = (<InstanceInfo>holder).multiname.toFlashlogString();
prefix = holderName + '/' + prefix;
}
if (holder && holder instanceof ClassInfo && (<ClassInfo>holder).trait) {
holderName = (<ClassInfo>holder).trait.multiname.toFlashlogString();
prefix = holderName + '$/' + prefix;
}
let prefixPos;
if (holderName && (prefixPos = name.indexOf('::')) > 0 &&
holderName.indexOf(name.substring(0, prefixPos + 2)) === 0) {
name = name.substring(prefixPos + 2);
}
return 'MTHD ' + prefix + name + ' ()';
}
isNative(): boolean {
return !!(this.flags & METHOD.Native);
}
needsRest(): boolean {
return !!(this.flags & METHOD.NeedRest);
}
needsArguments(): boolean {
return !!(this.flags & METHOD.NeedArguments);
}
}