UNPKG

@awayfl/avm1

Version:

Virtual machine for executing AS1 and AS2 code

244 lines (243 loc) 9.71 kB
/** * Copyright 2014 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { alCoerceString, alToString } from './runtime'; import { installBuiltins } from './natives'; import { Debug, release, assert } from '@awayfl/swf-loader'; import { AVM1Key } from './lib/AVM1Key'; import { AVM1Mouse } from './lib/AVM1Mouse'; import { AVM1Stage } from './lib/AVM1Stage'; import { AVM1MovieClip } from './lib/AVM1MovieClip'; import { getAVM1Object } from './lib/AVM1Utils'; import { AssetLibrary } from '@awayjs/core'; var AVM1ActionsData = /** @class */ (function () { function AVM1ActionsData(bytes, id, parent, encryptedData) { if (parent === void 0) { parent = null; } this.bytes = bytes; this.id = id; this.parent = parent; this.encryptedData = encryptedData; this.debugPath = this.id; this.ir = null; this.compiled = null; } return AVM1ActionsData; }()); export { AVM1ActionsData }; var ActionsDataFactory = /** @class */ (function () { function ActionsDataFactory() { this._cache = new WeakMap(); } ActionsDataFactory.prototype.createActionsData = function (actionData, id, parent) { if (parent === void 0) { parent = null; } var isArray = (actionData instanceof Uint8Array); var bytes = isArray ? actionData : actionData.actionsData; var encryptedData = isArray ? undefined : actionData.encryptedData; var actionsData = this._cache.get(bytes); if (!actionsData) { actionsData = new AVM1ActionsData(bytes, id, parent, encryptedData); this._cache.set(bytes, actionsData); } release || assert(actionsData.bytes === actionData && actionsData.id === id && actionsData.parent === parent); return actionsData; }; return ActionsDataFactory; }()); export { ActionsDataFactory }; var AVM1Context = /** @class */ (function () { function AVM1Context(swfVersion) { this.eventObservers = {}; this.assets = {}; this.awayAssets = {}; this.assetsSymbols = []; this.assetsClasses = []; this.staticStates = new WeakMap(); this.swfVersion = swfVersion; this.globals = null; this.actionsDataFactory = new ActionsDataFactory(); if (swfVersion > 6) { this.isPropertyCaseSensitive = true; this.normalizeName = this.normalizeNameCaseSensitive; } else { this.isPropertyCaseSensitive = false; this._nameCache = Object.create(null); this.normalizeName = this.normalizeNameCaseInsensitive; } this.builtins = {}; installBuiltins(this); } AVM1Context.prototype.resolveTarget = function (target) { }; AVM1Context.prototype.resolveRoot = function () { }; AVM1Context.prototype.checkTimeout = function () { }; AVM1Context.prototype.executeActions = function (actionsData, scopeObj) { }; AVM1Context.prototype.executeFunction = function (fn, thisArg, args) { }; AVM1Context.prototype.normalizeNameCaseSensitive = function (name) { switch (typeof name) { case 'number': case 'string': return name; default: return alToString(this, name); } }; AVM1Context.prototype.normalizeNameCaseInsensitive = function (name) { switch (typeof name) { case 'number': return name.toString(); case 'string': break; default: name = alToString(this, name); } var normalizedName = this._nameCache[name]; if (normalizedName) { return normalizedName; } normalizedName = name.toLowerCase(); this._nameCache[name] = normalizedName; return normalizedName; }; AVM1Context.prototype._getEventPropertyObservers = function (propertyName, create) { if (!this.isPropertyCaseSensitive) { propertyName = propertyName.toLowerCase(); } var observers = this.eventObservers[propertyName]; if (observers) { return observers; } if (create) { observers = []; this.eventObservers[propertyName] = observers; return observers; } return null; }; AVM1Context.prototype.registerEventPropertyObserver = function (propertyName, observer) { var observers = this._getEventPropertyObservers(propertyName, true); observers.push(observer); }; AVM1Context.prototype.unregisterEventPropertyObserver = function (propertyName, observer) { var observers = this._getEventPropertyObservers(propertyName, false); if (!observers) { return; } var j = observers.indexOf(observer); if (j < 0) { return; } observers.splice(j, 1); }; AVM1Context.prototype.broadcastEventPropertyChange = function (propertyName) { var observers = this._getEventPropertyObservers(propertyName, false); if (!observers) { return; } observers.forEach(function (observer) { return observer.onEventPropertyModified(propertyName); }); }; AVM1Context.prototype.addAsset = function (className, symbolId, symbolProps) { //console.log("addAsset", className, symbolId, symbolProps); release || Debug.assert(typeof className === 'string' && !isNaN(symbolId)); this.assets[className.toLowerCase()] = symbolId; this.assetsSymbols[symbolId] = symbolProps; //80pro: directly store assets in dictionary this.awayAssets[className.toLowerCase()] = symbolProps; }; AVM1Context.prototype.registerClass = function (className, theClass) { className = alCoerceString(this, className); if (className === null) { this.utils.warn('Cannot register class for symbol: className is missing'); return; } var myAsset = AssetLibrary.getAsset(className, AVM1MovieClip.currentMCAssetNameSpace); if (!myAsset || !myAsset.adaptee) { console.warn('can not find symbol to register class ' + className); return; } //console.log("register", myAsset.adaptee.name, myAsset.adaptee.id); myAsset.adaptee.avm1Symbol = theClass; /* var symbolId = this.assets[className.toLowerCase()]; if (symbolId === undefined) { this.utils.warn('Cannot register ' + className + ' class for symbol'); return; } this.assetsClasses[symbolId] = theClass;*/ }; AVM1Context.prototype.getSymbolClass = function (symbolId) { return this.assetsClasses[symbolId] || null; }; AVM1Context.prototype.getAsset = function (className) { className = alCoerceString(this, className); if (className === null) { return undefined; } var symbolId = this.assets[className.toLowerCase()]; if (symbolId === undefined) { return undefined; } var symbol = this.awayAssets[className.toLowerCase()]; if (!symbol) { console.log('error in getAsset. not implemented to grab assets from loaderInfo'); /*symbol = this.loaderInfo.getSymbolById(symbolId); if (!symbol) { Debug.warning("Symbol " + symbolId + " is not defined."); return undefined; } this.assetsSymbols[symbolId] = symbol;*/ } return { symbolId: symbolId, symbolProps: symbol }; }; AVM1Context.prototype.reset = function () { this.eventObservers = Object.create(null); this.assets = {}; this.assetsSymbols = []; this.assetsClasses = []; this.awayAssets = {}; this.staticStates = new WeakMap(); AVM1Stage.bindStage(this, this.globals.Stage, null, null, null); }; AVM1Context.prototype.setStage = function (avmStage, avm1Handler, htmlElement) { AVM1Key.bindStage(this, this.globals.Key, avmStage, htmlElement); AVM1Mouse.bindStage(this, this.globals.Mouse, avmStage, htmlElement); AVM1Stage.bindStage(this, this.globals.Stage, avmStage, avm1Handler, htmlElement); }; AVM1Context.prototype.getStaticState = function (cls) { var state = this.staticStates.get(cls); if (!state) { state = Object.create(null); var initStatic = cls.alInitStatic; if (initStatic) { initStatic.call(state, this); } this.staticStates.set(cls, state); } return state; }; AVM1Context.prototype.resolveLevel = function (level) { release || Debug.assert(typeof level === 'number'); var as3Root = this.globals._getRootForLevel(level); if (!as3Root) { this.utils.warn('Unable to resolve level ' + level + ' root'); return undefined; } return getAVM1Object(as3Root, this); }; return AVM1Context; }()); export { AVM1Context };