@awayfl/avm2
Version:
Virtual machine for executing AS3 code
65 lines (62 loc) • 1.93 kB
text/typescript
import { safeGetPrototypeOf } from './safeGetPrototypeOf';
import { isNullOrUndefined } from '@awayfl/swf-loader';
import { AXObject } from './AXObject';
export class HasNext2Info {
constructor(public object: AXObject, public index: number) {
// ...
}
/**
* Determine if the given object has any more properties after the specified |index| and if so,
* return the next index or |zero| otherwise. If the |obj| has no more properties then continue
* the search in
* |obj.__proto__|. This function returns an updated index and object to be used during
* iteration.
*
* the |for (x in obj) { ... }| statement is compiled into the following pseudo bytecode:
*
* index = 0;
* while (true) {
* (obj, index) = hasNext2(obj, index);
* if (index) { #1
* x = nextName(obj, index); #2
* } else {
* break;
* }
* }
*
* #1 If we return zero, the iteration stops.
* #2 The spec says we need to get the nextName at index + 1, but it's actually index - 1, this
* caused me two hours of my life that I will probably never get back.
*
* TODO: We can't match the iteration order semantics of Action Script, hopefully programmers
* don't rely on it.
*/
next(object: AXObject, index: number) {
if (isNullOrUndefined(object)) {
this.index = 0;
this.object = null;
return;
} else {
this.object = object;
this.index = index;
}
let nextIndex = object.axNextNameIndex(this.index);
if (nextIndex > 0) {
this.index = nextIndex;
return;
}
// If there are no more properties in the object then follow the prototype chain.
while (!(nextIndex > 0)) {
object = safeGetPrototypeOf(object);
if (!object) {
this.index = 0;
this.object = null;
return;
}
nextIndex = object.axNextNameIndex(0);
}
this.index = nextIndex;
this.object = object;
return;
}
}