UNPKG

@awayfl/avm2

Version:

Virtual machine for executing AS3 code

129 lines (128 loc) 4.91 kB
import { Errors } from '../errors'; import { IS_AX_CLASS } from './AXClass'; var Scope = /** @class */ (function () { function Scope(parent, object, isWith) { if (isWith === void 0) { isWith = false; } this.parent = parent; this.object = object; this.isWith = isWith; this.defaultNamespace = null; this.cache = []; Scope.ID++; this[IS_AX_CLASS] = true; this.global = parent ? parent.global : this; object['__scope__'] = this; } Object.defineProperty(Scope.prototype, "superConstructor", { get: function () { var superCtr = this.object.superClass; if (!superCtr) { return null; } var r = superCtr[IS_AX_CLASS] ? superCtr.tPrototype.axInitializer : superCtr; // hack! // redefine field. Now it always return precomputed field. Object.defineProperty(this, 'superConstructor', { value: r }); return r; }, enumerable: false, configurable: true }); Scope.prototype.extend = function (object) { if (object === this.object) return this; var c = object['__scope__']; if (c && c.parent == this) { return c; } return new Scope(this, object, false); }; Scope.prototype.findDepth = function (object) { var current = this; var depth = 0; while (current) { if (current.object === object) { return depth; } depth++; current = current.parent; } return -1; }; Scope.prototype.getScopeObjects = function () { var objects = []; var current = this; while (current) { objects.unshift(current.object); current = current.parent; } return objects; }; Scope.prototype.getScopeProperty = function (mn, strict, scopeOnly) { return this.findScopeProperty(mn, strict, scopeOnly).axGetProperty(mn); }; Scope.prototype.findScopeProperty = function (mn, strict, scopeOnly) { if (mn.mutable || scopeOnly) return this._findScopeProperty(mn, strict, scopeOnly); if (mn.scope === this.object && !this.isWith) return mn.value; var value = this._findScopeProperty(mn, strict, scopeOnly); if (!this.isWith) { mn.value = value; mn.scope = this.object; } return value; }; Scope.prototype._findScopeProperty = function (mn, strict, scopeOnly) { // Multinames with a `null` name are the any name, '*'. Need to catch those here, because // otherwise we'll get a failing assert in `RuntimeTraits#getTrait` below. if (mn.name === null) { this.global.object.sec.throwError('ReferenceError', Errors.UndefinedVarError, '*'); } var object = this.cache[mn.id]; if (object) return object; // Scope lookups should not be trapped by proxies. Except for with scopes, check only trait // properties. if (this.object && this.object[IS_AX_CLASS] && (this.isWith ? this.object.axHasPropertyInternal(mn) : this.object.traits.getTrait(mn.namespaces, mn.name))) { return (this.isWith || mn.isRuntime()) ? this.object : (this.cache[mn.id] = this.object); } if (this.parent) { object = this.parent.findScopeProperty(mn, strict, scopeOnly); if (mn.kind === 7 /* CONSTANT.QName */) { this.cache[mn.id] = object; } return object; } if (scopeOnly) { return null; } // Attributes can't be stored on globals or be directly defined in scripts. if (mn.isAttribute()) { this.object.sec.throwError('ReferenceError', Errors.UndefinedVarError, mn.name); } // If we can't find the property look in the domain. var globalObject = this.global.object; if ((object = globalObject.applicationDomain.findProperty(mn, strict, true))) { return object; } // If we still haven't found it, look for dynamic properties on the global. // No need to do this for non-strict lookups as we'll end up returning the // global anyways. if (strict) { if (!(mn.getPublicMangledName() in globalObject)) { this.global.object.sec.throwError('ReferenceError', Errors.UndefinedVarError, mn.name); } } // Can't find it still, return the global object. return globalObject; }; Scope.prototype.toString = function () { return '' + this.parent + ' => ' + this.object + ' ' + this.isWith; }; Scope.ID = 0; return Scope; }()); export { Scope };